Ticket 102: Binary Flight-Log Ingestion (ArduPilot .bin, PX4 ULog)¶
Status¶
Planned.
Goal¶
Ingest the binary flight-log formats that real operators and public datasets
actually produce — ArduPilot DataFlash binary (.bin) and PX4 ULog (.ulg) —
into the existing NormalizedFlightTrace, so calibration (Ticket 082) is not
limited to the rare hand-exported DataFlash text (.log) format.
Current Gap¶
adapters/flight_log/ only parses ArduPilot DataFlash text (.log). In
practice:
- ArduPilot flight controllers record binary
.bin;.logis a manual conversion most operators never produce. - PX4 / the public Flight Review log database (review.px4.io) — the largest
source of real logs with battery current/voltage — uses ULog (
.ulg).
So the ingestion path cannot consume the formats needed to calibrate against real, publicly available flights.
Scope¶
- Introduce a format-dispatch entry point that selects an adapter by content (header magic bytes) with extension as a fallback, rather than assuming text.
- ArduPilot
.bin: head bytes0xA3 0x95. - ULog
.ulg: magic0x55 0x4C 0x6F 0x67 0x01 0x12 0x35(ULog\x01\x12\x35). - Add an ArduPilot DataFlash binary adapter producing the same
NormalizedFlightTraceas the text adapter (reuse the row→record normalization, missing-field detection, GPS-fix filtering, and provenance). - Add a PX4 ULog adapter mapping PX4 topics to the normalized record fields
(
vehicle_gps_position,battery_status,vehicle_local_position/wind_estimate,vehicle_statusflight mode, etc.). - Record the concrete source format in
FlightTraceProvenance.source_format(e.g.ardupilot_dataflash_binary,px4_ulog). - Preserve determinism: identical input bytes yield byte-identical canonical output.
Dependency Decision (resolve in this ticket)¶
Two viable approaches; pick one explicitly and record the rationale:
- Library-backed —
pymavlink(DFReaderhandles both.binand.log) andpyulogfor ULog. Least hand-written parsing and most robust to format edge cases; adds dependencies (acceptable in principle —mavsdkis already a dependency — butpymavlink/pyulogenlarge the footprint and must be carried into the bvlos-mission-control worker image). - Hand-rolled — parse the self-describing
FMT/format messages directly. No new dependencies and matches the existing text adapter's style, but ULog in particular is intricate (subscriptions, multi-id topics, appended data) and risky to fully cover without real sample files.
Recommendation: library-backed for ULog (correctness density is high), and
either approach for .bin. Decide and note the choice before implementing.
Integration Requirements¶
- Public API stays
adapters.flight_log— add binary adapters behind the dispatch; existingingest_dataflash_logtext path is unchanged. - Reuse
FlightTraceRecord/NormalizedFlightTrace/FlightTraceProvenanceand the canonical-JSON writer; no schema-version bump unless a new field is required. - Add synthetic binary fixtures (build minimal
.bin/.ulgbyte streams in tests) so the adapters are tested without checking in large real logs. - Keep arbitrary-file-read and resource constraints consistent with the bvlos-mission-control subprocess boundary.
Acceptance Criteria¶
- A
.binand a.ulgfile each ingest into a validNormalizedFlightTracewith GPS position, groundspeed, altitude, battery, flight mode, and wind where present. - Format is auto-detected from content; an unknown/unsupported file raises a
clear
FlightLogIngestionError. source_formatdistinguishes text, binary, and ULog inputs.- GPS-fix filtering, missing-field reporting, and provenance behave identically to the text adapter.
- Deterministic: re-ingesting the same file produces identical canonical JSON.
Out of Scope¶
- Parameter fitting / calibration math (Ticket 082).
- Non-ArduPilot / non-PX4 autopilot formats.
- Live/streaming telemetry ingestion.
Prerequisites¶
Ticket 080 (text ingestion) and Ticket 081 (segmentation) are implemented and provide the normalization, GPS-fix filtering, and provenance this ticket reuses.