Repository navigation
feat(urbannav): Deep-Urban-1, the aided run on real urban GNSS (#131) - #180
Merged
Merged
Conversation
…e sizes (#131) The aided run (a sequence without an outage) now also reports the gate's alpha and the rejections expected at it, the Wilson 95% interval of the rejection rate on the raw count and on the effective count (ADR-0029), and the effective sample size of the horizontal and attitude NEES series with the upper-bound flag. A constant over-the-level series has no estimate and counts every fix, which the new fix_rejection_ess_defined flag says. Aided rows only: the Tunnel-1 quantities and rows are untouched. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Adds the Deep-Urban-1 rows (aided run, declared and per-fix variants, five seeds) to the run and data CSVs through the merge writer, and the Tunnel-1 lines of both files are byte-identical to before. The aided run now also reports counts of far fixes, the mean NIS and the gate level, the claimed sigma against the receiver's, and the NEES by third of the run. New: `navkit urbannav fixerrors` and docs/data/urbannav_fix_errors.csv, the time correlation of the receiver's own fix errors against the reference for both sequences. The page gets the Deep-Urban-1 findings, each tied to the CSVs by a test, an INTERPRETATION that says what it does not prove, and no typed number. ADR-0026 gets a dated context section (no Decision text). Data-gated tests for the real files skip without the data. The byte-prefix tests now use a new sequence name, so they still prove that the committed rows are untouched. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This was referenced Oct 24, 2026
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
CI measured 93.76% against the 94.31% recorded, a gap above the 0.5 points allowed. Regenerated with scripts/metrics.py --write --coverage after merging origin/main. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01L6ro5x4WRA4P7sQHLyPPGa
…etic sequence CI has no real dataset, so urbannav_check and urbannav_fix_errors were at 73% and 58% line coverage, and total coverage fell 0.55 points below metrics.json. These tests run measure(), the CSV and page-block paths and main() on the generated fixture. Both modules are now above 99%. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QnVDRzD2rMdsXzjGpA5up9
Generated by scripts/metrics.py --write --coverage after the new study tests. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QnVDRzD2rMdsXzjGpA5up9
Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QnVDRzD2rMdsXzjGpA5up9
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.
Closes #131
Step 2b of the Deep-Urban-1 package. The data stayed read-only in the maintainer's checkout (through a symlink and
--root). Nothing was written into it (0 files modified, checked by modification time after the full run), and no data is committed (S2). The INSPVAX choice (option A, text reference only) is recorded as context in ADR-0026, and this PR adds a dated context section there. No Decision text, no outage rule change, no Tunnel-1 number change.What changes
Rows.
docs/data/urbannav_run.csv(aided run, declared and per_fix, seeds 0 to 4) anddocs/data/urbannav_data.csvget Deep-Urban-1 rows through the merge writer. Both files are pure additions. The Tunnel-1 lines are byte-identical:de65bb1c4a9cee30aaaafc02f8046ab23b339d0bf7379d3a279433ec815783c3b9d3fc433e183e15c30c6a44a5c9a4c28b86cdc973fc0da8b439486a480a0b68The committed bytes of both files are an exact prefix of the new ones. A page test pins both hashes.
New aggregates (aided run only). Gate alpha and level, mean NIS, expected rejections, Wilson 95% intervals of the rejection rate on the raw and the effective count (ADR-0029), effective sample sizes of the horizontal and attitude NEES, NEES by thirds, fixes over 3 receiver sigmas, the receiver's median sigma against the filter's claimed one. The effective count of the rejection rate has one convention: a constant over-the-level series (no rejection) has no autocorrelation to estimate and counts every fix, which
fix_rejection_ess_definedflags. The page states it.New CSV and command.
navkit urbannav fixerrorswritesdocs/data/urbannav_fix_errors.csvfor both sequences: mean offset, RMS about it, the correlation of the fix error at lags 1, 10, 30 and 60 s (pairs within 0.5 s of the lag, per axis and pooled), and the effective sample size per axis (navkit.eval.statistics, mean removed). A separate file, so no existing row moves.Page.
docs/urbannav.md: the Deep-Urban-1 section is final. ATE stays in the CSV and is not in the page tables (the unused height dominates it). Every statement has a test against the CSVs, and the prose has no typed number. One statement is labelled INTERPRETATION (the filter treats fixes as independent; the fix errors are correlated over tens of seconds; the filter was not run with a correlated-error model, so this proves nothing about the cause; the reference's own error is unknown). The stale wording from the step 2a PR is updated (status, the "has not been fetched or run" bullet, "What follows", ADR-0026 "What this does not settle", WB-7, theurbannavhelp text).Tests. The four tests that assumed no Deep-Urban-1 rows are strengthened: the prefix tests now add a new sequence name, and a second test rewrites Deep-Urban-1 and checks the Tunnel-1 lines are identical. Data-gated tests for the real Deep-Urban-1 files skip without the data.
Sanity checks (scratch runs, not committed; seed 0 unless noted)
The maintainer's facts held: 1539 fixes, all GGA quality 2, 12 satellites, zero outages, 614782 IMU samples, reference codes 1 to 5, 10.8% of fixes (166) more than 3 sigma off. The filter sees 1537 fixes, because two lie outside the IMU span.
Rows (ranges over the five seeds)
Fix statistics (same in both): median 2.36 m, p95 7.50 m, p99 12.97 m; mean of (difference / receiver sigma) squared 3.285; 166 fixes over 3 sigma, 48 over 10 m, the gate rejects none.
Fix-error time behaviour (new CSV). Deep-Urban-1: pooled correlation 0.948 at 10 s, 0.760 at 30 s, 0.472 at 60 s; effective sample size 16.5 (east) and 17.9 (north) for 1539 fixes. These match the maintainer's hand measurements (0.95, 0.47, about 17). Tunnel-1: 0.233 at 10 s pooled (per axis 0.077 and 0.356), about zero at 30 and 60 s; effective sample size 66.8 and 18.3. The ESS and the long lags agree with the hand values. The 10 s value for Tunnel-1 depends on the estimator and axis (0.04 to 0.36 over the variants tried; the hand value 0.15 is inside that range), because there are only 250 fixes and a few tens-of-metres ones at the tunnel edges. The page claims only that Tunnel-1 is less correlated than Deep-Urban-1 at 10 s, which a test checks.
Runtime
One run: 38.6 s of filter time (62.8 us per IMU step), about 72 s wall with scoring (two at once). The ten-run command: 13 min 38 s. PR #169 had extrapolated 350 to 440 us per step.
Checks
ruff, ruff format, mypy: clean.
check_doc_tables.pyagainst a freshly generated benchmark in a scratch path,metrics.py --checkafter--write(only the test count moved),check_links.py(0 broken),mkdocs build --strict: pass.tests/test_framing.py,tests/test_quoted_numbers.py,test_quoted_metrics.py,test_ci_docs_tests.pyaftergit add: pass. Full suite WITH the data: 2352 passed, 1 skipped (results/benchmark.jsonnot generated), 2 xfailed, 0 failed. Full suite with the data hidden: 2319 passed, 34 skipped (every skip is a data test, the new Deep-Urban-1 ones included), 2 xfailed, 0 failed. Mutation checks, each reverted: a rejected fix in one seed's CSV row fails 3 page tests; a lowered Deep-Urban-1 lag-10 correlation fails the interpretation test and the block test.Risks and what this does not show
coverage_report.py) was not run locally.🤖 Generated with Claude Code