Skip to content

feat(sdk): R-IEKF system-level NEES verdict via the VioEstimator front-end (#347) #365

Description

@Ravenwater

Why

The R-IEKF observability fix (epic #347) is unit-proven and mergedSE2(3) state (#353), invariant propagation (#354), invariant camera update (#356), and MsckfInvariantBackend (#357). Each piece annihilates / preserves the 4-DoF unobservable gauge (global translation + gravity-yaw) by construction, at any state, with no FEJ.

What's missing is a trustworthy system-level verdict: does that unit-level fix actually yield a consistent filter end to end?

The current attempt — the hand-rolled Monte-Carlo loop in tools/src/invariant_nees_verdict.cpp (#360) — is broadly over-confident, but the attitude split shows why: yaw ≈ 7× vs roll/pitch ≈ 3400×. Roll/pitch is gravity-observable and cannot leak yaw, so the over-confidence is driver over-fusion / marginal stability in the hand-rolled loop (clone correlation, relinearization, triangulation at drifted poses), not a failure of the observability fix. The loop is the confounder.

Goal

Drive MsckfInvariantBackend through the validated VioEstimator front-end / track manager (the same path the body-frame filter and tests/sdk/vio_euroc.cpp use) instead of the hand-rolled loop, and produce a gauge-anchored attitude-NEES verdict that is trustworthy.

Scope

  • Adapter: implement a VioBackend-conforming wrapper around MsckfInvariantBackend so VioEstimator can drive it — initialize (seed nav + prior), process_imu (propagate), process_camera (augment clone, run the existing track lifecycle, triangulate, invariant_update on tracks leaving the window), and expose NavState + covariance for the consistency harness.
  • Reuse the track manager: the over-fusion in the hand-rolled loop must be avoided by reusing the validated feature-track lifecycle / triangulation / clone-window management (either a thin adapter over the front-end, or factor the body-frame backend's track lifecycle into a shared component both backends use — author's choice).
  • Measure: run the gauge-anchored NEES machinery (eval/nav_consistency.hpp, consistency.hpp) on the assembled invariant filter over the synthetic Monte-Carlo (CI-runnable; real EuRoC is env-gated), reporting full-nav NEES, per-block NEES, and the yaw vs roll/pitch attitude split (the discriminator).

Acceptance criteria

  • The invariant backend is driven by the real front-end / track manager — no hand-rolled update loop.
  • Gauge-anchored attitude-NEES is reported, alongside the body-frame baseline on the same data, with the yaw-vs-roll/pitch split.
  • Verdict, one of:
    • attitude-NEES lands near consistent (≈ dof) → the R-IEKF fix is confirmed end-to-end ⇒ flip the default backend and close out the NEES over-confidence; or
    • the residual over-confidence is localized to a specific, named cause (with a follow-up issue), and the result is documented.

Out of scope

  • The observability math itself (proven; do not re-derive).
  • A real-EuRoC-only verdict (env-gated, not CI-runnable) — the synthetic Monte-Carlo with the EuRoC camera model is the proxy.

References

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestphase-3-vioVisual-Inertial Odometry

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions