wls: add RAIM fault detection & exclusion to reject outlier SVs#1
Closed
mx4 wants to merge 1 commit into
Closed
Conversation
The WLS solver had no per-SV outlier rejection, so a single bad pseudorange was least-squares-smeared across the whole fix. On the ION HackRF set a cross-correlation false lock on G05 (~220 km / 0.73 ms too long) pushed the published fix 63 km horizontally and 37.5 km up (altitude 37,530 m), while HDOP/VDOP stayed 1.0/1.7 — geometry factors are blind to a measurement blunder. The only guard, the |pos| in [6.25e6, 6.5e6] terrestrial gate, tolerates ~±125 km of altitude and let it through. Add a RAIM detect-identify-exclude loop around the core solve: while the pool still has redundancy, drop the SV whose residual is the largest multiple of a fixed a-priori sigma (10 m) when it exceeds a 6-sigma gate, then re-solve. The test deliberately normalizes against a nominal sigma, not the self-calibrated weighting sigma — a gross outlier inflates the latter (G05 drove sigma_GPS to ~68 km), which would mask the fault. Excluded SVs are reported in WlsSolution::excluded, logged as `raim-excl=...`, and dropped from the published SV count. On ION HackRF the final fix is now 52.1773,4.4900 h=84.8 m with raim-excl=G05, sigma_GPS 3.9 m, ISB +2.3 ns (was -102 us). Co-Authored-By: Claude Opus 4.8 <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.
Problem
The ION HackRF recording was producing a fix with an improbable 37,530 m altitude (52.734, 4.543), while HDOP/VDOP read a healthy 1.0/1.7 and 11 SV.
Root cause, traced via the built-in
GNSS_TRUTH_ECEFresidual probe: at the true receiver location (52.1773°N, 4.4900°E, ~85 m), 10 of 11 satellites' residuals collapse to a common 168.0 ± 0.3 km (the receiver-clock term). One satellite, G05, sat at 388 km — its pseudorange ~220 km (≈0.73 ms) too long, a classic cross-correlation / wrong-code-phase false lock.The WLS solver (
wls.rs) self-calibrates a per-constellation σ but had no per-SV outlier rejection (RAIM). So G05's gross error was least-squares-smeared across the solution: position slid ~63 km horizontally and ~37.5 km up, and the nuisance states blew up (σ_GPS→68 km, ISB→−102 µs, clock jumped +3.7 ms). HDOP/VDOP are pure geometry and never reflected the blunder. The only guard — the|pos| ∈ [6.25e6, 6.5e6]terrestrial gate — tolerates ~±125 km of altitude, so it passed.Fix
Add a RAIM detect–identify–exclude loop around the core solve:
The integrity test deliberately normalizes against a nominal σ (10 m), not the self-calibrated weighting σ — a gross outlier inflates the latter (G05 drove σ_GPS to ~68 km), which would mask the very fault we're testing for. A 6σ gate gives a per-SV false-alarm rate ~2e-9, so healthy SVs are essentially never dropped, while a km-scale blunder trips it by orders of magnitude.
Excluded SVs are reported in
WlsSolution::excluded, logged asraim-excl=…, and removed from the published SV count.Result
On the ION HackRF set, the final fix is now:
raim-excl=G05Tests
cargo test --release— 74 pass, 0 fail (incl. thewls_solvecross-check)cargo fmt --checkandcargo clippy --releasecleanNotes / out of scope
+2048GPS week reconstruction atgps_lnav.rs:600is only valid for 2019-04…2038-11, and this NL recording predates that window (off by one 1024-week rollover). Independent of the altitude; not touched here.|pos|terrestrial gate is left in place as a backstop.🤖 Generated with Claude Code