Commit Graph
121 Commits
Author SHA1 Message Date
Adriano Dal Pastro 3e4e8055db feat(right_arm): /detect/front con proxy fallback per YOLO 2026-05-20 12:20:02 +02:00
Adriano Dal Pastro 22e13435b1 feat(right_arm): endpoint /snapshot/{front,wrist} 2026-05-20 12:16:33 +02:00
Adriano Dal PastroandClaude Opus 4.7 dd2053cc47 feat(right_arm): router skeleton con /state e /activate
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:13:33 +02:00
Adriano Dal Pastro 55e84778d8 feat(right_arm): math puro per delta-toward (sign flips + z-floor) 2026-05-20 12:09:35 +02:00
Adriano Dal Pastro 757eb01200 feat(deps): aggiungi front_camera() e tab_right_arm_cfg() 2026-05-20 12:07:11 +02:00
Adriano Dal Pastro 04cc5fc345 feat(geometry): aggiungi conversioni RPY (deg) ↔ quaternion xyzw 2026-05-20 12:04:39 +02:00
Adriano Dal Pastro 64742479b1 feat(config): aggiungi services.front_camera e blocco tab_right_arm 2026-05-20 12:01:14 +02:00
Adriano Dal PastroandClaude Opus 4.7 779f506701 docs(plan): implementation plan tab Braccio DX
13 task TDD per il nuovo tab: config, geometry, math puro, 6 endpoint
router /api/right_arm/*, markup HTML + CSS, JS module. Spec:
docs/superpowers/specs/2026-05-20-right-arm-tab-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:33:06 +02:00
Adriano Dal PastroandClaude Opus 4.7 53c0e03219 docs(spec): design tab Braccio DX (G1 right, front + wrist Nuwa)
Design del nuovo tab "Braccio DX": fronte (depth cam fissa sul robot)
+ polso (Nuwa eye-in-hand) + controlli move/home/custom-pose. Router
/api/right_arm/*, JS dedicato, persistenza in config tab_right_arm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:04:08 +02:00
Adriano Dal PastroandClaude Opus 4.7 491d1b60aa revert(find_model): drop plane filter — pass full SAM21 cluster to Open3DModel
The pre-SAM21 depth filter and post-SAM21 partition_by_plane were
fighting each other and drowning the actual object cluster. Per
operator request, send Open3DModel the raw SAM21 cluster and let
RANSAC handle outliers itself. The accepted/excluded/SAM21 overlays
in the GUI continue to work; excluded is now always empty and
accepted == SAM21 cluster.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:59:15 +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 f1f9d8f638 feat(find_model): zero below-plane depth before SAM21 segmentation
Previously SAM21 ran on the raw aligned depth and frequently leaked the
mask onto the table around the object: ~88% of segmented points (2136
of 2440 in a sample run) were table pixels filtered away by the post
partition_by_plane step. Open3DModel got a noisy cluster mostly off
the object.

New pipeline: with a calibrated work plane, depth pixels whose 3D
back-projection sits below the plane are zeroed BEFORE SAM21 sees the
depth PNG. SAM21 cannot back-project zero-depth pixels, so only true
above-plane points end up in the cloud regardless of mask outline.

Same sample run after the change: 513 SAM21 -> 513 accepted, 0 excluded.

The post-partition still runs (now a no-op on a calibrated plane), so
the find_model response shape is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:50:01 +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 4a83305b5e fix(work_plane): project fit inliers from CV-frame pts_cv (not raw pc)
NuwaClient.pointcloud_roi's docstring claims OpenCV frame, but in
practice the raw payload arrives in Nuwa native frame (Z<0 forward).
nuwa_to_cv_frame is what actually flips it. Using `pts_cv` (post-flip
+ post-outlier-mask) makes the projection drop none of the inliers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:13:20 +02:00
Adriano Dal PastroandClaude Opus 4.7 ae510e4387 feat(work_plane gui): overlay inliers used for fit as blue dots on RGB
The fit endpoint now returns fit_points_px (the post-outlier-filter
inliers projected to RGB pixels via Nuwa's RGB intrinsics). The GUI
draws them on the same overlay as the ROI rectangle so the user can
visually verify which depth pixels were fed to fit_plane_svd.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:10:25 +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 92506d62c6 fix(work_plane gui): preserve ROI overlay across RGB live-refresh
Setting canvas.width/height clears its bitmap; the live RGB tick was
firing the img.load handler every second, wiping the ROI rectangle and
breaking the two-click flow (third click was interpreted as restart).

- Only mutate canvas size when image resolution actually changes.
- Re-paint the overlay after each load so the ROI persists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:58:41 +02:00
Adriano Dal PastroandClaude Opus 4.7 1bdf407072 chore(config): set wrist_side=left to match calibrated H1 arm
Right side has no calibration in data/calibration_right.yaml;
the H1 left arm is the one with samples + solved hand-eye.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:17:48 +02:00
Adriano Dal PastroandClaude Opus 4.7 cb940dc1cd fix(open3dmodel): unwrap {success,data,error} envelope from /api/recipes
Open3DModel returns the same envelope for /api/recipes as for /api/pose;
the bare-list code path stays as a fallback for older mocks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:17:48 +02:00
Adriano Dal PastroandClaude Opus 4.7 33d66019ee feat(web): Cerca modello — model picker + find_model overlay handlers
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:12:46 +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 3857ef533a feat(api): POST /api/grasp/find_model with pose-fit + overlay projection
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:09:47 +02:00
Adriano Dal PastroandClaude Opus 4.7 5d9166ed77 feat(api): GET /api/models/recipes proxy to Open3DModel
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:08:11 +02:00
Adriano Dal PastroandClaude Opus 4.7 430e342c48 feat(api): _deps factories for Open3DModel client + recipe cache
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:07:18 +02:00
Adriano Dal PastroandClaude Opus 4.7 87abe26476 refactor(sam21_bridge): extract segment_with_sam21 (no plane filter)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:06:41 +02:00
Adriano Dal PastroandClaude Opus 4.7 684bd2de5e feat(clients): LRU mesh cache for Open3DModel recipes (etag-validated)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:05:05 +02:00
Adriano Dal PastroandClaude Opus 4.7 16ffe6ac20 feat(clients): Open3DModel client (list_recipes, estimate_pose, get_stl_bytes)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:03:41 +02:00
Adriano Dal PastroandClaude Opus 4.7 b85f4b9a48 feat(perception): project camera-frame 3D points to image pixels
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:02:20 +02:00
Adriano Dal PastroandClaude Opus 4.7 d1b27433d5 feat(perception): parse STL + uniform surface sampling
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:01:25 +02:00
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