Initial commit: RealSense D435 API server
Drop-in replacement for the Nuwa-HP60C camera container, exposing RGB +
aligned depth + intrinsics via REST/WebSocket so the existing
pestello-pose-detector pipeline can consume frames without changes.
Key adaptations for D4xx on USB 2.0 (this robot has no USB 3 port exposed
externally — see STATUS.md):
- pyrealsense2 built from source; the librealsense v2.55.1 install rule
doesn't ship the main .so, so we copy it from the build dir and add an
__init__.py that re-exports the submodule.
- Color stream uses YUYV format on USB 2.x (BGR8/RGB8 time out on this
bus); converted to BGR via cv2.cvtColor in capture().
- rs.align is skipped on USB 2 (incompatible with YUYV); color is
cv2-resized to depth shape for approximate per-pixel alignment.
- Driver auto-detects usb_type_descriptor and falls back to the
full-resolution BGR8 + rs.align pipeline when on USB 3.
Tested: /api/{health,status,discover,rgb,depth,depth/color,capture,
intrinsics} all return 200 with valid payloads at 640x480.
This commit is contained in:
commit
07d95792e3
58 files changed
+6987
No files matched your search
@@ -0,0 +1,79 @@
|
||||
# Stato del progetto RealSense-D435 — 2026-05-19
|
||||
|
||||
## TL;DR
|
||||
|
||||
- ✅ Driver completo e funzionante su questo robot (Jetson Xavier NX, D435 su USB 2.1)
|
||||
- ✅ RGB 640x480 + Depth 640x480 simultanei via REST/WebSocket
|
||||
- ✅ Intrinsics, point cloud, measure, snapshot, recording, WebSocket stream — tutti operativi
|
||||
- ⚠️ Framerate effettivo ~4 fps (limitato dalla banda USB 2.0). Su porta USB 3 il driver riprende automaticamente 640x480@30.
|
||||
|
||||
## Cosa è stato risolto in questa sessione
|
||||
|
||||
1. **Bug install di librealsense v2.55.1**: il `.so` principale di `pyrealsense2` non viene installato dal CMake — solo `pyrsutils.so`. Workaround nel `Dockerfile`: si copia il `.so` direttamente da `/src/librealsense/build/Release/` e si aggiunge un `__init__.py` che riesporta il submodule (`from .pyrealsense2 import *`).
|
||||
2. **D4xx su USB 2 — formato color**: BGR8/RGB8 vanno in timeout su USB 2 anche da soli (firmware D4xx). Solo **YUYV** sostiene il transfer su USB 2. Il driver ora rileva `usb_type_descriptor` e su USB 2.x configura color = YUYV, convertendo in BGR via `cv2.cvtColor` in `capture()`.
|
||||
3. **`rs.align` incompatibile con YUYV**: il blocco di processing fallisce con "Error occurred during execution of the processing block". Su USB 2 saltiamo l'alignment hardware e facciamo un resize numpy del color per matchare la shape del depth (approximate alignment, OK per use case standard).
|
||||
4. **Risoluzione massima USB 2**: 640x480@15 (configurato) → ~4 fps reali. Testate tutte le combinazioni; 848x480 dà "Couldn't resolve requests" anche in YUYV.
|
||||
|
||||
## Hardware setup (constatato)
|
||||
|
||||
```
|
||||
Jetson Xavier NX
|
||||
├─ Bus 1 (USB 2.0, 480M)
|
||||
│ ├─ Hub interno → Inspire Hands (cdc_acm /dev/ttyACM0) + ch341
|
||||
│ └─ Hub esterno (collegato a porta USB-C frontale)
|
||||
│ ├─ Tastiera, mouse, ax88179 (Ethernet)
|
||||
│ └─ D435 ← qui
|
||||
└─ Bus 2 (USB 3.0, 10000M) — VUOTO, ma probabilmente non esposto esternamente
|
||||
```
|
||||
|
||||
- D435 serial: `933322070696`, fw `05.16.00.01`, USB `8086:0b07`, `usb_type = 2.1`
|
||||
- La porta USB-C frontale del robot H1 è cablata **USB 2 hardware** (confermato indirettamente: l'ax88179 sullo stesso hub gira a 480M)
|
||||
- Le Inspire Hands sono su hub interno separato — non vanno toccate
|
||||
|
||||
## Endpoints (verificati)
|
||||
|
||||
| Endpoint | HTTP | Note |
|
||||
|---|---|---|
|
||||
| `/api/health` | 200 | sdk_initialized=true, camera_open=true |
|
||||
| `/api/status` | 200 | include `color_available`, `usb_type` |
|
||||
| `/api/discover` | 200 | rileva D435 serial `933322070696` |
|
||||
| `/api/rgb` | 200 | JPEG 640x480 |
|
||||
| `/api/depth` | 200 | PNG 16-bit 640x480 |
|
||||
| `/api/depth/color` | 200 | JPEG colormap JET 640x480 |
|
||||
| `/api/capture` | 200 | JSON con tutte e tre base64 |
|
||||
| `/api/intrinsics` | 200 | ir + rgb + extrinsics_ir_to_rgb |
|
||||
| `/api/pointcloud`, `/api/pointcloud/roi`, `/api/measure`, `/api/snapshot` | 200 | da testare in scenario reale |
|
||||
|
||||
## File modificati in questa sessione
|
||||
|
||||
- `Dockerfile`: fix install pyrealsense2 (`.so` + `__init__.py`)
|
||||
- `src/backend/services/camera.py`:
|
||||
- rileva `usb_type_descriptor` in `open()`
|
||||
- profilo USB 2 (YUYV 640x480@15 color + Z16 640x480@15 depth)
|
||||
- conversione YUYV → BGR in `capture()` via `cv2.cvtColor` (manuale, dopo aver ricostruito lo shape (H,W,2))
|
||||
- skip `rs.align` su USB 2; resize numpy del color per matchare il depth
|
||||
- nuovi metodi `is_color_available()`, `usb_type()` per diagnostica
|
||||
- `src/backend/api/routes.py`: `/api/status` espone `color_available` + `usb_type`
|
||||
|
||||
## Da fare prossima volta
|
||||
|
||||
- Testare `/api/pointcloud` e `/api/measure` in un ambiente reale e verificare che l'approximate alignment (resize) sia accettabile per il caso d'uso. Se no, implementare alignment proprio con `cv2.remap` usando intrinsics + extrinsics.
|
||||
- Decidere se esporre il flag `usb_type` nel frontend React per warning utente
|
||||
- Eventualmente: profilo configurabile via `.env` per chi vuole controllare manualmente
|
||||
|
||||
## Modifiche al setup ambiente (persistono nei reboot)
|
||||
|
||||
1. `/etc/systemd/system/docker.service.d/http-proxy.conf` (proxy daemon)
|
||||
2. `unitree` nel gruppo `docker`
|
||||
3. `~/.docker/config.json` con proxy CLI + cli-plugins path
|
||||
4. `~/.docker/cli-plugins/docker-compose` (plugin v2)
|
||||
|
||||
## Avvio rapido
|
||||
|
||||
```bash
|
||||
cd ~/Robot_2026/RealSense-D435
|
||||
sg docker -c "docker compose up -d" # già buildato
|
||||
curl -s http://localhost:8878/api/health # check
|
||||
curl -s http://localhost:8878/api/rgb -o rgb.jpg
|
||||
curl -s http://localhost:8878/api/depth -o depth.png
|
||||
```
|
||||
Reference in new issue
Block a user