ManiSkill ↔ MetaSim / Sapien integration#
ManiSkill3 is a SAPIEN-backed
manipulation benchmark with dozens of tabletop tasks. RoboVerse’s
MetaSim already speaks SAPIEN3, so the integration goal is task-level
parity: a roboverse_pack.tasks.maniskill.* task should behave like
the ManiSkill gym.make("...-v1") env it mirrors.
Live report (with embedded videos and gap analysis): http://localhost:8000/#roboverse/maniskill_integration.
Status#
Harness:
tools/maniskill_integration/mirrors the mjlab harness layout —inventory.pycatalogs 4 tabletop tasks;maniskill_rollout.pydrivesgym.makeand captures actions / reward / success flags / qpos / qvel / object pose / goal pose / TCP / rgb frames;run_sweep.pywrites per-taskruns/<task>/maniskill.{npz,mp4}andsummary.json.MetaSim side: the existing
roboverse_pack.tasks.maniskill. pick_cube.PickCubeTaskinstantiates + steps on Sapien3 (nq=9,T=20,final_cube_z=0.0198 munder zero-delta target). It is a RoboVerse-flavored task, not a 1:1 reimplementation of PickCube-v1.Gap to numeric parity: 10 items, all localised to one task module. See the gap analysis section below.
Coverage#
Gym ID |
Notes |
|---|---|
|
Lift a 4 cm cube into a 2.5 cm goal sphere |
|
Push a cube to a target region |
|
Stack red cube on green cube |
|
Pull a cube to a target zone |
All four roll out + render under the harness; zero-action reward sums range 2.3–5.4 (no task is succeeded by a stationary robot, as expected).
What it takes to reach 1:1 parity#
roboverse_pack/tasks/maniskill/pick_cube.py needs:
Cube — change
size=(0.04,0.04,0.04)tosize=(0.02,0.02,0.02)(PickCube uses half-size 0.02 → 4 cm box overall). Drop the explicit mass and let SAPIEN’s default density govern.Goal sphere — add a kinematic
PrimitiveSphereCfg("goal", radius=0.025, no collision). Reset position tocube.pos + (0, 0, U(0, 0.3)).Robot — fork the Franka asset into
panda_v2with finger friction 2.0 (ManiSkill’s custom Panda).Initial qpos — override
default_joint_positionsto ManiSkill’s pose (joint2 = π/8, joint4 = −5π/8, joint6 = 3π/4). AddN(0, 0.02²)noise inside_get_initial_states.Controller — implement
pd_joint_delta_pos: 7-D arm delta (clipped to ±1, scaled by 0.1) + 1-D gripper mimic.Reset distribution — sample cube XY in
U([-0.1, 0.1]²), z-only rotation; goal Z incube.z + U(0, 0.3). Seed fromenv.reset().Dense reward — port the
reaching + grasp + place·grasp + static·placedformula.is_graspedneeds SAPIEN contact queries; the handler lacks a public method but the underlying scene exposesget_contacts()— encapsulate inside the task module per the no-framework-edits rule.Success —
(cube → goal ≤ 0.025) AND (max|qvel[:-2]| < 0.2); grasping NOT required at success.Episode length — 50 steps, not 250.
Each item ≈ 30–90 min of focused edit; ≈ 1 day total for PickCube-v1.
Known Sapien3 handler gaps#
(Pulled forward from the recon report.)
No contact-force query on
BaseSimHandler— ManiSkill’sis_graspedneeds pairwise contacts at both finger pads.Single-env only;
env_idssilently ignored.No seeding hook; task layer must seed numpy + sapien scene in
reset().Scenario lights ignored (hard-coded ambient + 3 point lights).
How to reproduce#
conda activate roboverse
pip install mani_skill # 3.0.1
cd "$ROBOVERSE" # repo root
PYTHONPATH="$ROBOVERSE:$METASIM" \
python -m tools.maniskill_integration.run_sweep --n-steps 50 --seed 0
Artefacts: reports/maniskill_integration/
(maniskill_summary.json, plus runs/<task>/maniskill.{npz,mp4} and
summary.json).