Conversation
Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
Scenes no longer include the arm. Each marks an arm's base with a
`{prefix}robot_mount` frame, and robot_profile.load_scene_model attaches
the vendored Menagerie SO-101 there with MjSpec.attach. The bimanual scene
uses left_/right_ prefixes, so every joint, actuator, camera, and body keeps
its name.
SO101_PROFILE adapts the Menagerie model to the earlier one: calibrated
joint ranges (wrist_roll up to 2.84121 rad), 3.35 N m force limits, the
`wrist` camera pose and field of view, and no gripper collision meshes or
camera-mount visuals. Normalized units, camera images, and grasp contacts
stay the same. Shared rendering settings, the default contact dimension,
sky and floor move to scenes/scene_common.xml; each scene sets its own
physics options.
Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
Nothing loads so101.xml, the so101_robot_{config,bodies}.xml includes, the so101_dual/ copies, the Onshape .part files or garment_PL_019.obj any more. urdf/so101/*.urdf and their STL meshes stay for Studio's 3D robot view, which resolves meshes next to the URDF. The owner example now starts the single_pick_place scene.
Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
Pin the arm to the earlier 26 collision primitives with non-colliding visual geoms, check that each bimanual arm gets its own prefixed default classes, that composed scenes have no keyframes (their raw qpos would depend on where the arm is attached), and that bundled STLs are real meshes rather than Git LFS pointers. Log the robot options the scene overrides at debug level and document that the scene is the single source of physics options. Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
…ckage Depend on mujoco-menagerie==2026.9.4, which downloads robotstudio_so101 (about 4 MB) on first use into a per-user cache, instead of vendoring the model and its meshes. The compiled scenes are identical to the vendored model's. Signed-off-by: Max Xiang <xiangxiang.ma@intel.com>
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 1
Open (4)
The return annotation referencesmujoco.MjModel, butmujocois only imported under… · New Hard-pinningmujoco-menageriein a library package can create downstream dependency resolution… · New Copying options by iteratingdir(scene.option)is brittle:dir()can include non-option… · New The root element<scene_common>is not a standard MJCF tag. Even if MuJoCo’s<include>happens… · New
What changed in this PR
Refactors the MuJoCo SO-101 plugin to source the robot model from MuJoCo Menagerie and to keep scenes robot-free, attaching the arm(s) at load time via a robot profile.
Changes:
- Introduces
RobotProfile/SO101_PROFILEand scene composition utilities to attach SO-101 at{prefix}robot_mountframes. - Updates all bundled scenes to remove embedded robot definitions and share common rendering assets via
scene_common.xml. - Updates tests, docs, and examples to load composed models via
SceneConfig.load_model()/load_scene_model(); removes legacy SO-101 MJCF fragments.
| File | Description |
|---|---|
| packages/physicalai-mujoco-so101-plugin/urdf/so101_dual/so101_dual_robot_config.xml | Removes legacy dual-arm robot config MJCF fragment (now attached at load time). |
| packages/physicalai-mujoco-so101-plugin/urdf/so101_dual/so101_dual_robot_bodies.xml | Removes legacy dual-arm robot body MJCF fragment (now attached at load time). |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/so101_robot_config.xml | Removes legacy single-arm robot config MJCF fragment (replaced by Menagerie + profile). |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/so101_robot_bodies.xml | Removes legacy single-arm robot body MJCF fragment (now attached at load time). |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/so101.xml | Removes monolithic legacy SO-101 MJCF model (robot now comes from Menagerie). |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/wrist_roll_pitch_so101_v2.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/wrist_roll_follower_so101_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/waveshare_mounting_plate_so101_v2.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/upper_arm_so101_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/under_arm_so101_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/sts3215_03a_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/sts3215_03a_no_horn_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/rotation_pitch_so101_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/moving_jaw_so101_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/motor_holder_so101_wrist_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/motor_holder_so101_base_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/garment_PL_019.obj | Removes bundled garment mesh asset from the legacy SO-101 assets directory. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/base_so101_v2.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/so101/assets/base_motor_holder_so101_v1.part | Removes CAD metadata asset no longer needed with Menagerie-based model. |
| packages/physicalai-mujoco-so101-plugin/urdf/scenes/yahtzee/scene.xml | Converts scene to robot-free form, includes scene_common.xml, adds robot_mount frame, updates asset paths. |
| packages/physicalai-mujoco-so101-plugin/urdf/scenes/single_pick_place/scene.xml | Converts scene to robot-free form, includes scene_common.xml, adds robot_mount frame. |
| packages/physicalai-mujoco-so101-plugin/urdf/scenes/scene_common.xml | Adds shared rendering/sky/floor defaults for all scenes. |
| packages/physicalai-mujoco-so101-plugin/urdf/scenes/garment_fold/scene.xml | Converts bimanual scene to robot-free form with left_/right_ mount frames. |
| packages/physicalai-mujoco-so101-plugin/urdf/scenes/conveyor_sort/scene.xml | Converts scene to robot-free form, includes scene_common.xml, adds robot_mount frame, updates asset paths. |
| packages/physicalai-mujoco-so101-plugin/tests/test_scene_models.py | Updates tests to compile composed models via SceneConfig.load_model() and validates wrist camera pose/FOV contract. |
| packages/physicalai-mujoco-so101-plugin/tests/test_robot_profile.py | Adds coverage for profile composition (mount frames, naming/prefixing, collisions, offline guidance). |
| packages/physicalai-mujoco-so101-plugin/tests/test_mujoco_robot.py | Updates mocking to patch load_scene_model instead of mujoco.MjModel.from_xml_path. |
| packages/physicalai-mujoco-so101-plugin/tests/test_conveyor_demo.py | Loads composed conveyor model via SceneConfig.load_model(). |
| packages/physicalai-mujoco-so101-plugin/tests/test_conveyor.py | Loads composed conveyor model via SceneConfig.load_model(). |
| packages/physicalai-mujoco-so101-plugin/src/physicalai_mujoco_so101_plugin/scene_registry.py | Adds SceneConfig.load_model() that compiles scene + attached robot(s). |
| packages/physicalai-mujoco-so101-plugin/src/physicalai_mujoco_so101_plugin/robot_profile.py | Introduces Menagerie-backed SO-101 profile, robot customization, and scene composition/compile helpers. |
| packages/physicalai-mujoco-so101-plugin/src/physicalai_mujoco_so101_plugin/mujoco_robot.py | Switches robot loading and scene switching to use load_scene_model (scene + attached robot). |
| packages/physicalai-mujoco-so101-plugin/scripts/run_conveyor_demo.py | Loads composed model via SceneConfig.load_model(). |
| packages/physicalai-mujoco-so101-plugin/pyproject.toml | Adds pinned mujoco-menagerie dependency used by robot composition. |
| packages/physicalai-mujoco-so101-plugin/examples/run_mujoco_owner.py | Uses default scene XML + scene_config instead of removed so101.xml. |
| packages/physicalai-mujoco-so101-plugin/README.md | Documents Menagerie download/cache behavior and the new robot-free scene composition approach. |
| packages/physicalai-mujoco-so101-plugin/CHANGELOG.md | Notes breaking change: scenes compile without arms unless loaded via composition helpers. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…starts `start` now downloads the robot model in the launcher, before it spawns the owner subprocess. A slow first download no longer fails as an unrelated owner startup timeout, shows its progress, and an offline machine gets a one-line error instead of a traceback. Custom models without mount frames skip it. Add `physicalai-mujoco-so101 prefetch`, which downloads every robot profile's model ahead of time, and use it in CI behind a cache of the Menagerie models. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…include root Address review: enumerate the option binding's writable properties instead of dir(), and give scene_common.xml the conventional <mujocoinclude> root. Compiled models and 200-step rollouts are unchanged for every scene.
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Dynamic model composition and an externally downloaded robot model affect every simulation scene and warrant final human validation.
Review effort: Balanced
Findings: None
Resolved since last review (4)
The return annotation referencesmujoco.MjModel, butmujocois only imported under… The root element<scene_common>is not a standard MJCF tag. Even if MuJoCo’s<include>happens… Copying options by iteratingdir(scene.option)is brittle:dir()can include non-option… Hard-pinningmujoco-menageriein a library package can create downstream dependency resolution…


Stacked on #310. The SO-101 now comes from MuJoCo Menagerie (
robotstudio_so101) instead of our own MJCF. Scenes no longer include a robot; the arm is attached when the scene loads. This prepares the plugin for other arms that Menagerie provides.Joint names, units, cameras and physics are unchanged, so existing datasets and policies keep working.
Changes
mujoco-menagerie==2026.9.4. The model (about 4 MB) is downloaded on first start;physicalai-mujoco-so101 prefetchorMENAGERIE_ROOTcover offline machines.robot_profile.pykeeps the plugin's existing joint ranges, force limit, wrist camera and gripper geometry.<frame name="{prefix}robot_mount"/>, andSceneConfig.load_model()attaches the arm there.so101.xmland the files it included. The URDFs stay for Studio's 3D view.Validation
conveyor_sortbefore this change still works.