Files
Presa-Mano/README.md
T
Adriano Dal PastroandClaude Opus 4.7 8f7b52cc20 docs: update README for SAM21 + work-plane features
- Add SAM21 (NuwaSeg :8002) to the upstream services table.
- New "Calibrazione Piano" tab documented: 2-click ROI, fit preview, 3D
  camera-POV viewer with red = excluded points, offset_mm semantics
  (positive = permissive buffer below, negative = aggressive cut above for
  depth noise), save persists to data/work_plane.json.
- "TrovaUtensile" tab renamed to "Cerca modello".
- New section "Pipeline cloud-from-bbox" describing the SAM21-first flow
  with bbox fallback and the work-plane filter, plus the response meta
  fields (source, plane_applied, n_points_before_plane,
  sam21_fallback_reason).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:54:30 +02:00

109 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# presa-mano
Microservizio Python (FastAPI) che orchestra:
1. **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**.
2. **Riconoscimento oggetto** via YOLO (bbox) + **segmentazione 3D** via SAM2.1 →
nuvola di punti dell'oggetto.
3. **Calibrazione piano di lavoro** + filtro "sotto piano" applicato a ogni cloud.
4. **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 |
| SAM21 (NuwaSeg) | http://localhost:8002 | Segmentazione promptable: bbox → cloud 3D filtrata |
| 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
```bash
docker compose up -d presa-mano
# Apri http://localhost:8890
```
## GUI
Tab principali:
- **Calibrazione**: muovi il polso in varie pose, *Acquisisci sample*, poi *Risolvi*.
Salva `data/calibration_<side>.yaml`.
- **Calibrazione Piano**: clicca due angoli sull'RGB per definire la ROI sul tavolo
→ *Calcola piano* fa il fit SVD sui punti depth, mostra in 3D (vista camera) il
piano e l'intera scena con punti esclusi in rosso / tenuti in ciano. Il parametro
*offset (mm)* regola la soglia del filtro "punti sotto piano" (positivo = buffer
permissivo, negativo = esclude anche un buffer sopra il piano per togliere rumore
depth). *Salva piano* persiste in `data/work_plane.json`.
- **Cerca modello**: rileva oggetto via YOLO, segmenta via SAM21 (con fallback bbox
se SAM21 è down), visualizza bbox + asse, esegui (toggle dry-run).
- **Movimento EE**: lettura pose correnti, invio pose assolute/relative, apri/chiudi mano,
emergency stop.
## Pipeline cloud-from-bbox
Dopo che YOLO ha trovato un bbox, gli endpoint `/api/grasp/{plan,execute}`,
`/api/perception/{scan,object_points}` estraggono la nuvola di punti
dell'oggetto con questa pipeline:
1. **SAM21** segmenta il bbox usando RGB + depth allineata IR→RGB
(`perception/depth_align.py`) → cloud nell'OpenCV camera frame, in metri.
Su fallimento (transport / `SEGMENTATION_EMPTY` / `<10` punti) → fallback
trasparente al path bbox legacy (Nuwa ROI pointcloud).
2. **Filtro piano**: se `data/work_plane.json` esiste, scarta i punti con
`signed_distance < -offset_mm/1000` (vedi tab Calibrazione Piano).
3. Le response includono `source ∈ {"sam21","bbox_roi"}`, `plane_applied`,
`n_points_before_plane` e — su fallback SAM21 — `sam21_fallback_reason`.
Disabilitabile via `grasp.use_sam21: false` in `config.yaml`.
## 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_s` e `traj_step_mm` non 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/absolute` su 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_neutral` diretto.
Vedi `CLAUDE.md` per i dettagli di architettura e per le frame conventions
(Nuwa native vs OpenCV vs Nuwa ROI).