diff --git a/README.md b/README.md index 72f0e93..b7df381 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,10 @@ 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 server + point cloud Nuwa. -3. **Pianificazione presa**: asse dell'oggetto (PCA) + posa polso per il robot attivo. +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 @@ -14,6 +16,7 @@ Microservizio Python (FastAPI) che orchestra: | 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) | @@ -30,14 +33,38 @@ docker compose up -d presa-mano ## GUI -Tre tab: +Tab principali: - **Calibrazione**: muovi il polso in varie pose, *Acquisisci sample*, poi *Risolvi*. Salva `data/calibration_.yaml`. -- **Grasp**: rileva oggetto, visualizza bbox + asse, esegui (toggle dry-run). +- **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/`: