mujoco: support joint mimic constraints#990
Merged
Merged
Conversation
- Support universal joints in the MuJoCo plugin by creating two hinge joints in series and two actuators. - Add basic state integration tests and out-of-bounds DOF safety checks across MuJoCo, Dartsim, and Bullet-Featherstone wrappers. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
- Support screw joints in the MuJoCo physics engine plugin using coupled slide/hinge joints and equality constraints. - Make the rotational hinge joint the primary axis in the MuJoCo plugin, fully aligning its coordinate units (radians) with DARTsim. - Add a new anchored screw joint model with static damping in the test world. - Add a unified screw joint integration test suite inside joint_features, validating kinematic coupling and damping decay. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
…DF strings - Revert test.world back to its pristine state to ensure all other engine tests (dartsim, tpe) expecting exactly 9 models pass cleanly. - Migrate Universal joint checks in SDFFeatures_TEST to load a self-contained SDF string. - Migrate Screw joint coupling and damping checks in joint_features to load a self-contained SDF string. Generated-by: Gemini 3.0 Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
- Verify screw joint position limits enforcement across DARTsim and MuJoCo plugins. - Enforce position limits purely on the translational Slide joint to allow exact kinematic constraint coupling without solver damping. Generated-by: Gemini 3.0 Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
- Add an eqIndices vector to JointInfo to track equality constraint indices compiled in the mjModel. - Resolve and store associated equality constraint indices during model compilation in resolveJointIndices. - Dynamically resolve active degrees of freedom by subtracting eqIndices.size() from the physical joints compiled on the child body in GetJointDegreesOfFreedom. - Refactor simultaneous position and velocity updates to utilize eqIndices and updateCoupledSecondaryJoint helper to avoid code duplication. - Safely ensure Gazebo API queries are always backed by the actual compiled MuJoCo solver state, preventing out-of-bounds coordinate access. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
- Add convertScrewThreadPitch helper function to convert SDFormat screw thread pitch (m/rev) to MuJoCo coordinate ratio (m/rad). - Document screw thread pitch conversion helper along with physical units. - Deduplicate pitch conversion logic in Slide limits and equality constraint ratio calculations. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
- Replace manual index assignments with robust C++ std::fill zero-initialization. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Replace implicit body ID comparisons and search loops with a high-performance pointer-based constraint tracking scheme that stores direct mjsEquality* pointers and caches the resolved screwEqIndex in O(1) time. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Implement joint mimic features in the MuJoCo physics engine plugin, supporting coupling for standard 1-DOF and multi-DOF joints. Because MuJoCo solves joint equality constraints as soft force constraints, dynamic keyframe state-teleportation (e.g. SetJointPosition) without coordinate alignment generates severe physical spring-force solver spikes. We resolve this by performing automated C++ coordinate state propagation to pre-align downstream follower states in the active state arrays at the keyframing boundary. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Sdf Joint degree-of-freedom queries are fired by Gazebo Sim's model parser before the active world spec has undergone its first dynamic MuJoCo compilation pass. Querying standard compiled tables during this phase results in false-positive safety violations and startup failures. We resolve this by implementing a static spec DOM tree fallback path inside GetJointDegreesOfFreedom when query indices are uncompiled (out-of-bounds). We also add a virtual destructor to the Base class to make it polymorphic for safe casting, and add the GetJointDegreesOfFreedomPreCompiled unit test to assert this fallback path using a dummy model-swap trick. Generated-by: Gemini 3.0 Pro Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Contributor
|
cool demos! we need to add those to gz-sim example worlds once this gets in |
iche033
reviewed
Jun 2, 2026
| if(this->PhysicsEngineName(name) != "bullet-featherstone" && | ||
| this->PhysicsEngineName(name) != "mujoco") | ||
| { | ||
| GTEST_SKIP(); |
Contributor
There was a problem hiding this comment.
based on #930 (comment), I think we need to be using continue instead of GTEST_SKIP?
Contributor
Author
There was a problem hiding this comment.
I think this is actually okay. The different tests are ran as different executables. The for loop is iterating through potential plugins found in each shared library. In theory, a shared library can have multiple plugins, but none of our physics engines do that.
| for (const std::string &name : this->pluginNames) | ||
| { | ||
| CHECK_SUPPORTED_ENGINE(name, "mujoco") | ||
| CHECK_SUPPORTED_ENGINE(name, "bullet-featherstone") |
Contributor
There was a problem hiding this comment.
Just realized these macros call GTEST_SKIP which may not be what we want?
Comment on lines
+204
to
+205
| if (c.followerJointInfo.lock() == _followerJoint && | ||
| c.followerDof == _followerDof) |
Contributor
There was a problem hiding this comment.
minor optimization to short circuit the check if DOF does not match so avoid doing the lock()
Suggested change
| if (c.followerJointInfo.lock() == _followerJoint && | |
| c.followerDof == _followerDof) | |
| if (c.followerDof == _followerDoft && | |
| c.followerJointInfo.lock() == _followerJoin) |
Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
iche033
approved these changes
Jun 4, 2026
yaswanth1701
pushed a commit
to yaswanth1701/gz-physics
that referenced
this pull request
Jun 6, 2026
Implement joint mimic features in the MuJoCo physics engine plugin, supporting coupling for standard 1-DOF and multi-DOF joints. Because MuJoCo solves joint equality constraints as soft force constraints, dynamic keyframe state-teleportation (e.g. SetJointPosition) without coordinate alignment generates severe physical spring-force solver spikes. We resolve this by performing automated C++ coordinate state propagation to pre-align downstream follower states in the active state arrays at the keyframing boundary. Generated-by: Gemini 3.0 Pro --------- Signed-off-by: Addisu Z. Taddese <addisuzt@intrinsic.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎉 New feature
Part of #299
Summary
Implement joint mimic features in the MuJoCo physics engine plugin, supporting coupling for standard 1-DOF and multi-DOF joints. Because MuJoCo solves joint equality constraints as soft force constraints, dynamic keyframe state-teleportation (e.g. SetJointPosition) without coordinate alignment generates severe physical spring-force solver spikes. We resolve this by performing automated C++ coordinate state propagation to pre-align downstream follower states in the active state arrays at the keyframing boundary.
Test it
Screen capture
Screen.Recording.2026-05-27.at.16.54.47.mp4
A dynamic spring-suspended scissor lift. It showcases multi-stage joint mimic constraints using an open-tree topology, keeping the cargo platform perfectly flat and stable as a heavy rolling payload shifts the suspension's gravity center under real-time spring-damper physics!
File: https://gist.github.com/azeey/acf33ed620084a4e82e032edc0bd4bce#file-scissor_lift_demo-sdf
Screen.Recording.2026-05-27.at.16.36.10.mp4
A concentric, stacked planetary Orrery. Driven by a single master PID force controller, it showcases 9 high-precision mimic joint constraints—simulating accurate Keplerian orbital speed ratios and the perfect synchronous tidal locking of the Moon as they spin in harmony.
File: https://gist.github.com/azeey/acf33ed620084a4e82e032edc0bd4bce#file-orrery_demo-sdf
Checklist
codecheckpassed (See contributing)Generated-by: Gemini 3.0 Pro
Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining
Signed-off-byandGenerated-bymessages.Backports: If this is a backport, please use Rebase and Merge instead.