Skip to content

Remove deprecated Model.mujoco.dof_passive_damping#3623

Open
adenzler-nvidia wants to merge 4 commits into
newton-physics:mainfrom
adenzler-nvidia:adenzler/remove-dof-passive-damping
Open

Remove deprecated Model.mujoco.dof_passive_damping#3623
adenzler-nvidia wants to merge 4 commits into
newton-physics:mainfrom
adenzler-nvidia:adenzler/remove-dof-passive-damping

Conversation

@adenzler-nvidia

@adenzler-nvidia adenzler-nvidia commented Jul 23, 2026

Copy link
Copy Markdown
Member

Description

Remove Model.mujoco.dof_passive_damping, deprecated in 1.3.0 in favor of Model.joint_damping: the runtime alias on the mujoco namespace, the mujoco:dof_passive_damping custom attribute, and its finalize-time merge into joint_damping with the conflict check.

The custom attribute was doing double duty as a parsing channel, so the removal re-homes both import paths:

  • USD: mjc:damping now resolves through SchemaResolverMjc into joint_damping, like the other direct-mapped MuJoCo attributes (mjc:armature, mjc:frictionloss). It resolves via a new damping_per_rad schema key because MuJoCo authors damping in SI units (per radian for angular DOFs), unlike the USD per-degree convention behind the plain damping key. Behavior change: mjc:damping is no longer parsed implicitly when MuJoCo custom attributes are registered — pass schema_resolvers=[..., SchemaResolverMjc()] to ModelBuilder.add_usd() when importing MuJoCo-authored USD (noted in the changelog).
  • MJCF: hinge/slide damping was already parsed natively and is unaffected. Ball-joint damping, however, had only ever reached joint_damping through the removed custom-attribute merge — surfaced by the Cassie menagerie comparison (achilles-rod and loop-closure ball joints losing their damping="0.01"). The MJCF importer now parses it natively in the ball branch, mirroring its frictionloss handling.

The second commit removes the now-orphaned namespace deprecated-alias machinery (AttributeNamespace.add_deprecated_alias, the alias branches in __getattr__/__setattr__, the namespace-attribute collision guard, and the coupled solver's compaction filter that existed solely to skip alias entries); the removed alias was its only user.

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)

Test plan

uv run --extra dev -m newton.tests --strict-warnings -k test_mujoco_solver
uv run --extra dev -m newton.tests --strict-warnings -k test_import_usd
uv run --extra dev -m newton.tests --strict-warnings -k test_import_mjcf
uv run --extra dev -m newton.tests --strict-warnings -k test_schema_resolver
uv run --extra dev -m newton.tests --strict-warnings -k test_coupled_solver
uv run --extra dev -m newton.tests --strict-warnings -k test_model
uvx pre-commit run -a

All pass, including test_mjc_damping_from_usd_via_schema_resolver (now exercising the resolver path end to end) and the TestMenagerie_AgilityCassie model comparison that guards the ball-joint damping fix.

Summary by CodeRabbit

  • New Features
    • Added support for importing per-radian joint damping (damping_per_rad) from USD.
    • MJCF ball joints now preserve authored damping values.
  • Breaking Changes
    • Removed the deprecated dof_passive_damping alias; use joint_damping instead.
    • USD MuJoCo damping resolution now requires explicitly registering the MuJoCo schema resolver to map mjc:damping into joint_damping.
  • Documentation
    • Updated MuJoCo solver docs to reflect removal of the deprecated alias behavior.
  • Tests
    • Expanded import test coverage for additional MJCF behaviors and USD resolver registration.

Remove the dof_passive_damping custom attribute, its finalize-time
merge into joint_damping, and the deprecated runtime alias on the
mujoco namespace (deprecated in 1.3.0); use Model.joint_damping.

USD mjc:damping now resolves through SchemaResolverMjc like the
other direct-mapped MuJoCo attributes (armature, frictionloss),
via a new damping_per_rad schema key: MuJoCo authors damping in SI
units, so it bypasses the USD per-degree convention that applies to
the plain damping key on angular DOFs. It is no longer parsed
implicitly when MuJoCo custom attributes are registered; pass
SchemaResolverMjc in schema_resolvers when importing MuJoCo-authored
USD.

The MJCF importer now parses damping on ball joints natively,
mirroring its frictionloss handling; ball-joint damping previously
reached joint_damping only through the removed custom-attribute
merge (surfaced by the Cassie menagerie comparison). Hinge and
slide damping was already parsed natively and is unaffected.
Remove AttributeNamespace.add_deprecated_alias and its alias lookup
in __getattr__/__setattr__; the dof_passive_damping alias was its
only user. Also drop the coupled solver's compaction filter and the
namespace-attribute collision guard that existed solely to skip
alias entries.
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

MuJoCo damping import now supports explicit per-radian USD mappings and MJCF ball-joint damping propagation. The deprecated dof_passive_damping alias and related namespace plumbing are removed, with documentation and import tests updated.

Changes

MuJoCo damping behavior

Layer / File(s) Summary
Remove deprecated damping alias
newton/_src/solvers/mujoco/solver_mujoco.py, newton/_src/sim/model.py, newton/_src/solvers/coupled/solver_coupled.py, docs/solvers/mujoco.rst, CHANGELOG.md
Removes the deprecated alias, finalizer wiring, namespace handling, coupled projection exclusion, and related documentation.
Resolve USD damping per radian
newton/_src/usd/schemas.py, newton/_src/utils/import_usd.py, newton/tests/test_import_usd.py
Maps mjc:damping to damping_per_rad, applies source-aware unit conversion for revolute and D6 joints, and explicitly registers schema resolvers in the USD import test.
Propagate MJCF ball-joint damping
newton/_src/utils/import_mjcf.py, newton/tests/test_import_mjcf.py
Parses native ball-joint damping with default fallback and passes it to builder.add_joint_ball; related MJCF parsing coverage is updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ModelBuilder
  participant SchemaResolverMjc
  participant USDImporter
  participant Model
  ModelBuilder->>SchemaResolverMjc: Resolve mjc:damping
  SchemaResolverMjc->>USDImporter: Return damping_per_rad
  USDImporter->>Model: Populate joint_damping
Loading

Possibly related PRs

Suggested reviewers: eric-heiden

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately matches the main change: removing the deprecated Model.mujoco.dof_passive_damping alias.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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.

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

🧹 Nitpick comments (1)
newton/_src/utils/import_usd.py (1)

1755-1766: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate SI-vs-legacy damping resolution logic.

The damping/damping_per_rad resolution and its paired conditional /DegreesToRadian conversion is duplicated almost verbatim between the single-DOF path (resolve_dof_params, lines 1571-1583 and 1642) and this D6 path. If the priority/conversion rule ever needs a fix, both copies must be updated in lockstep.

♻️ Suggested extraction
+def _resolve_dof_damping(
+    R,
+    prim,
+    default_joint_damping: float,
+    verbose: bool,
+) -> tuple[float, bool, bool]:
+    """Return (damping, authored, is_si) resolving damping_per_rad (SI) over legacy damping (per-degree)."""
+    _damping_usd = R.get_value(prim, prim_type=PrimType.JOINT, key="damping", default=None, verbose=verbose)
+    _damping_per_rad_usd = R.get_value(
+        prim, prim_type=PrimType.JOINT, key="damping_per_rad", default=None, verbose=verbose
+    )
+    damping_si = _damping_per_rad_usd is not None
+    damping_authored = damping_si or _damping_usd is not None
+    if damping_si:
+        return _damping_per_rad_usd, damping_authored, damping_si
+    if damping_authored:
+        return _damping_usd, damping_authored, damping_si
+    return default_joint_damping, damping_authored, damping_si

Then both resolve_dof_params and the D6 branch call _resolve_dof_damping(...) and apply damping / DegreesToRadian if damping_authored and not damping_si else damping for angular DOFs.

Also applies to: 1963-1965

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@newton/_src/utils/import_usd.py` around lines 1755 - 1766, Extract the shared
SI-versus-legacy damping selection and authored-status logic from
resolve_dof_params and the D6 branch into a helper such as _resolve_dof_damping.
Update both callers, including the later D6 occurrence, to use the helper and
retain the existing damping / DegreesToRadian conversion only for authored
non-SI angular damping.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@newton/_src/utils/import_usd.py`:
- Around line 1755-1766: Extract the shared SI-versus-legacy damping selection
and authored-status logic from resolve_dof_params and the D6 branch into a
helper such as _resolve_dof_damping. Update both callers, including the later D6
occurrence, to use the helper and retain the existing damping / DegreesToRadian
conversion only for authored non-SI angular damping.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9cb0517d-00ff-412d-b78f-2f0e158a5120

📥 Commits

Reviewing files that changed from the base of the PR and between 3138037 and 008aa12.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • docs/solvers/mujoco.rst
  • newton/_src/sim/model.py
  • newton/_src/solvers/coupled/solver_coupled.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/_src/usd/schemas.py
  • newton/_src/utils/import_mjcf.py
  • newton/_src/utils/import_usd.py
  • newton/tests/test_import_mjcf.py
  • newton/tests/test_import_usd.py
💤 Files with no reviewable changes (3)
  • docs/solvers/mujoco.rst
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_import_mjcf.py

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.11111% with 4 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
newton/_src/solvers/mujoco/solver_mujoco.py 86.95% 3 Missing ⚠️
newton/_src/utils/import_usd.py 94.11% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Signed-off-by: Alain Denzler <adenzler@nvidia.com>
Re-register mujoco:dof_passive_damping with usd_attribute_name="mjc:damping"
so USD files authored with the MuJoCo convention continue to have their
passive joint damping picked up when SolverMuJoCo.register_custom_attributes
is called, without requiring an explicit SchemaResolverMjc.

The deprecated runtime alias (Model.mujoco.dof_passive_damping as a proxy
for Model.joint_damping) stays removed. The attribute now lives as a plain
Warp array on model.mujoco; its values are copied into joint_damping by the
finalizer at model build time, matching the pre-1.3 behaviour.

The MJCF path is unaffected: the importer already parses damping directly
into joint_damping for hinge/slide joints (and ball joints since this PR),
so no mjcf_attribute_name is registered here.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
newton/_src/solvers/mujoco/solver_mujoco.py (1)

7-7: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Remove the deprecated damping staging path entirely.

Renaming the finalizer does not remove the deprecated behavior: it still performs the old conflict check and merge into model.joint_damping. Lines 994-1009 also register dof_passive_damping with assignment=MODEL, so model.mujoco.dof_passive_damping remains exposed. With SchemaResolverMjc now resolving mjc:damping through damping_per_rad, this creates a duplicate import path that can falsely reject converted values. Remove the finalizer, registration, and unused math import; let the schema resolver own this mapping and add a regression check that the deprecated field is absent.

Per the PR objectives, SchemaResolverMjc should resolve USD damping directly into joint_damping.

Also applies to: 123-156, 994-1010

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@newton/_src/solvers/mujoco/solver_mujoco.py` at line 7, Remove the deprecated
damping finalizer, its dof_passive_damping registration with assignment=MODEL,
and the now-unused math import in solver_mujoco.py. Ensure SchemaResolverMjc
resolves USD mjc:damping directly into joint_damping without the legacy
conflict-check or merge path. Add a regression check confirming
model.mujoco.dof_passive_damping is absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@newton/_src/solvers/mujoco/solver_mujoco.py`:
- Line 7: Remove the deprecated damping finalizer, its dof_passive_damping
registration with assignment=MODEL, and the now-unused math import in
solver_mujoco.py. Ensure SchemaResolverMjc resolves USD mjc:damping directly
into joint_damping without the legacy conflict-check or merge path. Add a
regression check confirming model.mujoco.dof_passive_damping is absent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: ed361e2f-8079-41f8-8618-747d799a914c

📥 Commits

Reviewing files that changed from the base of the PR and between 584d8eb and 075eee1.

📒 Files selected for processing (1)
  • newton/_src/solvers/mujoco/solver_mujoco.py

Comment on lines +497 to +500
# MuJoCo damping is authored in SI units (per radian for angular
# DOFs), unlike the USD per-degree convention behind the plain
# "damping" key, so it resolves through the _per_rad variant.
"damping_per_rad": SchemaAttribute("mjc:damping", None),

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.

🟠 Please also consume this mapping for spherical joints in newton/_src/utils/import_usd.py. The spherical branch currently calls add_joint_ball(**joint_params) without resolving damping_per_rad, so resolver-only imports silently discard authored mjc:damping. MuJoCo ball joints have three angular DOFs, and their scalar damping applies uniformly to all three. Resolve the source-aware value, broadcast it across the three DOFs, pass it through add_joint_ball(damping=...), and add a resolver-only spherical-joint regression test.

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