cc19f73b9672b3c3790bbf9f600d721d129a2f93
Nuwa /api/intrinsics omits width/height from the rgb and ir blocks, so
SAM21 rejected the payload with KeyError('width') and we silently fell
back to bbox on every request. Derive the dimensions from the decoded
BGR + IR depth shapes and augment intr_full before building
CameraRegistration and calling SAM21. Verified end-to-end: source=sam21,
~2200 segmented points on Mortaio at 128 ms GPU inference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
presa-mano
Microservizio Python (FastAPI) che orchestra:
- Calibrazione hand-eye (eye-to-hand) tra la Nuwa depth camera (fissa) e la base del robot, usando un ArUco sul polso. Supporta G1 e H1.
- Riconoscimento oggetto via YOLO server + point cloud Nuwa.
- Pianificazione presa: asse dell'oggetto (PCA) + posa polso per il robot attivo.
Microservizi usati
| Servizio | URL (default) | Scopo |
|---|---|---|
| Nuwa-HP60C | http://localhost:8877 | RGB, depth, point cloud, intrinsics |
| Marker-finder | http://localhost:8082 | Detection 2D ArUco (corners + pose) |
| YOLO Server | http://localhost:8879 | Bbox oggetto da prendere |
| G1 API Server | http://localhost:8765 | Controllo polso/mano G1 (dry-run se down) |
| H1 API Server | http://localhost:8767 | Controllo polso/mano H1 (network host, 4 DoF) |
Il servizio presa-mano espone GUI + API su http://localhost:8890. Il robot attivo
è scelto da config.yaml > robot.active (g1 | h1); l'orchestrator fa routing
automatico verso il bridge corrispondente.
Quick start
docker compose up -d presa-mano
# Apri http://localhost:8890
GUI
Tre tab:
- Calibrazione: muovi il polso in varie pose, Acquisisci sample, poi Risolvi.
Salva
data/calibration_<side>.yaml. - Grasp: rileva oggetto, visualizza bbox + asse, esegui (toggle dry-run).
- Movimento EE: lettura pose correnti, invio pose assolute/relative, apri/chiudi mano, emergency stop.
Calibrazione automatica via script
In scripts/:
| Script | Cosa fa |
|---|---|
explore_and_calibrate.py |
Probe assiale dell'envelope di visibilità tag → workspace JSON + PNG → N sample random nel workspace → solve. |
extend_calibration.py |
Estende la calibrazione esistente fino a n_used >= TARGET_GOOD (default 30). Riusa il workspace, NON cancella i sample. |
repeatability.py |
N detection consecutive a polso fermo per misurare σ del marker-finder (diagnostica bias vs noise). |
Tutti producono file in data/: workspace_<side>.json, workspace_<side>.png,
samples_<side>.json, calibration_<side>.yaml.
Configurazione
config.yaml contiene i default; l'API espone GET/PUT /api/config per override
runtime (es. cambiare ID/size ArUco, robot attivo, side di default).
Default rilevanti:
calibration.method: DANIILIDIS— sui dati H1+Nuwa con bias intrinsics di marker-finder, DANIILIDIS dà ~4× meno residuo di TSAI (default OpenCV).robot.active: h1/robot.wrist_side: right.
Caveat noti
- Wrist passthrough: i campi
speed_mm_setraj_step_mmnon sono nello schema di/api/wrist/{absolute,relative}. Per move "precisi" (closed-loop, slow, waypoint fitti) bisogna chiamare direttamente il bridge robot, es.POST http://localhost:8767/wrist/absolutesu H1. - Marker-finder intrinsics: il sibling service usa intrinsics D435i bakeate che
non corrispondono alla Nuwa → bias sistematico in
T_cam_marker. È il floor del residuo hand-eye (~14 mm su H1+Nuwa). Per scendere serve ricalibrare quel servizio. - H1 4 DoF: nessun polso articolato. Si comanda solo posizione; l'orientamento del polso è output dell'IK e drifta con la posa (fino a ~30° su Y ai bordi dell'envelope). I solver hand-eye risentono della scarsa diversità rotazionale.
/api/arms/go_neutral: il proxy nell'orchestrator non è montato (404). Per riportare le braccia H1 a home:POST http://localhost:8767/arms/go_neutraldiretto.
Vedi CLAUDE.md per i dettagli di architettura e per le frame conventions
(Nuwa native vs OpenCV vs Nuwa ROI).
Languages
Python
62.6%
JavaScript
27%
HTML
5.1%
CSS
4.8%
Shell
0.3%
Other
0.2%