Il commit della Task 1 aveva incluso per errore (via git add -u) drift runtime
di config.yaml (cloud_params size/flip) persistito dall'app live. Lo rimuovo dal
branch: config.yaml resta uguale a main. I valori live restano come modifica
non committata nel working tree.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Design per: detection tag su tutte le camere attive (Nuwa rosso + D435i),
rinomina "Tag camera frontale" -> "Tags", calibrazione persistente
Nuwa->frontale via tag condiviso (Umeyama similarity), flag+pulsante
"Allinea" nella sezione Cloud cross-camera.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
L'overlay tag frontale (D435i) ri-eseguiva la detection ArUco ad ogni
tick di pollState() finche' il flag era attivo. Ora gira solo:
- al toggle on del checkbox
- a fine acquireClouds() (pulsante Acquisisci) se il flag e' attivo
Rimosso il piggyback in pollState() e lo stato front_tags.in_flight
ormai inutilizzato.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Sidebar a 3 tab verticali (POSE / CAMERAS / MISC) per ridurre lo scroll
- Tag locator: POST /api/pose_3d/tag_offset/{save,} salva crocetta nel
viewport con snapshot giunti, current.json + archive rotation
- Front-camera tag overlay (MISC):
- GET /api/pose_3d/front_tags scansiona ArUco sul D435i e per ogni tag
misura i 4 corner 3D via depth sensor (indipendente da solvePnP);
outlier rejection ±20% dalla mediana per ignorare corner che catturano
background sul bordo del marker
- Rendering quad cyan + label compatta (id, edge_mm, distanza camera)
agganciato al d435_link, segue la camera anche in modalita' hand-eye
- Trigger via pollState() quando il flag e' on, niente timer separato
- Cloud cross-camera: memorizza step/max_depth/sizes/scale_xy/flip/handeye
in pose_3d.cloud_params al click di Acquisisci, ripopola UI da config
al primo poll (state.cloud_params_populated guard)
- D435i front cloud: applica nuwa_to_cv_frame (il servizio ritorna native,
non OpenCV come si pensava)
- Cache-bust per pose_3d.js e pose_3d.css
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Allineati alla rimozione del modulo agent e alle nuove funzionalità:
- Tab Braccio DX e Pose 3D documentate in GUI
- Servizi front_camera (D435i) e G1 /diagnostics nella tabella upstream
- Endpoint right_arm/* e pose_3d/* nella lista API
- Convenzioni Pose 3D (graceful offline, clouds, joints mirroring) in CLAUDE.md
- Router list e _deps aggiornati (front_camera(), 12 router modules)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rimosso il modulo agent (LLM chat) e la relativa config OpenRouter.
La tab Pose 3D ora: espone i giunti reali via G1 /diagnostics per
specchiare l'URDF senza IK; acquisisce point cloud Nuwa+D435i
(/api/pose_3d/clouds); mostra il modello 3D della camera sul polso;
degrada gracefully a 200 (wrist=null) quando il robot è offline.
Il vecchio renderer canvas-2D (app.js view3d + diagnostic3d.js) è
stato consolidato nel viewport Three.js di pose_3d.js.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sostituisce torso/head/hips/gambe/spalle primitive in tab Pose 3D con il
modello URDF G1 (g1_body29_hand14), caricato via urdf-loader 0.12.6.
Vendor:
- web/vendor/g1/g1.urdf + 64 mesh STL (~52 MB, copiati da
G1_API_Server/assets/g1/)
- web/vendor/three/addons/loaders/URDFLoader.js (npm urdf-loader@0.12.6),
import path adattato a 'three/addons/loaders/STLLoader.js' (importmap
del sito) e ColladaLoader stubbato (G1 URDF è solo STL)
- web/vendor/three/addons/loaders/URDFClasses.js (companion del loader)
pose_3d.js:
- Aggiunge loadG1Urdf(scene) async che configura loader.loadMeshCb per
servire le STL dal mount /static/vendor/g1/meshes/
- Best-effort: in caso di errore di parsing/fetch il body non viene
aggiunto ma la tab continua a funzionare (polsi, UCS, gizmo)
Plan dettagliato per la tab "Pose 3D" (writing-plans skill),
basato sullo spec del 2026-05-21. 15 task suddivisi in backend
(routes + tests TDD) e frontend (Three.js viewport + gizmo +
mode toggle Editor/Jog).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lavoro accumulato nella sessione 2026-05-21 prima del brainstorming
della tab Pose 3D:
- compute_delta_wrist generalizzato con cam_to_wrist_perm: la mappa
cam->polso non e' solo sign-flip ma una permutazione (default
identita' per backward compat). DeltaOversize ora espone X/Y/Z
nella stringa d'errore. Test aggiornati.
- G1Client.wrist_absolute / wrist_relative: precise=True di default
(era False). Stessa cosa per wrist_routes.AbsoluteReq Pydantic
e per agent.tools move_wrist_*. Movimenti reali ora chiedono
controllo accurato salvo override esplicito.
- Tab Braccio DX:
- /verify_tag endpoint: snapshot wrist FK + tag id=1 dalla front
camera. Per verifica relativa moveto vs marker (no calibrazione).
- GUI: pannello "Verifica tag id=1" + campi camera_offset_wrist_mm.
- markUserTouchedOnInput esteso a raOff/raSgn/raCamOff.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds CRUD for named wrist poses persisted in config.yaml under
pose_3d.named_poses. PUT validates the name against ^[A-Za-z0-9_-]{1,40}$
and normalizes the quaternion. DELETE returns 404 if the pose is missing.
Bypasses update_config's deep-merge for wholesale named_poses replacement
(deep-merge cannot remove nested keys) via a small helper that mutates
the in-memory singleton then persists with an empty patch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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) <noreply@anthropic.com>
Tuning da prima sessione live: move_offset_camera_mm.x=100 (lateral
verso il pestello), camera_offset_wrist_mm.z=100 (mounting verticale
della Nuwa sopra il TCP destro), cluster_depth_window_m=0.20.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tre miglioramenti al move-toward dopo il primo uso live:
1. checkbox "force" accanto a "Muovi": bypassa max_step_m quando
l'utente sa che il delta richiesto e' grande ma corretto (es. primo
avvicinamento all'oggetto).
2. camera_offset_wrist_mm: il modello assumeva camera e TCP coincidenti
(sole sign flips). La camera Nuwa e' invece montata con traslazione
costante rispetto al polso. La formula diventa:
delta_wrist = sign * (centroid_cam - offset_cam) + t_wrist_cam
Esposto in config (default 0,0,0), GUI (3 input "Camera rispetto a
polso (mm)") e in /state. Il termine compensa il fatto che muovere
il polso porta la camera, non il TCP, sul punto di presa.
3. filter_nearest_cluster: il centroide era media di tutti i punti
SAM21 della mask. In presenza di sfondo lontano visibile attraverso
buchi della depth del primo piano la media veniva trascinata a
metri di distanza. Ora si tiene il cluster piu' vicino:
z_near = p5(Z)
keep = punti con Z <= z_near + cluster_depth_window_m
Default window 0.20 m, configurabile. La risposta di /detect/wrist
espone n_sam21_points, n_centroid_points e z_near/z_cutoff per
diagnosi.
Aggiornata anche la persistenza: /offset accetta camera_offset_wrist_mm.
GUI: i campi Offset/Sign/CamOff rispettano "user touched" (refresh non
li cancella mentre l'utente digita).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>