Skip to content

refactor(manipulation): replace the pick module with a composed one - #3732

Draft
mustafab0 wants to merge 1 commit into
mainfrom
mustafa/manip/m1-pick-module-swap
Draft

refactor(manipulation): replace the pick module with a composed one#3732
mustafab0 wants to merge 1 commit into
mainfrom
mustafa/manip/m1-pick-module-swap

Conversation

@mustafab0

Copy link
Copy Markdown
Contributor

Main's PickAndPlaceModule was a ManipulationModule subclass that piled nine agent skills onto the primitive RPC module and reached into its privates to do it; this replaces it with a plain module that gets motion, reachability and the gripper through Specs. The primitives move down onto ManipulationModule, including the perception objects port and the obstacle-monitor RPCs that used to live on the subclass, so the planner keeps seeing detected objects instead of going collision-blind. Grasp geometry now comes from HeuristicGraspModule reading the object cloud rather than the occlusion-inset and tall-object constants it replaces, and #3701's grasp verification is wired through unchanged.

Verifying this on the xArm7 sim turned up two pre-existing bugs it also fixes. Re-opening jaws already resting at their measured 0.947 could only ever time out, since that is neither travel nor arrival at the commanded 1.0, so await_gripper_settle now takes an arrival_tolerance. And make_xarm7_sim_robot_config placed the arm at the origin while xarm7.xml bolts it to a 12cm pedestal, so the planner solved every pose 12cm below the arm it was driving and every grasp closed on air.

Deliberately dropped: look, get_scene_info, place_back, drop_on, pick_and_place, and clear_perception_obstacles, whose documented use was to delete the world when planning hit COLLISION_AT_START. The multi-candidate retry loop and far-reach pre-grasp shortening are dropped too; both want the contact primitive rather than a reimplementation here.

Swaps main's 829-line PickAndPlaceModule, a ManipulationModule subclass that
piled nine agent skills onto the primitive RPC module, for a plain module that
reaches motion, reachability and the gripper through Specs. The primitives it
needs move down onto ManipulationModule: the verified gripper pair that wraps
#3701's await_gripper_settle, lift_if_low, the robot model's pre-grasp standoff,
and the perception objects port with the obstacle-monitor RPCs that used to live
on the subclass, so the planner keeps seeing detected objects. Grasp geometry
now comes from HeuristicGraspModule reading the object cloud rather than the
occlusion-inset and tall-object constants it replaces.

Two bugs surfaced while verifying this on the xArm7 sim. Re-opening jaws that
already rest at their measured 0.947 could only ever time out, because that is
neither travel nor arrival at the commanded 1.0; await_gripper_settle takes an
arrival_tolerance so a caller that already accepts a band around the target can
say so. And make_xarm7_sim_robot_config placed the arm at the origin while
xarm7.xml bolts it to a 12cm pedestal, so the planner solved every pose 12cm
below the arm it was driving and every grasp closed on air.

Dropped on purpose: look, get_scene_info, place_back, drop_on, pick_and_place,
and the clear_perception_obstacles skill, whose documented use was to delete the
world when planning hit COLLISION_AT_START. The obstacle RPCs remain on
ManipulationModule. Also dropped: the multi-candidate retry loop and the
far-reach pre-grasp shortening, both of which want the contact primitive rather
than a reimplementation here.
@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This change replaces the inherited pick-and-place flow with composed perception, grasp-generation, motion, and gripper operations.

A failed object selection can leave a previously selected grasp active. The reproduced sequence selected object A, failed to select missing object B, and then successfully commanded motions for A when picking. Fresh scan detections also are not added to the planning world before collision-aware grasp filtering runs, so immediate pick planning can miss newly detected scene geometry.

T-Rex validation blocked

The planning-world refresh check could not reach its scan and collision assertions because required runtime packages were missing: dimos_lcm, zenoh, psutil, and torch. The affected scan-to-planning path remains reported because the missing refresh is present in the code path.

Confidence Score: 3/5

Not safe to merge until failed selections clear executable grasp state and fresh detections are materialized for collision-aware planning.

One failure was reproduced with a focused executable check and an empty-selection comparison. The planning-world issue is directly visible in the composed scan and collision-check flow, but its runtime comparison could not run because required packages are unavailable.

Files Needing Attention: dimos/manipulation/pick_and_place.py needs selection-state cleanup and a connection from fresh scan results to planning-world obstacle refresh.

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a proof for a posted P1 finding and attached the harness script and before/after logs.
  • T-Rex attempted the focused comparison harness but imports were blocked by missing packages (dimos_lcm, zenoh, psutil, torch), so no scan or collision assertions were executed.
  • T-Rex attempted validation with the authored harness, progressed through stubs for missing runtime dependencies, but stopped at the torch import and did not reach scan/grasp assertions.
  • T-Rex produced an additional P1 finding proof.
  • Execution trace from the stale-grasp-selection-harness.py showed initial_select success=True selected=A, then failed_select with code=OBJECT_NOT_DETECTED, and pick_after_failure with object_id=A and motion calls, while the empty baseline reported empty_pick success=False, confirming the failed selection gates the picker.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "refactor(manipulation): replace the pick..." | Re-trigger Greptile

Comment on lines +113 to +125
self._scene.set_prompts(prompts)
with self._objects_condition:
fresh = self._objects_condition.wait_for(
lambda: self._objects_version > objects_version,
timeout=self.config.scan_timeout,
)
objects = self._objects
if not fresh:
return SkillResult.fail(
"OBJECT_NOT_DETECTED",
f"No detections published within {self.config.scan_timeout:.1f}s of the scan",
)
return SkillResult.ok(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Scans skip obstacle refresh

When scan_objects receives fresh detections, it returns without materializing the cached objects into the planning world. The subsequent collision-aware IK and motion planning therefore remain blind to detected scene objects, allowing approach paths to intersect surrounding geometry.

T-Rex Ran code and verified through T-Rex

Comment on lines +150 to +156
obj = self.get_object(object_id)
if obj is None:
return SkillResult.fail("OBJECT_NOT_DETECTED", f"No object with ID {object_id!r}")
try:
candidates = self._grasp_generator.propose_grasps(obj.pointcloud)
except ValueError as exc:
return SkillResult.fail("GRASP_INPUT_INVALID", str(exc))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Failed selection retains an executable grasp

After a grasp for object A has been selected, selecting a missing object B returns OBJECT_NOT_DETECTED without clearing the stored grasp and pregrasp poses. pick_selected only checks that those poses are present, so it proceeds to move to A even though the most recent selection failed. Clear the selection on every unsuccessful select_grasp path, or clear it before validating a new selection so a failure leaves picking in INVALID_STATE.

Artifacts

trex-artifacts/stale-grasp-selection-harness.py

  • Executable focused harness that reproduces A selection, missing-B failure, and the ensuing pick motion calls.

trex-artifacts/stale-grasp-01-before.log

  • Executed empty-selection baseline showing `INVALID_STATE` and `motion_calls=0`.

trex-artifacts/stale-grasp-02-after.log

  • Executed stale-selection repro showing failed B selection retains A and `pick_selected` succeeds with three A motions.

View artifacts

T-Rex Ran code and verified through T-Rex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant