Files
NODEDC_MISSION_CORE/docs/audits/2026-09-20-route-wide-relocalization.md
T
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

207 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.