Files
RealSense-D435i-G1/STATUS.md
T
robot 07d95792e3 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.
2026-05-19 00:58:23 +02:00

4.3 KiB

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

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