Broaden scope: the Orin Nano is the target, the Pi 5 was the test rig
Written as a Pi 5 project because that is where the first camera went. That was never the destination — the camera is meant for an Orin Nano, and the Pi was convenient and available first. ⚠ This is not a wording change. The two boards do not share a camera stack: libcamera/picamera2 on the Pi, V4L2/GStreamer with Argus for CSI Bayer sensors on the Jetson. Code written directly against picamera2 does not run on the Orin at all. So capture goes behind an interface with a backend per platform, chosen at runtime from what the hardware reports, and everything above it depends only on "a source of frames". Recorded as the main design constraint rather than left to be discovered when the code moves. The same split decides where face recognition can live: TensorRT on GPU/DLA on the Orin, CPU-only on the Pi. The Pi proves the pipeline, never the performance, and AGENTS.md now requires a measurement to say which board it came from. Also generalises the camera-not-detected section to cover both boards, and keeps the cable notes that cost a module: the Pi 5's 22-pin FPC versus 15-pin Pi 4-era cables, and that Jetson carriers use their own pinout, so a cable fitting a Pi does not necessarily carry the same signals. Status corrected to "no camera connected anywhere" — the first module's cable is confirmed faulty and the module may be damaged; a second is being tried on an Orin.
This commit is contained in:
@@ -1,62 +1,78 @@
|
||||
# Working in this repo
|
||||
|
||||
Project instructions for Codex on `pi5`. The client-wide prompt lives in `~/.codex/AGENTS.md`; this
|
||||
file is the project-specific part.
|
||||
Project instructions for Codex. The client-wide prompt lives in `~/.codex/AGENTS.md`; this file is
|
||||
the project-specific part.
|
||||
|
||||
## Where you are
|
||||
## Know which board you are on
|
||||
|
||||
**You are running on the target hardware.** `pi5` is the Raspberry Pi 5 this software is *for*, so
|
||||
you can test against the real camera, the real CPU and the real network — there is no emulation step
|
||||
and no deploy step. Use that: prefer running the thing over reasoning about whether it would run.
|
||||
This project spans **two different single-board computers with incompatible camera stacks**, and
|
||||
Codex is installed on both. Getting this wrong produces code that runs where you tested it and
|
||||
nowhere else.
|
||||
|
||||
Call `platform_info` if you need to confirm which machine you are on. It is client-local and reports
|
||||
this Pi, not `halogen`.
|
||||
- **Jetson Orin Nano** — the *target*. L4T / JetPack, CUDA, TensorRT. V4L2 / GStreamer, with Argus
|
||||
(`nvarguscamerasrc`) for CSI Bayer sensors.
|
||||
- **Raspberry Pi 5** — the *test platform*. libcamera / `rpicam` / `picamera2`. CPU-only inference.
|
||||
|
||||
## The camera is not detected yet
|
||||
**Call `platform_info` before writing anything platform-specific.** It is client-local and reports
|
||||
the machine you are actually on, not `halogen`. Do not infer the board from the fact that both are
|
||||
aarch64 — that is the one thing they have in common.
|
||||
|
||||
`rpicam-hello --list-cameras` reports **"No cameras available!"**, and `dmesg` has no sensor probe
|
||||
lines. See README.md for the diagnosis.
|
||||
⚠ **Code written directly against `picamera2` will not run on the Orin.** Put capture behind an
|
||||
interface with a backend per platform, selected at runtime from what the hardware reports. Everything
|
||||
above capture — streaming, UI, recognition — depends only on "a source of frames".
|
||||
|
||||
⚠ **This is a hardware/cabling problem, and you cannot fix it from software.** Do not add
|
||||
`dtoverlay=` lines, edit `/boot/firmware/config.txt`, or install packages to try to make it appear —
|
||||
`camera_auto_detect=1` is already correct, and a silent `dmesg` means the sensor is not being reached
|
||||
electrically. Report the state and ask the operator to reseat the cable.
|
||||
⚠ **The Pi proves the pipeline, never the performance.** Face recognition on the Orin goes through
|
||||
TensorRT on GPU/DLA; on the Pi it is CPU-only and will not hold a live stream. Never present a Pi
|
||||
timing as evidence the target is fast enough, and say which board a measurement came from.
|
||||
|
||||
⚠ **Do not take `/dev/video*` as proof of a camera.** Those nodes are the Pi's codec and ISP blocks
|
||||
and exist with nothing attached.
|
||||
## No camera is connected yet
|
||||
|
||||
Until a sensor appears, work that does not depend on live capture is still available: the web UI
|
||||
shell, the streaming plumbing against a test pattern or a still image, project structure, tests.
|
||||
**Say plainly when you are working against a placeholder** rather than a real frame.
|
||||
No working camera has been attached to either board. The first module was not detected on the Pi 5 at
|
||||
all — traced to a cable fault, with the module possibly damaged too. See README.md for the evidence
|
||||
and the check commands.
|
||||
|
||||
⚠ **You cannot fix camera detection from software.** Do not add `dtoverlay=` lines, edit
|
||||
`/boot/firmware/config.txt`, or install packages to make a sensor appear. On the Pi,
|
||||
`camera_auto_detect=1` is already correct; a silent `dmesg` and a missing i2c bus mean the sensor is
|
||||
not being reached electrically. Report the state and stop.
|
||||
|
||||
⚠ **`/dev/video*` is not evidence of a camera** — those nodes exist on both boards with nothing
|
||||
attached.
|
||||
|
||||
Work that does not need live capture is still available: the capture interface and a synthetic or
|
||||
still-image backend, the streaming plumbing, the web UI, project structure, tests. **Say plainly when
|
||||
you are working against a placeholder** rather than a real frame.
|
||||
|
||||
## Constraints
|
||||
|
||||
- **Python 3 with `picamera2`** is the expected capture path once a sensor exists. It is not
|
||||
installed yet; install it via `apt` (`python3-picamera2`), not `pip` — it binds to system
|
||||
libcamera, and the pip build will not match.
|
||||
- **Do not commit captured images or video.** Frames of a real room are not test fixtures. If a
|
||||
fixture is genuinely needed, generate a synthetic one.
|
||||
- This is a **4-core Pi 5**. Face recognition must run on downscaled frames and off the capture
|
||||
thread; a per-frame full-resolution model will not hold a live stream.
|
||||
- Prefer the **stdlib and system packages** over adding dependencies. Every dependency here is one
|
||||
more thing that has to build on aarch64.
|
||||
- **Install capture libraries from system packages, not pip.** `python3-picamera2` on the Pi; the
|
||||
Jetson camera stack ships with L4T. Both bind to system libraries and a pip build will not match.
|
||||
- **Do not commit captured images or video.** Frames of a real room are not test fixtures. Generate a
|
||||
synthetic fixture if one is genuinely needed.
|
||||
- Keep dependencies few. Everything here has to build on aarch64, and on the Jetson it has to
|
||||
coexist with a vendor-pinned CUDA and Python.
|
||||
- Face recognition runs on **downscaled frames, off the capture thread**.
|
||||
|
||||
## Verifying your work
|
||||
|
||||
Claims about the camera or the stream must be backed by a command that ran:
|
||||
Claims about hardware, the stream, or performance need a command that ran:
|
||||
|
||||
```bash
|
||||
rpicam-hello --list-cameras # is a sensor present at all
|
||||
dmesg | grep -iE 'imx|ov5647|cfe' # did it probe
|
||||
curl -sI http://localhost:<port>/ # is the server actually serving
|
||||
# is a sensor present
|
||||
rpicam-hello --list-cameras # Pi 5
|
||||
v4l2-ctl --list-devices # Orin
|
||||
|
||||
# is the server actually serving frames
|
||||
curl -sI http://localhost:<port>/
|
||||
```
|
||||
|
||||
⚠ **The absence of an error is not evidence something works.** A stream endpoint that returns 200
|
||||
with no frames, and a working one, look identical to `curl -o /dev/null`. Check what came back.
|
||||
⚠ **The absence of an error is not evidence that something works.** A stream endpoint returning 200
|
||||
with no frames and a working one are indistinguishable to `curl -o /dev/null` — check what actually
|
||||
came back. The same applies to a capture backend that constructs cleanly and yields nothing.
|
||||
|
||||
## Git
|
||||
|
||||
The remote is Gitea at `192.168.2.199:3005`, reachable from this Pi over SSH on port 2222.
|
||||
The remote is Gitea at `192.168.2.199:3005`, reachable over SSH on port 2222.
|
||||
|
||||
⚠ **`tea` (the Gitea CLI) is denied by policy** and is blocked by a `PreToolUse` hook. Ordinary
|
||||
`git` is fine. **Do not push** unless the operator asks — commit locally and say what is ready.
|
||||
⚠ **`tea` (the Gitea CLI) is denied by policy** and blocked by a `PreToolUse` hook. Ordinary `git` is
|
||||
fine. **Do not push** unless the operator asks — commit locally and say what is ready.
|
||||
|
||||
Reference in New Issue
Block a user