[AZ-599] Batch 79: FT-P-02 Derkachi builder + _common.py extraction

- Add build_p02_fixtures.py: IMU CSV → tlog conversion (RAW_IMU +
  ATTITUDE pairs, centidegrees→radians yaw) and orchestrator that
  runs gps-denied replay against Derkachi MP4 + generated tlog,
  verifying ≥1 record_type="estimate" in the FDR archive.
- Extract run_gps_denied_replay + FDR-parent-dir helpers into
  sitl_replay_builder/_common.py; refactor build_p01_fixtures.py
  to import from _common (b78 tests preserved).
- Add 20 unit tests under e2e/_unit_tests/fixtures/test_sitl_
  replay_builder_p02.py covering AC-1..AC-5; total unit suite
  686/686 passing (regression gate AC-6).
- README updated to document FT-P-01 + FT-P-02 builders.
- Advance autodev state: last_completed_batch=79, current_batch=80;
  prune verbose detail blob.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-17 13:40:07 +03:00
parent 2f1fb4d0d0
commit 4e0717e543
10 changed files with 1111 additions and 76 deletions
@@ -0,0 +1,77 @@
# FT-P-02 Derkachi fixture builder (IMU CSV → tlog, real-motion replay)
**Task**: AZ-599_ft_p_02_derkachi_builder
**Complexity**: 3 points
**Dependencies**: AZ-598 (shared `run_gps_denied_replay` helper)
**Component**: Blackbox Tests / Test Infrastructure (epic AZ-262)
**Tracker**: AZ-599
## Problem
FT-P-02 (Derkachi continuous-flight drift) needs an offline-replay
FDR archive so the scenario can compute drift between satellite
anchors. The b78 FT-P-01 builder doesn't apply directly — FT-P-02
uses real video + real IMU CSV instead of still images + synthetic
stationary tlog.
## Strategy
Same overall shape as b78 (drive `gps-denied-replay` against a video
+ tlog pair), with two differences:
1. **Video is already MP4** — skip the OpenCV encoding step.
2. **IMU is real recorded telemetry**`data_imu.csv` has 10 Hz
`SCALED_IMU2` + `GLOBAL_POSITION_INT` columns. Need a CSV → tlog
conversion that packs each row as a `RAW_IMU` + `ATTITUDE`
MAVLink pair, with yaw synthesised from `GLOBAL_POSITION_INT.hdg`
and roll/pitch=0 (acceptable for fixed-wing cruise).
Output: the SUT's natural FDR archive directory (the b78 schema-
projection step is dropped because FT-P-02 reads the FDR directly).
## Files Touched
* `e2e/fixtures/sitl_replay_builder/_common.py` (new) — extracts
`run_gps_denied_replay` + `write_observer_fixture` from
`build_p01_fixtures.py` so b78 + b79 share one implementation.
* `e2e/fixtures/sitl_replay_builder/build_p01_fixtures.py` (edit)
— re-export the moved helpers from `_common.py` for backwards
compatibility; b78 tests must still pass unchanged.
* `e2e/fixtures/sitl_replay_builder/build_p02_fixtures.py` (new) —
the FT-P-02 builder.
* `e2e/fixtures/sitl_replay_builder/README.md` (edit) — document
both flows.
* `e2e/_unit_tests/fixtures/test_sitl_replay_builder_p02.py` (new)
— b79 builder tests.
* `e2e/_unit_tests/test_directory_layout.py` (edit) — register
the three new paths.
## Acceptance Criteria
**AC-1**: `convert_imu_csv_to_tlog` parses every row of
`data_imu.csv` and writes one RAW_IMU + one ATTITUDE pair per row.
**AC-2**: `convert_imu_csv_to_tlog` raises `ValueError` on missing
required columns OR malformed numeric rows OR empty CSV.
**AC-3**: Heading conversion uses centidegrees → radians
(`hdg_cdeg * pi / 18000`).
**AC-4**: `build_p02_fixtures` invokes `run_gps_denied_replay` with
the Derkachi MP4 + the generated tlog; the resulting FDR archive
contains ≥1 `record_type="estimate"` record (`verify_fdr_has_estimates`
helper).
**AC-5**: `run_gps_denied_replay` is in `_common.py`; b78 +
b79 both import it from there; b78 tests still pass.
**AC-6**: Full e2e unit-test suite passes.
## Out of Scope
* Live capture EXECUTION (manual operator step, same as b78).
* FT-P-04 / FT-P-05 (also use Derkachi but each needs its own
builder; deferred).
* iNav adapter.
* True SCALED_IMU2 → RAW_IMU unit conversion (pass-through; will
re-visit if the SUT's tlog parser rejects).