diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f45732c..78029af 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -35,7 +35,7 @@ The Orin runs headless: no local video out. The tablet app is the display. | `decoder` | Raw frames → named signals via DBC | 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 (USB UVC, MJPEG), software H.264 encoding, recording and live view; on-device inference later | No | +| `vision` | Camera capture (any V4L2 camera; in practice USB UVC, MJPEG), live view, software H.264 recording; on-device inference later. Repo `svc-vision`, Python (decision 29) | No | Each ships as a systemd unit. The host-level prerequisites they depend on (kernel modules, device permissions, gpsd) are the environment repo's job, not @@ -351,7 +351,7 @@ rewriting the document. | 2 | Displays are bus subscribers; no display-specific logic upstream | Accepted | 2026-08-14 | | 3 | Listen-only sniffing + active OBD-II, single writer | Accepted | 2026-08-14 | | 4 | MQTT as the bus | **Proposed** | 2026-08-14 | -| 5 | Rust for on-Orin services, Python for off-car tooling, Dart for the display client | Accepted | 2026-09-04 | +| 5 | Rust for on-Orin services, Python for off-car tooling, Dart for the display client. One exception: decision 29 | Accepted | 2026-09-04 | | 21 | Two clocks per envelope; `monotonic` orders, `timestamp` references | Accepted | 2026-09-05 | | 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 | @@ -375,3 +375,4 @@ rewriting the document. | 20 | Every display is data-only. Directly-driven screens are for permanently installed, car-powered panels only | Accepted | 2026-09-04 | | 27 | Camera live view is the one video stream to the tablet: its own connection beside the boundary, paced to the link (≤ ~4 MB/s), never on the bus. Exception to 20 | **Proposed** | 2026-10-11 | | 28 | Every Orin → tablet sender caps its socket (`SO_MAX_PACING_RATE`, ~5 MB/s); unpaced bursts stall the USB link for seconds | **Proposed** | 2026-10-11 | +| 29 | `svc-vision` is Python: camera pipelines and inference live in that ecosystem. Exception to 5 | Accepted | 2026-10-12 | diff --git a/docs/ORIN-RUNTIME.md b/docs/ORIN-RUNTIME.md index 9e012dc..4956a33 100644 --- a/docs/ORIN-RUNTIME.md +++ b/docs/ORIN-RUNTIME.md @@ -69,7 +69,7 @@ Ordered by what is lost if a tier is late. | 0 | kernel modules, gpsd, network | Host layer; nothing of ours can precede it | | 1 | `mosquitto`, `can-bridge`, `recorder` | **Data is lost if late.** Must reach ready fastest | | 2 | `decoder`, `gnss`, `obd-poller` | Derive from tier 1; a late start loses nothing | -| 3 | `svc-gw`, `svc-nav` | Serving; a display can wait | +| 3 | `svc-gw`, `svc-nav`, `svc-vision` | Serving; a display can wait | | 4 | voice — ASR, TTS | Interactive; seconds late is harmless | **Capture first** is the whole principle. A CAN frame missed at tier 1 is gone diff --git a/docs/REPOS.md b/docs/REPOS.md index b6c6bb5..ac689aa 100644 --- a/docs/REPOS.md +++ b/docs/REPOS.md @@ -27,6 +27,7 @@ contracts repo, not copied into each consumer. | [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 | +| [svc-vision](gitea:yukart/svc-vision) | Camera: capture and the live view; recording and inference to come | | [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 | @@ -133,7 +134,8 @@ docs/BOM.md only where the repo owns hardware | Where | Language | Why it is there | |---|---|---| -| `svc-*` — on the Orin | **Rust** | No GC, low resident memory on a shared 8 GB pool, and fast start for the tier-1 capture services | +| `svc-*` — on the Orin, except `svc-vision` | **Rust** | No GC, low resident memory on a shared 8 GB pool, and fast start for the tier-1 capture services | +| `svc-vision` — on the Orin | **Python** | Camera pipelines (GStreamer) and inference live in the Python ecosystem (decision 29). Standard library and host packages only, until a dependency earns its place | | `tool-*` — off-car | **Python** | Batch work where development speed is the only constraint that binds | | `app-flutter` | **Dart** | Flutter | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 33229bb..89dc1dd 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,7 +1,7 @@ --- type: plan status: active -updated: 2026-10-11 +updated: 2026-10-12 --- # Roadmap @@ -97,12 +97,14 @@ cores at 1080p; frame rate falls with the light. tablet, inference input, or several - [ ] Measure in the car: daylight and night frame rate and MJPEG size on a road scene -- [ ] One capture process owns `/dev/video0` (V4L2 is single-reader) and feeds +- [ ] One capture process owns the camera (V4L2 is single-reader) and feeds the others; sets UVC controls on open, since they reset on re-enumeration - [ ] Recording: H.264 segments on the recorder's clock and session marks, bounded like CAN sessions (~2.7 GB per hour at 6 Mbit/s) -- [ ] Live view in `app-flutter` (decision 27, proposed): 720p MJPEG passthrough - (~3.4 MB/s, no CPU) or H.264, paced per decision 28 +- [x] Live view (decision 27, proposed), 2026-10-12: `svc-vision` serves 720p + MJPEG passthrough on `:7710` (`yukart-vision.service`, ~2% of a core), + paced per decision 28, camera-agnostic, says when there is no camera; + `app-flutter` shows it with exposure and gain controls - [ ] Inference — deferred; plan for evicting voice, not for coexisting with it ([ORIN-RUNTIME.md](ORIN-RUNTIME.md))