Skip material randomization on physics backends that don't support it#5151
Skip material randomization on physics backends that don't support it#5151Kripner wants to merge 3 commits intoisaac-sim:developfrom
Conversation
randomize_rigid_body_material uses PhysX-specific APIs (link_paths, max_shapes, get/set_material_properties) that don't exist on Newton's ArticulationView. This causes an AttributeError when running tasks like Isaac-Open-Drawer-Franka-v0 with env.sim=newton. Detect backend support via hasattr check on get_material_properties and skip the term with a warning when unsupported. Also use the asset's num_shapes_per_body property when available instead of the PhysX-specific link_paths workaround.
Greptile SummaryThis PR adds graceful degradation to Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["__init__ called"] --> B{"hasattr(root_view,\n'get_material_properties')?"}
B -- No --> C["_supported = False\nlog warning\nreturn early"]
B -- Yes --> D["_supported = True"]
D --> E{"BaseArticulation AND\nbody_ids != slice(None)?"}
E -- No --> F["num_shapes_per_body = None"]
E -- Yes --> G{"hasattr(asset,\n'num_shapes_per_body')?"}
G -- Yes --> H["Use asset.num_shapes_per_body directly"]
G -- No --> I["PhysX workaround:\nbuild list from link_paths\nvalidate sum == max_shapes"]
H --> J["Sample material_buckets"]
F --> J
I --> J
K["__call__ invoked"] --> L{"_supported?"}
L -- No --> M["return (no-op)"]
L -- Yes --> N["Randomize & apply\nmaterial properties"]
Reviews (1): Last reviewed commit: "Skip material randomization on physics b..." | Re-trigger Greptile |
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot
Summary
This PR adds Newton backend compatibility to randomize_rigid_body_material by detecting whether the physics backend supports get_material_properties via hasattr and skipping the term with a warning when unsupported. It also adds a fast path using asset.num_shapes_per_body when available (Newton provides this natively) instead of the PhysX-specific link_paths + create_rigid_body_view workaround.
Design Assessment
Silently skipping is the right approach for this term. The alternative — raising an error — would break every task that uses material randomization when run on Newton (≥15 task configs across locomotion, manipulation, dexterous tasks). The warning at init time is appropriate.
However, two design points deserve attention:
- The
hasattrcheck is a duck-typing probe, not a formal capability query. If Newton eventually addsget_material_propertiesbut with a different signature, this will silently break at runtime rather than at init. Consider documenting this assumption. - When
hasattr(self.asset, "num_shapes_per_body")is True, the value is used without validation againstmax_shapes. The PhysX path validatessum(num_shapes_per_body) == max_shapes. The Newton path trusts the backend blindly. If Newton ever returns incorrect data, there's no guardrail.
Architecture Impact
- Blast radius: ~15 task configurations reference
randomize_rigid_body_material. All will silently degrade to no-op on Newton. This is acceptable for an initial compatibility fix. - Other event terms:
randomize_rigid_body_collider_offsetsalso usesroot_view.get_rest_offsets()/root_view.get_contact_offsets()— these likely need the same treatment for Newton. This PR doesn't address that, but it's out of scope. - No cross-module impact beyond the events module.
Implementation Verdict
Minor fixes requested — Two concrete issues below, one cleanup and one correctness concern.
Test Coverage
No tests added. Given this is a backend-specific guard, unit-testing would require mocking the Newton backend. At minimum, a note in the PR description about manual testing on Newton would be valuable. The author mentions Isaac-Open-Drawer-Franka-v0 with env.sim=newton — was this actually tested end-to-end?
CI Status
labeler check ran (passed). No linting, unit tests, or integration tests executed on this PR. The CI pipeline appears incomplete — this is a repo-level concern, not a PR-level one.
Findings
[Low] Redundant import logging (cleanup)
Lines 208-209: logging is imported inside the if not self._supported block, but it's already imported at module level (line 18) and used via the module-level logger. This redundant import should be removed in favor of using the existing logger object.
[Medium] Missing validation on Newton's num_shapes_per_body
Line 221: When hasattr(self.asset, "num_shapes_per_body") is True, the value is assigned directly without the sum(num_shapes_per_body) == max_shapes sanity check that the PhysX path performs. If Newton's property is malformed, material assignment will silently corrupt the wrong shape indices. The validation should apply to both paths.
[Info] Warning fires once but skip is perpetual
The logging.warning() fires in __init__, but the if not self._supported: return in __call__ executes silently on every invocation. For mode="reset" terms (e.g., ShadowHand configs), this means material randomization is silently skipped every episode reset without any ongoing indication. This is acceptable behavior, but worth documenting in the class docstring.
| # check if the physics backend supports material property randomization | ||
| self._supported = hasattr(self.asset.root_view, "get_material_properties") | ||
| if not self._supported: | ||
| import logging |
There was a problem hiding this comment.
[Low] Redundant import: logging is already imported at module level (line 18). Use the existing module-level logger instead:
if not self._supported:
logger.warning(
"randomize_rigid_body_material: skipping because the current physics backend"
" does not support material property randomization."
)This also avoids creating a new logger instance and is consistent with the rest of the file.
| f" Expected total shapes: {expected_shapes}, but got: {num_shapes}." | ||
| ) | ||
| # check if the asset already provides num_shapes_per_body (e.g. Newton backend) | ||
| if hasattr(self.asset, "num_shapes_per_body"): |
There was a problem hiding this comment.
[Medium] Missing validation: The PhysX path (lines 224-233) validates sum(num_shapes_per_body) == max_shapes. This Newton path trusts the backend property blindly. If it's ever wrong, materials will be assigned to incorrect shape indices.
Suggestion — add the same sanity check:
if hasattr(self.asset, "num_shapes_per_body"):
self.num_shapes_per_body = self.asset.num_shapes_per_body
# validate against max_shapes (same check as PhysX path)
num_shapes = sum(self.num_shapes_per_body)
expected_shapes = self.asset.root_view.max_shapes
if num_shapes != expected_shapes:
raise ValueError(
"Randomization term 'randomize_rigid_body_material' failed to parse the number of shapes"
f" per body. Expected total shapes: {expected_shapes}, but got: {num_shapes}."
)Remove unnecessary local import. Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Signed-off-by: Matěj Kripner <kripnermatej@gmail.com>
Clarify comment. Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Signed-off-by: Matěj Kripner <kripnermatej@gmail.com>
|
this PR should support it : D, I am closing this PR for now. |
Summary
randomize_rigid_body_materialuses PhysX-specific APIs (link_paths,max_shapes,get/set_material_properties) that don't exist on Newton'sArticulationView, causingAttributeErrorwhen running tasks likeIsaac-Open-Drawer-Franka-v0withenv.sim=newton.hasattrcheck onget_material_propertiesand skip the term with a warning when unsupported.num_shapes_per_bodyproperty when available (Newton provides this directly) instead of the PhysX-specificlink_pathsworkaround.