Commit Graph
91 Commits
Author SHA1 Message Date
Adriano Dal PastroandClaude Opus 4.7 876224a71d feat(perception): partition_by_plane returns accepted + excluded sets
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:00:09 +02:00
Adriano Dal PastroandClaude Opus 4.7 9ae3e00f65 build: add numpy-stl + Open3DModel config block for find_model
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 09:57:52 +02:00
Adriano Dal PastroandClaude Opus 4.7 edbd5b5136 docs: implementation plan for Cerca modello 3D pose-fit overlay
13 bite-sized TDD tasks covering: numpy-stl dep + config, partition_by_plane,
stl_sampler, projection, Open3DModel client + LRU mesh cache, sam21_bridge
refactor, _deps factories, GET /api/models/recipes proxy, POST
/api/grasp/find_model handler, GUI rebuild, manual integration smoke test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:42:33 +02:00
Adriano Dal PastroandClaude Opus 4.7 ba5be511d2 docs: design spec for Cerca modello 3D pose-fit overlay
Brainstorming → approved spec for the GUI/backend redesign of tab "Cerca
modello": YOLO+SAM21 cluster feeds Open3DModel /api/pose, presa-mano
samples the recipe STL, projects onto a snapshot RGB with togglable
overlays for accepted/excluded points and the fitted model points.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:35:53 +02:00
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
Adriano Dal PastroandClaude Opus 4.7 f75b9626be fix(work_plane): /fit returns full-scene cloud, not just ROI
The 3D viewer was only seeing points inside the ROI rectangle used for
the plane fit. Now /fit also fetches nuwa.pointcloud (step=4, full frame),
flips to CV frame, and returns it as points_camera (downsampled to
max_preview_points). The user sees the entire scene with red = excluded
by the below-plane filter, cyan = kept.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:45:54 +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 b4db712cd0 fix(gui): work_plane RGB feed via same-origin proxy
Direct fetch to http://localhost:8877/api/rgb fails from the browser due
to CORS (page is served from :8890). Switch to /api/calibration/rgb.jpg
which presa-mano already proxies same-origin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:36:56 +02:00
Adriano Dal Pastro 6f1649b384 Merge feat/work-plane-filter: work-plane calibration + below-plane filter
8 commits — perception/work_plane module, filter wiring on 3 sites,
/api/work_plane/* endpoints, visual-servo removal, Calibrazione Piano tab,
GUI cleanup (Cerca modello + Precisione/Dettagli removed).

- New: perception/work_plane.py owns WorkPlane (+offset_mm), fit_plane_svd,
  disk persistence, apply_below_plane_filter. 8 unit tests.
- Filter applied at all three cloud sites (sam21_bridge, _points_via_bbox,
  _object_cloud_cv bbox branch). Responses carry plane_applied +
  n_points_before_plane on /scan, /object_points, /grasp/{plan,execute}.
- Endpoints: POST /api/work_plane/fit (preview, no save), /save, GET,
  DELETE. Two-stage fit/save UX.
- Visual-servo feature removed entirely (~1500 lines: endpoints, helpers,
  visual_servo.py, servo.js, tab GUI).
- New tab "Calibrazione Piano": shift+drag ROI on RGB, fit preview, 3D
  viewer with colored scatter (green/yellow/red/grey by signed distance),
  offset slider re-colors client-side, save/clear.
- GUI cleanup: "TrovaUtensile" renamed "Cerca modello"; removed
  "Precisione (ultime 5 detection)" stats panel and "Dettagli" JSON dump.
- Verified live: baseline (no plane) → plane_applied:false everywhere;
  with saved plane → plane_applied:true on all 3 endpoints + JSON file on
  disk; DELETE → file gone + plane_applied:false. Zero ERROR logs.
2026-05-11 17:27:15 +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 565c3df2f4 feat(api): /api/work_plane/{fit,save,get,delete} endpoints
POST /fit returns a candidate WorkPlane + a downsampled CV-frame cloud
preview, without writing to disk. POST /save persists the plane. GET
returns the current saved plane (or null). DELETE clears it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:00:24 +02:00
Adriano Dal PastroandClaude Opus 4.7 2478e9201c fix(grasp): sync visual-servo plane writes into perception singleton
Until Task 4 removes the duplicate WorkPlane code in grasp/visual_servo.py,
the visual-servo plane endpoints must also update perception.work_plane's
singleton so the below-plane filter (which reads from the perception side)
sees the newly-calibrated plane within the same process lifetime.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:59:01 +02:00
Adriano Dal PastroandClaude Opus 4.7 3b0a65554a feat: apply work-plane filter at all three cloud sites
points_via_sam21, _points_via_bbox, and _object_cloud_cv (bbox branch)
now call apply_below_plane_filter on the CV-frame cloud before the
<10-points guard. Responses carry plane_applied + n_points_before_plane.
Without a saved plane the filter is a no-op (plane_applied=false).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:52:17 +02:00
Adriano Dal PastroandClaude Opus 4.7 28ba0dd9f2 test(work_plane): drop unused imports
tempfile, Path, and unittest.mock.patch were imported but unused.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:50:05 +02:00
Adriano Dal PastroandClaude Opus 4.7 16e32bf1c1 feat(perception): work_plane module with below-plane filter
Owns WorkPlane (with new offset_mm field), fit_plane_svd, disk-backed
get/set, and the apply_below_plane_filter helper. WorkPlane.normal lives
in OpenCV RGB-camera frame and is oriented toward the camera. The filter
keeps points where signed_distance >= -offset_mm/1000.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:41:35 +02:00
Adriano Dal PastroandClaude Opus 4.7 2338ee7ea2 docs: implementation plan for work-plane filter
6 task TDD-first: perception/work_plane.py + 8 unit tests, filter wiring
ai 3 call sites con plane_applied/n_points_before_plane nelle response,
nuovi endpoint /api/work_plane/{fit,save,get,delete}, rimozione totale
del visual-servo (backend + GUI), nuova tab Calibrazione Piano con
work_plane.js (ROI + fit preview + 3D viewer con scatter colorato +
offset live-recolor), verifica live end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:34:12 +02:00
Adriano Dal PastroandClaude Opus 4.7 f7661a782a docs: design work-plane calibration + below-plane filter
Repurpose the "Servo Visuale" tab into "Calibrazione Piano". Reuses the
existing WorkPlane + fit_plane_svd infrastructure (moved out of
grasp/visual_servo.py into perception/work_plane.py), extends WorkPlane
with offset_mm, splits fit (preview) from save (commit), and applies a
below-plane + offset filter to every object cloud (sam21_bridge,
_points_via_bbox, _object_cloud_cv bbox branch). Visual-servo feature
removed entirely; the only survivors are the plane bits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:27:39 +02:00
Adriano Dal PastroandClaude Opus 4.7 3b96589bf8 feat(perception): extend SAM21 to /scan and /object_points
Extract the SAM21 wiring out of grasp_routes.py into a shared module
perception/sam21_bridge.py (Sam21Fallback + points_via_sam21). Both
/api/perception/scan and /api/perception/object_points now try SAM21
first and fall back to the bbox ROI path on any Sam21Fallback. Response
now carries 'source' (sam21 | bbox_roi) and optional 'sam21_fallback_reason'.

Side-effect: 'points_camera' on both endpoints is now in OpenCV
RGB-camera frame (same as 'points_base' minus the T_base_camera
transform), regardless of which path produced the cloud. Previously the
bbox path stored points in Nuwa-native frame here. The web GUI plots
points_base when available, so the scatter views automatically pick up
the SAM21-segmented cloud.

Verified live: /scan → source=sam21 n=2414 sam21=111ms;
/object_points → source=sam21 n=2347 sam21=118ms;
/grasp/plan regression → source=sam21 n=2390 sam21=119ms;
/scan with SAM21 down → source=bbox_roi fallback='unreachable: ...'

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:06:00 +02:00
Adriano Dal PastroandClaude Opus 4.7 ba0259aa90 feat(gui): surface SAM21 source + n_points in TrovaUtensile status bar
Status line on "Pianifica grasp" now shows source=sam21 / source=bbox_roi
(with fallback reason if any) plus n_points, so SAM21 vs fallback path is
visible at a glance without opening DevTools.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:52:04 +02:00
Adriano Dal Pastro 002d462da4 Merge feat/sam21-segmentation: SAM21 segmentation in grasp pipeline
12 commits — spec, plan, implementation, fixes, live integration.

- New: Sam21Client (clients/sam21.py), align_depth_to_rgb
  (perception/depth_align.py), _points_via_sam21 helper in
  grasp_routes.py, services.sam21 + grasp.use_sam21 config keys, pytest
  scaffold + 11 unit tests.
- _object_points_in_base: try SAM21 first (default on), fall back to the
  legacy bbox path on any non-fatal failure. Nuwa failures during prep
  raise 502 immediately. Single-log discipline.
- Verified live: source=sam21 with ~2200 segmented points at 128 ms GPU
  inference; SAM21 down → automatic bbox_roi fallback; class filter +
  recovery on restart all work.
2026-05-11 15:50:01 +02:00
Adriano Dal PastroandClaude Opus 4.7 7624327487 docs: update CLAUDE.md for SAM21 + fix httpx import order
- Note that tests now exist and run with uv run pytest.
- Add SAM21 to the upstream services table.
- Add sam21() to the _deps factory list.
- Add a convention bullet about the SAM21 vs bbox frame asymmetry so
  future contributors don't add nuwa_to_cv_frame to the SAM21 branch.
- Move 'import httpx' into the third-party imports block.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:49:11 +02:00
Adriano Dal PastroandClaude Opus 4.7 cc19f73b96 fix(sam21): inject rgb/ir width+height into intrinsics from decoded images
Nuwa /api/intrinsics omits width/height from the rgb and ir blocks, so
SAM21 rejected the payload with KeyError('width') and we silently fell
back to bbox on every request. Derive the dimensions from the decoded
BGR + IR depth shapes and augment intr_full before building
CameraRegistration and calling SAM21. Verified end-to-end: source=sam21,
~2200 segmented points on Mortaio at 128 ms GPU inference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:33:52 +02:00
Adriano Dal PastroandClaude Opus 4.7 b9bf878445 fix(grasp): single-log SAM21 fallback + fail-fast on Nuwa errors
- All SAM21-path logging now lives in _points_via_sam21 at the right
  level (WARNING for operational, ERROR for bug codes / unexpected).
  _object_points_in_base no longer double-logs on fallback.
- Nuwa failures during SAM21 prep now raise HTTPException(502)
  immediately instead of running the futile bbox fallback (which would
  also fail because Nuwa is down).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:30:01 +02:00
Adriano Dal PastroandClaude Opus 4.7 1537a9e389 feat(grasp): SAM21 segmentation branch with bbox fallback
When grasp.use_sam21=true (default), _object_points_in_base feeds the YOLO
bbox to SAM21 and uses the segmented cloud directly. Any failure
(transport, segmentation empty, no valid depth, payload bug) logs and falls
back to the legacy bbox path. Response meta includes source ∈ {sam21,
bbox_roi} and sam21_fallback_reason when applicable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:51:11 +02:00
Adriano Dal PastroandClaude Opus 4.7 2f76df4c06 refactor(grasp): extract _points_via_bbox helper
Pure refactor in preparation for the SAM21 branch. _object_points_in_base
keeps its signature and the bbox→ROI→base-frame logic moves into the
private helper. Meta now includes source='bbox_roi'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:46:47 +02:00
Adriano Dal PastroandClaude Opus 4.7 e3f6ff2908 fix(_deps): fail-fast on missing services.sam21.base_url
Align sam21() with nuwa()/marker()/yolo(): require base_url to be present
in config rather than silently defaulting. Misconfiguration now raises
KeyError at factory call instead of masking as a transport error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:45:47 +02:00
Adriano Dal PastroandClaude Opus 4.7 748f5f58f7 feat: wire Sam21Client into _deps and config
Adds services.sam21 (base_url + timeout_s) and grasp.use_sam21 toggle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:43:18 +02:00
Adriano Dal PastroandClaude Opus 4.7 0bc1e02f11 fix(sam21): broader httpx catch + tighter test assertions
Catch httpx.RequestError so DecodingError etc. trigger the bbox fallback
instead of propagating raw. Lock the intrinsics dict shape in the
happy-path test, drop unused imports.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:42:18 +02:00
Adriano Dal PastroandClaude Opus 4.7 75da9add84 feat(clients): Sam21Client wrapper for /api/segment_pointcloud
Posts (rgb_png, depth_png, intrinsics, bbox) and returns (N,3) points in
meters in OpenCV RGB-camera frame. Normalises transport vs semantic errors
into Sam21Unavailable / Sam21Error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:30:16 +02:00
Adriano Dal PastroandClaude Opus 4.7 810a6102fb test(depth_align): real z-buffer collision + drop dead var
The 2× focal-length collision test wasn't actually colliding (adjacent IR
pixels rounded to different RGB columns). 4× makes them collapse, so the
np.minimum.at reduce is now exercised. Also drop unused H_ir, W_ir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:28:15 +02:00
Adriano Dal PastroandClaude Opus 4.7 5354c51d60 feat(perception): vectorised IR→RGB depth alignment
Forward-project IR depth pixels into the RGB pixel grid with a z-buffer.
Output uint16 mm at RGB resolution, ready to feed SAM21.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:23:11 +02:00
Adriano Dal PastroandClaude Opus 4.7 f898d9b0da test: add pytest dev dep + tests scaffold
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:19:12 +02:00
Adriano Dal PastroandClaude Opus 4.7 e2f06d2624 docs: implementation plan for SAM21 segmentation in grasp pipeline
7 task TDD-first: pytest scaffold, depth_align (vectorised IR→RGB),
Sam21Client (httpx mock unit tests), _deps + config wiring, refactor
estraendo _points_via_bbox, branch SAM21 con fallback, verifica live.
Allinea config key a base_url (consistente con altri servizi).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:42:27 +02:00
Adriano Dal PastroandClaude Opus 4.7 adefc93949 docs: design SAM21 segmentation in grasp pipeline
Spec brainstorming validato: SAM21 si inserisce tra YOLO bbox e PCA con
fallback automatico al path bbox legacy. Tre componenti nuovi
(clients/sam21.py, perception/depth_align.py, helper _points_via_sam21)
e due modifiche minori (config.yaml, api/_deps.py). Out-of-scope: scan/
object_points, mask UI, nuwa_to_cv_frame cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 12:30:08 +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 4981306062 feat: calibration helper scripts + DANIILIDIS solver default + dual-robot README
- scripts/: explore_and_calibrate.py (probe envelope from actual + random sampling),
  extend_calibration.py (loop fino a n_used >= TARGET_GOOD), repeatability.py
  (diagnostica bias vs noise sul marker-finder)
- config.yaml: calibration.method TSAI → DANIILIDIS (sweep su 49 sample H1 sx
  mostra 4× meno residuo di TSAI per via del bias intrinsics-dipendente di
  marker-finder)
- README: dual-robot G1/H1, scripts dir, caveat noti (wrist passthrough,
  marker-finder intrinsics floor, H1 4 DoF, /api/arms/go_neutral non proxato)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:34:59 +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