# 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).
