diff --git a/deploy/README.md b/deploy/README.md index fb19438..808581a 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -79,8 +79,40 @@ model (`/opt/move-detect/models/movenet_lightning.onnx`). - [ ] Pull the network cable → events keep queueing (`QUEUE_DB` grows) → restore → the queue flushes. (End-to-end behavior verified in the edge e2e harness.) +## Hailo-8 HAT + CSI camera path (optional, faster) + +The default bundle runs CPU MoveNet + USB webcam. To use the Hailo-8 accelerator +and/or a CSI camera, add these SYSTEM packages on the Pi (they are apt packages, not +pip wheels — the venv sees them because it is created with `--system-site-packages`): + +```bash +sudo apt install -y hailo-all python3-picamera2 python3-opencv +``` + +- `hailo-all` — HailoRT runtime + driver + the Python `hailo_platform` bindings. +- `python3-picamera2` — CSI camera stack (libcamera). + +Then place the pose model and switch backends in `/etc/move-detect/edge.env`: + +```ini +POSE_BACKEND=hailo +HAILO_HEF=/opt/move-detect/models/yolov8s_pose.hef # copy the compiled HEF here +CAMERA_BACKEND=csi +CSI_DEVICE=0 +``` + +Validate on device per `docs/hardware-bringup.md` before trusting output (the Hailo +decode is unit-locked, but the HailoRT inference + picamera2 color order are hardware- +validated). USB webcam stays available anytime via `CAMERA_BACKEND=uvc`. + +> **Air gap:** `hailo-all` / `python3-picamera2` are the ONE piece this bundle can't +> carry (Hailo's own driver + apt tree). Pre-install them on the Pi image, or transfer +> their `.deb`s separately, before running `install_offline.sh`. The pose HEF is +> likewise supplied out-of-band (compiled from the Hailo Model Zoo). + ## Not bundled (by design) - **MySQL / the cloud app** — a separate host; see `cloud/docs/cloud-deploy.md`. -- **HailoRT + `yolov8s_pose.hef`** — the Hailo runtime and HEF are installed via - Hailo's own Pi packages; the CPU MoveNet path here needs neither. +- **HailoRT + `yolov8s_pose.hef` + picamera2** — Hailo's runtime/driver, the compiled + HEF, and the CSI camera stack are Pi system packages installed out-of-band (above); + the default CPU MoveNet + USB path needs none of them. diff --git a/deploy/bundle/install_offline.sh b/deploy/bundle/install_offline.sh index 4a3c157..5b38159 100644 --- a/deploy/bundle/install_offline.sh +++ b/deploy/bundle/install_offline.sh @@ -40,7 +40,13 @@ cp "$HERE/models/"*.onnx "$PREFIX/models/" cp "$HERE/docs/"*.md "$PREFIX/docs/" 2>/dev/null || true echo ">> [3/6] python venv + offline wheel install (--no-index)" -python3 -m venv "$PREFIX/venv" +# --system-site-packages so the venv can import the Pi SYSTEM packages that are NOT +# pip-installable: hailo_platform (HailoRT, apt: hailo-all) for POSE_BACKEND=hailo, and +# picamera2 (apt: python3-picamera2) for CAMERA_BACKEND=csi. The wheelhouse install +# below adds our deps into the venv; where a system copy already satisfies a wheel's +# version constraint pip keeps it (ABI-compatible on the target images), otherwise the +# bundled wheel installs into the venv and shadows the system copy. +python3 -m venv --system-site-packages "$PREFIX/venv" "$PREFIX/venv/bin/pip" install --no-index --find-links "$WHEELHOUSE" --upgrade pip >/dev/null 2>&1 || true "$PREFIX/venv/bin/pip" install --no-index --find-links "$WHEELHOUSE" "${RUNTIME_PKGS[@]}" diff --git a/deploy/systemd/move-detect-edge.env.example b/deploy/systemd/move-detect-edge.env.example index 9296314..b152ba0 100644 --- a/deploy/systemd/move-detect-edge.env.example +++ b/deploy/systemd/move-detect-edge.env.example @@ -22,8 +22,12 @@ POSE_BACKEND=movenet MOVENET_ONNX=/opt/move-detect/models/movenet_lightning.onnx # HAILO_HEF: required when POSE_BACKEND=hailo (uncomment and set). #HAILO_HEF=/opt/move-detect/models/yolov8s_pose.hef +# CAMERA_BACKEND: "uvc" (USB webcam, uses UVC_DEVICE) or "csi" (Pi CSI camera, uses CSI_DEVICE). +CAMERA_BACKEND=uvc # UVC_DEVICE: OpenCV VideoCapture index for the USB (UVC) webcam. UVC_DEVICE=0 +# CSI_DEVICE: picamera2 camera_num for the CSI camera (used when CAMERA_BACKEND=csi). +CSI_DEVICE=0 # TARGET_FPS: frame pacing = 1/TARGET_FPS. TARGET_FPS=12