# Component Fit Matrix — Index & Summary

> Mode A Phase 2 — engine Step 7.5 (Component Applicability Gate, structured per-component candidate-selection table). One row per component area (C1–C10 from `../00_question_decomposition.md`); each row enumerates candidates with status, license, key fit dimensions, and a cite of the per-numbered-Restriction × per-numbered-AC sub-matrix in [`../02_fact_cards/`](../02_fact_cards/) that supports the status. Rows are filled progressively as SQ3+SQ4 closes per component.

This folder replaces the previous monolithic `06_component_fit_matrix.md` (284 lines, dominated by very wide tables that no longer fit in a single editor view). Each component lives in its own file. Open the file matching the component you need — every status verdict and Plan-phase decision is preserved verbatim.

---

## Status vocabulary (per engine rule)

| Status | Meaning |
|---|---|
| **Selected** | Documentary verification ✅ + Jetson Orin Nano Super hardware MVE ✅; promoted as the implementation choice for the project |
| **Documentary lead** | Documentary verification ✅ (mode pinned, MVE block, sub-matrix); Jetson MVE pending; eligible for Selected promotion in the dedicated bring-up phase |
| **Experimental only** | Documentary verification surfaced a partial mismatch or contradiction; cannot be Selected without the deferred Jetson MVE explicitly resolving the contradiction (per Per-Mode API Capability Verification rule) |
| **Conditional** | Candidate fits only as a sub-component of a hybrid design; cannot be a drop-in lead (e.g., VO-only candidate that requires an external IMU wrapper) |
| **Mandatory simple-baseline** | Candidate is required by the engine's Component Option Breadth rule as a runnable fallback / regression baseline; not a lead |
| **Rejected — disqualified** | Documentary evidence explicitly contradicts a hard project disqualifier (e.g., AC-4.2 memory budget, license blocks dual-use); excluded from further consideration |
| **N/A** | Candidate is not applicable to this component area (cataloged for completeness only) |

---

## Component index

| File | Component | Closure status | Top documentary leads | Hard disqualifiers |
| --- | --- | --- | --- | --- |
| [`C1_vio.md`](C1_vio.md) | **C1** — Visual / Visual-Inertial Odometry | Closed at documentary level (2026-05-08) | OKVIS2/OKVIS2-X (BSD/permissive track lead), OpenVINS (GPL-3.0 track lead), VINS-Mono (GPL-3.0 alternate, sub-20-Hz caveat), Pure VO + ESKF (mandatory simple-baseline) | DROID-SLAM (>11 GB VRAM exceeds AC-4.2), RTAB-Map + ORB-SLAM3 (rejected by SPRIN-D evidence at >1 km / >2 m/s) |
| [`C2_vpr.md`](C2_vpr.md) | **C2** — Visual Place Recognition | Mandatory pre-screen CLOSED at 5/5 (2026-05-08); conditional AnyLoc/BoQ/DINOv2-VLAD GATED on INT8 survey | EigenPlaces (MIT, viewpoint-robust, simplest CNN), MixVPR (MIT, ResNet50 + MLP-Mixer), SelaVPR (MIT, DINOv2-L two-stage, best cross-season Tokyo24/7), SALAD (GPL-3.0, DINOv2-B + optimal-transport), NetVLAD (mandatory simple-baseline) | SuperGlue-as-reranker (matcher-class, not VPR-class) |
| [`C3_matchers.md`](C3_matchers.md) | **C3** — Cross-domain registration (Matchers) | Closed at 5/N (2026-05-08); mandatory simple-baseline COMPLETE; modern-competitive-lead axis MATERIALLY EXPANDED | DISK+LightGlue (D-C3-1 RECOMMENDED-PRIMARY: clean Apache-2.0 throughout, +7.99 AUC@5° over SP), XFeat (D-C3-1 ALTERNATE: clean Apache-2.0, strongest embedded signal, cheapest retrain), ALIKED+LightGlue (D-C3-1 SECONDARY), SP+LightGlue (documentary baseline), SuperGlue+SuperPoint (mandatory simple-baseline) | SuperPoint Magic Leap noncommercial-research SLA blocks dual-use deployment (canonical SP+LightGlue + SuperGlue+SuperPoint); SuperGlue training code never released; MASt3R/RoMa/DKM/LoFTR dense matchers fail AC-4.1 latency |
| [`C4_pose_estimation.md`](C4_pose_estimation.md) | **C4** — Pose estimation (PnP + RANSAC + LM) | IN PROGRESS at 3/N (mandatory simple-baseline + 2 modern-competitive-leads COMPLETE 2026-05-08); D-C4-1 (3-DoF vs 4-DoF vs 6-DoF lift) carried forward from Fact #20 + REINFORCED by Fact #52; D-C4-2 (covariance-recovery-strategy) NEW from Fact #52 + UPDATED by Fact #54 (GTSAM Marginals NATIVE); D-C4-3 (license-clearance verification) + D-C4-4 (maintenance-staleness mitigation) NEW from Fact #53 (OpenGV-only) | OpenCV `cv::solvePnPRansac` (mandatory simple-baseline, clean Apache-2.0 throughout, JetPack 6 canonical distribution = zero-effort Jetson deployment); **GTSAM `Marginals.marginalCovariance`** (modern-competitive-lead-covariance-honest, clean BSD-3-Clause throughout, **NATIVE 6×6 pose covariance — only C4 candidate to satisfy AC-NEW-4 NATIVELY**, daily-active maintenance, 1121 context7 code snippets); OpenGV `absolute_pose::AbsolutePoseSacProblem(KNEIP)` (modern-competitive-lead-richer-minimal-solver, BSD-3-Clause-equivalent CONTINGENT on D-C4-3, ~3-year stale CONTINGENT on D-C4-4, NO planar-scene solver) | (none yet) |
| [`C5_state_estimator.md`](C5_state_estimator.md) | **C5** — State estimator / sensor fusion | **CLOSED at 2/N (batch 1 closed 2026-05-08)** — mandatory simple-baseline + 1 modern-competitive-lead-factor-graph COMPLETE | Manual ESKF (Solà 2017 canonical aerial/quaternion reference, public-domain academic preprint + project's Apache-2.0 implementation, mandatory simple-baseline, native 6×6 covariance via analytic Jacobian propagation); **GTSAM iSAM2 + CombinedImuFactor (Forster et al. RSS 2015) + smart factors + Marginals.marginalCovariance + IncrementalFixedLagSmoother** (modern-competitive-lead-factor-graph, clean BSD-3-Clause throughout, **architecturally couples with C4 Fact #54 GTSAM Marginals via shared substrate**, **NATIVE AC-4.5 look-back refinement**, daily-active maintenance) | (none yet) |
| [`C6_tile_cache_spatial_index.md`](C6_tile_cache_spatial_index.md) | **C6** — Tile cache + spatial index | **CLOSED at 2/N (batch 1 closed 2026-05-08)** — mandatory simple-baseline + 1 modern-competitive-lead-spatial-extension COMPLETE; **Cand 1 RECOMMENDED PRIMARY** | **Cand 1 (RECOMMENDED PRIMARY)**: Manual mirror of existing parent-suite `satellite-provider` pattern — PostgreSQL btree composite on slippy-map `(tile_zoom, tile_x, tile_y, version)` + bytea descriptor blobs + app-side FAISS HNSW loaded at takeoff + filesystem tile storage at `./tiles/{zoom}/{x}/{y}.{image_type}` (clean PostgreSQL License + MIT + LGPL/MIT-Apache; trivial dependency footprint; project-pattern alignment; empirically-confirmed Postgres-on-Jetson viability per Source #97 March 2026); **Cand 2 (DEFERRED secondary)**: PostgreSQL + PostGIS GiST on geography(POINT,4326) + pgvector HNSW for descriptor ANN + filesystem tile storage (modern-competitive-lead-spatial-extension; native KNN + radius + combined-SQL capabilities BUT 5-10× slower geographic lookup vs Cand 1 + heavier dependency + GPL-2.0-or-later license complexity + DIVERGENT from suite pattern + improvements marginal-to-negative in project's specific 3 Hz spatial-grid query operating context) | PostGIS GPL-2.0-or-later may CONTINGENT REJECT Cand 2 under D-C1-1 = (b) BSD/permissive-only-track |
| [`C7_inference_runtime.md`](C7_inference_runtime.md) | **C7** — On-Jetson inference runtime | **CLOSED at 3/N (batch 1 closed 2026-05-08)** — top-2 documentary leads + mandatory simple-baseline COMPLETE; **Cand 1 RECOMMENDED PRIMARY** | **Cand 1 (RECOMMENDED PRIMARY)**: TensorRT native — JetPack 6.2 bundled TensorRT 10.3 + `IInt8EntropyCalibrator2` + `BuilderFlag.FP16+INT8` mixed-precision + engines built directly on Jetson Orin Nano Super SM 87 (clean Apache-2.0 in TensorRT 10.x; ships with JetPack so zero-effort install; lowest-latency primary path; 2-3× speedup at INT8 vs FP16 per Source #102 YOLO26 evidence); **Cand 2 (interop alternate)**: ONNX Runtime + TensorRT EP — `onnxruntime-gpu` via Jetson AI Lab JP6/CU126 wheel index + `TensorrtExecutionProvider` config + automatic CUDA EP / CPU EP subgraph fallback (clean MIT throughout; cross-architecture portability for replay/SITL on x86 dev hosts; modern-competitive-lead-cross-architecture-portability); **Cand 3 (mandatory simple-baseline)**: pure PyTorch FP16 — `torch.amp.autocast` + `model.half()` + Jetson AI Lab PyTorch 2.5 ARM64 wheel (clean BSD-3-Clause throughout; zero-conversion regression baseline; reference-correctness oracle for accuracy validation of TRT-built engines) | INT8-only candidates marked Experimental until D-C7-1 calibration dataset materializes; matchers (LightGlue, XFeat, XFeat+LighterGlue) are FP16-only — NO INT8 — per D-C7-6 cross-component model-family precision policy due to Source #103 quantization-sensitivity finding |
| [`C8_fc_adapter.md`](C8_fc_adapter.md) | **C8** — MAVLink / MSP2 FC adapter | **CLOSED at 3/N (batch 1 closed 2026-05-08)** — top-1 per FC for ArduPilot + parallel-evaluation per FC for iNav after mid-batch contradiction recovery COMPLETE; **Cand 1 RECOMMENDED PRIMARY for AP, Cand 2 RECOMMENDED PRIMARY for iNav** | **Cand 1 (RECOMMENDED PRIMARY for ArduPilot)**: pymavlink → MAVLink `GPS_INPUT` (msg 232) cooperative-path; `master.mav.gps_input_send(...)` periodic injection at 5 Hz over MAVLink (UART/USB/UDP); FC-side `GPS1_TYPE=14` MAVLink + `EK3_SRC1_POSXY=3` GPS source-set drives EKF3 ingestion via `AP_GPS_MAV` (LGPL-3.0 pymavlink linkable from Apache-2.0 app per LGPL §6; canonical ArduPilot stack); **Cand 2 (RECOMMENDED PRIMARY for iNav)**: `MSP2_SENSOR_GPS` (id 7939 / 0x1F03) via Python MSP V2 implementation YAMSPy or INAV-Toolkit `msp_v2_encode`; `mspGPSReceiveNewData()` direct passthrough; covariance fields `hPosAccuracy/vPosAccuracy/hVelAccuracy` align directly with AP `GPS_INPUT.horiz_accuracy/vert_accuracy/speed_accuracy` (MIT throughout; clean dual-use compatible; locked SQ6 + AC-4.3 transport); **Cand 3 (DEFERRED secondary for iNav)**: UBX impersonation via pyubx2 NAV-PVT — forging u-blox NAV-PVT frames through standard GPS pipeline; iNav-side `gpsMapFixType()` validation gate requires `flags & 0x01 = 1` (gnssFixOK) AND `fixType ∈ {2,3}`; pyubx2 BSD-3-Clause; **does NOT clear user's "significant-improvement-only" bar over Cand 2** (richer protocol surface + AC-NEW-7 forgery posture + stricter validation gate + AP-path field-name divergence outweigh pyubx2 library-maturity advantage). **Mid-batch correction**: I caught a contradiction between my own initial AskQuestion phrasing ("UBX impersonation as ONLY iNav path") and locked SQ6 + AC-4.3 + restrictions.md verdicts (MSP2_SENSOR_GPS as iNav primary); user re-locked scope via `c8_inav_recovery=B` to evaluate both as parallel candidates | (none yet — pymavlink LGPL-3.0 license posture handled via D-C8-3 = (a) bundle-unmodified-with-version-pin per LGPL §6 standard compliance) |
| [`C10_preflight_provisioning.md`](C10_preflight_provisioning.md) | **C10** — Pre-flight cache provisioning (CROSS-COUPLING MINIMAL scope per 2026-05-08 user choice C; operator CLI/desktop tooling, sector classification, freshness schema deferred to Plan-phase) | **CLOSED at 2/N (batch 1 closed 2026-05-08)** — D-C6-3 + D-C7-7 cross-component gates closed; no further C10 batches required at research layer | **D-C6-3 confirmation**: direct `faiss.write_index` / `faiss.read_index` Python API + `python-atomicwrites` + content-hash verification gate at takeoff + manifest-hash-driven rebuild trigger + `IO_FLAG_MMAP_IFC` mmap load (FAISS MIT, atomicwrites MIT throughout); **D-C7-7 confirmation**: hybrid Polygraphy CLI primary for INT8-calibrating builds + `trtexec` for cache-reuse fast rebuilds + direct `IBuilderConfig` Python API for unusual models (LightGlue dynamic shapes) — Polygraphy + TensorRT 10.x Apache-2.0 throughout, calibration corpus per D-C7-1 closure | (none — both candidates Apache-2.0/MIT clean; FAISS "no internal integrity check" warning mitigated by content-hash gate; `trtexec --int8` random-data caveat mitigated by project-side wrapper enforcing `--calib=<existing_cache>` non-empty precondition) |
| [`99_cross_component_gates.md`](99_cross_component_gates.md) | **Cross-component process gates** | Open — Plan-phase Choose blocks raised by C1+C2+C3+C4+C5+C6+C7+C8+C10 closures | D-C1-1 license posture, D-C1-2 Jetson MVE, D-C2-1..11 (VPR retrain/cache/dim), D-C3-1..6 (matcher mitigation/runtime/K-pairs/ALIKED-mode/DISK-weights/XFeat-mode), D-C4-1..4, **D-C5-1..5 (Manual ESKF + GTSAM iSAM2)**, **D-C6-1..7**, **D-C7-1..9**, **D-C8-1..8**, **D-C10-1 (descriptor-cache rebuild trigger — manifest-hash-driven recommended, NEW from Fact #100)**, **D-C10-2 (descriptor-cache atomic-write strategy — `python-atomicwrites` recommended, NEW from Fact #100)**, **D-C10-3 (content-hash verification gate at takeoff load — reject + STATUSTEXT + refuse takeoff recommended, NEW from Fact #100, CROSS-COMPONENT with AC-NEW-7)**, **D-C10-4 (descriptor-cache load path — mmap with `madvise(MADV_WILLNEED)` pre-fault recommended, NEW from Fact #100)**, **D-C10-5 (TensorRT engine-build orchestration tool — hybrid Polygraphy + trtexec + direct API recommended, NEW from Fact #101, CROSS-COMPONENT with C7)**, **D-C10-6 (TensorRT calibration-cache reuse strategy — rebuild-on-calib-corpus-SHA-256-change recommended, NEW from Fact #101, CROSS-COMPONENT with D-C7-1)**, **D-C10-7 (TensorRT engine on-disk filename schema — self-describing `<model>_sm<SM>_jp<JP>_trt<TRT>_<precision>.engine` recommended, NEW from Fact #101)**, **D-C10-8 (TensorRT prebuilt-fallback engine generation venue — reference Jetson at HQ + deployed-Jetson-copy-to-archive recommended, NEW from Fact #101)**, Fact #40 dual-rate camera pipeline | n/a |

---

## Reading order

For first-time readers:

1. **Start here** — read this index plus the status vocabulary above.
2. Read the closed component rows in order: [`C1_vio.md`](C1_vio.md) → [`C2_vpr.md`](C2_vpr.md) → [`C3_matchers.md`](C3_matchers.md). These three are the dense rows; each carries its own per-license-track preliminary ranking and per-row Plan-phase deliverables.
3. Skim [`C4_pose_estimation.md`](C4_pose_estimation.md) for the pinned input/output contract and D-C4-1 carry-forward.
4. Skim [`C5_state_estimator.md`](C5_state_estimator.md) for the pinned input/output contract + GTSAM-as-shared-C4+C5-substrate hybrid path D-C5-5 = (c) recommendation.
5. Skim [`C6_tile_cache_spatial_index.md`](C6_tile_cache_spatial_index.md) for the pinned input/output contract + Cand 1 (mirror-suite-pattern) RECOMMENDED PRIMARY rationale + Cand 2 (PostGIS+pgvector) DEFERRED-secondary criteria.
6. Skim [`C7_inference_runtime.md`](C7_inference_runtime.md) for the pinned input/output contract + TensorRT-native RECOMMENDED PRIMARY rationale + per-model-family precision policy (D-C7-6).
7. Skim [`C8_fc_adapter.md`](C8_fc_adapter.md) for the pinned per-FC input/output contract + pymavlink-GPS_INPUT (AP) + MSP2_SENSOR_GPS (iNav) RECOMMENDED PRIMARY rationale + UBX-impersonation DEFERRED-secondary criteria (Cand 3 vs Cand 2 comparative-improvement verdict).
8. Skim [`C10_preflight_provisioning.md`](C10_preflight_provisioning.md) for the C10 cross-coupling-minimal scope (D-C6-3 descriptor-cache rebuild + D-C7-7 TensorRT engine build confirmation pipelines; operator tooling design deferred to Plan).
9. Cross-reference [`99_cross_component_gates.md`](99_cross_component_gates.md) when reviewing Plan-phase decisions; it consolidates every D-Cx-y gate raised across rows with the owner and resolution path.

For session-by-session updates: append to the matching row file. The summary table here only needs an update when a row's closure state, top documentary leads, or hard disqualifiers change.

---

## Editing rules

1. Each row file owns its candidate table, per-license-track ranking, and Plan-phase deliverables. Do not duplicate that content here; just refresh the one-line "Top documentary leads" / "Hard disqualifiers" cells when a row's verdict moves.
2. Keep the "Sub-matrix cite" column in row files pointing at `../02_fact_cards/Cx_*.md` (not the deprecated `02_fact_cards.md`).
3. New cross-cutting Plan-phase decisions (D-Cx-y) go into [`99_cross_component_gates.md`](99_cross_component_gates.md) under the matching component owner.
4. When a C-row's candidate list changes, also touch the matching `../02_fact_cards/Cx_*.md` so the fact bindings stay aligned.
