Odometry confidence tiers: capture-time signal + BA weighting - #71
Merged
Conversation
Record the worst ARKit/ARCore tracking state observed over each between-snap interval as Frame::odom_state (see the new OdometryConfidence enum), serialized into frames.json. Offline bundle adjustment / loop closure will map these tiers to odometry-edge weights; this commit only carries the signal, it does not consume it. Uses NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT so older frames.json without the field parse as 0 (Normal), preserving prior uniform-trust behavior. Verified via JSON round-trip (4 -> 4) and legacy-default (0). Spec: docs/ODOMETRY_CONFIDENCE.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scale each odometry edge's information matrix in addOdometry by odomConfidenceWeight(frame.odom_state): HIGH (Normal) = 1.0, MEDIUM (Limited*) = 0.25, LOW (Relocalizing/Unavailable) = 0.02. A shaky or relocalizing between-snap interval is now down-weighted rather than trusted like a clean one, so bundle adjustment (and future loop closure) lets drift correction land on the low-confidence edges. These three constants are the only tunable knobs; the capture side emits the categorical tier untouched (see docs/ODOMETRY_CONFIDENCE.md). Unknown odom_state values fall back to full trust, so pre-signal captures behave as before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
ARKit gives excellent relative pose but drifts globally, and its tracking quality varies across a capture (excessive motion, low texture, relocalization). Until now every ARKit-derived odometry constraint in bundle adjustment was trusted equally. This adds a coarse, capture-time confidence signal per between-snap odometry edge and uses it to weight those edges in BA — and it's the input the upcoming vision loop-closure work needs to decide where drift correction should land.
Design contract: the capture side makes no numeric decisions (it records only the platform's own categorical tracking label), and all tuning lives offline in the refiner. See
docs/ODOMETRY_CONFIDENCE.md.Changes
Frame::odom_state+OdometryConfidenceenum (frame.h): a platform-neutral int = the worst tracking state observed over the interval into that frame (severity-ordered, somax()is the reduction). Serialized intoframes.jsonviaNLOHMANN_..._WITH_DEFAULTso older captures without the field parse as0(Normal) — no migration, no regression.bundle_adjustment.cpp):addOdometryscales the odometry information matrix byodomConfidenceWeight(odom_state)— HIGH (Normal)=1.0, MEDIUM (Limited*)=0.25, LOW (Relocalizing/Unavailable)=0.02. These three constants are the only tunable knobs; unknown values fall back to full trust.Platform-neutral (iOS today, Android-ready)
The on-disk enum is not ARKit-specific: iOS maps
ARCamera.trackingState→ the int; a future ARCore app mapsTrackingState + TrackingFailureReason→ the same values. Everything downstream is identical regardless of capture platform. (The capture-side accumulator + bridge lands in a companion lar-swift PR.)Verification
odom_state:4→ 4; erasing the key → default0.make fastbuildslar_refine_colmap+lar_create_mapclean.Not in this PR (by design)
🤖 Generated with Claude Code