Skip to content

build: require mplib>=0.2.1 and add API compatibility shim - #14

Open
shaoxiang wants to merge 2 commits into
RoboMME:mainfrom
shaoxiang:fix-mplib-0.2.1-compat-rebased
Open

build: require mplib>=0.2.1 and add API compatibility shim#14
shaoxiang wants to merge 2 commits into
RoboMME:mainfrom
shaoxiang:fix-mplib-0.2.1-compat-rebased

Conversation

@shaoxiang

Copy link
Copy Markdown

Summary

Upgrade mplib from 0.1.x to >=0.2.1 and add a compatibility shim so existing ManiSkill/RoboMME motion-planning code continues to work.

Problem

  • mplib 0.1.x segfaults inside mplib.pymp.ArticulatedModel when DemonstrationWrapper builds a Panda motion planner for live motion planning.
  • mplib 0.2.1 fixes the crash but introduces two breaking API changes:
    1. Planner.set_base_pose() now expects an mplib.pymp.Pose object instead of a 7-DOF numpy array.
    2. Planner.plan_screw() / Planner.plan_qpos_to_pose() no longer accept use_point_cloud.

Changes

  • pyproject.toml: add mplib>=0.2.1.
  • Add src/robomme/robomme_env/utils/mplib_compat.py: monkey-patch mplib.Planner methods to transparently adapt legacy callers to 0.2.x signatures.
  • Install the shim at import time in DemonstrationWrapper, RecordWrapper, and subgoal_planner_func.
  • Update the direct plan_screw call in subgoal_planner_func.py to pass a sapien.Pose and remove the unsupported use_point_cloud kwarg.

Verification

Smoke-tested on PickXtimes with skip_motion_planning=False:

  • mplib==0.2.1
  • planner initializes successfully
  • 100 rollout steps complete without segfault or API error

mplib 0.1.x segfaults when RoboMME's DemonstrationWrapper builds a Panda
motion planner.  mplib 0.2.1 resolves the crash, but changes two public
APIs that ManiSkill/RoboMME code was written against:

- Planner.set_base_pose now expects an mplib.pymp.Pose instead of a
  7-DOF numpy array.
- plan_screw / plan_qpos_to_pose no longer accept use_point_cloud.

Changes:
- Pin mplib>=0.2.1 in pyproject.toml.
- Add src/robomme/robomme_env/utils/mplib_compat.py: a centralized
  monkey-patch that adapts legacy callers to the 0.2.x signatures.
- Install the shim on import in DemonstrationWrapper, RecordWrapper, and
  subgoal_planner_func so every planner instantiation path is covered.
- Update the direct plan_screw call in subgoal_planner_func.py to pass a
  sapien.Pose and drop the unsupported use_point_cloud kwarg.

Smoke-tested on PickXtimes with skip_motion_planning=False:
planner initializes and 100 rollout steps complete without segfault.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hongzefu

Copy link
Copy Markdown
Collaborator

Thanks for this — the shim approach is right, and the set_base_pose /
use_point_cloud adaptations work (PickXtimes + screw planning run clean on
0.2.1 with the shim). Two problems we hit while testing the branch:

1. uv sync can't resolve the branch as-is. mani-skill 3.0.0b21 pins
mplib==0.1.1; platform_system=="Linux"
(setup.py#L43),
which conflicts with the new mplib>=0.2.1:

Because mani-skill==3.0.0b21 depends on mplib==0.1.1 and your project depends
on mplib>=0.2.1, the requirements are unsatisfiable.

So uv sync (and the Dockerfile's uv sync --frozen) fail — the PR only
verifies because uv pip install "mplib>=0.2.1" is imperative and bypasses the
resolver. Fix: add [tool.uv] override-dependencies = ["mplib>=0.2.1"] and
refresh uv.lock.

2. The shim misses the plan_qpos_to_poseplan_pose rename, which breaks the screw→RRT* fallback.

Trajectory generation uses two planners:

  • move_to_pose_with_screwplan_screw (fast straight-line — the shim handles this ✅)
  • move_to_pose_with_RRTStar / move_to_pose_with_RRTConnectplan_qpos_to_pose (sampling-based, for harder poses)

In demonstration / dataset generation the solver tries screw first and falls
back to RRT*
when screw fails — that's exactly what planner_fail_safe.py
(ScrewPlanFailure / FailAwarePandaArmMotionPlanningSolver) exists for
(screw ×3 → RRT* ×3 → give up).

0.2.x renamed plan_qpos_to_poseplan_pose, but the shim guards that patch
with hasattr(planner, "plan_qpos_to_pose"), which is False on 0.2.1, so it
never applies. So move_to_pose_with_RRTStar / RRTConnect
(base_motionplanner/motionplanner.py:103,128) raise
AttributeError: 'Planner' object has no attribute 'plan_qpos_to_pose'.

The screw path works (line 152 passes a legacy array the shim converts), so a
PickXtimes smoke test never reaches RRT* and looks green. But any episode where
screw fails and falls back to RRT* hits the AttributeError — and since the
fallback is wrapped in except Exception: continue, it's swallowed and the
episode silently fails with no crash. Per-seed isolated runs, ep10:

mplib 0.1.1:  seed0 success=True   (screw failed 3×, RRT* fallback succeeded)
mplib 0.2.1:  seed0 success=False  (screw failed 3×, RRT* → AttributeError, swallowed)
              seeds 1–4 success=True on both (screw succeeded, never hit RRT*)

Fix: alias plan_qpos_to_poseplan_pose on 0.2.x and handle/drop the RRT*
kwargs (planner_name, rrt_range, planning_time, use_point_cloud).

- Add [tool.uv] override-dependencies so uv sync resolves mplib>=0.2.1
  despite mani-skill's mplib==0.1.1 pin.
- Regenerate uv.lock (mplib 0.1.1 -> 0.2.1).
- Extend mplib_compat shim to wrap plan_pose on 0.2.x and add a
  plan_qpos_to_pose alias, fixing the screw->RRT* fallback.
- Drop obsolete RRT* kwargs (planner_name, use_point_cloud) while
  preserving rrt_range/planning_time where supported.

Co-Authored-By: Claude <noreply@anthropic.com>
@shaoxiang

Copy link
Copy Markdown
Author

更新了两个 reviewer 提到的问题:

  1. [tool.uv] override-dependencies = ["mplib>=0.2.1"] 已加入 pyproject.toml,并重新生成了 uv.lock(mplib 从 0.1.1 升级到 0.2.1)。
  2. mplib_compat.py 现已包装 mplib 0.2.x 的 plan_pose,并兼容旧名 plan_qpos_to_pose;同时丢弃 legacy RRT* kwargs(planner_nameuse_point_cloud),确保 screw→RRT* fallback 能正常工作。

本地已 smoke-test 通过 mplib 0.2.1。请 review。

@hongzefu

hongzefu commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks @shaoxiang for the work here! We weren't able to reproduce the segfault on our end, and can't fully verify the underlying mplib swap (the pin is owned by ManiSkill upstream) — so we won't merge this into main, but we're keeping this branch as a troubleshooting reference for anyone who hits the issue. Thanks again!

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.

3 participants