The project's README from github.com/jnz/INSLIB. As one markdown file: README.md.

A portable C library for 3D navigation state estimation. Mail: [email protected]

Example video of pure inertial tracking with a TDK ICM-45686 low-cost Inertial Measurement Unit (IMU)
INSLIB is a portable C library for 3D navigation state estimation. Its core is a set of Kalman filters fusing measurements from an inertial measurement unit (IMU) with GNSS/GPS measurements, barometer, magnetometer, local position references, absolute yaw references, scalar ground speed and zero-velocity / zero-rotation information.
Typical use cases:
The core library is written in pure C (C11), has no external dependencies and is optimized for embedded microcontrollers. A useful collection of Python helper programs and GUI apps are included in this repository.
>90% Test Coverage including MC/DC testing (also used in aerospace DO-178 DAL-A or ISO26262 ASIL-D developments)make reqs), aerospace-stylebaro_alt vertical channel) and full attitude, not just raw IMU integrationAHRS_MODE_ARS mode (5-state, freely-integrated yaw) runs from IMU data alone
inspostgui.py is a GUI to post-process measurements: pick a dataset directory
(CSVs + config.yaml), tweak its settings, and replay it.
sh python/setup_venv.sh # one-time (also runs `make pylib`)
. env.sh # activate the venv (POSIX/git-bash, any OS)
python3 python/inspostgui.py datasets/fog
.csv Data FormatThe input format is plain CSV, one file per sensor. First item is a common
t_us timestamp in microseconds. IMU example:
# t_us, gyr_frd_x [rad/s], gyr_frd_y [rad/s], gyr_frd_z [rad/s], acc_frd_x [m/s^2], acc_frd_y [m/s^2], acc_frd_z [m/s^2]
0,-0.0016361766,-1.39143679e-08,-0.000272652038,-0.114920214,0.191539065,-9.84495283
50003,-0.0016361766,-1.39143679e-08,-0.000272652038,-0.114920214,0.191539065,-9.84495283
100005,-0.000272652038,-0.000272707696,0.000818123087,-0.0861961461,0.248990132,-9.7587816
GNSS/magnetometer/barometer/speed .csv files follow the same pattern. Example files:
config.yamlA dataset directory with CSV files carries one config.yaml that
tells the filter how to run: aiding mode, sensor noise, lever arms, which
channels are enabled. Two annotated examples to start from:
doc/example_conf/config_basic.yaml
(GNSS+IMU+baro+mag) and
doc/example_conf/config_local_inertial.yaml
(GNSS-free, pure inertial dead-reckoning). The keys are documented in
doc/INSLIB_manual.pdf, section "Dataset
configuration: config.yaml".
replay.py Command Line Post-Processing Versionreplay.py is the command line counterpart to
the inspostgui.py Python GUI above.
sh python/setup_venv.sh # one-time (also runs `make pylib`)
. env.sh # activate the venv (POSIX/git-bash, any OS)
python3 python/replay.py datasets/fog --plot --plot-out /tmp/plots.pdf
Example PDF plot output from replay.py:

Google Earth .kml output is also possible with --kml output.kml:


GNSS receivers report data with some latency
(transmission, internal processing, filtering) but
receiver and configuration dependent. inspostgui.py and replay.py measure
the real value for a specific configuration: IMU + barometric altitude has near-zero
latency, cross-correlating its vertical velocity against the
GNSS-reported vertical velocity around a real climb/descent results in a lag
with a sharp correlation peak (see the plot above).
Example for a u-blox X20P receiver delay estimation:
python3 python/replay.py datasets/pedestrian/07_outdoor_only/ --estimate-gnss-delay
insrcv listens for UDP packets with sensor measurements. The packet
format is documented in tools/inslib_protocol.md.
Any process that sends this protocol format can feed it on UDP port 29800
(default). Output goes to PlotJuggler (UDP :9870, JSON) and optionally in
MAVLink format (UDP :14550).
make insrcv
./build/insrcv --mavlink # run and wait for UDP sensor input
In action, fusing a live Galileo HAS-corrected GNSS fix:


<10 cm horizontal accuracy (1-sigma) without a correction service (requires compatible antenna)3-6 cm accuracy and convergence in seconds (source: u-blox)1 cm accuracy, from your own GNSS base station, a virtual base station, or a regional service such as SAPOS(Not all datasets have an absolute ground truth available, e.g. the ArduPilot dataset is comparing the INSLIB solution with the ArduPilot solution)
The core C library only needs a C11 compiler and make (see Quickstart
above). The Python bindings, plotting and reference-board tools additionally
need a virtual environment:
sh python/setup_venv.sh # one-time (Windows: python\setup_venv.bat)
. env.sh # activate the venv (POSIX/git-bash, any OS)
📂 inslib/
├── Makefile # Build: make test, make insrcv, ...
├── src/ # Core library (.c/.h), no heap, no OS dependencies
│ └── nav_suite.h # Main header: INS + AHRS + baro_alt wrapper
├── KFCore/ # Submodule: linear algebra, UDU/Bierman-Thornton filter
├── tests/ # Unit/integration tests
├── datasets/ # Real-world + simulated replay datasets
├── tools/ # C/Python reference board tools: calibration, GUI
├── python/ # Python bindings, plotting, replay harness
├── magneticmodel/ # WMM lookup table
├── doc/ # Documentation, Doxygen, images
└── tutorial/ # Minimal C + Python usage examples
All tools (tools/) speak an open (UBX-based) protocol,
documented in tools/inslib_protocol.md.
The reference board is a low-cost and ready-to-use development module (IMU, u-blox GNSS receiver, magnetometer, barometer) for running INSLIB on real hardware with pre-calibrated sensors. It implements the protocol above and is ready to use out of the box. Its firmware itself is not public, get in touch if you're interested in a collaboration with my university institute or in getting a unit.

Building your own sensor suite is also possible, an example conf (mid 2026 sensor landscape):
| Sensor | Example part | Notes |
|---|---|---|
| IMU | TDK InvenSense ICM-45686, Bosch BMI563/BMI570, Analog Devices ADIS16505 or Murata SCH16T-K10 | |
| Magnetometer | MEMSIC MMC5603NJ or ST LIS3MDL | |
| Barometer | Bosch BMP581 or TE MS5611 | |
| GNSS receiver | u-blox F9P or X20 | X20-series has L1/L2/L5 support and Galileo HAS decoding |

IMU/Magnetometer-Calibration + Housing-Alignment, user-friendly GUI for the reference board. The GUI allows an easy calibration of the sensor hardware for bias, scale and misalignment without the need for an expensive calibration environment like robotic arms, except for a controlled temperature environment. The sensor must be placed still for a few seconds in a variety of different orientations on a stable surface:

Live-Control center for reference INS board


inslib_hub.py Stream, forward and log input data from reference boardinslib_convert_ubx_to_csv.py Convert reference board to .csv filesinslib_ubx_imu_calib.py Command line IMU-calibration toolinslib_cfg.py Reference board config read/writeinslib_clock_error.py Estimate MCU-clock error from reference board .csv loginslib_obd_speed.py Stream car velocity from OBD-II dongleIMU sensor processing is unforgiving: it is not enough to get one thing right, the whole chain (timestamps, axis conventions, calibration, filtering, etc.) has to line up properly. A list of common mistakes:
t_us). Clock issues break the
library.gnss: leverarm_frd) has a significant impact on position and attitude,
especially during dynamic turns.gnss: delay_ms biases position
during dynamic motion, see GNSS Latency
Estimation.baro_height_disable: 1 in
config.yaml to force GNSS/local-position height instead.src/) and the KFCore library is designed and written by a human with 20 years of experience in this fieldREADME.md is written by a humaninsrcv is largely written by Claude