Skip to content

Add nested models support in mujoco plugin#1002

Merged
azeey merged 25 commits into
mainfrom
shameek/mj_nested_models
Jul 9, 2026
Merged

Add nested models support in mujoco plugin#1002
azeey merged 25 commits into
mainfrom
shameek/mj_nested_models

Conversation

@shameekganguly

@shameekganguly shameekganguly commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

🎉 New feature

Part of #299

Summary

Mujoco plugin now supports nested models.

  • Implemented ConstructNestedModel in mujoco/src/SDFFeatures.cc
  • Handled nested model removal in mujoco/src/EntityManagementFeatures.cc
  • Added a new common test to check that link poses are correct for nested models after removing the models and adding them again (similar to the reset implementation in gz-sim Physics system). This is currently failing in bullet-featherstone. I will follow up with a fix.

Backport Policy

Can be backported with the rest of the PRs that add the Mujoco plugin.

  • This is safe to backport to the following versions:
    • Jetty
    • Ionic
    • Harmonic
    • Fortress
  • This should not be backported
  • I am not sure
  • Other (fill in yourself)

Test it

gz sim -s -v 4 src/gz-sim/examples/worlds/nested_model.sdf --physics-engine gz-physics-mujoco-plugin
mj nested model

Checklist

  • Signed all commits for DCO
  • Added a screen capture or video to the PR description that demonstrates the feature
  • Added tests
  • Added example and/or tutorial
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • Updated Bazel files (if adding new files). Created an issue otherwise.
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers
  • Was GenAI used to generate this PR? If so, make sure to add "Generated-by" to your commits. (See this policy for more info.)

Generated-by: Gemini 3.1 pro in Antigravity

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by and Generated-by messages.

Backports: If this is a backport, please use Rebase and Merge instead.

Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
…ested models in mujoco plugin

Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly force-pushed the shameek/mj_nested_models branch from 95e5e6d to cc76c26 Compare June 11, 2026 15:05
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly force-pushed the shameek/mj_nested_models branch from cc76c26 to bfcbfc9 Compare June 11, 2026 15:09
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly marked this pull request as ready for review June 11, 2026 17:50
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@github-project-automation github-project-automation Bot moved this from Inbox to In review in Core development Jun 15, 2026

@azeey azeey left a comment

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.

I haven't finished reviewing yet, but I wanted to start a conversation about how self_collide tags are handled.

Comment thread mujoco/src/SDFFeatures.cc
Comment thread mujoco/src/SDFFeatures.cc
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
// every pair
auto &objMap = modelInfo->links.objectToID;
for (auto it1 = objMap.begin(); it1 != objMap.end(); ++it1)
std::vector<const mjsBody *> allBodies;

@azeey azeey Jun 24, 2026

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.

This differs from the current behavior in DART. I did a quick test and came up with the following table that summarizes the behavior of the self_collide tag on a parent and nested models.

Parent flag nested model (child) flag note
true true Bodies in the parent collide against other bodies in the parent.
Bodies in the child collide against other bodies in the child.
Bodies in the parent collide against other bodies in the child and vice-versa.
true false Bodies in the parent collide against other bodies in the parent.
Bodies in child do not collide against each other.
Bodies in the parent collide against other bodies in the child and vice-versa.
false true Bodies in the parent do not collide against other bodies in the parent.
Bodies in the child collide against other bodies in the child.
Bodies in the parent collide against other bodies in the child and vice-versa
false false Bodies in the parent do not collide against other bodies in the parent.
Bodies in child do not collide against each other.
Bodies in the parent collide against other bodies in the child and vice-versa.

I believe what this code does is completely ignore the self_collide tag of nested models and treat all bodies as though they were in the parent model.

I've also created a simple SDF file to demonstrate the different behaviors with AI assistance:
https://gist.github.com/azeey/3f2392c0fc05a586d56869da23f28d40

All four cases are laid out side-by-side:

  • Case 1 (Parent: true, Child: true): Located at x = -4.5
  • Case 2 (Parent: true, Child: false): Located at x = -1.5
  • Case 3 (Parent: false, Child: true): Located at x = 1.5
  • Case 4 (Parent: false, Child: false): Located at x = 4.5

For each case, three tests run independently:

  1. PP (Parent-Parent) at y = -1.5: A parent-level dropper (red sphere) falls onto a parent-level platform (red box).
  2. CC (Child-Child) at y = 0.0: A nested child-level dropper (blue sphere) falls onto a nested child-level platform (blue box).
  3. PC (Parent-Child) at y = 1.5: A nested child-level dropper (blue sphere) falls onto a parent-level platform (red box).

DART

Screen.Recording.2026-06-24.at.15.50.13.mov

MuJoCo

Screen.Recording.2026-06-24.at.15.50.59.mov

Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment on lines +777 to +778
// Parent body is worldbody.
childPoseInParent = _rootSdfModel.RawPose() * childPoseInRoot;

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.

This was discovered by Gemini, but I agree with it. The root model here might be a nested model itself. However, if we're the parent body is null, we need it's pose relative to the worldbody (absolute pose) rather than using RawPose which is the pose relative to its parent model.

Comment thread mujoco/src/SDFFeatures.cc
azeey and others added 3 commits June 26, 2026 08:28
* mujoco: Implement AttachFixedJointFeature and DetachJointFeature

- Implemented `AttachFixedJoint` using MuJoCo equality weld constraints.
- Optimized `AttachFixedJoint` and `DetachJoint` to reuse and toggle constraints (`active = 0/1`) to avoid expensive `mjModel` recompilations.
- Implemented `CastToFixedJoint` to identify fixed joints.
- Added comprehensive unit tests in `detachable_joint.cc`.

Generated-by: Gemini 3.1 Pro

---------

Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Set compiler.degree option to false to prevent MuJoCo from interpreting joint limits specified in radians as degrees.
Also added a test case asserting the compiled joint limits of joint_limit_test.

Generated-by: Gemini 3.5 Flash

Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly force-pushed the shameek/mj_nested_models branch from bade604 to c71af2b Compare June 26, 2026 15:28
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly requested a review from azeey June 26, 2026 17:20

@azeey azeey left a comment

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.

Disclaimer: I've used Gemini to help with the reviews.

Comment thread mujoco/src/EntityManagementFeatures.cc
Comment thread mujoco/src/EntityManagementFeatures.cc Outdated
Comment thread mujoco/src/EntityManagementFeatures.cc
Comment thread mujoco/src/SDFFeatures.cc Outdated
Comment thread mujoco/src/EntityManagementFeatures.cc Outdated
Comment thread mujoco/src/EntityManagementFeatures.cc Outdated
Comment thread mujoco/src/SDFFeatures.cc Outdated
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly requested a review from azeey July 6, 2026 21:07

@azeey azeey left a comment

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.

Looks great! Thanks for iterating. Just one more small comment.

Comment thread mujoco/src/EntityManagementFeatures.cc Outdated
Signed-off-by: Shameek Ganguly <shameek@intrinsic.ai>
@shameekganguly
shameekganguly force-pushed the shameek/mj_nested_models branch from 6e73e36 to f7b29e0 Compare July 9, 2026 14:38
@azeey
azeey enabled auto-merge (squash) July 9, 2026 16:24
@azeey
azeey merged commit 06f474d into main Jul 9, 2026
14 checks passed
@azeey
azeey deleted the shameek/mj_nested_models branch July 9, 2026 16:45
@github-project-automation github-project-automation Bot moved this from In review to Done in Core development Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants