contested-nav¶
Is the filter right about how wrong it is?
A captioned explainer built from one benchmark run: the same GNSS outage with the camera off and on, the measured accuracy and calibration, and the decision that follows.

contested-nav is a 21-state error-state Kalman filter and an evaluation harness for GNSS-denied
navigation. It measures not only how accurate the trajectory is, but whether the uncertainty the
filter reports is honest.
| Configuration | ATE RMSE | Claimed 1σ | Mean NEES (expected 3) | 2σ-per-axis coverage (expected 99.3%) |
|---|---|---|---|---|
| GNSS denied, vision off | 3.760 m | 0.567 m | 4.1 | 100.0% |
| GNSS denied, vision on | 2.322 m | 0.162 m | 286.2 | 20.5% |
Accuracy improved. Calibration failed. The filter converges and is confidently wrong, so visual fusion ships off by default. The overconfidence held in every run of every sweep; the accuracy gain did not (see Results).
Mostly synthetic evidence
The table above comes from a deterministic known-answer fixture. The recorded-data pages use a real IMU with GNSS simulated from the ground truth. No number here is a field measurement.
How it works¶
flowchart TB
IMU["IMU, always on"] --> F
GNSS["GNSS, can be denied"] --> FDIR["Fault detection: screens each measurement"]
CAM["Camera motion, opt-in"] -.-> FDIR
FDIR --> F["Navigation filter: position, and how sure it is"]
F --> ACC["Accuracy: error against the truth"]
F --> HON["Honesty: is the truth inside the claimed area?"]
TRUTH["Known truth: synthetic runs, recorded datasets"] --> ACC
TRUTH --> HON
ACC --> GATE{"Gate B1"}
HON --> GATE
GATE -- "met" --> ON["Camera fusion on"]
GATE -- "not met" --> OFF["Camera fusion off by default (ADR-0003)"]
Every run is scored twice: how far the estimate is from the truth, and whether the truth falls inside the area the filter claims. A feature that improves the first and breaks the second stays off. A short captioned explainer is on the project page; the module-level design is in docs/architecture.md.
Where to start¶
- Getting started: install, run the headline case in 19 seconds, reproduce every number.
- Concepts: why this is not a tuning problem, what is in the filter, how calibration is measured.
- Results: the benchmark scenarios, the sweeps and what they do and do not show.
- On recorded data: EuRoC, TUM VI, where the outage error comes from and a real front end.
- On spoofing and fault classes: honest returns, slow ramps, classification and multipath.
- Model and interface contract: units, frames, every configuration key, the result format and a fault-mode table.
- Scope and responsible use and Status and limits.