From 2478e9201cff5693329669c115ddedf8dacac465 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Mon, 11 May 2026 16:59:01 +0200 Subject: [PATCH] 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) --- src/presa_mano/api/grasp_routes.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/presa_mano/api/grasp_routes.py b/src/presa_mano/api/grasp_routes.py index 7d36d32..103c4e3 100644 --- a/src/presa_mano/api/grasp_routes.py +++ b/src/presa_mano/api/grasp_routes.py @@ -25,7 +25,12 @@ from ..grasp.visual_servo import ( ) from ..perception import ObjectDetector, filter_outliers, nuwa_to_cv_frame from ..perception.sam21_bridge import Sam21Fallback, points_via_sam21 -from ..perception.work_plane import apply_below_plane_filter, get_work_plane +from ..perception.work_plane import ( + WorkPlane as PerceptionWorkPlane, + apply_below_plane_filter, + get_work_plane, +) +from ..perception.work_plane import set_work_plane as _set_perception_work_plane from .perception_routes import _bbox_to_roi from ..timing import Stopwatch from . import _deps @@ -341,6 +346,14 @@ def visual_servo_plane_fit(req: PlaneFitReq) -> dict[str, Any]: created_at=time.time(), ) set_work_plane(wp) + # Keep perception.work_plane singleton in sync until Task 4 removes + # the visual-servo duplicate. Default offset_mm so the filter has a + # reasonable threshold without forcing the user through the new endpoint. + _set_perception_work_plane(PerceptionWorkPlane( + normal=wp.normal, offset=wp.offset, centroid=wp.centroid, + n_inliers=wp.n_inliers, fit_rms_mm=wp.fit_rms_mm, + roi=wp.roi, offset_mm=5.0, created_at=wp.created_at, + )) return {"ok": True, "plane": asdict(wp)} @@ -353,4 +366,5 @@ def visual_servo_plane_get() -> dict[str, Any]: @router.delete("/visual_servo/plane") def visual_servo_plane_clear() -> dict[str, Any]: set_work_plane(None) + _set_perception_work_plane(None) return {"ok": True, "set": False}