Adds fix for Cassie with ability to force newton to create joint drives#5251
Conversation
Greptile SummaryThis PR adds an
Confidence Score: 4/5Safe to merge after adding the required changelog entries and version bumps for both packages. The core logic is correct and the fix is well-scoped. The only blocking concern is the missing CHANGELOG and extension.toml version bumps for both source/isaaclab/docs/CHANGELOG.rst, source/isaaclab/config/extension.toml, source/isaaclab_assets/docs/CHANGELOG.rst, source/isaaclab_assets/config/extension.toml Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["modify_joint_drive_properties(prim_path, cfg)"] --> B{Prim is revolute\nor prismatic?}
B -- No --> C[return False]
B -- Yes --> D{Is tendon child\nwithout root?}
D -- Yes --> C
D -- No --> E[Get/Apply DriveAPI]
E --> F["cfg = cfg.to_dict()\nensure_drives = cfg.pop('ensure_drives_exist')"]
F --> G{ensure_drives AND\ncfg stiffness is None AND\ncfg damping is None?}
G -- No --> I[Apply unit conversions\nrad to deg for angular]
G -- Yes --> H["Read cur_stiffness,\ncur_damping from USD"]
H --> H2{both zero\nor None?}
H2 -- No --> I
H2 -- Yes --> H3["cfg['stiffness'] = 1e-3\n(minimal placeholder)"]
H3 --> I
I --> J[Write attrs to USD\nvia DriveAPI]
J --> K[return True]
|
| ensure_drives_exist: bool = False | ||
| """If True, ensure every joint has a non-zero drive so that physics backends | ||
| (e.g. Newton) create proper actuators for it. | ||
|
|
||
| When a USD asset defines ``PhysicsDriveAPI`` with ``stiffness=0`` and | ||
| ``damping=0``, some backends treat the joint as passive (no PD control). | ||
| Enabling this flag writes a minimal stiffness (``1e-3``) to any drive whose | ||
| stiffness *and* damping are both zero, guaranteeing that the backend | ||
| recognises the drive as active. The actual gains are expected to be | ||
| overridden later by the actuator model. | ||
| """ |
There was a problem hiding this comment.
Missing unit annotation for
1e-3 stiffness
The docstring states a minimal stiffness of 1e-3 is written but doesn't indicate the unit. Looking at the implementation in schemas.py (line 696), this value is placed in cfg["stiffness"] before the angular unit conversion (* math.pi / 180.0), so it is interpreted as N-m/rad (simulation units), which gets stored to USD as ~1.745e-5 N-m/deg. The docstring should clarify the unit so callers understand the scale of the placeholder value.
| if ensure_drives and cfg["stiffness"] is None and cfg["damping"] is None: | ||
| # read the current values from the drive | ||
| cur_stiffness = usd_drive_api.GetStiffnessAttr().Get() | ||
| cur_damping = usd_drive_api.GetDampingAttr().Get() | ||
| if (cur_stiffness is None or cur_stiffness == 0.0) and (cur_damping is None or cur_damping == 0.0): | ||
| cfg["stiffness"] = 1e-3 |
There was a problem hiding this comment.
ensure_drives_exist silently skips when explicit stiffness/damping are provided
The outer guard cfg["stiffness"] is None and cfg["damping"] is None means ensure_drives_exist=True has no effect if a caller also passes an explicit stiffness=0.0 or damping=0.0 in the same config. This edge case is consistent with the "don't override explicit user values" intent, but it is not documented anywhere — callers who pass stiffness=0.0 expecting the fix to still activate will be silently surprised. A short note in the docstring (or as an inline comment) would prevent confusion.
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
This PR fixes Cassie robot support on the Newton physics backend by adding an ensure_drives_exist flag to JointDrivePropertiesCfg. When enabled, it injects a minimal stiffness (1e-3) into USD joint drives that have both stiffness and damping at zero — preventing Newton from treating them as passive joints. The approach is sound: it solves a real backend compatibility issue with a targeted, backward-compatible config addition.
Design Assessment
Design is sound. The fix correctly targets the USD schema layer (where Newton reads drive configuration) rather than hacking around the problem downstream. Key design decisions are well-considered:
- Opt-in flag (
ensure_drives_exist=Falseby default) — no impact on existing users or PhysX workflows - Minimal stiffness injection —
1e-3is small enough to not affect simulation behavior, while the real gains come from the actuator model override - Guard conditions — only fires when config stiffness and damping are both None (user hasn't set them) and the USD-authored values are both zero
- Clean
cfg.pop()— prevents the boolean from leaking into the USD attribute setter loop (which would raiseTypeError)
The only alternative would be fixing this at the Newton backend level, but that's outside this project's control.
Findings
🟡 Warning: Missing test coverage for new ensure_drives_exist path — source/isaaclab/test/sim/test_schemas.py
The existing test_modify_properties_on_articulation_* tests use stiffness=10.0, damping=0.1, so they never exercise the new ensure_drives_exist code path. Since this is a bug fix PR, a regression test would strengthen confidence that the fix works and doesn't regress.
A useful test would:
- Create a joint with
stiffness=0, damping=0in USD - Call
modify_joint_drive_propertieswithJointDrivePropertiesCfg(ensure_drives_exist=True)(stiffness/damping left as None) - Verify that the resulting USD drive stiffness is non-zero (
1e-3for linear,1e-3 * π/180for angular) - Also verify the negative case:
ensure_drives_exist=Falseleaves the zero drive untouched
🟡 Warning: Float equality check against USD-authored values — source/isaaclab/isaaclab/sim/schemas/schemas.py:695
if (cur_stiffness is None or cur_stiffness == 0.0) and (cur_damping is None or cur_damping == 0.0):Direct == 0.0 comparison works for cleanly-authored USD attributes (which are typically set to exact 0.0), but could miss near-zero values written by other tools or roundtrip serialization. A tolerance-based check would be more robust:
if (cur_stiffness is None or abs(cur_stiffness) < 1e-6) and (cur_damping is None or abs(cur_damping) < 1e-6):
This is a minor concern since USD attributes are typically authored as exact values, but worth considering for robustness.
🔵 Suggestion: Add CHANGELOG entry — CHANGELOG.rst
The PR checklist notes that changelog and version updates are expected for user-facing changes. Adding ensure_drives_exist to JointDrivePropertiesCfg is a public API addition that users may want to discover.
Test Coverage
- Bug fix PR: No regression test included
- New config field: Not tested with valid/invalid values
- Existing tests: Pass through this code path but don't exercise the new branch (stiffness/damping are always set to non-None values)
- Recommendation: Add at least one test for the
ensure_drives_exist=Truepath with a zero-drive joint
CI Status
All checks pending (freshly pushed). Docker image builds passed. Pre-commit and test suites still running.
Verdict
COMMENT
The implementation is clean and the design is correct. The two warnings above are suggestions to improve robustness and test coverage — neither is a blocking issue. The fix addresses a real Newton backend limitation in a backward-compatible way, and the Cassie config change is the right consumer for it. Nice work.
| # read the current values from the drive | ||
| cur_stiffness = usd_drive_api.GetStiffnessAttr().Get() | ||
| cur_damping = usd_drive_api.GetDampingAttr().Get() | ||
| if (cur_stiffness is None or cur_stiffness == 0.0) and (cur_damping is None or cur_damping == 0.0): |
There was a problem hiding this comment.
🟡 Warning: Direct == 0.0 comparison works for cleanly-authored USD values, but could miss near-zero values from roundtrip serialization or other tools. Consider a tolerance-based check:
| if (cur_stiffness is None or cur_stiffness == 0.0) and (cur_damping is None or cur_damping == 0.0): | |
| if (cur_stiffness is None or abs(cur_stiffness) < 1e-6) and (cur_damping is None or abs(cur_damping) < 1e-6): |
Minor concern since USD attributes are typically exact values, but improves robustness.
There was a problem hiding this comment.
This is not needed since we precisely want to avoid the case where the values would be exactly 0.0. This is because newton will not create a mujoco actuator if and only if the values are exactly 0.
Update isaaclab (4.5.31) and isaaclab_assets (0.3.2) changelogs to document the ensure_drives_exist flag and the Cassie config fix.
# Conflicts: # source/isaaclab/config/extension.toml # source/isaaclab/docs/CHANGELOG.rst
…int drives (isaac-sim#5251)" This reverts commit caab0de.
…int drives (isaac-sim#5251)" This reverts commit caab0de.
…oint drives (isaac-sim#5251)" This reverts commit ebad4e7.
…es (isaac-sim#5251) # Description Adds fix for Cassie with ability to force newton to create joint drives ## Type of change - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) ## Checklist - [ ] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [ ] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] I have updated the changelog and the corresponding version in the extension's `config/extension.toml` file - [ ] I have added my name to the `CONTRIBUTORS.md` or my name already exists there
Description
Adds fix for Cassie with ability to force newton to create joint drives
Type of change
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there