docs: rewrite README for G1 deploy
Updates the README from the H1 description to the current G1 state: D435i over USB 3.2, librealsense pinned to v2.50.0 for FW 05.15.x compatibility, host-side React build, and the video_hub_pc4 stop prerequisite. Adds a G1-vs-H1 hardware comparison table and three new troubleshooting entries (wait_for_frames timeout, resolve request failure, npm DNS). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fcbb087438
commit
1451d51211
1 file changed
+194
-84
@@ -1,14 +1,16 @@
|
|||||||
# RealSense D435 — API Server
|
# RealSense D435i — API Server (G1)
|
||||||
|
|
||||||
Container Docker che espone una Intel RealSense D4xx (testata su D435) via
|
Container Docker che espone una Intel RealSense D4xx via REST + WebSocket,
|
||||||
REST + WebSocket, con la **stessa shape API del Nuwa-HP60C**: envelope
|
con la **stessa shape API del Nuwa-HP60C**: envelope `ApiResponse`,
|
||||||
`ApiResponse`, endpoint `/api/...`, header `X-Api-Key`, WebSocket `/ws`.
|
endpoint `/api/...`, header `X-Api-Key`, WebSocket `/ws`. Pensato come
|
||||||
Pensato come drop-in replacement del container Nuwa nella pipeline del
|
drop-in replacement del container Nuwa nella pipeline del pestello, così
|
||||||
pestello, così i client esistenti (`pestello-pose-detector`, frontend
|
i client esistenti (`pestello-pose-detector`, frontend React, ecc.)
|
||||||
React, ecc.) consumano frame senza modifiche.
|
consumano frame senza modifiche.
|
||||||
|
|
||||||
Gira sul robot **Unitree H1** (Jetson Xavier NX, JetPack 5.1.x). Il repo
|
Questo branch (`camera-g1`) è la porta del repo originale H1 verso il
|
||||||
è su [git.humion.it](https://git.humion.it/Labotics-OnGianni/RealSense-D435-H1).
|
robot **Unitree G1** (Jetson Xavier NX, JetPack 5.1.x). Il repo upstream
|
||||||
|
è su [git.humion.it](https://git.humion.it/Labotics-OnGianni/RealSense-D435-H1)
|
||||||
|
— il nome `…-H1` è storico, non cambia il fatto che gira anche su G1.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ Gira sul robot **Unitree H1** (Jetson Xavier NX, JetPack 5.1.x). Il repo
|
|||||||
│ ▼ │
|
│ ▼ │
|
||||||
┌───────────────────┴────┐ │
|
┌───────────────────┴────┐ │
|
||||||
│ RealSense-D435-H1 ⬅️ │ ← QUESTO REPO │
|
│ RealSense-D435-H1 ⬅️ │ ← QUESTO REPO │
|
||||||
│ (sul robot, port 8878)│ │
|
│ (sul G1, port 8878) │ │
|
||||||
└────────────────────────┘ │
|
└────────────────────────┘ │
|
||||||
(era: Nuwa-HP60C) │
|
(era: Nuwa-HP60C) │
|
||||||
│
|
│
|
||||||
@@ -37,35 +39,81 @@ niente pose estimation. Quella logica vive in container separati su harry.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Hardware constraint importante: D435 su USB 2.0
|
## Hardware — G1 vs H1
|
||||||
|
|
||||||
Sul robot H1 la D435 è collegata a una porta USB-C frontale che, anche se
|
Il robot G1 ha la D435i nella testa, collegata a un bus **USB 3.2**
|
||||||
fisicamente è USB-C, è **cablata USB 2.0** lato Jetson (verificato: anche
|
nativo del Jetson. È una situazione molto più semplice della H1, dove
|
||||||
un adapter ax88179 sullo stesso bus gira a 480 Mbps invece dei suoi 5
|
la stessa famiglia di camera era cablata su USB 2 e richiedeva
|
||||||
Gbps nativi). Il controller USB 3 del Jetson esiste ma non è esposto
|
workaround pesanti nel driver.
|
||||||
esternamente sulla scocca.
|
|
||||||
|
|
||||||
Per cui il driver, all'apertura del device, controlla
|
| | **G1 (questo deploy)** | H1 (vedi `main`) |
|
||||||
`usb_type_descriptor` e si adatta:
|
|
||||||
|
|
||||||
| | **USB 2.x** (situazione attuale) | **USB 3.x** (se mai) |
|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Color format | YUYV (l'unico che il D4xx sostiene su USB 2) | BGR8 |
|
| Camera | Intel RealSense **D435i** | Intel RealSense D435 |
|
||||||
| Color resolution | 640x480 @ 15 fps (≈4 fps reali) | 640x480 @ 30 fps |
|
| Serial / FW | `243722073572` / `05.15.01.55` | `933322070696` / `05.16.00.01` |
|
||||||
| Depth resolution | 640x480 @ 15 fps | 640x480 @ 30 fps |
|
| Bus | USB 3.2 (xhci `2-2.1`) | USB 2.1 (hub esterno frontale) |
|
||||||
| Alignment depth↔color | Approximate (resize numpy) | Hardware (rs.align) |
|
| Color format | BGR8 nativo | YUYV (convertito in BGR via cv2) |
|
||||||
| Conversione YUYV→BGR | sì, via `cv2.cvtColor` | non serve |
|
| Risoluzione effettiva | 640x480 @ 30 fps | 640x480 @ ~4 fps reali |
|
||||||
|
| Alignment depth↔color | Hardware (`rs.align`) | Approximate (resize numpy) |
|
||||||
|
| librealsense SDK | **v2.50.0** (pinned, vedi sotto) | v2.55.1 |
|
||||||
|
|
||||||
I dettagli sui workaround applicati sono in [STATUS.md](STATUS.md).
|
Il driver `src/backend/services/camera.py` rileva `usb_type_descriptor`
|
||||||
|
all'apertura e sceglie il profilo: il path USB 2 è ancora presente per
|
||||||
|
non rompere la build H1, ma su G1 non viene attivato.
|
||||||
|
|
||||||
|
### Perché librealsense v2.50.0 e non l'ultima
|
||||||
|
|
||||||
|
Il firmware `05.15.01.55` del D435i della G1 è più vecchio della
|
||||||
|
"recommended" (`05.13.00.50` ← sì, il numero più basso *è* più nuovo
|
||||||
|
nella numerazione D4xx, ma il punto è che la nostra è non-standard).
|
||||||
|
Con librealsense v2.55.x il device si apre regolarmente ma
|
||||||
|
`wait_for_frames` va in timeout indefinitamente — sembra essere una
|
||||||
|
regressione del nuovo USB backend contro firmware D4xx vecchio. Pinnando
|
||||||
|
il container a v2.50.0 (la stessa versione del clone di librealsense
|
||||||
|
installato sull'host in `/home/unitree/librealsense`) il flusso frame
|
||||||
|
torna a funzionare. Vedi `Dockerfile` riga 11.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
### Sul robot (deploy)
|
### Prerequisito: liberare `/dev/video4`
|
||||||
|
|
||||||
|
Sul G1 c'è un servizio Unitree chiamato `video_hub_pc4` che apre
|
||||||
|
`/dev/video4` (uno dei nodi V4L2 esposti dal D435i) all'avvio del
|
||||||
|
sistema. Se è attivo, il container non riesce a inizializzare la
|
||||||
|
pipeline e si vede `RuntimeError: Failed to resolve request`. Fermarlo:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd ~/Robot_2026/RealSense-D435
|
/unitree/sbin/mscli stopservice video_hub_pc4
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ Questo va rifatto a ogni reboot. Per renderlo persistente bisognerebbe
|
||||||
|
disattivare l'autostart Unitree — non lo abbiamo ancora fatto perché
|
||||||
|
non sappiamo se serve a qualcos'altro nel sistema.
|
||||||
|
|
||||||
|
### Build del frontend (una tantum, lato host)
|
||||||
|
|
||||||
|
Il vecchio Dockerfile H1 buildava il React frontend in uno stage Docker.
|
||||||
|
Sul Jetson del G1, però, `npm` dentro al container non riesce a
|
||||||
|
risolvere `registry.npmjs.org` (il resolver di default di Docker —
|
||||||
|
`127.0.0.53` — è lo stub systemd-resolved dell'host, che non funziona
|
||||||
|
da dentro i container). Quindi buildiamo il frontend una volta sull'host,
|
||||||
|
e il Dockerfile copia solo il `dist/` già pronto.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/robot/RealSense-D435-H1
|
||||||
|
docker run --rm --dns 8.8.8.8 \
|
||||||
|
-v "$(pwd)/src/frontend/react:/app" -w /app \
|
||||||
|
node:22-alpine sh -c 'npm install && npm run build'
|
||||||
|
# → produce src/frontend/react/dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
Da rifare solo quando cambi qualcosa sotto `src/frontend/react/`.
|
||||||
|
|
||||||
|
### Run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/robot/RealSense-D435-H1
|
||||||
|
|
||||||
# Build + run (la prima volta build di librealsense da source: ~25 min)
|
# Build + run (la prima volta build di librealsense da source: ~25 min)
|
||||||
sg docker -c "docker compose up -d"
|
sg docker -c "docker compose up -d"
|
||||||
@@ -79,12 +127,12 @@ sg docker -c "docker compose down"
|
|||||||
```
|
```
|
||||||
|
|
||||||
Il container ha `restart: unless-stopped`, quindi resta su dopo reboot
|
Il container ha `restart: unless-stopped`, quindi resta su dopo reboot
|
||||||
del robot (purché `docker.service` parta — `systemctl enable docker` se
|
del robot (purché `docker.service` parta e tu abbia rifatto lo stop di
|
||||||
non lo è già).
|
`video_hub_pc4`).
|
||||||
|
|
||||||
### Dal tuo PC (consumare lo stream)
|
### Dal tuo PC (consumare lo stream)
|
||||||
|
|
||||||
Dall'IP LAN del robot (`192.168.123.99`) o via mDNS (`ubuntu.local`):
|
Dall'IP LAN del robot (`192.168.123.99`, eth0) o `ubuntu.local` via mDNS:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Verifica connettività
|
# Verifica connettività
|
||||||
@@ -101,9 +149,8 @@ firefox http://192.168.123.99:8878/gui
|
|||||||
firefox http://192.168.123.99:8878/apidocs
|
firefox http://192.168.123.99:8878/apidocs
|
||||||
```
|
```
|
||||||
|
|
||||||
Da harry (192.168.123.100) sostituisci nell'`.env` del
|
Da harry (192.168.123.100), nel `pestello-pose-detector` sostituisci nel
|
||||||
`pestello-pose-detector` l'URL della camera con
|
suo `.env` l'URL della camera con `http://192.168.123.99:8878`.
|
||||||
`http://192.168.123.99:8878`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -134,7 +181,8 @@ Da harry (192.168.123.100) sostituisci nell'`.env` del
|
|||||||
|
|
||||||
Tutti gli endpoint sotto `/api/` (eccetto `/api/health`) richiedono
|
Tutti gli endpoint sotto `/api/` (eccetto `/api/health`) richiedono
|
||||||
header `X-Api-Key: <valore di API_KEY nel .env>`. Per disabilitare l'auth
|
header `X-Api-Key: <valore di API_KEY nel .env>`. Per disabilitare l'auth
|
||||||
in dev, mettere `API_KEY=` (vuoto) — sconsigliato in produzione.
|
in dev, mettere `API_KEY=` (vuoto) — sconsigliato in produzione. Sul G1
|
||||||
|
attualmente `.env` ha `API_KEY=` vuoto, niente auth.
|
||||||
|
|
||||||
### Payload calibrazione
|
### Payload calibrazione
|
||||||
|
|
||||||
@@ -149,39 +197,57 @@ frontend Nuwa, ma su D4xx significano:
|
|||||||
## Configurazione (`.env`)
|
## Configurazione (`.env`)
|
||||||
|
|
||||||
```env
|
```env
|
||||||
|
API_HOST=0.0.0.0
|
||||||
API_PORT=8878
|
API_PORT=8878
|
||||||
API_KEY=<chiave-segreta>
|
API_KEY=
|
||||||
|
|
||||||
|
# NATS (disabled by default — attivabile col profilo `nats` del compose)
|
||||||
|
NATS_URL=
|
||||||
|
NATS_TOKEN=
|
||||||
|
|
||||||
|
# Identità servizio
|
||||||
|
SERVICE_NAME=realsense-g1
|
||||||
|
SERVICE_DOMAIN=vision
|
||||||
|
|
||||||
|
# Stream
|
||||||
CAMERA_WIDTH=640
|
CAMERA_WIDTH=640
|
||||||
CAMERA_HEIGHT=480
|
CAMERA_HEIGHT=480
|
||||||
CAMERA_FPS=30
|
CAMERA_FPS=30
|
||||||
CAMERA_AUTO_OPEN=1
|
CAMERA_AUTO_OPEN=1
|
||||||
|
|
||||||
|
# CORS
|
||||||
CORS_ORIGINS=*
|
CORS_ORIGINS=*
|
||||||
```
|
```
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
- `CAMERA_WIDTH/HEIGHT/FPS` sono **ignorati su USB 2** (forziamo 640x480@15
|
- `CAMERA_WIDTH/HEIGHT/FPS` su G1 vengono **rispettati** (USB 3 → tutto
|
||||||
YUYV perché è l'unica combinazione che la D4xx sostiene). Su USB 3 invece
|
il range supportato dalla D435i è disponibile). Sul branch H1 erano
|
||||||
vengono rispettati.
|
ignorati e forzati a 640x480@15 YUYV.
|
||||||
- `.env` è nel `.gitignore` — non viene committato. Tienine una copia di
|
- `.env` è nel `.gitignore` — non viene committato. Tieni una copia di
|
||||||
backup; `.env.example` è la struttura di riferimento.
|
backup; `.env.example` è la struttura di riferimento.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Modello hardware corrente del robot
|
## Modello hardware corrente del robot G1
|
||||||
|
|
||||||
```
|
```
|
||||||
Jetson Xavier NX
|
Jetson Xavier NX (G1)
|
||||||
├─ Bus 1 (USB 2.0, 480M)
|
├─ Bus 1 (USB 2.0, 480M)
|
||||||
│ ├─ Hub interno → Inspire Hands (cdc_acm /dev/ttyACM0) + ch341
|
│ └─ (varia in base a periferiche collegate — non usato dalla D435i)
|
||||||
│ │ ⚠️ Non staccare questi — sono elettronica del robot
|
└─ Bus 2 (USB 3.0, 10000M)
|
||||||
│ └─ Hub esterno (porta USB-C frontale)
|
└─ Hub interno testa → D435i ← qui, /dev/video0…video5
|
||||||
│ ├─ Tastiera, mouse, ax88179 (Ethernet)
|
|
||||||
│ └─ D435 ← qui
|
|
||||||
└─ Bus 2 (USB 3.0, 10000M) — VUOTO, non esposto esternamente
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- D435 serial: `933322070696`, firmware `05.16.00.01`, `usb_type = 2.1`
|
- D435i serial: `243722073572`, firmware `05.15.01.55`, `usb_type = 3.2`
|
||||||
- Robot IP: `192.168.123.99` (eth0), `10.99.99.101` (ZeroTier)
|
- Bus path: `/sys/devices/platform/3610000.xhci/usb2/2-2/2-2.1`
|
||||||
|
- VID:PID `8086:0b3a` (D435i depth+IR+RGB module)
|
||||||
|
- Robot IP: `192.168.123.99` (eth0), `192.168.1.85` (wlan0 DHCP)
|
||||||
|
|
||||||
|
### Servizio Unitree da fermare
|
||||||
|
|
||||||
|
`video_hub_pc4` apre `/dev/video4` all'avvio (vedi
|
||||||
|
[Prerequisito](#prerequisito-liberare-devvideo4)). Se al boot lasci che
|
||||||
|
parta, il container backend non riesce a inizializzare la pipeline.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -192,25 +258,32 @@ Il codice "live" gira sul robot. Per modifiche:
|
|||||||
### Opzione A — Modifichi sul robot, sync su harry, push da harry
|
### Opzione A — Modifichi sul robot, sync su harry, push da harry
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Sul robot
|
# 1. Sul robot G1
|
||||||
cd ~/Robot_2026/RealSense-D435
|
cd ~/robot/RealSense-D435-H1
|
||||||
# ...modifiche...
|
# ...modifiche...
|
||||||
|
|
||||||
|
# (se hai toccato il frontend)
|
||||||
|
docker run --rm --dns 8.8.8.8 \
|
||||||
|
-v "$(pwd)/src/frontend/react:/app" -w /app \
|
||||||
|
node:22-alpine sh -c 'npm install && npm run build'
|
||||||
|
|
||||||
sg docker -c "docker compose build backend && docker compose up -d --force-recreate"
|
sg docker -c "docker compose build backend && docker compose up -d --force-recreate"
|
||||||
curl http://localhost:8878/api/health # verifica
|
curl http://localhost:8878/api/health # verifica
|
||||||
|
|
||||||
# 2. Rsync su harry (esclude .env, models/, images/, __pycache__)
|
# 2. Rsync su harry (esclude .env, models/, images/, __pycache__, dist/)
|
||||||
rsync -avz --delete \
|
rsync -avz --delete \
|
||||||
--exclude='.env' --exclude='__pycache__' --exclude='*.pyc' \
|
--exclude='.env' --exclude='__pycache__' --exclude='*.pyc' \
|
||||||
--exclude='.pytest_cache' --exclude='.venv' \
|
--exclude='.pytest_cache' --exclude='.venv' \
|
||||||
--exclude='node_modules' --exclude='src/frontend/react/dist' \
|
--exclude='node_modules' --exclude='src/frontend/react/dist' \
|
||||||
--exclude='images/*' --exclude='models/*' \
|
--exclude='images/*' --exclude='models/*' \
|
||||||
--exclude='.claude' --exclude='.omc' \
|
--exclude='.claude' --exclude='.omc' \
|
||||||
~/Robot_2026/RealSense-D435/ \
|
~/robot/RealSense-D435-H1/ \
|
||||||
harry@192.168.123.100:/opt/docker/robotserver/RealSense-D435/
|
harry@192.168.123.100:/opt/docker/robotserver/RealSense-D435-H1/
|
||||||
|
|
||||||
# 3. Push da harry
|
# 3. Push da harry (il G1 non può push diretto a git.humion.it — vedi sotto)
|
||||||
ssh harry@192.168.123.100
|
ssh harry@192.168.123.100
|
||||||
cd /opt/docker/robotserver/RealSense-D435
|
cd /opt/docker/robotserver/RealSense-D435-H1
|
||||||
|
git checkout camera-g1
|
||||||
git add . && git commit -m "..." && git push
|
git add . && git commit -m "..." && git push
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -218,36 +291,58 @@ git add . && git commit -m "..." && git push
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Su harry
|
# 1. Su harry
|
||||||
cd /opt/docker/robotserver/RealSense-D435
|
cd /opt/docker/robotserver/RealSense-D435-H1
|
||||||
|
git checkout camera-g1
|
||||||
git pull # o sviluppa direttamente
|
git pull # o sviluppa direttamente
|
||||||
# ...modifiche...
|
# ...modifiche...
|
||||||
git add . && git commit -m "..." && git push
|
git add . && git commit -m "..." && git push
|
||||||
|
|
||||||
# 2. Sul robot
|
# 2. Sul robot G1
|
||||||
cd ~/Robot_2026/RealSense-D435
|
cd ~/robot/RealSense-D435-H1
|
||||||
# ⚠️ Il robot non può push/pull diretto verso git.humion.it (proxy lo blocca).
|
|
||||||
# Sync via rsync nella direzione opposta:
|
|
||||||
rsync -avz --delete \
|
rsync -avz --delete \
|
||||||
--exclude='.env' --exclude='__pycache__' --exclude='*.pyc' \
|
--exclude='.env' --exclude='__pycache__' --exclude='*.pyc' \
|
||||||
--exclude='images/*' --exclude='models/*' \
|
--exclude='images/*' --exclude='models/*' \
|
||||||
--exclude='.claude' --exclude='.omc' \
|
--exclude='.claude' --exclude='.omc' \
|
||||||
harry@192.168.123.100:/opt/docker/robotserver/RealSense-D435/ \
|
harry@192.168.123.100:/opt/docker/robotserver/RealSense-D435-H1/ \
|
||||||
~/Robot_2026/RealSense-D435/
|
~/robot/RealSense-D435-H1/
|
||||||
|
|
||||||
|
# rifare la build frontend se è cambiata, poi:
|
||||||
sg docker -c "docker compose build backend && docker compose up -d --force-recreate"
|
sg docker -c "docker compose build backend && docker compose up -d --force-recreate"
|
||||||
```
|
```
|
||||||
|
|
||||||
Nota: sul robot l'SSH verso `git.humion.it:222` viene bloccato dal
|
Nota: come sull'H1, anche sul G1 l'SSH verso `git.humion.it:222` passa
|
||||||
tinyproxy locale. Si può risolvere con una regola in `~/.ssh/config` se
|
tipicamente da tinyproxy locale e non funziona "out of the box". Se in
|
||||||
in futuro vorrai pushare diretto dal robot.
|
futuro vuoi pushare diretto dal robot, va aggiunta una regola in
|
||||||
|
`~/.ssh/config`. Per ora si passa da harry.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Risoluzione di problemi noti
|
## Risoluzione di problemi noti
|
||||||
|
|
||||||
|
### `wait_for_frames failed: Frame didn't arrive within 5000`
|
||||||
|
|
||||||
|
Su G1 questo significa quasi sempre **una di due cose**:
|
||||||
|
|
||||||
|
1. `video_hub_pc4` è ancora attivo e tiene `/dev/video4`. Verifica con
|
||||||
|
`lsof /dev/video4` o `fuser /dev/video4`. Stoppalo come sopra.
|
||||||
|
2. Hai (re)buildato il container con una librealsense diversa da
|
||||||
|
v2.50.0. Il D435i fw `05.15.x` non funziona con v2.55+. Controlla
|
||||||
|
`Dockerfile` riga 11 — deve essere `ARG RS_VERSION=v2.50.0`.
|
||||||
|
|
||||||
|
Se invece sei sul branch `main` (H1), su USB 2 questo errore è quasi
|
||||||
|
sempre un mismatch di profilo color (BGR8 vs YUYV) — vedi STATUS.md.
|
||||||
|
|
||||||
|
### `RuntimeError: Failed to resolve request`
|
||||||
|
|
||||||
|
Pipeline non riesce a fare match tra config richiesta e device. Su G1
|
||||||
|
in pratica significa: device non disponibile (occupato da
|
||||||
|
`video_hub_pc4`) o cavo USB scollegato.
|
||||||
|
|
||||||
### `pyrealsense2` ha `AttributeError: module ... has no attribute 'context'`
|
### `pyrealsense2` ha `AttributeError: module ... has no attribute 'context'`
|
||||||
Il bug install di `librealsense@v2.55.1` (il `.so` principale non viene
|
|
||||||
installato dal CMake) è risolto nel `Dockerfile`. Se vuoi ricontrollare:
|
Il bug install di `librealsense` (il `.so` principale non viene installato
|
||||||
|
dal CMake in alcune versioni) è risolto nel `Dockerfile` copiando
|
||||||
|
direttamente i `.so` dal build dir. Per verificare:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sg docker -c "docker compose exec backend python3 -c \
|
sg docker -c "docker compose exec backend python3 -c \
|
||||||
@@ -255,21 +350,22 @@ sg docker -c "docker compose exec backend python3 -c \
|
|||||||
# → True
|
# → True
|
||||||
```
|
```
|
||||||
|
|
||||||
Vedi `Dockerfile` righe ~36-46 e il commento.
|
Vedi `Dockerfile` righe ~40-50 (sezione "Collect both the python
|
||||||
|
bindings and the native runtime .so").
|
||||||
|
|
||||||
### `wait_for_frames failed: Frame didn't arrive within 5000`
|
### `npm install` fallisce con `getaddrinfo ENOTFOUND registry.npmjs.org`
|
||||||
Il device è su USB 2 e il driver è in modalità errata (es. configurato per
|
|
||||||
BGR8). Verifica:
|
Stai cercando di buildare il frontend dentro Docker senza override DNS.
|
||||||
|
Il resolver di default di Docker eredita `127.0.0.53` (systemd-resolved
|
||||||
|
stub), che non funziona dentro i container. Usa `--dns 8.8.8.8`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl http://localhost:8878/api/status | jq .data.usb_type
|
docker run --rm --dns 8.8.8.8 -v "$(pwd)/src/frontend/react:/app" \
|
||||||
# → "2.1" → il driver dovrebbe essere in modalità YUYV
|
-w /app node:22-alpine sh -c 'npm install && npm run build'
|
||||||
```
|
```
|
||||||
|
|
||||||
Se il problema persiste, controlla `docker compose logs backend` per
|
|
||||||
warning con "USB2 profile".
|
|
||||||
|
|
||||||
### Voglio attivare il bottone "Predict" nella GUI
|
### Voglio attivare il bottone "Predict" nella GUI
|
||||||
|
|
||||||
Quel bottone è un avanzo del codice copiato dal Nuwa, ma in produzione
|
Quel bottone è un avanzo del codice copiato dal Nuwa, ma in produzione
|
||||||
non viene usato — l'inferenza YOLO gira sul container `yolo-server` su
|
non viene usato — l'inferenza YOLO gira sul container `yolo-server` su
|
||||||
harry (con il modello custom `best.onnx` per il pestello). Vedi
|
harry (con il modello custom `best.onnx` per il pestello). Vedi
|
||||||
@@ -282,6 +378,7 @@ ma utile per test):
|
|||||||
3. Settare `YOLO_*` nel `.env`
|
3. Settare `YOLO_*` nel `.env`
|
||||||
|
|
||||||
### Posso pushare/pullare git direttamente dal robot?
|
### Posso pushare/pullare git direttamente dal robot?
|
||||||
|
|
||||||
Al momento no — il tinyproxy del robot blocca l'SSH verso `git.humion.it:222`.
|
Al momento no — il tinyproxy del robot blocca l'SSH verso `git.humion.it:222`.
|
||||||
Workaround: `rsync` da/verso harry e push da lì. Vedi
|
Workaround: `rsync` da/verso harry e push da lì. Vedi
|
||||||
[Workflow di sviluppo](#workflow-di-sviluppo).
|
[Workflow di sviluppo](#workflow-di-sviluppo).
|
||||||
@@ -291,13 +388,13 @@ Workaround: `rsync` da/verso harry e push da lì. Vedi
|
|||||||
## Struttura del repo
|
## Struttura del repo
|
||||||
|
|
||||||
```
|
```
|
||||||
RealSense-D435/
|
RealSense-D435-H1/
|
||||||
├── Dockerfile # multi-stage: librealsense + frontend + runtime
|
├── Dockerfile # multi-stage: librealsense v2.50.0 + runtime
|
||||||
├── docker-compose.yml # backend + nats opzionale + frontend-dev
|
├── docker-compose.yml # backend + nats opzionale + frontend-dev
|
||||||
├── .env / .env.example # config (NON committare .env)
|
├── .env / .env.example # config (NON committare .env)
|
||||||
├── pyproject.toml # deps Python (per uv/pip)
|
├── pyproject.toml # deps Python (per uv/pip)
|
||||||
├── README.md # questo file
|
├── README.md # questo file (G1)
|
||||||
├── STATUS.md # snapshot ultima sessione di lavoro
|
├── STATUS.md # snapshot ultima sessione di lavoro (H1)
|
||||||
├── scripts/
|
├── scripts/
|
||||||
│ └── entrypoint.sh
|
│ └── entrypoint.sh
|
||||||
├── src/backend/
|
├── src/backend/
|
||||||
@@ -311,7 +408,8 @@ RealSense-D435/
|
|||||||
│ ├── camera.py # ⭐ driver RealSense (detection USB 2/3, YUYV, etc.)
|
│ ├── camera.py # ⭐ driver RealSense (detection USB 2/3, YUYV, etc.)
|
||||||
│ ├── detector.py # wrapper ONNX YOLO (non usato in produzione)
|
│ ├── detector.py # wrapper ONNX YOLO (non usato in produzione)
|
||||||
│ └── image_saver.py
|
│ └── image_saver.py
|
||||||
├── src/frontend/react/ # GUI a /gui (built via stage 2 del Dockerfile)
|
├── src/frontend/react/ # GUI a /gui
|
||||||
|
│ └── dist/ # ⚠️ buildare a mano sull'host (vedi Quick start)
|
||||||
├── tests/ # pytest, da rilanciare quando si tocca services/
|
├── tests/ # pytest, da rilanciare quando si tocca services/
|
||||||
├── models/ # vuoto — modello sta su yolo-server, non qui
|
├── models/ # vuoto — modello sta su yolo-server, non qui
|
||||||
└── images/ # output snapshot/recording, gitignored
|
└── images/ # output snapshot/recording, gitignored
|
||||||
@@ -319,9 +417,21 @@ RealSense-D435/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Branches
|
||||||
|
|
||||||
|
- `main` — deploy storico H1 (D435 su USB 2, YUYV, ~4 fps)
|
||||||
|
- `camera-g1` — **questo branch**, deploy G1 (D435i su USB 3.2, BGR8, 30 fps)
|
||||||
|
|
||||||
|
Il driver Python è lo stesso su entrambi — distingue il path runtime
|
||||||
|
leggendo `usb_type_descriptor` del device. Le differenze tra branch sono
|
||||||
|
nel `Dockerfile` (versione SDK, stage frontend) e nel `.env` (identità
|
||||||
|
servizio).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Riferimenti
|
## Riferimenti
|
||||||
|
|
||||||
- [librealsense](https://github.com/IntelRealSense/librealsense) — buildato da source perché manca wheel ARM64 (`librealsense@v2.55.1`)
|
- [librealsense](https://github.com/IntelRealSense/librealsense) — buildato da source perché manca wheel ARM64. Su G1 pinnato a `v2.50.0` per compatibilità col firmware `05.15.x` del D435i.
|
||||||
- [Nuwa-HP60C](https://git.humion.it/Labotics-gianniact/) — container originale di cui questo è il drop-in equivalent
|
- [Nuwa-HP60C](https://git.humion.it/Labotics-gianniact/) — container originale di cui questo è il drop-in equivalent
|
||||||
- [yolo-server](https://git.humion.it/Labotics-gianniact/) — microservizio YOLO usato da pestello-pose-detector
|
- [yolo-server](https://git.humion.it/Labotics-gianniact/) — microservizio YOLO usato da pestello-pose-detector
|
||||||
- [pestello-pose-detector](https://git.humion.it/Labotics-gianniact/pestello-pose-detector) — consumer reale di questo stream
|
- [pestello-pose-detector](https://git.humion.it/Labotics-gianniact/pestello-pose-detector) — consumer reale di questo stream
|
||||||
Reference in new issue
Block a user