Files
NODEDC_MISSION_CORE/docs/audits/2026-09-20-route-wide-relocalization.md
DCCONSTRUCTIONS e515ab1b8c feat(planning): consolidate recorded-route localization and spatial scene
Preserve the completed teach-and-repeat laboratory stage: reference preparation, cascaded acquisition, local tracking and recovery, recording lifecycle, replay qualification, and persistent Rerun scene controls. Document the open grid-picking regression and Rerun upgrade contract. No autonomous driving or loop-closure optimization is claimed.
2026-09-21 08:47:19 +03:00

12 KiB
Raw Permalink Blame History

Route-wide stationary relocalisation — implementation boundary

Intent

Replace the laboratory assumption that an independent scanner session starts at the first pose of the selected route. A stationary prefix now retrieves candidate places from the full selected route before local GICP refinement. This supports recovery after an interrupted run at a known part of a route; it does not grant any rover, scanner, or navigation authority.

Implemented protocol

  1. The existing ten-second stationary prefix and its identity, monotonic-clock, gap and motion fences are unchanged.
  2. route_relocalization.py indexes the full reference map in a 10-m spatial grid and resamples the entire selected path at five-metre atlas anchors. Each anchor receives a compact rotation-invariant radial/height descriptor of its local reference submap. The full map is not subject to the 100,000 point cap for one GICP target; only each local target is. The query descriptor is ranked against every usable anchor, not against reference_path[0].
  3. The six best descriptor candidates receive a local target and three yaw hypotheses chosen from a polar descriptor. Every generated hypothesis is qualified by the existing small-gicp implementation, with a separately recorded relocalisation policy. The broader initial correction envelope is only for this isolated initial search; routine tracking retains its local policy.
  4. Candidate transforms are clustered by their transformed stationary query position. Similar-quality clusters at distinct route progress are rejected as ambiguous-route-location; no candidate yields no-route-location; a worker or search deadline yields incomplete-route-search.
  5. Only a complete, singular candidate becomes a provisional prior. The pre-existing three disjoint fresh registration windows still decide whether tracking is established. Candidate output retains localization_confirmed=false and vehicle_control=false.

All route-search policy values, descriptor coverage, generated-attempt count, clusters and chosen route progress are stored in the initialization artifact. The 30-s computational deadline deliberately remains below the bootstrap's 40-s source-age fence; a timeout is an observable incomplete calculation, not a geometric rejection or a stale provisional position.

Operator-visible states

  • During retrieval: «Поиск положения на маршруте».
  • No stable place: «Синхронизация маршрута не выполнена» with a request to remain near an explored area and repeat stationary calibration.
  • Repeated/similar geometry: an explicit multiple-similar-segments status; the system does not select one arbitrarily.
  • Incomplete computation: «Синхронизация маршрута не завершилась», distinct from a geometric no-match.

Validation completed in code

  • 90-m synthetic route with the query constructed at the middle: descriptor retrieval chose 4045 m and real GICP accepted the fit at 100% overlap and 0.0165 m RMSE.
  • Separate synthetic duplicated-place case rejects as ambiguous and clears correspondence colouring.
  • The bootstrap rejects a route result whose declared generated-attempt count does not match its recorded attempts.
  • Existing causal stationary bootstrap, route-length and live ownership tests remain green.

Not yet demonstrated

This is an implementation and synthetic qualification, not proof on the K1 field data. It does not establish capture radius, recovery at 10 m offset, recovery in the middle of the present 100-m route, kilometre-scale memory/time, mount transferability, absolute localisation accuracy, obstacle handling or autonomous vehicle motion. The next physical acceptance should start a fresh stationary run away from the route start, first around the current known route and then at a deliberately chosen mid-route point. Preserve each result, including explicit no-match, ambiguity or incomplete-search outcomes.

2026-09-20 field finding and corrective decision

The latest independent field attempt, ja-sun-010-100m-10left, started about 10 m opposite the normal route entry and reported no-route-location. This was not a route-entry-radius rejection: all 18 generated route hypotheses ran. The descriptor ranked the known entry region first (then the 5 m and 10 m anchors). Its best GICP result converged with 61.25% overlap, 0.811 m correction and 5.605° rotation, but was rejected solely because its 0.27594 m inlier RMSE exceeded the common 0.25 m tracking threshold.

The diagnosis also found a conflicting implementation detail: the stationary query accumulator silently retained only a 20 m radius even though the route search is intended to use the useful K1 scene around the operator. Therefore the correct first change is not a global threshold reduction.

  • route-relocalization/v2 explicitly records a 40 m stationary query radius for whole-route initialisation and its three fresh local confirmations. It is a numerical input footprint only: it is not a cap on route length, recording duration, scanner range, or the normal live presentation budget.
  • LiveCloudBuffer, StationaryPrefix and the fresh-confirmation buffer now receive that radius explicitly and persist it into each staged calculation. Ordinary short-range tracking retains its 20 m default profile.
  • The rejected-run screen now provides «Переинициализировать». It is admitted only for a running, unconfirmed lost state. The action clears the old derived preview, prior and result; it does not send a K1 command, stop recording, reuse an old cloud, or start a vehicle. The next pose/cloud pair starts a new ten-second stationary prefix and is stamped as the next attempt in the run evidence.

The 0.25 m tracking policy remains unchanged. Lowering it everywhere would weaken routine motion tracking and incorrectly treat a one-shot recovery near-miss as ongoing confirmation. If the repeat with the 40 m initial scene again selects the correct local anchor but stays in the 0.270.30 m band, the next bounded change is a separate provisional-initialisation policy, locked to that selected local target and still requiring all three disjoint fresh windows to agree before any tracking presentation. It must not alter vehicle authority, which remains false in this laboratory profile.

Code validation covers the 40 m accumulator request, lost → operator retry → new prefix → second route search without closing the source lease, the typed HTTP endpoint, existing stationary/route cases and the Control Station build. The required physical acceptance is a repeat of the same 10 m opposite-entry placement: keep the scanner still for the full prefix, save the resulting run, and compare candidate progress, overlap, RMSE, convergence and all three fresh windows before considering a separate provisional band.

2026-09-20 ja-sun-011 retry correction and 80-m footprint

ja-sun-011-100m-10left recorded the intended failure separately from K1 capture. Its first initialization generated all 18 route hypotheses in 2.94 s and ended at no-route-location; the nearest entry hypothesis reached 57.82% overlap but 0.2783 m RMSE, so it correctly did not bypass the 0.25 m gate.

The following retry began 0.16 s after the operator click, reached a new collecting prefix, and then surfaced the generic Stationary prefix/geometry failure as a terminal «Совмещение остановлено». The raw recording was still active, but the presentation made an operator repositioning mistake look like a K1 or route-search stop. The old worker also continued to ingest numerical receipts after an unconfirmed route loss, so carrying the scanner could contaminate the next prefix.

route-relocalization/v3 changes the boundary as follows:

  • The stationary query, presentation head and candidate GICP target now use K1's declared 80-m sensing footprint. This is not a maximum walk distance, capture duration or route length. A dense target is deterministically voxelised to the explicit per-GICP computational budget without reducing its radial footprint.
  • The 28-m radial/height descriptor remains only the compact retrieval key for selecting places across the route. Expanding it to 80 m made neighbouring anchors on the short synthetic route less distinctive. After retrieval, the actual GICP comparison receives the complete 80-m query and local target.
  • In unconfirmed lost, the raw K1 source continues but numerical receipts are deliberately ignored. The operator may carry the scanner to another observable point, stop there, then press «Переинициализировать».
  • If the button is pressed before the scanner has stopped, movement or a receipt gap during the new prefix returns to actionable lost with a reinitialization diagnostic; it does not terminate the research run or issue any K1 stop command. The following retry starts a clean buffer and prefix.
  • The vertical «Срез» control remains a Z-height visualization filter. Its 7.5 m label is measured height in the currently rendered cloud, not an 80-m sensor or relocalization range. The Planning "Движок" panel now shows the independent working radius explicitly.

Python validation covers 80-m capture, an 80-m dense target under the GICP budget, full-route retrieval, and lost → carry/retry interruption → retry → second route search while the exclusive source lease stays active. Control Station typecheck, 872 unit tests and production build also passed. This remains laboratory-only; the next field acceptance must preserve the retry result and its artifacts before any threshold adjustment is considered.

2026-09-20 v4 hybrid restoration after ja-sun-012 / ja-sun-013

The subsequent physical runs exposed that v3 had made normal startup depend on the global target representation. It did not exhaust the route-search budget: on ja-sun-013, it ranked the entry anchor first but the broad, voxel-reduced target stopped at 70.69% overlap and 0.2577 m RMSE. That is not a valid reason to relax the common 0.25 m acceptance limit.

route-relocalization/v4 therefore uses a staged strategy, dense-start-first-then-route-recovery/v1:

  1. A normal start first runs the established 108-seed stationary acquisition against a precise local reference window at the selected route start. Its query footprint remains 80 m. A successful local result has to satisfy all existing support, convergence and geometry checks; it remains provisional until the three disjoint fresh windows confirm it.
  2. Only a complete, honest local rejection enters full-route descriptor retrieval. That fallback receives only the remaining search time under the same 35-s / 40-s freshness fences. It cannot replace a valid dense start, become vehicle authority, or silently reuse an old sample.
  3. A retry whose prefix proves incomplete at start_search() now returns to actionable lost with the reinitialisation diagnostic. It no longer converts an operator repositioning attempt into terminal «Совмещение остановлено»; raw recording remains under its existing owner.

Offline replay through the actual isolated worker, using unchanged saved inputs, accepts both known-good runs in the dense-start stage:

  • ja-sun-013-100m: 94.11% overlap, 0.1504 m RMSE, 108 attempts, 21.54 s accumulated registration time.
  • ja-sun-012-100m-10left, step 3: 90.09% overlap, 0.1808 m RMSE, 108 attempts, 17.13 s accumulated registration time.

The global recovery path is deliberately retained but not claimed as field qualified yet. Its next bounded improvement is a coarse full-route retrieval followed by a high-resolution local refinement around the retrieved anchor, with separate field evidence at a deliberately chosen mid-route point. A blind threshold reduction or an unbounded scan of the whole map remains out of scope.