From e6ca835992a5896406188bd58c0b55851dcaff5c Mon Sep 17 00:00:00 2001 From: Mikkeli Date: Fri, 9 Oct 2026 20:24:32 +0900 Subject: [PATCH] Phase 1 recorder running; svc-core current; boundary v0 started The recorder runs on the car unit and reads SocketCAN and gpsd directly (decision 25, proposed). svc-gw and app-flutter talk boundary v0, both channels on one WebSocket with their own semantics (decision 26, proposed). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz --- docs/ARCHITECTURE.md | 4 +++- docs/REPOS.md | 4 ++-- docs/ROADMAP.md | 15 +++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 60c10a1..31b1a4c 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -33,7 +33,7 @@ The Orin runs headless: no local video out. The tablet app is the display. | `obd-poller` | Active OBD-II PID request/response | **Yes** | | `gnss` | gpsd client → position, speed, time fix | No | | `decoder` | Raw frames → named signals via DBC | No | -| `recorder` | Persist raw + decoded sessions to disk | No | +| `recorder` | Persist raw + decoded sessions to disk; raw CAN and GNSS read directly, not via the bus (decision 25) | No | | `telemetry-gw` | Serve external display clients | No | | `vision` | Camera capture and on-device inference (later) | No | @@ -354,6 +354,8 @@ rewriting the document. | 22 | `signals.json` is the single source for signal name and unit; both are derived, never authored twice | Accepted | 2026-09-05 | | 23 | Services build natively on the development Orin; both units stay on the same L4T release | Accepted | 2026-09-05 | | 24 | Link drops are routine: `svc-gw` detects dead clients by heartbeat and redelivers or expires pending reliable traffic; upstream commands are idempotent | **Proposed** | 2026-10-09 | +| 25 | The recorder reads SocketCAN and gpsd directly; raw capture never depends on the broker | **Proposed** | 2026-10-09 | +| 26 | Boundary v0 carries both channels of decision 15 on one WebSocket, each keeping its own semantics (drop-oldest down, acked and idempotent up) | **Proposed** | 2026-10-09 | | 6 | Local logging first; off-board LTE telemetry deferred | Accepted | 2026-08-14 | | 7 | Camera/AI inference is a later, separate task | Accepted | 2026-08-14 | | 8 | Self-hosted offline navigation (MapLibre GL + Valhalla + PMTiles) over a cloud maps SDK | Accepted | 2026-09-03 | diff --git a/docs/REPOS.md b/docs/REPOS.md index 99451dd..b6c6bb5 100644 --- a/docs/REPOS.md +++ b/docs/REPOS.md @@ -24,7 +24,8 @@ contracts repo, not copied into each consumer. | [orin-nano-env-setup](gitea:yukart/orin-nano-env-setup) | Jetson host bring-up | | [app-flutter](gitea:yukart/app-flutter) | Flutter display client | | [contracts](gitea:yukart/contracts) | Topic namespace, payload schemas, signal registry | -| [svc-gw](gitea:yukart/svc-gw) | Telemetry gateway — aggregation and the HTTP surface | +| [svc-core](gitea:yukart/svc-core) | Acquisition + processing cluster: `recorder` now; `can-bridge`, `obd-poller`, `gnss`, `decoder` to come | +| [svc-gw](gitea:yukart/svc-gw) | Telemetry gateway — aggregation and the display boundary | | [svc-nav](gitea:yukart/svc-nav) | Navigation service — routing and guidance | | [tool-mapmint](gitea:yukart/tool-mapmint) | Map artifact minting, workstation-side | | [tool-mock](gitea:yukart/tool-mock) | Mocks and fixtures — a fake car on a workstation | @@ -33,7 +34,6 @@ contracts repo, not copied into each consumer. | Repository | Role | Why separate | |---|---|---| -| `svc-core` | Acquisition + processing cluster: `can-bridge`, `obd-poller`, `gnss`, `decoder`, `recorder` | Developed and deployed as one unit on the Orin | | `app-esp32` | ESP32 RLCD/e-ink display firmware (Class B) | Embedded toolchain, flashed not deployed | | `tool-analysis` | Offline session analysis, reverse-engineering notebooks | Runs off-car, no runtime coupling | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 0ab0346..450b465 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -38,17 +38,22 @@ Tracked in [orin-nano-env-setup](gitea:yukart/orin-nano-env-setup). Get real Z27AG traffic onto disk before designing anything around it. +- [x] `recorder` — raw CAN + GNSS sessions on the car unit (`yukart-recorder.service`): + starts on traffic or `ctl start`, ends after 15 s idle, marks via `ctl mark` or + the app; fsync'd every second, bounded at 50 GB, ~20 MB per hour of driving - [ ] `can-bridge` — listen-only, timestamped frames onto the bus -- [ ] `recorder` — persist raw sessions - [ ] Capture drive sessions across varied conditions (idle, cold start, moving, lights/indicators/windows actuated) with a written log of what was done when The manual event log matters more than it sounds: it is what makes the raw -capture decodable later. +capture decodable later. Marks go into the session itself (`yukart-recorder ctl +mark …`, or the app's Mark button), on the same clock as the frames. ## Phase 2 — Decode -- [ ] Correlate captures against the event log; identify recurring frame IDs +- [ ] Correlate captures against the event log; identify recurring frame IDs — + prior art and first candidates (engine speed in `0x210` / `0x13D`) in contracts + `docs/impl/reports/Z27AG-CAN-PRIOR-ART.md` - [ ] Build the Z27AG DBC incrementally in `contracts` - [ ] `decoder` — raw frames to named signals - [ ] `obd-poller` — active OBD-II PIDs, single writer, rate-limited @@ -69,7 +74,9 @@ provides a cross-check for reverse-engineered ones. Order chosen by feedback speed, not ambition. - [ ] One display end-to-end first, proving the contract — `app-flutter` is the - quickest to iterate on, and is the only display in current scope + quickest to iterate on, and is the only display in current scope. + Started: boundary v0 (contracts `docs/BOUNDARY.md`) between `svc-gw` on the + car unit and a text-readout starter app; not yet run on the tablet - [ ] `app-esp32` — RLCD/e-ink glanceable subset. Deferred, no hardware in scope ## Phase 5 — Camera and inference · *separate task*