Skip to content

Fix eq_objtype mismatch for joint equality constraints#2459

Merged
vreutskyy merged 3 commits into
newton-physics:mainfrom
vreutskyy:2170-equality-constraints
Apr 16, 2026
Merged

Fix eq_objtype mismatch for joint equality constraints#2459
vreutskyy merged 3 commits into
newton-physics:mainfrom
vreutskyy:2170-equality-constraints

Conversation

@vreutskyy

@vreutskyy vreutskyy commented Apr 15, 2026

Copy link
Copy Markdown
Member

Description

Fix eq_objtype mismatch between Newton and native MuJoCo for joint equality constraints.

Part of #2170

Root cause

Newton's solver passed objtype=mujoco.mjtObj.mjOBJ_JOINT to spec.add_equality(), causing eq_objtype=3 in the compiled model. Native MuJoCo (from XML) produces eq_objtype=0. The spec API and XML parser set this field differently.

Fix

Don't pass objtype to spec.add_equality() for joint equality constraints. MuJoCo sets it automatically, matching the XML behavior.

Impact

  • FrankaEmikaPanda and FrankaFr3V2 no longer need {"eq_", "neq"} in model_skip_fields
  • Also fixes mimic constraint path (same issue)

Checklist

  • New or existing tests cover these changes
  • The documentation is up to date with these changes
  • CHANGELOG.md has been updated (if user-facing change) — N/A, internal fix

Test plan

uv run python -m unittest newton.tests.test_mujoco_solver.TestEqualityJointObjType
# 1 test OK

uv run python -m unittest newton.tests.test_menagerie_mujoco.TestMenagerie_FrankaEmikaPanda.test_model_comparison
# OK (no eq_ skip needed)

Bug fix

Steps to reproduce:

  1. Create a model with joint equality constraints
  2. Compare eq_objtype between Newton's mjwarp model and native MuJoCo
  3. Newton has 3 (mjOBJ_JOINT), native has 0

Minimal reproduction:

import mujoco

# Spec API (Newton's path): eq_objtype = 3
spec = mujoco.MjSpec()
b1 = spec.worldbody.add_body()
b1.add_joint(name="j1", type=mujoco.mjtJoint.mjJNT_HINGE)
b1.add_geom(size=[0.1, 0, 0])
eq = spec.add_equality(objtype=mujoco.mjtObj.mjOBJ_JOINT)
eq.type = mujoco.mjtEq.mjEQ_JOINT
eq.name1 = "j1"
m = spec.compile()
print(m.eq_objtype)  # [3]

# XML (native path): eq_objtype = 0
m2 = mujoco.MjModel.from_xml_string("""
<mujoco>
  <worldbody>
    <body><joint name="j1" type="hinge"/><geom size="0.1"/></body>
  </worldbody>
  <equality><joint joint1="j1"/></equality>
</mujoco>
""")
print(m2.eq_objtype)  # [0]

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed MuJoCo equality constraint generation so joint and mimic constraints match native MuJoCo behavior.
  • Tests

    • Added a regression test to validate equality-constraint object type matches native MuJoCo.
    • Updated test configurations to tighten tolerances and reduce robot-specific model skips for broader compatibility.

Don't pass objtype to spec.add_equality() for joint equality
constraints. The spec API sets eq_objtype=3 when objtype is specified,
but MuJoCo's XML parser produces eq_objtype=0. Omitting objtype
matches the XML behavior.

Remove eq_/neq model skip from FrankaEmikaPanda and FrankaFr3V2 —
both pass model comparison without it. Update Fr3V2 dynamics comment
(qpos drift is from body_ipos diff, not equality constraints).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 8b75a9c8-7c3b-469e-b9cc-7452d2032c78

📥 Commits

Reviewing files that changed from the base of the PR and between 3957668 and 9796c4b.

📒 Files selected for processing (2)
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_mujoco_solver.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • newton/tests/test_mujoco_solver.py
  • newton/_src/solvers/mujoco/solver_mujoco.py

📝 Walkthrough

Walkthrough

MuJoCo equality-constraint creation for joint and mimic constraints now calls spec.add_equality() without the explicit objtype argument; constraint eq.type and other fields remain set as before. Tests were adjusted to stop skipping equality-related model fields, and a new test asserts eq_objtype parity with native MuJoCo.

Changes

Cohort / File(s) Summary
Solver equality constraint creation
newton/_src/solvers/mujoco/solver_mujoco.py
Removed explicit objtype=mujoco.mjtObj.mjOBJ_JOINT argument from spec.add_equality() calls for EqType.JOINT and mimic-exported joint equalities; still assigns eq.type, eq.active, eq.name1, eq.name2, eq.data, and solref/solimp fields.
Test configuration cleanup
newton/tests/test_menagerie_mujoco.py
Removed robot-specific model_skip_fields entries that previously skipped model fields prefixed with eq_/neq for Franka tests; retained other per-robot settings (num_steps, fk_enabled, tolerances, backfill_model).
Regression test for equality constraints
newton/tests/test_mujoco_solver.py
Added TestEqualityJointObjType::test_joint_equality_objtype_matches_native() which builds a Newton model with a joint equality, loads an equivalent native MJCF model, and asserts mj_model.eq_objtype and neq match native values.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main change: fixing an eq_objtype mismatch for joint equality constraints, which is the core objective of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@newton/tests/test_mujoco_solver.py`:
- Around line 8810-8816: Replace the warp-path-specific access to
solver.mjw_model.eq_objtype with the backend-agnostic
solver.mj_model.eq_objtype, compare the full arrays
(solver.mj_model.eq_objtype.numpy().flatten()) to native_model.eq_objtype (not
just [:1]), and add an assertion that solver.mj_model.neq (or mj_model.neq)
matches the first element where appropriate so compile-time metadata and
number-of-equalities are verified consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 6e7d50e1-94ef-44e4-97f5-76395c6a1483

📥 Commits

Reviewing files that changed from the base of the PR and between b09dfc4 and 6d89e58.

📒 Files selected for processing (3)
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_menagerie_mujoco.py
  • newton/tests/test_mujoco_solver.py

Comment thread newton/tests/test_mujoco_solver.py Outdated
@vreutskyy vreutskyy requested a review from camevor April 15, 2026 14:47
@codecov

codecov Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

vreutskyy and others added 2 commits April 15, 2026 16:59
Use solver.mj_model (backend-agnostic) instead of solver.mjw_model.
Assert neq matches first, then compare full eq_objtype arrays instead
of slicing [:1].

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@camevor camevor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@vreutskyy vreutskyy added this pull request to the merge queue Apr 16, 2026
Merged via the queue into newton-physics:main with commit 779b126 Apr 16, 2026
25 checks passed
preist-nvidia added a commit to preist-nvidia/newton that referenced this pull request May 4, 2026
The pre-release audit found user-facing commits that landed since v1.1.0
without an [Unreleased] entry. Backfill five of them here. Kamino-related
commits (newton-physics#2280, newton-physics#2517, newton-physics#2554, newton-physics#2575) are intentionally omitted: Kamino is
still alpha and not currently tracked in CHANGELOG.

- Changed: contact-conversion overhead reduction in SolverMuJoCo
  ([newton-physicsGH-2393](newton-physics#2393))
- Fixed: target_voxel_size ignored on the texture-SDF path
  ([newton-physicsGH-2464](newton-physics#2464))
- Fixed: Newton-to-mujoco-warp material-combination mismatch
  ([newton-physicsGH-2439](newton-physics#2439))
- Fixed: eq_objtype mismatch on joint equality / mimic constraints in
  SolverMuJoCo ([newton-physicsGH-2459](newton-physics#2459))
- Fixed: _tiled_sum_kernel launch-dim handling under warp-lang 1.13
  ([newton-physicsGH-2546](newton-physics#2546))
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.

2 participants