Transitioned the autodev state to phase 21, reflecting the completion of Step 5 and the drafting of Step 6 epics. Revised the architecture documentation to clarify the roles of the Tile Manager and its components, ensuring accurate representation of the system's operational flow. Updated glossary entries for Flight State and Operator to incorporate recent changes and enhance clarity on component interactions and responsibilities.
5.9 KiB
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).
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.12.0 | RANSAC + reprojection residual computation |
| TensorRT | matches C7 | Backbone engine compilation/runtime |
Error Handling Strategy:
MatcherBackboneError: backbone forward pass failed on a candidate. Candidate dropped fromper_candidate; if all N=3 candidates fail, emitInsufficientInliersError.InsufficientInliersError: RANSAC inlier count below configurable threshold on every candidate. C5 falls back to VIO-only with provenance labelvisual_propagated. F6 satellite re-localization may trigger if the condition persists.- Catastrophic backbone failure (engine unloadable): treated as
MatcherBackboneErrorfor 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.
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).