svc-vision: camera live view, moved from app-flutter's test tool
Camera-agnostic (--camera auto finds any V4L2 capture device and finds it again after a replug; non-MJPEG cameras are encoded), says when the camera is unavailable, paced per decision 28. Python, standard library only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
---
|
||||
type: guidelines
|
||||
---
|
||||
# Vision guidelines
|
||||
|
||||
## 1. Camera-agnostic
|
||||
- Any V4L2 capture device works. Never hard-code a node such as `/dev/video0`:
|
||||
numbering follows enumeration order. Take a `/dev/v4l/by-id/` path, or find
|
||||
the camera at runtime (`--camera auto`).
|
||||
- Use what the camera offers. MJPEG passes through untouched; anything else is
|
||||
encoded here. A requested size or rate the camera lacks falls back to its own
|
||||
default rather than failing.
|
||||
- UVC control names differ between cameras and kernels. Look them up on the
|
||||
device; reply that a control is missing rather than guessing.
|
||||
|
||||
## 2. One process owns the camera
|
||||
- V4L2 capture is single-reader. This service opens the device; recording and
|
||||
inference take frames from it, never from the device.
|
||||
- UVC controls reset when the camera re-enumerates. Set them on open, not once.
|
||||
|
||||
## 3. The tablet link is the constraint
|
||||
- Every socket to a display is paced (`SO_MAX_PACING_RATE`, project-yukart
|
||||
decision 28). Unpaced bursts stall the USB link for seconds.
|
||||
- Latest frame wins. A slow client skips frames; it never gets a queue of old ones.
|
||||
- Say when there is no camera. A client must be able to tell "unavailable" from
|
||||
"slow".
|
||||
|
||||
## 4. Python, on purpose
|
||||
- Python 3.10 (the Orin's), standard library only; GStreamer and v4l-utils come
|
||||
from the host. The exception to Rust for Orin services is decision 29: camera
|
||||
pipelines and inference live in the Python ecosystem.
|
||||
- No pip installs on the car Orin until there is a reason; then a venv under
|
||||
`~/infra/svc-vision/`, never the system Python.
|
||||
|
||||
## 5. To be added
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
type: plan
|
||||
status: active
|
||||
updated: 2026-10-12
|
||||
---
|
||||
# Initial plan
|
||||
|
||||
## Scope
|
||||
|
||||
The camera end to end on the Orin: capture, the live view, recording, and later
|
||||
inference. Hardware facts for the current camera are in orin-nano-env-setup
|
||||
`docs/impl/reports/USB-CAMERA.md`; tablet link limits in app-flutter
|
||||
`docs/impl/reports/LINK-TEST-2026-10-11.md`.
|
||||
|
||||
## Order
|
||||
|
||||
0. **Live view** — in place: `src/liveview.py` as `yukart-vision.service` on
|
||||
`:7710`. Started as a test tool in app-flutter and moved here once the live
|
||||
view became a product feature (decision 27). Protocol in the module docstring.
|
||||
1. **Capture fan-out.** One capture process, frames to several consumers (live
|
||||
view, recorder, inference). Needed before a second consumer exists.
|
||||
2. **Recording.** H.264 in software (`x264enc`, ~1.3–2 cores at 1080p) in
|
||||
segments on the recorder's sessions, under the recordings bound.
|
||||
3. **Exposure for sign reading.** Manual exposure with own metering to hold the
|
||||
frame rate; LED signs flicker under short exposures.
|
||||
4. **Inference** — deferred (decision 7): road signs, speed limits first.
|
||||
|
||||
## Open
|
||||
|
||||
- The protocol lives in the docstring. It moves to contracts when a second
|
||||
client exists or it changes shape.
|
||||
Reference in New Issue
Block a user