From 19fba4287634f3a6184b450439bede7a60b7ab20 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Thu, 21 May 2026 15:14:46 +0200 Subject: [PATCH] docs: spec design tab "Pose 3D" (editor visuale + jog dei polsi) Specifica per nuova tab GUI con viewport Three.js, gizmo translate/rotate sui polsi DX e SX, modalita' Editor (preview) / Jog (auto-move al mouseup), safety guard sui movimenti grandi, checkbox precise toggle, save/load named poses in config.yaml. Brainstorming nella sessione 2026-05-21. Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 3 + .../specs/2026-05-21-pose-3d-tab-design.md | 298 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-21-pose-3d-tab-design.md diff --git a/.gitignore b/.gitignore index cfbc443..f52099f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ # Calibration data (per-installation, ricostruibile) data/ +# Brainstorming session files (visual companion) +.superpowers/ + # Python __pycache__/ *.py[cod] diff --git a/docs/superpowers/specs/2026-05-21-pose-3d-tab-design.md b/docs/superpowers/specs/2026-05-21-pose-3d-tab-design.md new file mode 100644 index 0000000..6adb966 --- /dev/null +++ b/docs/superpowers/specs/2026-05-21-pose-3d-tab-design.md @@ -0,0 +1,298 @@ +# Design — Tab "Pose 3D" (editor visuale + jog dei polsi) + +**Data:** 2026-05-21 +**Stato:** approvato per implementazione + +## Obiettivo + +Aggiungere una tab "3D" alla GUI di `presa-mano` che permetta di: + +1. Visualizzare la posa corrente dei polsi destro e sinistro del robot attivo in un viewport 3D. +2. Trascinare in 3D (gizmo translate+rotate) un polso alla volta per definire una nuova posa. +3. Validare la posa via il bridge G1 e (se in modalità Jog) muovere il robot reale. +4. Salvare/caricare pose con nome per riuso. + +Sostituisce il workflow attuale che richiede di editare manualmente campi numerici X/Y/Z + RPY nella tab Braccio DX, e fornisce una rappresentazione visuale per le 3 UCS di riferimento (base, polso DX, polso SX) finora invisibili. + +## Modalità di lavoro + +Toggle in header tab, due valori mutuamente esclusivi: + +- **Editor**: il drag aggiorna SOLO la posa ghost locale (preview). Il bottone "Applica" abilita un commit *simulato* (il ghost diventa "current" lato client, robot non si muove). Utile per pianificare/visualizzare senza rischio. +- **Jog**: il drag aggiorna il ghost; al rilascio del mouse (`mouseup`) parte automaticamente un comando reale `wrist_absolute` con `dry_run=false`. Nessun bottone Apply. 1 drag = 1 move. + +Safety guard in modalità Jog: prima dell'auto-apply, calcolo `||ghost_target − current_wrist||`. Se supera `pose_3d.live_max_step_m` (default 0.15 m), mostro un dialog di conferma "Movimento richiesto X mm. Procedi?" prima di inviare al robot. + +**Flag `precise`**: tutti i comandi reali (Editor Apply non incluso — è sim locale) hanno per default `precise=true` (controllo accurato del bridge). Il pannello espone un checkbox **"Precise"** abilitato di default; l'utente può disattivarlo se sa che il movimento è approssimativo / fuori workspace nominale (evita `arms: error_timeout` su movimenti grandi). Il toggle è di sessione, non persistito. + +## Architettura + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ BROWSER │ +│ web/pose_3d.html (markup) + web/pose_3d.js (Three.js + UI) │ +│ web/pose_3d.css │ +│ - Scene Three.js: torso, 2 link, 2 polso-sphere, 3 UCS │ +│ - TransformControls: gizmo translate+rotate sul polso attivo │ +│ - Sidebar: side selector, mode toggle, gizmo toggle, readout, │ +│ bottoni Apply (Editor)/Sblocca, save/load pose │ +│ - Polling GET /api/pose_3d/state ogni 1s per sync con robot │ +└──────────────────────────┬──────────────────────────────────────┘ + │ HTTP /api/pose_3d/* + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ ORCHESTRATOR (FastAPI, presa-mano) │ +│ src/presa_mano/api/pose_3d_routes.py │ +│ - GET /state -> {left_wrist, right_wrist, poses}│ +│ - POST /apply -> wrist_absolute(side, pos, quat) │ +│ - GET /poses -> dict {nome: NamedPose} │ +│ - PUT /poses/{name} -> salva/aggiorna posa │ +│ - DELETE /poses/{name} -> rimuove │ +│ - POST /poses/{name}/go -> esegue posa salvata │ +│ - POST /unlock -> proxy POST :8765/unlock │ +│ config.yaml > pose_3d.{named_poses, live_max_step_m} │ +└──────────────────────────┬──────────────────────────────────────┘ + │ chiama _deps.g1() (robot attivo h1|g1) + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ G1_API_Server (port 8765, esistente, NON modificato) │ +│ - GET /wrist -> {left_wrist, right_wrist} │ +│ - POST /wrist/absolute -> IK + motion │ +│ - POST /unlock -> sblocco arms (recovery error_timeout)│ +└─────────────────────────────────────────────────────────────────┘ +``` + +Dipendenze frontend (CDN, no build step): + +- `three@0.160` (~600 KB minified) +- `three/examples/jsm/controls/OrbitControls` +- `three/examples/jsm/controls/TransformControls` + +Caricate via `