Skip to content

Add passive stiffness and damping support for joints in MuJoCo solver#1082

Merged
adenzler-nvidia merged 18 commits into
newton-physics:mainfrom
jvonmuralt:passive-stiffness-damping
Dec 1, 2025
Merged

Add passive stiffness and damping support for joints in MuJoCo solver#1082
adenzler-nvidia merged 18 commits into
newton-physics:mainfrom
jvonmuralt:passive-stiffness-damping

Conversation

@jvonmuralt

@jvonmuralt jvonmuralt commented Nov 13, 2025

Copy link
Copy Markdown
Member

Description

Newton Migration Guide

Please ensure the migration guide for warp.sim users is up-to-date with the changes made in this PR.

  • The migration guide in docs/migration.rst is up-to date

Before your PR is "Ready for review"

  • Necessary tests have been added and new examples are tested (see newton/tests/test_examples.py)
  • Documentation is up-to-date
  • Code passes formatting and linting checks with pre-commit run -a

Summary by CodeRabbit

  • New Features

    • Per-joint stiffness and passive damping supported and propagated to DOF-level, exposed as model attributes and included in world-expanded fields.
    • Import now parses actuator position/velocity gains and maps them into per-DOF target gains.
  • Chores

    • Renamed default joint target parameters and integrated actuator parsing into the import flow.
  • Tests

    • New end-to-end tests validate import, DOF/actuator mappings, and multi-world propagation of stiffness/damping (duplicate test insertions present).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Nov 13, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds per-joint passive stiffness and per-DOF passive damping support end-to-end: MJCF/USD import and actuator parsing read gains/custom attributes; SolverMuJoCo registers and propagates them into expanded world fields; the Warp kernel conditionally writes jnt_stiffness and dof_damping; tests validate import and runtime propagation.

Changes

Cohort / File(s) Summary
Warp kernels
newton/_src/solvers/mujoco/kernels.py
Extended update_joint_dof_properties_kernel signature to accept joint_stiffness and joint_damping; added conditional writes to per-joint jnt_stiffness and per-DOF dof_damping alongside existing armature/friction/solimp/solref/limit handling.
MuJoCo solver integration
newton/_src/solvers/mujoco/solver_mujoco.py
Registered new MuJoCo custom attributes for stiffness/damping, read them during model import, propagated values into joint params during geo/joint setup, added jnt_stiffness/dof_damping to expanded model fields, and threaded them into the kernel launch to populate mjw_model.jnt_stiffness and mjw_model.dof_damping.
MJCF import / actuator parsing
newton/_src/utils/import_mjcf.py
Renamed defaults (default_joint_stiffness/dampingdefault_joint_target_ke/kd), added parse_actuators to extract position/velocity actuator target_ke/target_kd per-DOF, integrated actuator parsing into MJCF import flow, and emit warnings for unknown joints.
Tests
newton/tests/test_import_mjcf.py, newton/tests/test_import_usd.py, newton/tests/test_mujoco_solver.py
Added tests covering MJCF/USD import of stiffness/damping, actuator gain parsing, and multi-world propagation to MuJoCo fields. The diff contains duplicated insertions of the USD and MuJoCo solver tests (duplicate occurrences noted).
Project metadata
manifest_file, pyproject.toml, requirements.txt
Updated project manifest / metadata files (details not expanded in diff summary).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Import as MJCF/USD Import
    participant Parser as parse_actuators
    participant CA as CustomAttrs (mujoco:stiffness/damping)
    participant Solver as SolverMuJoCo
    participant Kernel as update_joint_dof_properties_kernel
    participant MJ as MuJoCo Model

    Import->>Parser: parse actuator blocks -> per-DOF target_ke/target_kd
    Import->>CA: read/register joint stiffness & damping attributes
    CA->>Solver: attach joint_stiffness / joint_damping to joint params
    Solver->>Kernel: pass joint_stiffness, joint_damping, dof fields, solimp/solref, limits
    note right of Kernel `#DDFFDD`: kernel conditionally writes per-DOF dof_damping and per-joint jnt_stiffness
    Kernel->>MJ: write jnt_stiffness, dof_damping, armature, friction, solimp/solref, limits into MuJoCo model
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Inspect per-joint ↔ per-DOF indexing and boundary arithmetic in kernels.py.
  • Verify custom-attribute registration/reading and expanded field alignment in solver_mujoco.py.
  • Validate actuator parsing, default renames, and messaging in import_mjcf.py.
  • Review added tests and resolve duplicate test insertions in test_import_usd.py and test_mujoco_solver.py.

Possibly related PRs

Suggested reviewers

  • adenzler-nvidia
  • eric-heiden
  • vreutskyy

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add passive stiffness and damping support for joints in MuJoCo solver' directly and clearly describes the main change: adding passive stiffness and damping support. This aligns with the primary objective evident from all file changes across kernels, solver, import utilities, and tests.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5f4a61 and 7ca19e5.

📒 Files selected for processing (5)
  • newton/_src/solvers/mujoco/kernels.py (5 hunks)
  • newton/_src/solvers/mujoco/solver_mujoco.py (9 hunks)
  • newton/tests/test_import_mjcf.py (1 hunks)
  • newton/tests/test_import_usd.py (1 hunks)
  • newton/tests/test_mujoco_solver.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • newton/tests/test_mujoco_solver.py
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-09-22T21:03:39.624Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Applied to files:

  • newton/tests/test_import_usd.py
  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-11-24T08:05:21.390Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.

Applied to files:

  • newton/tests/test_import_usd.py
  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-11-07T01:42:36.906Z
Learnt from: daniela-hase
Repo: newton-physics/newton PR: 1044
File: newton/_src/sensors/tiled_camera_sensor.py:224-256
Timestamp: 2025-11-07T01:42:36.906Z
Learning: In newton/_src/sensors/tiled_camera_sensor.py, the `# noqa: PLC0415` directives on the local PIL imports (lines 224 and 256 in save_color_image and save_depth_image methods) should be kept because they are required by the pre-commit configuration. The local imports are intentional for optional dependency handling.

Applied to files:

  • newton/tests/test_import_usd.py
📚 Learning: 2025-08-12T18:07:17.267Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/utils.py:30-33
Timestamp: 2025-08-12T18:07:17.267Z
Learning: In newton/_src/utils/import_usd.py, the PXR/USD modules are lazily loaded using try-except blocks within the functions (lines 109-111 and 1289-1291) rather than at module import time, making it safe to import parse_usd at the module level without causing import-time failures for users without USD dependencies.

Applied to files:

  • newton/tests/test_import_usd.py
📚 Learning: 2025-09-22T21:03:18.367Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:638-648
Timestamp: 2025-09-22T21:03:18.367Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently only supports additive updates, meaning it assumes n_coords == n_dofs. Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work.

Applied to files:

  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-07-21T19:11:04.077Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 450
File: newton/sim/ik.py:1286-1296
Timestamp: 2025-07-21T19:11:04.077Z
Learning: In Newton's IK system, the JointLimitObjective class intentionally only handles joints where DOF count equals coordinate count (1-1 mapping). This is appropriate because joint limits are typically only meaningful for simple joint types like revolute and prismatic joints, not complex joints like ball or free joints where DOF count != coordinate count.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
🧬 Code graph analysis (3)
newton/tests/test_import_usd.py (1)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
  • register_custom_attributes (151-226)
newton/tests/test_import_mjcf.py (1)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • SolverMuJoCo (77-2040)
  • register_custom_attributes (151-226)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
newton/_src/sim/builder.py (3)
  • add_custom_attribute (622-667)
  • ModelBuilder (70-5411)
  • CustomAttribute (304-394)
newton/_src/sim/model.py (2)
  • ModelAttributeFrequency (49-70)
  • ModelAttributeAssignment (31-46)
🪛 Ruff (0.14.6)
newton/tests/test_import_usd.py

1466-1466: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


1596-1596: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks / Run GPU Benchmarks on AWS EC2
  • GitHub Check: Run GPU Tests / Run GPU Unit Tests on AWS EC2
🔇 Additional comments (6)
newton/_src/solvers/mujoco/solver_mujoco.py (3)

203-226: Custom attributes for passive DOF stiffness/damping are well‑specified

dof_passive_stiffness / dof_passive_damping use JOINT_DOF frequency, MODEL assignment, wp.float32, and correct USD/MJCF attribute names, with a safe default of 0.0. This matches how they’re later indexed and keeps the feature opt‑in by default.


1000-1005: Stiffness/damping import and MuJoCo joint parameter wiring look consistent

Reading dof_passive_stiffness/dof_passive_damping via get_custom_attribute and threading them into joint_params["stiffness"] / ["damping"] for both linear and angular DOFs is consistent with the JOINT_DOF attribute shape and the existing per‑DOF joint construction. The is not None guards preserve backward compatibility when attributes are absent.

Also applies to: 1336-1348, 1414-1421


1670-1696: World expansion and kernel wiring for passive stiffness/damping are aligned

Adding "jnt_stiffness" and "dof_damping" to model_fields_to_expand and extending update_joint_dof_properties to fetch dof_passive_stiffness/damping and pass them into update_joint_dof_properties_kernel, writing to mjw_model.jnt_stiffness and mjw_model.dof_damping, follows the same multi‑world and DOF→MuJoCo joint mapping pattern already used for solimp/solref and margins. This should behave correctly for multi‑DOF and multi‑world setups.

Also applies to: 1817-1881

newton/tests/test_import_mjcf.py (1)

942-1002: MJCF stiffness/damping test gives good DOF‑level coverage

This test nicely validates that MJCF joint stiffness/damping and actuator kp/kv are imported into model.mujoco.dof_passive_* and joint_target_ke/kd at the correct DOF indices for each hinge joint, including joints with and without passive terms and with different actuator configurations.

newton/tests/test_import_usd.py (1)

1463-1621: USD joint stiffness/damping test aligns with custom attributes and gain scaling

The USD test exercises mjc:stiffness/mjc:damping plus angular drive stiffness/damping across three revolute joints and confirms they land in model.mujoco.dof_passive_stiffness/damping and joint_target_ke/kd at the correct DOF indices, using the same math.degrees(1.0) angular gain scaling as verify_usdphysics_parser. This gives solid end‑to‑end coverage for the USD path.

newton/_src/solvers/mujoco/kernels.py (1)

912-937: Kernel support for passive stiffness/damping matches solver‑side mapping

Extending update_joint_dof_properties_kernel with joint_stiffness/joint_damping inputs and jnt_stiffness/dof_damping outputs, and writing:

  • per‑DOF damping into dof_damping[worldid, mjc_dof_index], and
  • per‑MuJoCo‑joint stiffness into jnt_stiffness[worldid, mjc_joint_index]

using the existing joint_mjc_dof_start and dof_to_mjc_joint mapping, is consistent with how solimp/solref and margins are already handled. The optional‑array guards ensure backward compatibility when the new attributes are unset.

Also applies to: 963-995, 997-1027


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.

@codecov

codecov Bot commented Nov 13, 2025

Copy link
Copy Markdown

Codecov Report

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

Files with missing lines Patch % Lines
newton/_src/utils/import_mjcf.py 77.27% 10 Missing ⚠️

📢 Thoughts on this report? Let us know!

@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: 0

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

549-550: Clarify the relationship between default joint stiffness/damping and passive stiffness/damping.

The change from parsing MJCF stiffness/damping attributes to using default_joint_stiffness/default_joint_damping may be confusing. Based on the AI summary and related changes in solver_mujoco.py, it appears:

  • MJCF stiffness/damping attributes are now handled as passive joint properties (stored in custom MuJoCo attributes)
  • target_ke/target_kd are actuator gains (for active control)

However, the comment and variable names don't clearly distinguish these concepts. Consider:

  1. Adding a comment explaining that target_ke/target_kd are actuator gains, not passive properties
  2. Verifying that the MJCF stiffness/damping attributes are still being parsed into the custom MuJoCo attributes (via the mjcf_attribute_name mechanism in register_custom_attributes)
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32adea9 and 0a55d68.

📒 Files selected for processing (4)
  • newton/_src/solvers/mujoco/kernels.py (2 hunks)
  • newton/_src/solvers/mujoco/solver_mujoco.py (8 hunks)
  • newton/_src/utils/import_mjcf.py (2 hunks)
  • newton/tests/test_import_mjcf.py (2 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: shi-eric
Repo: newton-physics/newton PR: 521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:638-648
Timestamp: 2025-09-22T21:03:18.367Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently only supports additive updates, meaning it assumes n_coords == n_dofs. Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work.
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering, despite the general warp documentation suggesting copies are made by default.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-07-14T03:57:29.670Z
Learnt from: Kenny-Vilella
Repo: newton-physics/newton PR: 398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.670Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.

Applied to files:

  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
🧬 Code graph analysis (2)
newton/tests/test_import_mjcf.py (2)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
  • register_custom_attributes (152-192)
newton/_src/sim/builder.py (2)
  • ModelBuilder (70-5101)
  • add_mjcf (1131-1215)
newton/_src/solvers/mujoco/solver_mujoco.py (3)
newton/_src/solvers/mujoco/kernels.py (2)
  • update_joint_stiffness_kernel (932-945)
  • update_dof_properties_kernel (906-928)
newton/_src/sim/builder.py (2)
  • add_custom_attribute (584-629)
  • CustomAttribute (268-358)
newton/_src/sim/model.py (2)
  • ModelAttributeFrequency (49-70)
  • ModelAttributeAssignment (31-46)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
🔇 Additional comments (9)
newton/_src/utils/import_mjcf.py (1)

950-1002: LGTM! Actuator parsing is well-structured.

The new parse_actuators function correctly:

  • Handles position actuators by setting both target_ke (kp) and target_kd (kv)
  • Handles velocity actuators by setting target_kd (kv)
  • Validates joint names and provides helpful warnings
  • Applies gains to all DOFs of a joint

The integration into the main parse flow is appropriate.

newton/tests/test_import_mjcf.py (1)

704-846: Comprehensive test validates the passive stiffness/damping feature.

The test correctly:

  • Registers custom MuJoCo attributes before parsing MJCF
  • Validates that passive stiffness/damping are parsed into model.mujoco.stiffness and model.mujoco.damping
  • Verifies actuator gains (target_ke/target_kd) are set correctly from MJCF <actuator> section
  • Checks MuJoCo model internals (dof_damping, jnt_stiffness, actuator gains/biases)
  • Tests runtime updates via notify_model_changed

The test thoroughly covers the integration points between Newton, MJCF parsing, and MuJoCo solver.

newton/_src/solvers/mujoco/kernels.py (2)

905-929: LGTM! DOF properties kernel correctly extended for passive damping.

The kernel now:

  • Accepts joint_damping as an additional input
  • Writes to dof_damping output array
  • Maintains consistent indexing with existing armature and friction updates
  • Has an updated docstring

The implementation is straightforward and follows the existing pattern.


931-946: LGTM! Joint stiffness kernel correctly maps per-joint stiffness to MuJoCo DOFs.

The kernel:

  • Uses joint_qd_start to locate the first DOF of each joint
  • Maps to MuJoCo joint index via joint_mjc_dof_start
  • Only updates when a valid MuJoCo joint index exists (>= 0 check)
  • Handles per-world replication correctly

The implementation is consistent with the existing kernel patterns in this file.

newton/_src/solvers/mujoco/solver_mujoco.py (5)

169-192: LGTM! Custom attributes properly registered for passive stiffness and damping.

The custom attributes:

  • Use correct frequency (JOINT_DOF)
  • Have appropriate defaults (0.0 for both)
  • Leverage MuJoCo USD schema naming ("mjc:*")
  • Map to MJCF attribute names for parsing

This enables the MJCF importer to automatically populate these attributes via the mjcf_attribute_name mechanism.


969-970: LGTM! Stiffness and damping attributes correctly extracted.

The extraction uses the helper function get_custom_attribute which safely handles cases where the attributes may not exist.


1239-1242: LGTM! Passive stiffness and damping correctly set during joint creation.

The code:

  • Checks if the attributes exist before setting them
  • Applies them to both linear and angular DOFs
  • Uses the correct array indexing (per-DOF)

Also applies to: 1303-1306


1558-1558: LGTM! Stiffness and damping fields correctly added to expansion list.

The fields jnt_stiffness and dof_damping are properly included in the list of fields to expand when replicating across multiple worlds.

Also applies to: 1563-1563


1675-1742: LGTM! Joint DOF properties update correctly handles passive stiffness and damping.

The implementation:

  1. Updates actuator properties (force ranges, gains) as before
  2. Extracts stiffness/damping from custom attributes with safe fallbacks
  3. Launches update_dof_properties_kernel with damping input
  4. Launches new update_joint_stiffness_kernel to populate jnt_stiffness

The logic is well-structured and handles missing attributes gracefully by falling back to zero-filled arrays.

@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

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a55d68 and d00aa68.

📒 Files selected for processing (2)
  • newton/_src/utils/import_mjcf.py (3 hunks)
  • newton/tests/test_import_mjcf.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • newton/_src/utils/import_mjcf.py
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: shi-eric
Repo: newton-physics/newton PR: 521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-07-14T03:57:29.670Z
Learnt from: Kenny-Vilella
Repo: newton-physics/newton PR: 398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.670Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.

Applied to files:

  • newton/tests/test_import_mjcf.py
🧬 Code graph analysis (1)
newton/tests/test_import_mjcf.py (3)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • register_custom_attributes (152-192)
  • notify_model_changed (396-406)
newton/_src/sim/builder.py (2)
  • ModelBuilder (70-5101)
  • finalize (4609-4997)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)

Comment thread newton/tests/test_import_mjcf.py Outdated

@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

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d00aa68 and 9801a76.

📒 Files selected for processing (3)
  • newton/_src/solvers/mujoco/solver_mujoco.py (8 hunks)
  • newton/tests/test_import_mjcf.py (2 hunks)
  • newton/tests/test_import_usd.py (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: shi-eric
Repo: newton-physics/newton PR: 521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering, despite the general warp documentation suggesting copies are made by default.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-09-22T21:03:39.624Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Applied to files:

  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-09-22T21:03:18.367Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:638-648
Timestamp: 2025-09-22T21:03:18.367Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently only supports additive updates, meaning it assumes n_coords == n_dofs. Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work.

Applied to files:

  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-07-14T03:57:29.670Z
Learnt from: Kenny-Vilella
Repo: newton-physics/newton PR: 398
File: newton/examples/example_mujoco.py:352-352
Timestamp: 2025-07-14T03:57:29.670Z
Learning: The use_mujoco option in newton/examples/example_mujoco.py is currently unsupported and causes crashes. The code automatically disables this option with a warning message when users attempt to enable it. This is intentionally kept as a placeholder for future implementation.

Applied to files:

  • newton/tests/test_import_mjcf.py
🧬 Code graph analysis (3)
newton/tests/test_import_usd.py (3)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • register_custom_attributes (152-194)
  • notify_model_changed (398-408)
newton/_src/sim/builder.py (1)
  • ModelBuilder (70-5101)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
newton/_src/solvers/mujoco/solver_mujoco.py (3)
newton/_src/solvers/mujoco/kernels.py (2)
  • update_joint_stiffness_kernel (932-945)
  • update_dof_properties_kernel (906-928)
newton/_src/sim/builder.py (3)
  • add_custom_attribute (584-629)
  • ModelBuilder (70-5101)
  • CustomAttribute (268-358)
newton/_src/sim/model.py (2)
  • ModelAttributeFrequency (49-70)
  • ModelAttributeAssignment (31-46)
newton/tests/test_import_mjcf.py (2)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
  • register_custom_attributes (152-194)
newton/_src/sim/builder.py (2)
  • ModelBuilder (70-5101)
  • add_mjcf (1131-1215)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks (Pull Request)
  • GitHub Check: Run GPU Unit Tests on AWS EC2 (Pull Request)
🔇 Additional comments (4)
newton/tests/test_import_usd.py (1)

1271-1280: Correct indexing of jnt_stiffness using MuJoCo joint index.

This test correctly uses mjc_joint_idx (line 1279) to index jnt_stiffness, which is the proper MuJoCo joint index obtained from joint_mjc_dof_start. This is the correct and robust approach for accessing MuJoCo's per-joint arrays.

newton/_src/solvers/mujoco/solver_mujoco.py (2)

169-194: Custom attribute registration for passive stiffness and damping looks good.

The registration correctly uses JOINT_DOF frequency, sets appropriate defaults (0.0), and provides both USD and MJCF attribute name mappings. The usd_value_transformer lambda ensures scalar values are converted to lists as expected by the USD parser.


1704-1744: Safe fallback handling and correct kernel integration.

The code properly handles missing custom attributes by creating zero arrays as fallbacks (lines 1704-1713), ensuring the solver works even when stiffness/damping are not specified. The kernel launches correctly pass joint_damping to update_dof_properties_kernel and launch the new update_joint_stiffness_kernel with appropriate inputs including joint_qd_start and joint_mjc_dof_start for proper index mapping.

newton/tests/test_import_mjcf.py (1)

863-867: Same indexing inconsistency in the dynamic update verification.

Line 867 also uses joint_idx directly to index jnt_stiffness, but should use the MuJoCo joint index for consistency and correctness.

Apply this diff:

+        mjc_joint_idx = joint_mjc_dof_start[joint1_idx]
         updated_dof_damping = mjw_model.dof_damping.numpy()[0, mjc_dof_idx]
         self.assertAlmostEqual(updated_dof_damping, 1.5, places=4)
-        self.assertAlmostEqual(mjw_model.jnt_stiffness.numpy()[0, joint1_idx], 0.15, places=4)
+        self.assertAlmostEqual(mjw_model.jnt_stiffness.numpy()[0, mjc_joint_idx], 0.15, places=4)
⛔ Skipped due to learnings
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Comment thread newton/tests/test_import_mjcf.py Outdated

@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: 0

🧹 Nitpick comments (2)
newton/tests/test_import_mjcf.py (1)

1018-1020: Indexing jnt_stiffness with joint_idx works for this test but may be fragile.

The test uses joint_idx (Newton joint index) to index mjw_model.jnt_stiffness, while the USD test at line 1623 uses mjc_joint_idx. For single-DOF revolute joints with separate_worlds=False, these indices coincide, so the test passes. However, using mjc_joint_idx would be more consistent with the USD test and more robust if the test evolves to include multi-DOF joints.

-                self.assertAlmostEqual(
-                    mjw_model.jnt_stiffness.numpy()[0, joint_idx], expected["jnt_stiffness"], places=4
-                )
+                self.assertAlmostEqual(
+                    mjw_model.jnt_stiffness.numpy()[0, mjc_dof_idx], expected["jnt_stiffness"], places=4
+                )
newton/_src/solvers/mujoco/solver_mujoco.py (1)

191-212: Consider adding MJCF attribute names for import support.

The new stiffness and damping custom attributes are registered with usd_attribute_name but lack mjcf_attribute_name, unlike limit_margin (line 177) which has mjcf_attribute_name="margin". If importing these properties from MJCF files is intended, consider adding:

 builder.add_custom_attribute(
     ModelBuilder.CustomAttribute(
         name="stiffness",
         frequency=ModelAttributeFrequency.JOINT_DOF,
         assignment=ModelAttributeAssignment.MODEL,
         dtype=wp.float32,
         default=0.0,
         namespace="mujoco",
-        usd_attribute_name="mjc:stiffness"
+        usd_attribute_name="mjc:stiffness",
+        mjcf_attribute_name="stiffness"
     )
 )
 builder.add_custom_attribute(
     ModelBuilder.CustomAttribute(
         name="damping",
         frequency=ModelAttributeFrequency.JOINT_DOF,
         assignment=ModelAttributeAssignment.MODEL,
         dtype=wp.float32,
         default=0.0,
         namespace="mujoco",
-        usd_attribute_name="mjc:damping"
+        usd_attribute_name="mjc:damping",
+        mjcf_attribute_name="damping"
     )
 )
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9801a76 and 7f9977e.

📒 Files selected for processing (5)
  • newton/_src/solvers/mujoco/kernels.py (5 hunks)
  • newton/_src/solvers/mujoco/solver_mujoco.py (9 hunks)
  • newton/_src/utils/import_mjcf.py (3 hunks)
  • newton/tests/test_import_mjcf.py (1 hunks)
  • newton/tests/test_import_usd.py (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: shi-eric
Repo: newton-physics/newton PR: 521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-09-22T21:03:39.624Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Applied to files:

  • newton/_src/utils/import_mjcf.py
  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-11-24T08:05:21.390Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_import_usd.py
📚 Learning: 2025-09-22T21:03:18.367Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:638-648
Timestamp: 2025-09-22T21:03:18.367Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently only supports additive updates, meaning it assumes n_coords == n_dofs. Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-07-21T19:11:04.077Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 450
File: newton/sim/ik.py:1286-1296
Timestamp: 2025-07-21T19:11:04.077Z
Learning: In Newton's IK system, the JointLimitObjective class intentionally only handles joints where DOF count equals coordinate count (1-1 mapping). This is appropriate because joint limits are typically only meaningful for simple joint types like revolute and prismatic joints, not complex joints like ball or free joints where DOF count != coordinate count.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
🧬 Code graph analysis (1)
newton/tests/test_import_mjcf.py (3)
newton/_src/sim/builder.py (2)
  • ModelBuilder (70-5401)
  • copy (231-232)
newton/_src/solvers/mujoco/solver_mujoco.py (1)
  • register_custom_attributes (151-212)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Benchmarks / Run GPU Benchmarks on AWS EC2
  • GitHub Check: Run GPU Tests / Run GPU Unit Tests on AWS EC2
🔇 Additional comments (14)
newton/_src/utils/import_mjcf.py (2)

117-118: LGTM: Variable renaming from default_joint_stiffness/damping to default_joint_target_ke/kd.

The naming change clarifies these are active control gains (target stiffness/damping for actuators) rather than passive joint properties, which aligns with the new distinction between passive joint stiffness/damping and actuator-driven target gains.


1059-1111: LGTM: parse_actuators function correctly extracts actuator gains.

The implementation properly:

  1. Parses position actuators (kp → target_ke, kv → target_kd)
  2. Parses velocity actuators (kv → target_kd, overwriting position actuator's kv when both exist)
  3. Applies gains per-DOF for multi-DOF joints
  4. Warns when actuators reference unknown joints

The processing order (position before velocity) means velocity actuator's kv takes precedence for target_kd, which appears intentional per the test expectations.

newton/tests/test_import_mjcf.py (2)

909-973: Comprehensive test coverage for stiffness/damping parsing and propagation.

The test thoroughly validates:

  • Parsing of stiffness and damping MJCF joint attributes
  • Actuator kp/kv extraction into target_ke/target_kd
  • Correct handling of joints with only velocity actuators (joint4)
  • Interaction between position and velocity actuators on the same joint (joint1)

1055-1072: LGTM: Runtime property mutation and propagation test.

The test correctly validates that updating model.mujoco.stiffness and model.mujoco.damping followed by notify_model_changed(JOINT_DOF_PROPERTIES) propagates the changes to the MuJoCo solver's internal arrays.

newton/_src/solvers/mujoco/kernels.py (3)

918-931: LGTM: Extended kernel signature for stiffness/damping support.

The new inputs (joint_stiffness, joint_damping) and outputs (jnt_stiffness, dof_damping) are properly typed and positioned. The conditional writes using if joint_stiffness: and if joint_damping: ensure backward compatibility when these arrays are not provided.


966-981: LGTM: Per-DOF damping and per-joint stiffness updates for linear axes.

The implementation correctly:

  1. Writes damping per-DOF to dof_damping[worldid, mjc_dof_index]
  2. Writes stiffness per-joint to jnt_stiffness[worldid, mjc_joint_index]

This follows the Newton-MuJoCo mapping where each DOF maps to a distinct MuJoCo joint.


1000-1014: LGTM: Per-DOF damping and per-joint stiffness updates for angular axes.

The angular DOF handling mirrors the linear DOF logic, maintaining consistent behavior across axis types.

newton/tests/test_import_usd.py (3)

1425-1586: Comprehensive USD test for joint stiffness/damping parsing.

The test properly validates:

  • Parsing mjc:stiffness and mjc:damping USD attributes
  • USD drive gains (drive:angular:physics:stiffness/damping) scaled by math.degrees(1.0)
  • Correct handling of joints with drives vs without (Joint3 has no drive)
  • Integration with SolverMuJoCo custom attributes

1615-1652: LGTM: MuJoCo solver integration verification.

The test correctly uses mjc_joint_idx (derived from joint_mjc_dof_start) to index jnt_stiffness, which is more robust than using the Newton joint index directly. This is the preferred pattern for accessing MuJoCo per-joint arrays.


1654-1672: LGTM: Runtime property mutation test matches MJCF test pattern.

The test verifies that updating stiffness/damping in the Newton model and notifying the solver correctly propagates the changes to MuJoCo arrays.

newton/_src/solvers/mujoco/solver_mujoco.py (4)

989-990: LGTM!

The attribute retrieval follows the established pattern and correctly handles the case where attributes may not be present.


1331-1334: LGTM!

The stiffness and damping values are correctly propagated to MuJoCo joint parameters, with proper null checks and per-DOF indexing. The implementation is consistent across both linear and angular DOFs.

Also applies to: 1404-1407


1793-1858: LGTM!

The function correctly retrieves stiffness and damping from the model's custom attributes, passes them to the update kernel, and writes the results to the appropriate MuJoCo model fields. The docstring accurately reflects the new functionality.


1676-1676: Manual verification required — repository access unavailable.

Unfortunately, I cannot execute the verification scripts due to repository access issues. The original review comment appropriately requests verification of the index mapping between Newton DOFs and MuJoCo joints for the jnt_stiffness field expansion, based on the established learning that each Newton DOF maps to a distinct MuJoCo joint via the dof_to_mjc_joint array.

The concern is valid: the kernel must correctly use this mapping to write stiffness values to the appropriate MuJoCo joint indices without overwrites for multi-DOF joints. Manual code inspection of update_joint_dof_properties_kernel is needed to confirm the implementation follows this pattern correctly.

@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: 0

♻️ Duplicate comments (1)
newton/tests/test_import_mjcf.py (1)

981-1021: Use MuJoCo joint index (not Newton joint index) when asserting jnt_stiffness after updates

In the first half of this test you correctly derive mjc_joint_idx = joint_mjc_dof_start[joint_idx] and use that to index mjw_model.jnt_stiffness. After mutating model.mujoco.stiffness / damping and calling notify_model_changed, the final assertion switches to indexing jnt_stiffness with the Newton joint index (joint1_idx):

mjc_dof_idx = joint_mjc_dof_start[joint1_idx]
updated_dof_damping = mjw_model.dof_damping.numpy()[0, mjc_dof_idx]
self.assertAlmostEqual(updated_dof_damping, 1.5, places=4)
self.assertAlmostEqual(mjw_model.jnt_stiffness.numpy()[0, joint1_idx], 0.15, places=4)

Given the established mapping where each Newton DOF maps to a MuJoCo joint via dof_to_mjc_joint and joint_mjc_dof_start, mjw_model.jnt_stiffness should always be indexed with the MuJoCo joint index (mjc_joint_idx), not the Newton joint index. This is what you already do earlier in the test and what the USD test uses as well; the current code will be fragile for multi‑DOF or more complex joint layouts.

Please align the final assertion with the earlier pattern:

-            mjc_dof_idx = joint_mjc_dof_start[joint1_idx]
-
-            updated_dof_damping = mjw_model.dof_damping.numpy()[0, mjc_dof_idx]
-            self.assertAlmostEqual(updated_dof_damping, 1.5, places=4)
-            self.assertAlmostEqual(mjw_model.jnt_stiffness.numpy()[0, joint1_idx], 0.15, places=4)
+            mjc_joint_idx = joint_mjc_dof_start[joint1_idx]
+            mjc_dof_idx = mjc_joint_idx
+
+            updated_dof_damping = mjw_model.dof_damping.numpy()[0, mjc_dof_idx]
+            self.assertAlmostEqual(updated_dof_damping, 1.5, places=4)
+            self.assertAlmostEqual(mjw_model.jnt_stiffness.numpy()[0, mjc_joint_idx], 0.15, places=4)

Also applies to: 1069-1073

🧹 Nitpick comments (1)
newton/tests/test_import_usd.py (1)

1425-1672: USD stiffness/damping test exercises the full pipeline correctly

This test does a good job validating parsing of mjc:stiffness/mjc:damping, mapping into model.mujoco.* and joint_target_ke/kd, MuJoCo dof_damping / jnt_stiffness, actuator gain/bias parameters, and the notify_model_changed(SolverNotifyFlags.JOINT_DOF_PROPERTIES) path. Indexing via joint_mjc_dof_start is consistent with the solver’s DOF→joint mapping.

As a small cleanup, you could drop the inner import math and from newton.solvers import SolverMuJoCo here since both are already imported at the top of the file.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9801a76 and fa61e7d.

📒 Files selected for processing (5)
  • newton/_src/solvers/mujoco/kernels.py (5 hunks)
  • newton/_src/solvers/mujoco/solver_mujoco.py (9 hunks)
  • newton/_src/utils/import_mjcf.py (3 hunks)
  • newton/tests/test_import_mjcf.py (1 hunks)
  • newton/tests/test_import_usd.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • newton/_src/utils/import_mjcf.py
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: shi-eric
Repo: newton-physics/newton PR: 521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-11-24T08:05:21.390Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_import_usd.py
📚 Learning: 2025-09-22T21:03:39.624Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-09-22T21:03:18.367Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:638-648
Timestamp: 2025-09-22T21:03:18.367Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently only supports additive updates, meaning it assumes n_coords == n_dofs. Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-09-22T21:08:31.901Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/examples/ik/example_ik_franka.py:121-123
Timestamp: 2025-09-22T21:08:31.901Z
Learning: In the newton physics framework, when creating warp arrays for IK solver joint variables using wp.array(self.model.joint_q, shape=(1, coord_count)), the resulting array acts as a reference/pointer to the original model's joint coordinates, so updates from the IK solver automatically reflect in the model's joint_q buffer used for rendering.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-07-21T19:11:04.077Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 450
File: newton/sim/ik.py:1286-1296
Timestamp: 2025-07-21T19:11:04.077Z
Learning: In Newton's IK system, the JointLimitObjective class intentionally only handles joints where DOF count equals coordinate count (1-1 mapping). This is appropriate because joint limits are typically only meaningful for simple joint types like revolute and prismatic joints, not complex joints like ball or free joints where DOF count != coordinate count.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/_src/solvers/mujoco/kernels.py
  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
🧬 Code graph analysis (2)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
newton/_src/sim/builder.py (3)
  • add_custom_attribute (622-667)
  • ModelBuilder (70-5401)
  • CustomAttribute (304-394)
newton/_src/sim/model.py (2)
  • ModelAttributeFrequency (49-70)
  • ModelAttributeAssignment (31-46)
newton/tests/test_import_usd.py (3)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • register_custom_attributes (151-212)
  • notify_model_changed (417-427)
newton/_src/solvers/solver.py (2)
  • register_custom_attributes (307-314)
  • notify_model_changed (267-294)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Tests / Run GPU Unit Tests on AWS EC2
  • GitHub Check: Run GPU Benchmarks / Run GPU Benchmarks on AWS EC2
🔇 Additional comments (2)
newton/_src/solvers/mujoco/kernels.py (1)

918-929: Passive stiffness/damping propagation in joint DOF kernel looks consistent

The new joint_stiffness / joint_damping inputs and corresponding jnt_stiffness / dof_damping writes follow the existing solimplimit/limit_margin pattern and respect the dof_to_mjc_joint mapping and world indexing. I don’t see correctness issues in the added logic.

Also applies to: 966-983, 1000-1015

newton/_src/solvers/mujoco/solver_mujoco.py (1)

191-212: Stiffness/damping integration through SolverMuJoCo looks coherent

The new mujoco custom attributes (stiffness, damping), their retrieval in _convert_to_mjc, use in add_geoms joint parameter construction, inclusion in expand_model_fields, and propagation via update_joint_dof_properties into mjw_model.jnt_stiffness / dof_damping are all consistent with the existing solimplimit/limit_margin plumbing and the DOF→MuJoCo joint mapping (dof_to_mjc_joint / joint_mjc_dof_start). I don’t see correctness issues in these additions.

Also applies to: 978-991, 1331-1334, 1404-1407, 1660-1682, 1794-1858

@jvonmuralt jvonmuralt marked this pull request as ready for review November 27, 2025 13:10

@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: 0

🧹 Nitpick comments (2)
newton/tests/test_import_usd.py (2)

1560-1575: Optional: Rename deg_to_rad_scale to reflect actual meaning

deg_to_rad_scale = math.degrees(1.0) is a radians→degrees factor, but the variable name suggests degrees→radians. To avoid confusion for future readers, consider renaming it, e.g.:

-        deg_to_rad_scale = math.degrees(1.0)
+        rad_to_deg_scale = math.degrees(1.0)
...
-                "target_ke": 10000.0 * deg_to_rad_scale,
+                "target_ke": 10000.0 * rad_to_deg_scale,

(and similarly for other uses).


1591-1651: Optional: Strengthen actuator expectations for joints without drives

The MuJoCo-side checks are thorough for joints with actuators, and the mapping via mjc_axis_to_actuator[dof_idx] aligns with the per-DOF mapping used in the MuJoCo integration (per retrieved learnings). For the has_actuator=False case (Joint3), the test currently only asserts that any accidentally created actuators have zero gain:

else:
    if pos_actuator_idx != -1:
        ...
    if vel_actuator_idx != -1:
        ...

If the intended contract is “no actuators at all when there is no drive,” you could tighten this to assert pos_actuator_idx == -1 and vel_actuator_idx == -1, which would catch unexpected actuator creation instead of just non-zero gains.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa61e7d and 60397e0.

📒 Files selected for processing (1)
  • newton/tests/test_import_usd.py (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: shi-eric
Repo: newton-physics/newton PR: 521
File: newton/examples/example_cloth_hanging.py:36-36
Timestamp: 2025-08-12T05:17:34.423Z
Learning: The Newton migration guide (docs/migration.rst) is specifically for documenting how to migrate existing warp.sim functionality to Newton equivalents. New Newton-only features that didn't exist in warp.sim do not need migration documentation.
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-11-24T08:05:21.390Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.

Applied to files:

  • newton/tests/test_import_usd.py
🧬 Code graph analysis (1)
newton/tests/test_import_usd.py (3)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • register_custom_attributes (151-212)
  • notify_model_changed (417-427)
newton/_src/solvers/solver.py (2)
  • register_custom_attributes (307-314)
  • notify_model_changed (267-294)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
🪛 Ruff (0.14.6)
newton/tests/test_import_usd.py

1428-1428: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


1558-1558: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run GPU Benchmarks / Run GPU Benchmarks on AWS EC2
🔇 Additional comments (3)
newton/tests/test_import_usd.py (3)

1425-1545: End-to-end USD → Newton → MuJoCo coverage for stiffness/damping looks solid

The in-memory USD fixture with three joints (passive+driven, driven-only, passive-only) plus the call to SolverMuJoCo.register_custom_attributes(builder) before add_usd(stage) gives good coverage of parsing, model storage, and later solver use. No issues with the overall structure here.


1652-1670: Good coverage of notify_model_changed for JOINT_DOF_PROPERTIES

The final block that mutates model.mujoco.stiffness/damping, calls solver.notify_model_changed(SolverNotifyFlags.JOINT_DOF_PROPERTIES), and then re-reads mjw_model.dof_damping and jnt_stiffness is a nice regression guard that the JOINT_DOF_PROPERTIES path correctly refreshes MuJoCo-side buffers. No changes needed here.


1428-1428: Clean up unused # noqa and redundant math import (RUF100)

Ruff flags both of these as unused noqa directives:

  • Line 1428: from pxr import Usd # noqa: PLC0415
  • Line 1558: import math # noqa: PLC0415

Also, math is already imported at the top of the file (line 16), so the inner import math is redundant.

You can simplify and fix the lint warnings with something like:

-        from pxr import Usd  # noqa: PLC0415
+        from pxr import Usd
...
-        import math  # noqa: PLC0415
-
-        deg_to_rad_scale = math.degrees(1.0)
+        deg_to_rad_scale = math.degrees(1.0)

Also applies to: 1558-1561

⛔ Skipped due to learnings
Learnt from: daniela-hase
Repo: newton-physics/newton PR: 1044
File: newton/_src/sensors/tiled_camera_sensor.py:224-256
Timestamp: 2025-11-07T01:42:36.906Z
Learning: In newton/_src/sensors/tiled_camera_sensor.py, the `# noqa: PLC0415` directives on the local PIL imports (lines 224 and 256 in save_color_image and save_depth_image methods) should be kept because they are required by the pre-commit configuration. The local imports are intentional for optional dependency handling.
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/utils.py:30-33
Timestamp: 2025-08-12T18:07:17.267Z
Learning: In newton/_src/utils/import_usd.py, the PXR/USD modules are lazily loaded using try-except blocks within the functions (lines 109-111 and 1289-1291) rather than at module import time, making it safe to import parse_usd at the module level without causing import-time failures for users without USD dependencies.
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/utils.py:30-33
Timestamp: 2025-08-12T18:07:17.267Z
Learning: In newton/_src/utils/import_usd.py, the PXR/USD modules are lazily loaded using try-except blocks within the functions rather than at module import time, making it safe to import parse_usd at the module level without causing import-time failures for users without USD dependencies.
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/utils.py:30-33
Timestamp: 2025-08-12T18:07:17.267Z
Learning: In newton/_src/utils/import_usd.py, the PXR/USD modules are lazily loaded using try-except blocks within the functions rather than at module import time, making it safe to import parse_usd at the module level without causing import-time failures for users without USD dependencies.

@jvonmuralt jvonmuralt changed the title Passive stiffness damping Add passive stiffness and damping support for joints in MuJoCo solver Nov 27, 2025

@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: 2

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60397e0 and ced201a.

📒 Files selected for processing (1)
  • newton/tests/test_import_usd.py (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.
📚 Learning: 2025-09-22T21:03:39.624Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Applied to files:

  • newton/tests/test_import_usd.py
📚 Learning: 2025-11-24T08:05:21.390Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.

Applied to files:

  • newton/tests/test_import_usd.py
🧬 Code graph analysis (1)
newton/tests/test_import_usd.py (4)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • register_custom_attributes (151-212)
  • notify_model_changed (417-427)
newton/_src/solvers/solver.py (2)
  • register_custom_attributes (307-314)
  • notify_model_changed (267-294)
newton/_src/solvers/implicit_mpm/solver_implicit_mpm.py (1)
  • notify_model_changed (1809-1811)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
🪛 Ruff (0.14.6)
newton/tests/test_import_usd.py

1428-1428: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


1558-1558: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (1)
newton/tests/test_import_usd.py (1)

1585-1671: Excellent test coverage for MuJoCo integration.

The test thoroughly verifies:

  • Parsing of stiffness/damping from USD to Newton model
  • Propagation to MuJoCo solver (jnt_stiffness, dof_damping)
  • Actuator parameter mapping (gainprm, biasprm)
  • Runtime mutation via notify_model_changed

The test exercises all code paths and validates the complete feature end-to-end.

Comment thread newton/tests/test_import_usd.py
Comment thread newton/tests/test_import_usd.py

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

Looking good in general, just a few questions/suggestions.

Did you check whether the reference positions are correct? I guess this can be a follow-up, but we should check qpos0. Can you make a ticket for this?

Comment thread newton/_src/solvers/mujoco/solver_mujoco.py
Comment thread newton/_src/utils/import_mjcf.py
Comment thread newton/_src/utils/import_mjcf.py
Comment thread newton/tests/test_import_mjcf.py Outdated
Comment thread newton/tests/test_import_mjcf.py Outdated

@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: 0

🧹 Nitpick comments (2)
newton/tests/test_import_usd.py (1)

1558-1560: Remove redundant math import.

The math module is already imported at module level (line 16), making this local import unnecessary. The noqa: PLC0415 directive is also flagged as unused by static analysis.

-        import math  # noqa: PLC0415
-
-        angular_gain_unit_scale = math.degrees(1.0)
+        angular_gain_unit_scale = math.degrees(1.0)
newton/tests/test_mujoco_solver.py (1)

930-1036: Multi-world passive stiffness/damping test is correct; consider simplifying DOF-damping indexing

The overall structure of test_dof_passive_stiffness_damping_multiworld looks solid:

  • Registering dof_passive_stiffness/dof_passive_damping on the template builder, then using builder.replicate and per-world patterns on model.mujoco.dof_passive_*, is consistent with how other MuJoCo custom attributes are tested.
  • The mapping logic in assert_passive_values—using joint_qd_start/joint_dof_dim for Newton DOFs and dof_to_mjc_joint for MuJoCo joint indices—matches the pattern in test_jnt_solimp_conversion_and_updates and correctly respects the per-DOF → per-joint mapping. This should reliably catch any indexing regressions in the new stiffness/damping paths. Based on learnings, this is aligned with the intended dof_to_mjc_joint usage.

One optional simplification to reduce coupling to solver internals:

  • For the dof_damping check, you could avoid joint_mjc_dof_start and the joint loop entirely and mirror the style used in test_joint_attributes_registration_and_updates:

    dofs_per_world = model.joint_dof_count // model.num_worlds
    dof_damping = solver.mjw_model.dof_damping.numpy()
    
    for world_idx in range(model.num_worlds):
        world_dof_offset = world_idx * dofs_per_world
        for dof_idx in range(dofs_per_world):
            global_dof_idx = world_dof_offset + dof_idx
            self.assertAlmostEqual(
                dof_damping[world_idx, dof_idx],
                expected_damping[global_dof_idx],
                places=6,
                msg=f"dof_damping mismatch for world={world_idx}, dof={dof_idx}",
            )

    That keeps the test aligned with existing joint-DOF property tests and makes it a bit less sensitive to potential future changes in joint_mjc_dof_start/selection semantics, while still validating the same behavior.

If you prefer to keep the current joint-based mapping, it's also correct as written.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ced201a and e5f4a61.

📒 Files selected for processing (4)
  • newton/_src/solvers/mujoco/solver_mujoco.py (9 hunks)
  • newton/tests/test_import_mjcf.py (1 hunks)
  • newton/tests/test_import_usd.py (1 hunks)
  • newton/tests/test_mujoco_solver.py (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.
📚 Learning: 2025-11-24T08:05:21.390Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 1107
File: newton/_src/solvers/mujoco/kernels.py:973-974
Timestamp: 2025-11-24T08:05:21.390Z
Learning: In Newton's MuJoCo solver integration (newton/_src/solvers/mujoco/), the mapping between Newton joints and MuJoCo joints is not 1-to-1. Instead, each Newton DOF maps to a distinct MuJoCo joint. This means that for multi-DOF joints (like D6 with 6 DOFs), there will be 6 corresponding MuJoCo joints, each with its own properties (margin, solimp, solref, etc.). The mapping is done via dof_to_mjc_joint array, ensuring each DOF's properties are written to its own MuJoCo joint without overwriting.

Applied to files:

  • newton/tests/test_import_mjcf.py
  • newton/_src/solvers/mujoco/solver_mujoco.py
  • newton/tests/test_mujoco_solver.py
📚 Learning: 2025-09-22T21:03:39.624Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:739-752
Timestamp: 2025-09-22T21:03:39.624Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently intentionally only supports additive updates (assuming n_coords == n_dofs). Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work and should not be flagged as an issue in current reviews.

Applied to files:

  • newton/tests/test_import_mjcf.py
  • newton/tests/test_import_usd.py
📚 Learning: 2025-09-22T21:03:18.367Z
Learnt from: dylanturpin
Repo: newton-physics/newton PR: 806
File: newton/_src/sim/ik/ik_lbfgs_optimizer.py:638-648
Timestamp: 2025-09-22T21:03:18.367Z
Learning: The L-BFGS optimizer in newton/_src/sim/ik/ik_lbfgs_optimizer.py currently only supports additive updates, meaning it assumes n_coords == n_dofs. Velocity space integration for joints with mismatched coordinate/DOF dimensions (like free/ball joints) is planned for future work.

Applied to files:

  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-08-18T15:56:26.587Z
Learnt from: adenzler-nvidia
Repo: newton-physics/newton PR: 552
File: newton/_src/solvers/mujoco/solver_mujoco.py:0-0
Timestamp: 2025-08-18T15:56:26.587Z
Learning: In Newton's MuJoCo solver, when transforming joint axes from Newton's internal frame to MuJoCo's expected frame, use wp.quat_rotate(joint_rot, axis) not wp.quat_rotate_inv(joint_rot, axis). The joint_rot represents rotation from joint-local to body frame, so forward rotation is correct.

Applied to files:

  • newton/tests/test_import_mjcf.py
📚 Learning: 2025-11-07T01:42:36.906Z
Learnt from: daniela-hase
Repo: newton-physics/newton PR: 1044
File: newton/_src/sensors/tiled_camera_sensor.py:224-256
Timestamp: 2025-11-07T01:42:36.906Z
Learning: In newton/_src/sensors/tiled_camera_sensor.py, the `# noqa: PLC0415` directives on the local PIL imports (lines 224 and 256 in save_color_image and save_depth_image methods) should be kept because they are required by the pre-commit configuration. The local imports are intentional for optional dependency handling.

Applied to files:

  • newton/tests/test_import_usd.py
📚 Learning: 2025-08-12T18:07:17.267Z
Learnt from: nvlukasz
Repo: newton-physics/newton PR: 519
File: newton/utils.py:30-33
Timestamp: 2025-08-12T18:07:17.267Z
Learning: In newton/_src/utils/import_usd.py, the PXR/USD modules are lazily loaded using try-except blocks within the functions (lines 109-111 and 1289-1291) rather than at module import time, making it safe to import parse_usd at the module level without causing import-time failures for users without USD dependencies.

Applied to files:

  • newton/tests/test_import_usd.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, Example.use_mujoco is a high-level attribute that controls whether to use MuJoCo solver vs other solvers (like XPBD), while SolverMuJoCo.use_mujoco_cpu controls the backend within MuJoCo (CPU vs Warp). These are separate concepts serving different purposes - the PR rename only applies to the solver parameter, not the Example class attributes.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
📚 Learning: 2025-08-19T12:27:30.629Z
Learnt from: preist-nvidia
Repo: newton-physics/newton PR: 579
File: newton/examples/example_mujoco.py:350-354
Timestamp: 2025-08-19T12:27:30.629Z
Learning: In Newton examples, there's a distinction between solver parameters and Example class attributes. The Example class can have its own use_mujoco attribute for controlling example-level behavior (like CUDA graphs, rendering logic), while the solver uses use_mujoco_cpu for backend selection. These serve different purposes and should not be conflated during API renames.

Applied to files:

  • newton/_src/solvers/mujoco/solver_mujoco.py
🧬 Code graph analysis (3)
newton/tests/test_import_mjcf.py (1)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • SolverMuJoCo (77-2019)
  • register_custom_attributes (151-214)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
newton/_src/sim/builder.py (3)
  • add_custom_attribute (622-667)
  • ModelBuilder (70-5401)
  • CustomAttribute (304-394)
newton/_src/sim/model.py (2)
  • ModelAttributeFrequency (49-70)
  • ModelAttributeAssignment (31-46)
newton/tests/test_mujoco_solver.py (3)
newton/_src/sim/builder.py (2)
  • ModelBuilder (70-5401)
  • joint_count (928-932)
newton/_src/solvers/mujoco/solver_mujoco.py (2)
  • register_custom_attributes (151-214)
  • notify_model_changed (419-429)
newton/_src/solvers/flags.py (1)
  • SolverNotifyFlags (22-56)
🪛 Ruff (0.14.6)
newton/tests/test_import_usd.py

1428-1428: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)


1558-1558: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run GPU Tests / Run GPU Unit Tests on AWS EC2
  • GitHub Check: Run GPU Benchmarks / Run GPU Benchmarks on AWS EC2
🔇 Additional comments (8)
newton/tests/test_import_mjcf.py (1)

909-969: Well-structured test for MJCF stiffness/damping import.

The test comprehensively validates:

  1. Parsing of stiffness and damping joint attributes from MJCF
  2. Correct mapping to model.mujoco.dof_passive_stiffness and model.mujoco.dof_passive_damping
  3. Actuator gain parsing (target_ke/target_kd) including combined position+velocity actuators

The indexing via joint_qd_start[joint_idx] is correct for per-DOF attributes. Note that this is a single-world test; per past review feedback, consider adding a separate test in test_mujoco_solver.py to verify multi-world propagation and updates.

newton/tests/test_import_usd.py (1)

1425-1584: Comprehensive USD stiffness/damping import test.

The test validates:

  1. Parsing of mjc:stiffness and mjc:damping USD attributes
  2. Drive stiffness/damping parsing with angular gain unit scaling (math.degrees(1.0))
  3. Correct propagation to model attributes for all three joint configurations

The test structure mirrors the MJCF test appropriately, ensuring consistent coverage across import paths.

newton/_src/solvers/mujoco/solver_mujoco.py (6)

191-214: Custom attributes for passive stiffness/damping are well-defined.

The attributes are correctly registered with:

  • frequency=ModelAttributeFrequency.JOINT_DOF for per-DOF storage
  • Appropriate USD (mjc:stiffness/mjc:damping) and MJCF (stiffness/damping) attribute names
  • Default value of 0.0 matching MuJoCo semantics

The naming dof_passive_stiffness and dof_passive_damping clearly indicates these are per-DOF passive joint properties, addressing the past review concern about naming clarity.


991-992: Correct retrieval of passive stiffness/damping attributes.

Follows the established pattern for retrieving MuJoCo custom attributes, consistent with joint_dof_limit_margin and joint_solimp_limit retrieval above.


1333-1336: Correct propagation of stiffness/damping to linear DOF joint parameters.

The per-DOF indexing via ai = qd_start + i correctly maps to the DOF-level custom attributes.


1406-1409: Consistent stiffness/damping propagation for angular DOFs.

Mirrors the linear DOF handling, maintaining symmetry in the codebase.


1678-1683: Multi-world expansion includes stiffness/damping fields.

Adding jnt_stiffness and dof_damping to model_fields_to_expand ensures these properties are correctly replicated across worlds, consistent with other joint/DOF properties in the list.


1795-1860: Kernel integration for stiffness/damping property updates — verification pending.

The changes correctly:

  1. Retrieve dof_passive_stiffness and dof_passive_damping from model attributes
  2. Pass them as inputs to update_joint_dof_properties_kernel
  3. Map outputs to mjw_model.jnt_stiffness (per-joint) and mjw_model.dof_damping (per-DOF)

Based on learnings, the dof_to_mjc_joint mapping ensures each Newton DOF correctly maps to its corresponding MuJoCo joint for jnt_stiffness writes. The pattern is consistent with other DOF properties (solimplimit, limit_margin).

Verify the kernel signature in newton/_src/solvers/mujoco/kernels.py includes joint_stiffness and joint_damping in the inputs and outputs jnt_stiffness and dof_damping to confirm the function call alignment.

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

Looks good now, thank you very much!

@adenzler-nvidia adenzler-nvidia added this pull request to the merge queue Nov 28, 2025
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 28, 2025

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

approving again after merge from main.

@adenzler-nvidia adenzler-nvidia added this pull request to the merge queue Dec 1, 2025
Merged via the queue into newton-physics:main with commit b6f0e30 Dec 1, 2025
20 checks passed
JerryJiehanWang pushed a commit to JerryJiehanWang/newton that referenced this pull request Dec 2, 2025
…newton-physics#1082)

Co-authored-by: adenzler-nvidia <116633880+adenzler-nvidia@users.noreply.github.com>
@coderabbitai coderabbitai Bot mentioned this pull request Jan 9, 2026
4 tasks
eric-heiden pushed a commit to eric-heiden/newton that referenced this pull request Jan 28, 2026
…newton-physics#1082)

Co-authored-by: adenzler-nvidia <116633880+adenzler-nvidia@users.noreply.github.com>
mmacklin pushed a commit to mmacklin/newton that referenced this pull request Apr 7, 2026
…newton-physics#1082)

Co-authored-by: adenzler-nvidia <116633880+adenzler-nvidia@users.noreply.github.com>
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.

Support separate passive joint stiffness/damping and active actuator gains in MJCF import

2 participants