Skip to content

fix(binding_utils): compare jnt_type as int so hinge/slide joints pass on MuJoCo >= 3.12 - #832

Open
quinncheong wants to merge 1 commit into
ARISE-Initiative:masterfrom
quinncheong:fix/jnt-type-int-compare
Open

quinncheong wants to merge 1 commit into
ARISE-Initiative:masterfrom
quinncheong:fix/jnt-type-int-compare

Conversation

@quinncheong

@quinncheong quinncheong commented Oct 6, 2026 •

Copy link
Copy Markdown

What this does

Part of #831: this is item 2, the enum comparison. Item 1, the 1.5.3 release request, stays open.

MjModel.get_joint_qpos_addr and get_joint_qvel_addr read self.jnt_type[joint_id], which is a
numpy.int32, and then check joint_type in (mjJNT_HINGE, mjJNT_SLIDE). The in check calls
mjtJoint.__eq__(numpy.int32), and from MuJoCo 3.12.0 on that returns False. Every hinge and slide
joint then fails the assert, so robosuite.make(...) raises a bare AssertionError during the
first reset. This PR converts the value with int() at both sites. int compares correctly with
mjtJoint on every MuJoCo version tested (3.9.0, 3.11.0, 3.12.0, 3.14.0, 3.15.0).

The cause is the enum operator rewrite in pybind11 3.1.0 (pybind/pybind11#5887, listed in the
v3.1.0 release notes). MuJoCo 3.11.0 builds its Python bindings against pybind11 v3.0.4 and 3.12.0
against v3.1.0 (python/mujoco/CMakeLists.txt at each tag). I have reported the comparison behaviour
to pybind11 as pybind/pybind11#6192. Whatever happens there, MuJoCo wheels built against 3.1.0 are
already on PyPI, so the int() conversion is the robust option on robosuite's side.

Master pins mujoco<3.10 (#814), so this does not change behaviour on the supported range, and the
repo's CI (which installs within that pin) cannot exercise the failure. The new test passes on both
sides of the pin and is a guard for when the cap is lifted. Lifting the cap also needs the mj_fullM
signature change from MuJoCo 3.10 (reported in #817) handled in controllers/parts/controller.py;
that is not part of this PR. If you would rather land this as part of a single cap-lifting PR,
I am happy for it to be folded in there.

How it was tested

  • Added tests/test_utils/test_binding_utils.py::test_joint_addrs_all_joint_types. It builds a
    4-joint MJCF model (free, ball, hinge, slide) and checks the qpos/qvel addresses of each joint.
  • mujoco 3.15.0, master without the fix: 1 failed (AssertionError at binding_utils.py:528).
  • mujoco 3.15.0, with the fix: 1 passed.
  • mujoco 3.9.0 (inside the current pin), with the fix: 1 passed.
  • Full suite (pytest with NUMBA_DISABLE_JIT=1 as in run-tests.yaml, but locally with
    MUJOCO_GL=egl and CPython 3.11) on mujoco 3.9.0, mink 0.0.5: 262 passed, 61 skipped with the fix;
    261 passed, 61 skipped on master 5ce6643. The one extra pass is the new test.
  • black 22.10.0 and isort (repo pyproject settings): clean.

How to checkout & try? (for the reviewer)

MUJOCO_GL=egl pytest -sx tests/test_utils/test_binding_utils.py
# to see the original failure: pip install "mujoco>=3.12" and run the same test on master

This PR was prepared with an AI coding agent (Claude Code); I reviewed the change and ran the tests above before opening it.

…s on MuJoCo >= 3.12

From MuJoCo 3.12 the mjtJoint enum compares unequal to numpy integers when the enum is on the
left, so the hinge/slide assert in get_joint_qpos_addr/get_joint_qvel_addr fails for every arm joint.

This branch has not been deployed

No deployments
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.

1 participant