# Fact Cards

## Fact #1 — ArduPilot minimum GPS rate is 5Hz
- **Statement**: ArduPilot enforces a hard minimum of 5Hz for GPS_INPUT updates. The GPS_RATE parameter description states: "Lowering below 5Hz(default) is not allowed." The EKF scales buffers based on this rate.
- **Source**: Source #1 (ArduPilot AP_GPS_Params)
- **Phase**: Assessment
- **Target Audience**: ArduPilot-based flight controllers
- **Confidence**: ✅ High
- **Related Dimension**: Flight controller integration completeness

## Fact #2 — GPS_INPUT requires velocity + accuracy + GPS time fields
- **Statement**: GPS_INPUT message requires not just lat/lon/alt, but also: vn/ve/vd velocity components, hdop/vdop, horiz_accuracy/vert_accuracy/speed_accuracy, fix_type, time_week/time_week_ms, satellites_visible, and ignore_flags bitmap. The solution draft05 mentions GPS_INPUT but does not specify how these fields are populated (especially velocity from ESKF, accuracy from covariance, GPS time conversion from system time).
- **Source**: Source #2 (MAVLink GPS_INPUT definition), Source #3 (pymavlink example)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Flight controller integration completeness

## Fact #3 — ESKF state vector needs explicit definition
- **Statement**: Standard ESKF for UAV VIO fusion uses 15-16 state error vector: δp[3], δv[3], δθ[3] (attitude error in so(3)), δba[3] (accel bias), δbg[3] (gyro bias), optionally δg[3] (gravity). The solution draft05 says "16-state vector" and "ESKF + buffers ~10MB" but never defines the actual state vector, process model (F, Q matrices), measurement models (H matrices for VO and satellite), or noise parameters.
- **Source**: Source #5 (ludvigls/ESKF), Source #6 (EliaTarasov/ESKF)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Sensor fusion completeness

## Fact #4 — Monocular VIO has scale ambiguity without excitation
- **Statement**: Monocular visual-inertial odometry cannot observe metric scale during constant-velocity flight (zero accelerometer excitation). This is a fundamental observability limitation. The solution uses monocular cuVSLAM + IMU, and fixed-wing UAVs fly mostly at constant velocity. Scale must be provided externally — via known altitude (barometric + predefined mission altitude) or satellite matching absolute position.
- **Source**: Source #7 (Range-VIO scale observability paper)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Sensor fusion completeness, core algorithm correctness

## Fact #5 — cuVSLAM requires explicit camera calibration and IMU calibration
- **Statement**: PyCuVSLAM requires Camera(fx, fy, cx, cy, width, height) + Distortion model + ImuCalibration(gyroscope_noise_density, gyroscope_random_walk, accelerometer_noise_density, accelerometer_random_walk, frequency, T_imu_rig). The solution draft05 does not specify any camera calibration procedure, IMU noise parameters, or the T_imu_rig (IMU-to-camera) extrinsic transformation.
- **Source**: Source #4 (PyCuVSLAM docs)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Visual odometry completeness

## Fact #6 — cuVSLAM IMU fallback provides ~1s acceptable tracking
- **Statement**: When visual tracking fails (featureless terrain, darkness), cuVSLAM falls back to IMU-only integration which provides "approximately 1 second" of acceptable tracking quality before drift becomes unacceptable. After that, tracking is lost.
- **Source**: Source #4 (PyCuVSLAM/Isaac ROS docs)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Resilience, edge case handling

## Fact #7 — Disconnected route segments need satellite re-localization
- **Statement**: When a UAV makes a sharp turn and the next photos have no overlap with previous frames, cuVSLAM will lose tracking. The solution must re-localize using satellite imagery. The AC requires handling "more than 2 such disconnected segments" as a core strategy. Solution draft05 mentions this requirement but does not define the concrete re-localization algorithm (how satellite match triggers, how the new position is initialized in ESKF, how the map is connected to the previous segment).
- **Source**: Source #8 (NaviLoc), Source #9 (SatLoc-Fusion), AC requirements
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Functional completeness — disconnected segments

## Fact #8 — Coordinate transformation chain is undefined
- **Statement**: The system needs a well-defined coordinate transformation chain: (1) pixel coordinates → camera frame (using intrinsics), (2) camera frame → body frame (camera mount extrinsics), (3) body frame → NED frame (using attitude from ESKF), (4) NED → WGS84 (using reference point). For satellite matching: geo-referenced tile coordinates → WGS84. For object localization: pixel + camera angle + altitude → ground point → WGS84. None of these transformations are explicitly defined in draft05.
- **Source**: Source #15 (Istanbul Tech thesis), Source #7
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Coordinate system completeness

## Fact #9 — GSD normalization required for satellite-aerial matching
- **Statement**: Camera GSD at 600m altitude with ADTI 20L V1 (16mm, APS-C) is ~15.9 cm/pixel. Google Maps zoom 19 ≈ 0.3 m/pixel, zoom 18 ≈ 0.6 m/pixel. The GSD ratio is ~2:1 to ~4:1 depending on zoom level and altitude. Draft05's "pre-resize" step in the offline pipeline is mentioned but not specified: what resolution? what zoom level? The matching model (LiteSAM/XFeat) input size must match appropriately.
- **Source**: Source #14 (GSD matching paper), solution_draft05 calculations
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Satellite matching completeness

## Fact #10 — Google Maps imagery in conflict zones is intentionally outdated
- **Statement**: Google Maps deliberately serves older imagery (>1 year) for conflict zones in Ukraine. Ukrainian officials have flagged security concerns. The operational area (eastern/southern Ukraine) is directly in the conflict zone. Imagery may be 1-3+ years old, with seasonal differences (summer tiles vs winter flight, or vice versa). This is a HIGH-severity gap for satellite matching accuracy.
- **Source**: Source #12 (Google Maps Ukraine coverage)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Satellite imagery quality risk

## Fact #11 — No operational procedures defined
- **Statement**: Mature GPS-denied systems (Auterion, PX4) define: pre-flight checklist (set home position, verify sensors, verify tile coverage), in-flight monitoring procedures (what to watch, when to intervene), and post-flight analysis (compare estimated vs actual GPS on return). Solution draft05 has no operational procedures section.
- **Source**: Source #10 (Auterion), Source #11 (PX4)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system operators
- **Confidence**: ✅ High
- **Related Dimension**: Operational maturity

## Fact #12 — Object localization lacks implementation detail
- **Statement**: AC requires: "Other onboard AI systems can request GPS coordinates of objects detected by the AI camera." The solution says "trigonometric calculation using UAV GPS position, camera angle, zoom, altitude." But no API is defined, no coordinate math is shown, no handling of camera zoom/angle → ground projection is specified. The Viewpro A40 Pro gimbal angle and zoom parameters are not integrated.
- **Source**: Acceptance criteria, solution_draft05
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Object localization completeness

## Fact #13 — Tech stack document is inconsistent with draft05
- **Statement**: tech_stack.md says "camera @ ~3fps" in non-functional requirements. Draft05 corrected this to 0.7fps. tech_stack.md lists LiteSAM benchmark decision at 480px/640px/800px; draft05 uses 1280px. tech_stack.md doesn't mention EfficientLoFTR as fallback. These inconsistencies indicate the tech_stack.md was not updated after draft05 changes.
- **Source**: tech_stack.md, solution_draft05.md
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Document consistency, maturity

## Fact #14 — Confidence scoring is undefined in draft05
- **Statement**: Draft05 says "Confidence Scoring → GPS_INPUT Mapping — Unchanged from draft03" but draft05 is supposed to be self-contained. The actual confidence scoring logic (how VO confidence + satellite match confidence map to GPS_INPUT fix_type, hdop, horiz_accuracy) is never defined in the current draft. This is critical because ArduPilot's EKF uses these accuracy fields to weight the GPS data.
- **Source**: Source #2 (GPS_INPUT fields), solution_draft05
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Flight controller integration, confidence scoring

## Fact #15 — Initial bootstrap sequence is incomplete
- **Statement**: Draft05 startup reads GLOBAL_POSITION_INT to get initial GPS position. But: (1) cuVSLAM needs its first frame + features to initialize — how is the first satellite match triggered? (2) ESKF needs initial state — position from GPS, but velocity? attitude? (3) How does the system know GPS is denied and should start sending GPS_INPUT? (4) Is there a handoff protocol from real GPS to GPS-denied system?
- **Source**: solution_draft05, Source #10 (Auterion procedures)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Startup and bootstrap completeness

## Fact #16 — No recovery from companion computer reboot
- **Statement**: AC requires: "On companion computer reboot mid-flight, the system should attempt to re-initialize from the flight controller's current IMU-extrapolated position." Draft05 does not address this scenario. The system needs: read current FC position estimate, re-initialize ESKF, reload TRT engines (~1-3s), start cuVSLAM with no prior map, trigger immediate satellite re-localization.
- **Source**: Acceptance criteria, solution_draft05
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Resilience, failsafe completeness

## Fact #17 — No position refinement mechanism
- **Statement**: AC states: "The system may refine previously calculated positions and send corrections to the flight controller as updated estimates." Draft05 does not define how this works. When a satellite match provides an absolute correction, do previously estimated positions get retroactively corrected? Is this communicated to the flight controller? How?
- **Source**: Acceptance criteria, solution_draft05
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ⚠️ Medium (AC is ambiguous about necessity)
- **Related Dimension**: Position refinement

## Fact #18 — Tile storage requirements not calculated
- **Statement**: The solution mentions "preload tiles ±2km" and "GeoHash-indexed directory" but never calculates: how many tiles are needed for a mission area, what storage space is required, what zoom levels to use, or how to handle the trade-off between tile coverage area and storage limit. At zoom 19 (~0.3m/pixel), each 256×256 tile covers ~77m × 77m. Covering a 200km flight path with ±2km buffer would require ~130,000 tiles (~2.5GB JPEG).
- **Source**: solution_draft05, tech_stack.md
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ⚠️ Medium (estimates based on standard tile sizes)
- **Related Dimension**: Offline preparation completeness

## Fact #19 — 3 consecutive failed frames → re-localization request undefined
- **Statement**: AC requires: "If system cannot determine position of 3 consecutive frames by any means, send re-localization request to ground station operator via telemetry link." Draft05 does not define: (1) the re-localization request message format, (2) what "any means" includes (VO failed + satellite match failed + IMU drift exceeded threshold?), (3) how the operator response is received and applied, (4) what the system does while waiting.
- **Source**: Acceptance criteria, solution_draft05
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: Ground station integration, resilience

## Fact #20 — FastAPI endpoints mentioned but not defined
- **Statement**: Draft05 mentions FastAPI for "local IPC" but the REST API endpoints are only defined in security_analysis.md (POST /sessions, GET /sessions/{id}/stream, POST /sessions/{id}/anchor, DELETE /sessions/{id}). The solution draft itself doesn't specify the API contract, request/response schemas, or how other onboard systems interact.
- **Source**: solution_draft05, security_analysis.md
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ✅ High
- **Related Dimension**: API completeness

## Fact #21 — NaviLoc achieves 19.5m error with trajectory-level optimization
- **Statement**: Recent research (NaviLoc, 2025) shows that trajectory-level optimization treating satellite matching as noisy measurement achieves 19.5m mean error at 50-150m altitude, 16× better than per-frame matching. The solution's approach of per-keyframe satellite matching + ESKF correction is simpler but potentially less accurate than trajectory-level optimization.
- **Source**: Source #8 (NaviLoc)
- **Phase**: Assessment
- **Target Audience**: GPS-denied system
- **Confidence**: ⚠️ Medium (NaviLoc operates at lower altitude with higher overlap)
- **Related Dimension**: Algorithm maturity, accuracy potential
