diff --git a/docs/architecture.md b/docs/architecture.md index fd8ab28..b7d56eb 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -53,36 +53,38 @@ Shared state is mutex-guarded: latest `MotorTelemetry` (serial), `ControlCommand 1. **Startup** — `main()` parses CLI, resolves + loads config, constructs `Application`, which builds the motor/channel/camera (real or mock), the `ImagePipeline`, and the `CaptureScheduler`. -2. **Telemetry** — the real motor controller streams `$;...;` lines; `parseTelemetryLine` turns each into a - `MotorTelemetry` snapshot. The mock synthesizes one. +2. **Telemetry** — the real motor controller streams firmware `ST Y:...[ P:...]` lines; `parseTelemetryLine` + turns each into a per-axis `MotorTelemetry` snapshot (state + encoder counts + flags). The mock synthesizes + one. Encoder counts are mapped to/from degrees by `Geometry` (`[Motor]` calibration). 3. **Control input** — `IControlChannel::poll()` returns the latest `ControlCommand` (control code + target heading), clearing its "available" flags so each update is acted on once. -4. **Capture cycle** (`CaptureScheduler::tick`, per 10 ms): - - ControlCode 0: when the interval elapses, send `p` to advance/stop, then trigger the cameras. - - ControlCode 1: send `kd` to drive to the requested heading, then trigger. +4. **Capture cycle** (`CaptureScheduler::tick`, per 10 ms) — a move → settle → trigger machine: + - ControlCode 0: `MOVE ,` to the next `ScanGrid` waypoint (ping-pong). + - ControlCode 1: `MOVE` yaw to `target_HDG` (pitch held), converted to counts via `Geometry`. + - Trigger the cameras once **both axes report standstill at the target**, then advance the grid. 5. **Frame handling** — a triggered camera delivers a `Frame` to the callback, which `submit()`s it to the `ImagePipeline`. The worker rotates it 90° CCW, encodes JPEG XL (or copies the demo image), writes - `/