"""Replay `data_imu.csv` to the FC inbound at 10 Hz. CSV schema (from `_docs/00_problem/input_data/flight_derkachi/data_imu.csv`): timestamp_ms,ax,ay,az,gx,gy,gz,roll_deg,pitch_deg,yaw_deg,baro_m Owned by AZ-406 (public surface) + AZ-407 (concrete file-driver implementation). This module commits to the type signatures the per-scenario tests will import; the actual MAVLink / MSP2 emission is wired up by the downstream task. """ from __future__ import annotations from dataclasses import dataclass from pathlib import Path from typing import Protocol @dataclass(frozen=True) class ImuSample: """One row of `data_imu.csv` after parsing into native units.""" timestamp_ms: int accel_mss: tuple[float, float, float] gyro_rps: tuple[float, float, float] attitude_rad: tuple[float, float, float] # roll, pitch, yaw (radians) baro_alt_m: float class FcInboundEmitter(Protocol): """Abstract emitter — concrete impls are MAVLink (AP) or MSP2 (iNav).""" def emit(self, sample: ImuSample) -> None: ... class ImuReplayer: """Drives an `FcInboundEmitter` from a CSV file at the recorded cadence.""" def __init__(self, emitter: FcInboundEmitter, rate_hz: float = 10.0) -> None: self._emitter = emitter self._rate_hz = rate_hz def replay(self, csv_path: Path) -> int: """Replay the CSV file. Returns the number of samples emitted. Concrete implementation is owned by AZ-407 (FT-P-02 derkachi-drift + FT-P-04 frame-to-frame registration are the first consumers). """ raise NotImplementedError( "ImuReplayer.replay is owned by AZ-407 — AZ-406 supplies only " "the public surface." )