Skip to content

feat(gsdc): third pass on sjc-r A505U with its course seeds; pin the recipe to 57678818 - #665

Merged
rsasaki0109 merged 17 commits into
developfrom
claude/confident-clarke-k37g2b
Oct 27, 2026
Merged

rsasaki0109 merged 17 commits into
developfrom
claude/confident-clarke-k37g2b

Conversation

@rsasaki0109

Copy link
Copy Markdown
Owner

Summary

  • What changed?
    • gnss_fgo_imu_no_base now accepts --native-course-attitude-seeds-mount-deg together with --native-source-imu-initialization.
      • The initial IMU pass takes the course seeds instead of the source heading seeds.
      • The refinement pass turns course seeds off and takes the initial pass's optimized attitude, which it hands over as heading seeds.
      • Every other flag combination builds the same configuration as before.
    • The GSDC official recipe now rebuilds Kaggle submission 57678818 (Private 0.806 m / Public 0.816 m). The previous one was 57664241 (0.811 / 0.817 m). The third pass is now on 32 drives; these two are new:
      • sjc-r A505U, which keeps its course seeds;
      • lax-hh A325G.
    • The recipe's binary moves to the new build. The whole lane was rerun on it from scratch, byte-identical (see Validation).
  • Why?
    • sjc-r A505U, a Private drive, is mounted backwards and needs its course seeds (178.9 deg). The third pass needs source IMU initialization, and the solver rejected that combination.

Scope

  • Single feature / single operational improvement / single user-visible value
  • Adds or tightens one regression, sign-off, dogfood, or artifact-schema check
  • No unrelated refactor mixed in
  • No docs-only noise mixed into solver/protocol work. The docs record the score change.
  • Protocol ingest, parser work, runtime knobs, solver behavior, and docs are split unless this PR explicitly needs the boundary crossing. The solver change is one admission plus its config split, in its own commit.

External Reference

  • Source repo used for comparison: taroz/gsdc2023 (fgo_gnss_imu.m). Its final pass starts from the previous pass's attitude unless RPYReset is set.
  • What was adopted here: the same handoff for the course-seeded drive.
  • What was intentionally not adopted:
    • mtv-pe1 A325G: Kaggle Public was worse with the pass, 0.821 m vs 0.817 m.
    • mtv-e Pixel4 XL: no difference.
    • Mi8: still worse on train.

Behavior Boundary

  • Runtime default changed? No. The change only affects runs that pass both flags, which was a CLI rejection before.
  • Env-gated or config-gated? Yes, by CLI flags.
  • Artifact/schema changed? No schema change. The recipe's binary pin and two drive entries change.
  • Dataset or credentials required? The lane needs the taroz dataset_2023. The CLI test is admission-only and uses no data.

Validation

  • python3 tests/test_cli_tools.py
  • python3 tests/test_benchmark_scripts.py
  • python3 tests/test_packaging.py
  • python3 tests/test_python_bindings.py -v
  • python3 tests/test_ros2_node.py
  • ctest --test-dir build --output-on-failure

Focused checks run:

pytest tests/test_smartphone_course_attitude_seeds_cli.py   # 7 passed on the new build; the admission test fails on the old one
python3 tests/test_gnss_reproduce.py                          # OK
# A505U recipe argv without the pass on the new build: byte-identical to its pinned output (d68137e1)
# full lane from scratch on the new build (cccb04cc), four at a time on 4 cores, 2 h 21 min:
#   25/25 stage-0 identical, height-maps 25/25 match, 40/40 final identical (lax-p single_cpu),
#   assemble -> 2e0deb2c... MATCH

Sign-off / Benchmark Impact

  • Added or updated regression/sign-off:

    • The CLI test now admits course seeds with source IMU initialization and still rejects them with epoch heading seeds.
    • The tracked-recipe test pins 57678818 / 2e0deb2c and checks that 32 drives carry the refinement pass.
  • Affected dataset(s): GSDC 2023-2024 test (official).

  • Expected metric impact (Kaggle readback):

    Ref Change Public Private
    57664241 before 0.817 0.811
    57677499 plus sjc-r A505U 0.817 0.806
    57677502 probe: plus mtv-e Pixel4 XL 0.817 0.806
    57677505 probe: plus mtv-pe1 A325G 0.821 0.806
    57678818 plus lax-hh A325G (recipe) 0.816 0.806
  • Artifact(s) produced: none tracked.

Notes

  • Risk: low. The new code path is reachable only with a flag pair that used to be rejected.
  • Follow-up PRs: the Mi8 drives.
  • Explicit non-goals: changing heading-seed behavior on any other drive.

Generated by Claude Code

claude added 17 commits October 25, 2026 06:26
…9467

Submission 57600830 still had 31 drives at the MSVC research outputs of
56625084, so no single build reproduced it. The recipe lane reran those
drives, their 17 stage-0 runs and height maps with the same argv on the
Linux GCC 15 build of develop ed5f8d0 (86d1e81 links the same binary). The
9 GCC final drives and 8 GCC stage-0 runs came out byte-identical. The 31
rerun drives moved by median 0.001 m / P95 0.008 m / max 0.079 m.

Kaggle scores the rebuild (57619467, c46ca65f...) Private 0.844 m /
Public 0.885 m (57600830: 0.845 / 0.884). Every drive, stage-0 run and
height map is now pinned to one build. The MSVC provenance moves under
research_source.msvc_research.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
… to 57626255

In 57619467 the first 11 static minutes of 2022-04-25 ebf-x Mi8 (38% of
its scored rows) sat about 2 m from the taroz test output. Raw-ADR
epoch-to-epoch carrier displacements disagree with the native GNSS-first
and final trajectories by 1.2 m over the 40 s parking-lot exit, while taroz
agrees within 0.2 m; it is the only test drive with that symptom.

The recipe gains a per-drive input_window: the lane writes the drive's
Android GNSS rows from epoch 599 (taroz settings_test.csv IdxStart=600)
and its IMU rows from 2 s earlier (raw lines, SHA-256 pinned), and
assemble fills the leading keys with the first solved row, as taroz
submission.m does. The drive also takes source TDCP metre sigma and
Phase184 Huber (Highway, L5=1); the same flags regress on train, so
they stay on this drive.

Kaggle 57626255 (6c0eca7d...): Private 0.844 m / Public 0.850 m
(57619467: 0.844 / 0.885). The solver binary is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
…larke-k37g2b

# Conflicts:
#	README.md
#	configs/reproduce/gsdc-official.toml
#	configs/reproduce/gsdc_official_recipe.json
#	docs/gsdc2023_native_taroz_goal.md
#	docs/reproduce.md
#	docs/use_cases/records/gsdc2023_official_readback_20261024.json
#	scripts/experiments/gsdc/gsdc_official_reproduce.py
#	tests/test_gnss_reproduce.py
The lane copies native text verbatim, while the research fill step that
produced 57626255 dropped trailing zeros in 284 ebf-x rows. The two files
have the same coordinates. The lane-built file (f19acb58...) was submitted
as 57629197 and scores the same (Private 0.844 m / Public 0.850 m), so
the gate now pins it; 57626255 stays in the chain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
On train, with the per-phone test recipes, native and taroz are level
(0.718 vs 0.712 m), so the 0.062 m Private gap should sit in a few test
drives. Recorded checks that did not find them: the taroz result files
already carry the phone offset; the along-track excess is drive-specific
and a per-family shift makes train worse; raw-ADR TDCP arbitrates only at
low speed; height maps are not a common cause, and removing them on the
three Samsung drives that disagree most with taroz gives mixed results.
The readback record gains these notes and the open issues.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
The 0.2% highway-speed drift recorded in #654 was not in the raw-ADR
TDCP displacement check but in the comparison, which turned lat/lon into
metres on a 6,371 km sphere (0.19-0.24% scale error at 37 deg N). With
exact ECEF/ENU conversion the check matches ground-truth steps to about
10 ppm at 29 m/s on train. Rerun on all 40 test drives at all speeds, it
finds no second ebf-x-type failure; ADR is unusable on A325F, A32 and
S908B. The goal log and readback record now say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
…recipe

The Pixel5 heading recipe already carries source TDCP metre sigma and
Phase184 Huber (Highway), so adding them to ebf-xx leaves its solution
byte-identical; its exit still disagrees with TDCP by 2.6 / 1.7 m. The
goal log and the readback record's open issue say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
…on 30 drives)

Taroz solves each drive with fgo_gnss and then fgo_gnss_imu twice; the
last pass re-screens P/D around the first GNSS/IMU trajectory with the
final thresholds and solves again. The test recipes stopped after one
IMU solve. Thirty drives now add --native-imu-refinement-pass and the
flags it requires where missing (stage exports, source IMU
initialization, main-graph Doppler).

On 35 train drives with taroz output the mean moves 0.7358 -> 0.7187 m
(taroz 0.7123 m). Mi8 (worse on train), Pixel4 XL (prerequisites
+1.0 m), A325G (neutral), sjc-r A505U (course seeds exclude source
initialization) and ebf-z (Kaggle Public worse) keep their recipes.
Kaggle: 57663786 Private 0.811 / Public 0.836 m, 57663818 (ebf-z
reverted) 0.811 / 0.821 m, 57664241 (plus lax-p) 0.811 / 0.817 m,
from 0.844 / 0.850 m.

lax-p overflows the default 8 MB stack in its refinement solve. The
recipe marks it stack_limit "unlimited", and the lane lifts the child's
soft RLIMIT_STACK for it (refusing to run when the hard limit is finite).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
…imit

The lax-p refinement solve crashes in two of three runs with an 8 MB or
an unlimited stack: each SIGSEGV is a GTSAM TBB worker thread running
past its own stack, which RLIMIT_STACK does not size. Pinned to one CPU,
TBB starts no workers and the drive finishes in 1670 s with the pinned
solution (2d54abf7) under either stack limit. Replace the recipe's
stack_limit with single_cpu, which the lane applies with
sched_setaffinity in the child.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
--native-course-attitude-seeds-mount-deg rejected
--native-source-imu-initialization because source initialization turns
on the epoch heading seeds, which course seeds replace. The refinement
pass needs source initialization, so sjc-r A505U (mounted backwards,
course seeds at 178.9 deg) could not take it.

With both flags, the initial IMU pass now uses the course seeds instead
of the source heading seeds; the refinement pass, which hands over the
initial pass's optimized attitude as heading seeds, turns course seeds
off. Every other flag combination builds the same config as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
…and lax-hh)

sjc-r A505U now takes the third pass with its course seeds kept, on the
build that admits course attitude seeds with source IMU initialization,
and lax-hh A325G takes it too. Kaggle: 57677499 (A505U) Private 0.806 /
Public 0.817 m, 57678818 (plus lax-hh) 0.806 / 0.816 m, from 0.811 /
0.817 m. Probes on that file: mtv-e Pixel4 XL unchanged, mtv-pe1 A325G
Public 0.821 m (kept on its recipe although it moved 0.16 m toward
taroz).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
The full lane (25 stage-0 runs, 25 height maps, 40 final drives) reran
from scratch on gnss_fgo_imu_no_base cccb04cc, four at a time on 4
cores in 2 h 21 min; every pinned output and map is byte-identical and
assemble writes 2e0deb2c (Kaggle 57678818).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NWJ6qRF465rAzkFgQJvz7P
@rsasaki0109
rsasaki0109 merged commit 5418fce into develop Oct 27, 2026
11 checks passed
@rsasaki0109
rsasaki0109 deleted the claude/confident-clarke-k37g2b branch October 27, 2026 00:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants