# INSLIB: A Portable C Library for 3D Navigation with Kalman Filtering

> A pure C11 navigation library that fuses IMU, GNSS, barometer, magnetometer, and wheel-speed inputs through UDU Kalman filters to produce 3D position, velocity, and attitude estimates. It has no external dependencies, runs on bare-metal microcontrollers, and reaches 92.2% MC/DC test coverage with a statically analysed worst-case stack budget for every public API function.

**jnz/INSLIB** — Open Source Inertial Navigation Library

- Repository: https://github.com/jnz/INSLIB
- Stars: 584 · Forks: 93
- Language: C
- License: AGPL-3.0
- Published: 2026-09-17 · Updated: 2026-09-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/jnz-inslib

## What INSLIB Solves: Navigation State When GNSS Fails or Is Absent

GPS and GNSS receivers provide accurate global position when they have satellite visibility, but they fail inside tunnels, under dense canopy, during jamming, or when the vehicle moves faster than the receiver's update rate can track. Inertial measurement units provide continuous high-rate acceleration and angular rate data but accumulate drift over time without an external reference to correct them.

INSLIB fuses both sources through a Kalman filter that weights each measurement by its noise model. During a GNSS outage the filter continues integrating IMU data and switches to the barometric altitude channel for vertical velocity, so altitude and attitude remain available even with no satellite fix. The library supports zero-velocity updates for stationary phases, zero-rotation updates for periods of no angular movement, scalar ground-speed inputs from wheel odometry, and absolute yaw references from an external compass. Each additional sensor reduces the accumulated drift during GNSS-denied intervals.

The README lists the supported use cases as drones and UAVs, autonomous vehicles, robotics, aerospace, automotive, and embedded systems requiring precise tracking. A post-processing mode for replaying recorded sensor data is also included.

## The Kalman Filter Architecture and Its Numerics

The filter uses the UDU factorisation (Bierman-Thornton algorithm) rather than the standard covariance matrix form. The UDU form maintains the covariance as a product of upper triangular and diagonal factors, which keeps the covariance matrix positive semi-definite under floating-point arithmetic. The README describes this as increasing effective precision for the covariance.

All computations use 32-bit IEEE 754 float except GNSS coordinate processing, which uses double precision to avoid losing significant digits at global-scale coordinates. This means no 64-bit FPU hardware is required, which matters for microcontrollers that have single-precision float units but not double.

The library provides three top-level navigation modes. nav_suite combines INS, AHRS, and barometric altitude into the full navigation stack. ins_update handles the full inertial-aided navigation with GNSS. ahrs_update provides attitude estimation alone (roll, pitch, yaw) when position is not needed. A stripped-down mode, AHRS_MODE_ARS, runs a five-state filter on IMU data alone with no magnetometer, for platforms where a heading reference is unavailable or unreliable.

Measurement latency compensation handles the 100 to 200 millisecond delays typical of GNSS receivers: the filter corrects for the lag by cross-correlating the GNSS vertical velocity against the barometric vertical channel to estimate the actual delay.

## Post-Processing Quickstart with inspostgui.py

The library ships Python GUI and command-line tools for replaying recorded datasets. The one-time setup creates a virtual environment and compiles the Python bindings:

```sh
sh python/setup_venv.sh
```

Activate the environment, then open the GUI with a dataset directory:

```sh
. env.sh
python3 python/inspostgui.py datasets/fog
```

The GUI opens a dataset's config.yaml, lets you tweak parameters, and replays the sensors. For batch use, replay.py runs the same processing from the command line:

```sh
. env.sh
python3 python/replay.py datasets/fog --plot --plot-out /tmp/plots.pdf
```

Inputs are plain CSV files, one per sensor type. The IMU file uses a microsecond timestamp in the first column followed by gyroscope and accelerometer readings in the FRD (forward-right-down) frame:

```text
# 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
```

GNSS, magnetometer, barometer, and wheel-speed CSV files follow the same timestamp convention. The config.yaml in each dataset directory configures the filter parameters and which sensor channels are enabled.

## Worst-Case Stack Analysis and Real-Time Suitability

Every public API function in INSLIB has a worst-case stack budget, verified by static analysis at build time through make stack. The analysis uses GCC's -fcallgraph-info output and fails the build if any function exceeds its budget, uses recursion, uses variable-length arrays, or has unresolved function pointer calls.

The README publishes the stack numbers for x86_64-linux-gnu with GCC 14.2.0: nav_suite_update() uses 13,504 bytes, ins_update() uses 12,128 bytes, ahrs_update() uses 8,240 bytes, baro_alt_update() uses 7,904 bytes. For an embedded target with a smaller or different architecture the numbers will differ, but the same analysis command (make stack) runs on the target toolchain.

The Makefile also provides make test-asan for AddressSanitizer and UndefinedBehaviorSanitizer testing, make cppcheck for static analysis, and make clang-tidy for code style checking. These are not run as part of make test by default; the README notes they are available on demand or in CI. The CI badge in the README links to GitHub Actions.

## Test Coverage, Requirements Traceability, and AGPL-3.0

The core library in src/ achieves 99.7% C0 (line) coverage, 92.3% C1 (branch) coverage, and 92.2% MC/DC coverage. MC/DC (Modified Condition and Decision Coverage) is the structural coverage metric required for avionics software at DO-178 DAL-A and for automotive software at ISO 26262 ASIL-D. The README explicitly cites both standards as use cases.

Requirements traceability links the source code to a machine-checked requirements database in the requirements/ directory. The make reqs command validates the links. This is aerospace-style documentation practice and makes the library accessible to teams who need an evidence trail from requirements to implementation.

The library is licensed under AGPL-3.0. This means using it in a product that is distributed externally requires either releasing the corresponding source code under AGPL-3.0 or obtaining a separate commercial license from the author (contact: jan.zwiener@h-da.de). The built-in World Magnetic Model tables for magnetometer declination compensation are derived from NOAA data and are included in the src/ directory as generated header files.

The latest release is v1.1.0, labelled The Automotive Update, tagged on 2026-09-20, followed by v1.1.1 for smaller fixes on 2026-09-28. The v1.1.0 release name suggests the automotive use case received specific additions; the full changelog is in CHANGELOG.md. The repository also ships a Software Bill of Materials at sbom.cdx.json and a CITATION.cff file for academic attribution.

## How INSLIB Compares to ROS nav2

ROS nav2 is a navigation stack for ROS 2 that provides path planning, obstacle avoidance, and sensor fusion through a plugin architecture. It uses the robot_localization package for EKF-based state estimation and runs on Linux with the full ROS 2 middleware. Nav2 is designed for mobile robots operating in mapped environments and assumes a running OS, a message-passing layer, and substantial CPU and memory resources.

INSLIB targets the opposite end of the spectrum: bare-metal microcontrollers, no OS, no dynamic allocation, and a focus on IMU-GNSS fusion for vehicles and aircraft rather than indoor robot navigation. The two are not interchangeable. A drone firmware project that needs to run on an STM32 cannot use nav2. A service robot running on a Jetson or Raspberry Pi has no use for INSLIB's no-heap constraints.

The practical decision point is whether the navigation target runs an OS. If it does, nav2 or similar higher-level stacks offer a richer plugin ecosystem. If it runs bare-metal or RTOS, INSLIB's lack of dependencies and known stack budgets are the determining advantage.

## Conclusion

INSLIB is the right choice for embedded navigation projects that cannot tolerate heap allocation, OS dependencies, or unbounded loop latency and that need a documented, gated worst-case stack budget per function. The MC/DC coverage and requirements traceability make it applicable to safety-critical developments targeting DO-178 DAL-A or ISO 26262 ASIL-D, where those levels of structural coverage are required. Teams building desktop or server-side navigation software that run a full OS will find the no-heap, no-OS constraints unnecessary overhead; a higher-level library is more appropriate in those environments. The most recent release is v1.1.1, tagged on 2026-09-28.

## FAQ

### What is the difference between GNSS and INS?

GNSS (Global Navigation Satellite System) provides absolute position from satellite signals but fails inside buildings, tunnels, or under jamming. INS (Inertial Navigation System) uses an IMU to integrate acceleration and rotation, providing continuous estimates but accumulating drift over time. INSLIB fuses both: GNSS corrects the INS drift, and the INS provides estimates when GNSS is unavailable.

### Is INS more accurate than GPS?

In the short term, INS (inertial navigation) provides higher update rates and is not disrupted by interference, but it accumulates drift over time. GPS provides globally referenced absolute accuracy over long periods but degrades in signal-denied environments. The README describes INSLIB's filter as designed to combine both, using GPS corrections to bound inertial drift.

### What is INS used for?

The README lists typical use cases as drones and UAVs, autonomous vehicles, robotics, aerospace, automotive, and embedded systems requiring precise position and attitude tracking. INSLIB supports post-processing of recorded sensor data as well as real-time operation in control loops.

### What is INS vs IMU?

An IMU (Inertial Measurement Unit) is the sensor hardware that measures acceleration and angular rate. INS (Inertial Navigation System) is the algorithm that integrates those measurements, optionally fused with GNSS and other sensors, to produce position, velocity, and attitude. INSLIB implements the INS algorithm layer that sits above raw IMU data.

## Sources

- [Issues](https://github.com/jnz/INSLIB/issues)
- [jnz/INSLIB on GitHub](https://github.com/jnz/INSLIB)
- [License: AGPL-3.0](https://github.com/jnz/INSLIB/blob/main/LICENSE)
- [README](https://github.com/jnz/INSLIB/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jnz-inslib
