Commit Graph
22 Commits
Author SHA1 Message Date
Adriano Dal PastroandClaude Opus 4.7 6c2452fe20 refactor(pose_3d): rimuovi agent/chat, aggiungi cloud+diagnostics+camera polso
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>
2026-05-27 17:34:42 +02:00
Adriano Dal Pastro d5bb9cebd3 feat(pose_3d): workspace check client-side (ghost verde/rosso) + SHOULDER da URDF 2026-05-21 17:21:09 +02:00
Adriano Dal Pastro 18dce0d951 feat(pose_3d): bottone Sincronizza con robot (refetch state + reset target) 2026-05-21 17:08:09 +02:00
Adriano Dal Pastro b852976a4a feat(pose_3d): readout XYZ/RPY editabili (input number, drive il ghost) 2026-05-21 17:01:03 +02:00
Adriano Dal Pastro c4124a2983 feat(pose_3d): markup HTML + CSS della tab 2026-05-21 15:50:49 +02:00
Adriano Dal PastroandClaude Opus 4.7 57954b5c8d feat(right_arm): perm assi cam->polso, precise=true default, verify_tag UI
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>
2026-05-21 15:44:48 +02:00
Adriano Dal PastroandClaude Opus 4.7 1fa7d12ad7 feat(right_arm): force, camera↔polso offset, cluster filter sul centroide
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>
2026-05-21 12:18:24 +02:00
Adriano Dal PastroandClaude Opus 4.7 2f6444c0a5 fix(right_arm): bbox dict, image_size da /api/status, tab non seleziona robot
Tre problemi della tab Braccio DX dopo il primo rodaggio:

1. /detect/front e /detect/wrist ritornavano bbox raw dal YOLO server,
   che lo manda come lista [x1,y1,x2,y2]; la GUI legge bbox.x1 e mostra
   NaN. Ora il router normalizza il payload via perception/detector
   ._normalize, allineandosi al resto del codice. Aggiunta regressione
   con payload reale del server.

2. La tab gateava su robot.active==g1 && wrist_side==right con banner
   "Attiva G1 right" e POST /activate. Confonde: la selezione del
   robot e' globale e non si flippa per-feature. Rimossi banner,
   bottone, endpoint /activate e _guard_g1_right(); gli endpoint
   operano sul polso destro del robot attivo qualunque esso sia.

3. image_size: [0,0] perche' Nuwa /api/intrinsics non include
   width/height; vivono in /api/status > data.resolution. Aggiunto
   NuwaClient.image_size() e usato in detect_front. Aggiornato
   docstring di intrinsics() per coerenza con il payload reale.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 11:43:05 +02:00
Adriano Dal Pastro 2f8c7006ba feat(gui): markup + CSS tab Braccio DX 2026-05-20 12:38:01 +02:00
Adriano Dal PastroandClaude Opus 4.7 b0a2d7141d feat(find_model gui): toggle to overlay work plane as a violet polygon
The find_model response now returns plane_polygon_px (4 corners of a
30 cm square anchored at the work plane centroid, projected to RGB
pixels via the same K used for the SAM21 cloud). The GUI gains a
'Piano (viola)' checkbox that draws the polygon as a translucent
violet quad with an outline, helping the operator see whether the
plane sits where expected relative to the object.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:53:16 +02:00
Adriano Dal PastroandClaude Opus 4.7 2fe7a7a7fa feat(find_model gui): toggle to overlay full SAM21 cluster (yellow)
Adds a 4th checkbox 'Punti SAM21 (gialli)' that draws the full SAM21
segmentation (input to both the plane partition and Open3DModel) on
the RGB result canvas. The backend now returns sam21_points_px and
n_sam21 alongside the existing accepted/excluded splits.

Useful as a sanity check: visualise what was actually segmented vs
what the plane filter kept/rejected vs where the STL got placed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:40:24 +02:00
Adriano Dal PastroandClaude Opus 4.7 767d91acdc feat(work_plane gui): show fit inliers as blue scatter in 3D, drop wrong plane mesh
The 0.4x0.4 PlaneGeometry square was a fixed-size proxy that did not
reflect the actual ROI extent — visually misleading. Replace it with
an explicit blue point cloud of the inliers fed to fit_plane_svd, so
the user can see *exactly* which depth pixels the plane was fit on.

- Backend: fit response now returns fit_points_camera (CV frame) instead
  of the (parallax-shifted) RGB pixel projection.
- Frontend: drop the purple plane mesh; new three.setFitInliers paints
  the inliers in blue. The RGB overlay no longer carries blue dots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:20:03 +02:00
Adriano Dal PastroandClaude Opus 4.7 76e0739620 fix(work_plane): allow negative offset_mm + readable validation errors
- Drop the ge=0 constraint on FitReq.offset_mm (negative values are a
  documented usage: aggressive noise cull above the plane).
- HTML input min lowered to -200 to match.
- Render FastAPI 422 validation arrays as a human-readable string in the
  status chip (was showing "[object Object]").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:03:36 +02:00
Adriano Dal PastroandClaude Opus 4.7 af8d4d6fc4 feat(web): rebuild Cerca modello tab — model picker + result canvas
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:10:35 +02:00
Adriano Dal PastroandClaude Opus 4.7 56f8888217 fix(gui): work_plane 3D view = camera POV + red = excluded points
- Camera at origin (CV frame) looking at +Z with screen-up = CV −Y, so
  the rendered scene matches the camera's vantage point. OrbitControls
  retargets to the plane centroid on fit so rotation feels natural.
- Simplify scatter coloring to two tones: red for filter-excluded points
  (signed_distance < −offset_mm/1000), cyan-white for everything kept.
  Matches the backend filter contract exactly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:41:03 +02:00
Adriano Dal PastroandClaude Opus 4.7 652fa4b912 fix(gui): two-click ROI on Calibrazione Piano (was shift+drag)
User asked for "2 punti" — replace the drag-to-rectangle interaction with
two discrete clicks: first click places corner A (cross marker), second
click defines the rectangle, third click starts a new selection.
Rectangles smaller than 10×10 px are rejected. Status chip guides the
flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:38:43 +02:00
Adriano Dal PastroandClaude Opus 4.7 57bd252375 fix(gui+api): cleanup before merge
- Rename "TrovaUtensile" tab → "Cerca modello".
- Remove the "Precisione (ultime 5 detection)" stats panel and the
  "Dettagli" JSON dump from the grasp tab; keep hidden stubs so the
  existing app.js continuous-loop code doesn't null-deref.
- Add work_plane_routes to api/__init__.py imports + __all__ (consistency
  with the other routers).
- Trim the misleading "drag = pan · wheel = zoom · doppio click = reset"
  hint from the Calibrazione Piano RGB label — pan/zoom isn't wired.
- Disable wpClearBtn initially so it doesn't flash clickable before
  fetchSaved() resolves.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:23:29 +02:00
Adriano Dal PastroandClaude Opus 4.7 ae84739c64 feat(gui): Calibrazione Piano tab (ROI + fit preview + 3D viewer)
New tab replaces the removed Servo Visuale. Shift+drag on the RGB image
defines a rectangle, 'Calcola piano' calls POST /api/work_plane/fit and
renders the plane + a colored scatter in 3D. Adjusting the offset slider
re-colors the scatter client-side. 'Salva piano' persists; 'Rimuovi piano
salvato' clears.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:08:32 +02:00
Adriano Dal PastroandClaude Opus 4.7 eb53f30e23 refactor: remove visual-servo feature
The marker-relative servo (endpoints /api/grasp/visual_servo/{plan,step,
plane/*}, helpers in grasp_routes.py, the bulk of grasp/visual_servo.py,
web/servo.js, and the Servo Visuale GUI tab) is gone. Plane fitting now
lives in /api/work_plane/* and perception/work_plane.py; Task 5 wires the
new Calibrazione Piano tab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:04:00 +02:00
Adriano Dal PastroandClaude Opus 4.7 0c211630cc refactor: rimuove feature Auto-Calibrazione (tab + endpoint + job runner)
Elimina il flusso di acquisizione griglia automatica: tab GUI, modulo
autocal3d.js, AutoRunner/auto_job, e gli endpoint /auto/* + /auto_grid.
La calibrazione resta operabile via sample manuali + /solve.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 11:03:23 +02:00
Adriano Dal PastroandClaude Opus 4.7 f6197488f9 refactor: cleanup GUI + AI movement controls + depth-correction polish
GUI:
- Rimossa tab "Calibrazione" (sostituita dalla calibrazione via AI con saved
  task `calibrazione_dx`/`calibrazione_sx`, oppure dalla tab "Auto-
  Calibrazione" per il flusso a griglia automatica). Backend
  calibration_routes invariato — tool AI continuano a usarlo.

AI tools:
- Esposto `precise` su `move_wrist_absolute` e `move_wrist_relative`
  (forwarded al campo omonimo del bridge robot, controlla la modalità di
  controllo: false=veloce/tolleranza ampia, true=lento/posa accurata).
- Aggiunto `arms_go_neutral` come tool dedicato (POST /arms/go_neutral del
  bridge): usato dall'AI per "torna a casa / posizione di riposo". Niente
  side, agisce su entrambe le braccia.
- Fix `device_status`: ora wrappa la risposta con `_ok(...)` così il
  dispatcher la classifica correttamente.

Prompt:
- System prompt aggiornato: l'AI ora passa SEMPRE `precise=true` di default
  sui movimenti, escluso quando l'utente chiede esplicitamente velocità.
  Sezione dedicata su come tornare a riposo (arms_go_neutral).
- Documentato che `measured_side_mm` (ritornato da get_marker_3d) viene
  distorto dalla correzione affine sul depth — non usarlo per validare la
  size_mm dichiarata.

Saved tasks:
- `calibrazione_dx` e `calibrazione_sx` ora partono e finiscono con
  `arms_go_neutral`, cancellano i sample preesistenti per quel lato, e
  acquisiscono ≥10 sample con `precise=true` su una griglia ±80mm + ±15° di
  rotazione attorno alla posa home.

Config:
- Marker corrente: id=10, size=40mm (cambiato il tag fisico sul polso).
- Addendum prompt allentato: niente più "max 3 righe", ora chiede di
  riportare il risultato di OGNI tool chiamato.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:05:52 +02:00
Adriano Dal PastroandClaude Opus 4.7 ac573505b7 feat: initial commit — orchestratore presa-mano con AI assistant + dual-robot
Pipeline completa per calibrazione hand-eye e grasp planning su robot
Unitree G1/H1 con camera depth Nuwa-HP60C. Esposta come FastAPI + GUI vanilla
JS, con assistente AI (OpenRouter + tool calling curato) per pilotare il
sistema in linguaggio naturale.

Architettura:
- FastAPI orchestrator (porta da .env, default 8890) che coordina 4
  microservizi upstream: Nuwa-HP60C, marker-finder, YOLO, robot bridge.
- Dual-robot: services.g1 e services.h1 in config.yaml; switchabili a
  runtime via PUT /api/home/robot.
- Calibrazione hand-eye eye-to-hand split per-side (right/left).
- Marker pose: marker-finder riceve gli intrinseci RGB della Nuwa al boot,
  PnP server-side con quei dati. Nessun re-PnP locale richiesto.
- Depth-to-RGB: registrazione iterativa IR↔RGB per back-projection 3D
  corretta (Nuwa /api/measure usa coords IR; il nostro /api/perception/
  measure_rgb prende pixel RGB e ritorna 3D nel frame RGB OpenCV).
- Correzione affine sul depth bias (calibrabile via marker come
  ground-truth) — riduce errore Z da ~6% a ~1.5% nei test.
- AI assistant: 16 tool curati (move_wrist_*, hand_action, get_marker[_3d],
  detect_object, calibration_*, set_active_robot…), system prompt
  dinamico che riflette robot attivo + marker config + addendum
  customizzabile da GUI. Temperature di default 0.1 per evitare invenzioni.

GUI (7 tab):
- Home: stato comunicazione device + selettore robot attivo G1/H1
- Assistente AI: chat con OpenRouter, history persistita lato browser,
  task riutilizzabili (prompt salvati), trace tool calls
- Impostazioni AI: modello da combo curata, temperature, max iterations,
  prompt addendum, anteprima system prompt
- Calibrazione, Auto-Calibrazione, TrovaUtensile, Servo Visuale, Vista 3D,
  Movimento EE — invariate dalle versioni precedenti

Setup:
- Variabili in presa-mano/.env (template in .env.example)
- OPENROUTER_API_KEY richiesta solo per il tab Assistente AI
- PRESA_MANO_PORT configurabile

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 13:28:23 +02:00