Files
Oleksandr Bezdieniezhnykh c1f27e4681 [autodev] Step 13 partial: c1/c2/c2_5/c3 cycle-1 doc sync
Item 2 (C1) + item 3 batch 1 of ~5 (C2 VPR, C2.5 Rerank, C3 Matcher)
of the cycle-1 component-description reconciliation called out in
ripple_log_cycle1.md.

For each touched description.md:
- Add a "Cycle-1 operational reality" paragraph in section 1 that
  names the _STRATEGY_REGISTRY + register_airborne_strategies()
  runtime gate (AZ-591), the pre_constructed dict path through
  compose_root (AZ-618 umbrella), the per-component
  AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS row, and any cycle-1
  strategy-default vs documented-primary disambiguation
  (net_vlad as the C2 default; xfeat parked from the C3 airborne
  registry).
- Relax the OpenCV row in section 5 Key Dependencies to the
  D-CROSS-CVE-1 cycle-1 pin (>=4.11.0.86,<4.12) wherever the
  component imports cv2 (C2 preprocessors, C2.5 ORB placeholder,
  C3 RANSAC + reprojection).
- Add a "Cycle-1 Tier-2 follow-up dependencies" subsection in
  section 7 only for components with a strategy module that is
  built but parked from the airborne registry (C3 xfeat).

Refresh ripple_log_cycle1.md follow-up ordering with per-batch
progress + extracted batch pattern so the next batch session has
a self-contained recipe. Bump _autodev_state.md sub_step.detail
to reflect batch 1 completion (10 components + 8 helpers + tests/
remain).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 16:49:41 +03:00

7.7 KiB
Raw Permalink Blame History

C3 — Cross-domain Matcher

1. High-Level Overview

Purpose: produce 2D-3D correspondences between the current NavCameraFrame and the top-N=3 satellite tiles from C2.5, with RANSAC-filtered inliers and reprojection residual statistics. C3 is the cross-domain step (nav-camera ↔ satellite-imagery domain gap) and is the dominant compute cost in F3.

Architectural Pattern: Strategy — CrossDomainMatcher interface, with concrete implementations DISK+LightGlue (D-C3-1 = (a) primary), ALIKED+LightGlue (secondary), XFeat (alternate). Selection at startup by config (ADR-001); build-time gating by BUILD_* flags (ADR-002); composition-root wired (ADR-009).

Cycle-1 operational reality: the airborne binary wires C3 through _STRATEGY_REGISTRY + register_airborne_strategies() (AZ-591) on top of the BUILD_MATCHER_* build-flag matrix (disk_lightglue / aliked_lightglue / xfeat — see runtime_root/airborne_bootstrap.py::C3_MATCHER_BUILD_FLAGS). The c3_matcher airborne slot registers only disk_lightglue + aliked_lightgluexfeat has its build-flag wired but is parked as a Tier-2 follow-up (no airborne registry slot, no airborne _C3_MATCHER_STRATEGIES entry). Constructor injection flows through the pre_constructed dict passed to compose_root(config, pre_constructed=...) (AZ-618 umbrella → AZ-621 c3 helpers phase + AZ-622 LightGlue runtime builder + AZ-623 c7 inference phase). The c3_matcher slot lists ("c3_lightglue_runtime", "c282_ransac_filter", "c7_inference") in AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS; clock and c13_fdr are optional. Missing required keys raise AirborneBootstrapError at composition time, naming the consumer and missing key.

Upstream dependencies:

  • C2.5 → RerankResult (top-N=3 candidates).
  • C7 InferenceRuntime → backbone forward pass.
  • Camera calibration artifact — for nav-frame preprocessing.
  • C6 TileStore — for tile pixels (handle carried in RerankCandidate).

Downstream consumers:

  • C3.5 ConditionalRefiner (consumes MatchResult; passthrough or AdHoP refinement).

2. Internal Interfaces

Interface: CrossDomainMatcher

Method Input Output Async Error Types
match NavCameraFrame, RerankResult, CameraCalibration MatchResult No MatcherBackboneError, InsufficientInliersError
health_snapshot () MatcherHealth No

Input DTOs:

NavCameraFrame:                see C1
RerankResult:                  see C2.5
CameraCalibration:             see C5

Output DTOs:

MatchResult:
  frame_id:                    uuid
  per_candidate:               list[CandidateMatchSet] (length up to N=3, drop on failure)
  best_candidate_idx:          int — argmax(inlier_count) among per_candidate
  reprojection_residual_px:    float — best candidate's median residual
  matched_at:                  monotonic_ns
  matcher_label:               string — for FDR provenance

CandidateMatchSet:
  tile_id:                     composite (zoomLevel, lat, lon)
  inlier_count:                int
  inlier_correspondences:      ndarray[I, 4, dtype=float32] — (px_query, py_query, px_tile, py_tile)
  ransac_outlier_count:        int
  per_candidate_residual_px:   float

MatcherHealth:
  consecutive_low_inlier:      int
  mean_inliers_60s:            float

3. External API Specification

Not applicable.

4. Data Access Patterns

Query Frequency Hot Path Index Needed
Tile pixel access (3 tiles per frame) 3 Hz × 3 = 9 Hz Yes C6 mmap

No additional caching beyond C6.

5. Implementation Details

Algorithmic Complexity: O(N · F · F) for the matching pass per backbone (N=3 candidates, F features per image), plus RANSAC O(I · trials) on inliers. Dominant cost is the backbone forward pass.

State Management: stateless per-frame. Holds the shared LightGlue / DISK runtime handle.

Key Dependencies:

Library Version Purpose
DISK (Python) upstream HEAD pinned per Plan-phase Primary feature extractor (D-C3-1 = (a))
LightGlue (Python) upstream HEAD pinned per Plan-phase Primary matcher; replaces SuperPoint+SuperGlue (Magic Leap noncommercial)
ALIKED (Python) upstream HEAD pinned per Plan-phase Secondary feature extractor
XFeat (Python) upstream HEAD pinned per Plan-phase Alternate (lightweight) feature+matcher
OpenCV >=4.11.0.86,<4.12 (cycle-1 relaxed pin; D-CROSS-CVE-1 deferred — see _docs/_process_leftovers/2026-05-11_d_cross_cve_1_opencv_pin_deferred.md) RANSAC + reprojection residual computation (consumed via the shared RansacFilter helper)
TensorRT matches C7 Backbone engine compilation/runtime

Error Handling Strategy:

  • MatcherBackboneError: backbone forward pass failed on a candidate. Candidate dropped from per_candidate; if all N=3 candidates fail, emit InsufficientInliersError.
  • InsufficientInliersError: RANSAC inlier count below configurable threshold on every candidate. C5 falls back to VIO-only with provenance label visual_propagated. F6 satellite re-localization may trigger if the condition persists.
  • Catastrophic backbone failure (engine unloadable): treated as MatcherBackboneError for every frame until F8 reboot recovery.

6. Extensions and Helpers

Helper Purpose Used By
LightGlueRuntime shared LightGlue inference handle C2.5, C3
RansacFilter RANSAC + reprojection residual computation thin wrapper C3, C3.5, C4

7. Caveats & Edge Cases

Known limitations:

  • The cross-domain gap (nav-camera vs satellite tile) is the hardest step in the pipeline. Backbone choice depends on the deployment camera's spectral and resolution characteristics; the current default (DISK+LightGlue) is locked per Mode B Fact #110 / D-C3-1 = (a) pending IT-12 verdict.
  • D-C2-12 (DINOv2-feature-based matcher) is a carryforward research item that may displace DISK in a future cycle.

Cycle-1 Tier-2 follow-up dependencies:

  • XFeat — build-flag (BUILD_MATCHER_XFEAT) + matcher_factory._STRATEGY_TO_BUILD_FLAG + concrete c3_matcher/xfeat.py module are all in place, but c3_matcher's _C3_MATCHER_STRATEGIES tuple in runtime_root/airborne_bootstrap.py registers only disk_lightglue + aliked_lightglue. Selecting xfeat via airborne config currently raises StrategyNotLinkedError from the _STRATEGY_REGISTRY lookup. Tier-2 follow-up: extend the airborne registration tuple + airborne Jetson validation against Derkachi-class fixtures.

Potential race conditions:

  • Shared LightGlue runtime with C2.5; serial access from one ingest thread.

Performance bottlenecks:

  • C3 dominates the F3 latency budget. The D-CROSS-LATENCY-1 hybrid does NOT change C3 (K=N=3 stays); it changes C4 covariance recovery.

8. Dependency Graph

Must be implemented after: C2.5 (input), C7 (inference runtime).

Can be implemented in parallel with: C1, C6 — independent paths.

Blocks: C3.5 / C4 / C5, F3 / F6.

9. Logging Strategy

Log Level When Example
ERROR InsufficientInliersError; all N=3 candidates failed C3 zero-inlier on all candidates; frame=12345; backbone=disk_lightglue
WARN reprojection residual above threshold (will trigger AdHoP at C3.5) C3 residual=4.2px > threshold=2.5px; frame=12345; will refine
INFO Strategy ready C3 ready: matcher=disk_lightglue
DEBUG per-candidate inlier + residual C3 frame=12345 candidates=[(412,1.1px),(287,1.4px),(198,2.0px)]

Log format: structured JSON. Log storage: stdout / journald / FDR via C13 (ERROR + WARN only).