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>
This commit is contained in:
Adriano Dal PastroandClaude Opus 4.7 committed 2026-05-11 16:59:01 +02:00
1 parent 3b0a65554a
commit 2478e9201c
1 file changed
+15 -1
+15 -1
View File
@@ -25,7 +25,12 @@ from ..grasp.visual_servo import (
) )
from ..perception import ObjectDetector, filter_outliers, nuwa_to_cv_frame from ..perception import ObjectDetector, filter_outliers, nuwa_to_cv_frame
from ..perception.sam21_bridge import Sam21Fallback, points_via_sam21 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 .perception_routes import _bbox_to_roi
from ..timing import Stopwatch from ..timing import Stopwatch
from . import _deps from . import _deps
@@ -341,6 +346,14 @@ def visual_servo_plane_fit(req: PlaneFitReq) -> dict[str, Any]:
created_at=time.time(), created_at=time.time(),
) )
set_work_plane(wp) 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)} return {"ok": True, "plane": asdict(wp)}
@@ -353,4 +366,5 @@ def visual_servo_plane_get() -> dict[str, Any]:
@router.delete("/visual_servo/plane") @router.delete("/visual_servo/plane")
def visual_servo_plane_clear() -> dict[str, Any]: def visual_servo_plane_clear() -> dict[str, Any]:
set_work_plane(None) set_work_plane(None)
_set_perception_work_plane(None)
return {"ok": True, "set": False} return {"ok": True, "set": False}