Support OVPhysX in randomize_rigid_body_collider_offsets MDP event - #7569
Conversation
_CPU_ONLY_TYPES omitted eight tensor types that are CPU-resident even on a GPU simulation: the articulation and rigid-body collision-shape contact and rest offsets, both gravity-disable flags, and the DOF drive type and drive model. Because _native_device consults this set, it returned the simulation device for host-resident data. Every access staged a hidden host-to-device copy on a path the view believed was device-native, and _check_device rejected a buffer placed on the host, where the data actually lives, with DeviceMismatch. Residency was measured rather than assumed: ovphysx exposes no residency query, so each type was classified by counting CUDA memcpys around a binding read into a host buffer and into a device buffer, under the DirectGPU configuration isaaclab_ov itself sets. All eight measured CPU-resident across every GPU sample scene in the ovphysx wheel, and all previously classified members measured as declared. The guarding test compared the view's derived set against the canonical set it is derived from, so it could not fail for any contents. It now asserts against an independent inventory of measured residency, mirroring the existing _EXPECTED_READ_ONLY_NAMES pattern, so an incomplete set is caught.
ovphysx documents ARTICULATION_DOF_DRIVE_TYPE as read-only, but the attribute was missing from _READ_ONLY_NAMES, so set_attribute accepted writes to it and forwarded them to the binding instead of raising. An audit of the whole classification against the wheel's type table found this to be the only gap: of the twenty-one types ovphysx documents as read-only, twenty were already classified, and no member was misclassified. This is a behavior change. Writes to articulation_dof_drive_type that were previously accepted now raise OvPhysxView.ReadOnlyAttribute. Drive type is authored through the USD drive schema, not the tensor path. The existing read-only behavior test is parameterized over the expected inventory, so adding the name there also asserts that a write raises and leaves no binding behind.
The eight types added to the CPU-only classification were referenced through the raw ``_TT`` enum, leaving the candidate tuple as a mix of module aliases and raw enum members and giving a future reader no reason why these eight were different. This module is the alias layer over the ovphysx enum, so a type worth classifying is worth naming. Each alias carries the shape, dtype and units taken from the wheel's own type table, which the raw references did not. Naming follows the established convention: the ``ARTICULATION_`` prefix is dropped for articulation types, as with DOF_STIFFNESS and BODY_MASS, and retained for rigid-body ones, as with RIGID_BODY_MASS.
The term's backend dispatch tested only for Newton and fell through to the PhysX implementation on every other manager. On OVPhysX the asset's root_view is an OvPhysxView, which has none of the PhysX offset accessors, so adding the term to an environment config raised AttributeError from OvPhysxManager.reset() and the environment never built. Add an OVPhysX implementation that writes rest and contact offsets per collision shape through the asset's OvPhysxView, selecting the articulation or rigid-body offset tensor types by asset class. Match the dispatch of randomize_rigid_body_material: check ovphysxmanager first, then Newton, then PhysX, and raise a ValueError naming the backend for anything else instead of silently selecting PhysX. Cover the public term on a real OVPhysX RigidObject and Articulation so the dispatch itself is exercised.
Greptile SummaryAdds OVPhysX support to rigid-body collider-offset randomization and replaces implicit backend fallback with explicit dispatch.
Confidence Score: 5/5The PR appears safe to merge with no actionable correctness or security issues identified. The backend dispatch now selects a dedicated OVPhysX implementation, and the added tests cover rigid-object and articulation writes for selected and all environments across CPU and CUDA configurations. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[randomize_rigid_body_collider_offsets] --> B{Physics manager}
B -->|ovphysxmanager| C[OVPhysX implementation]
B -->|contains newton| D[Newton implementation]
B -->|contains physx| E[PhysX implementation]
B -->|other| F[Raise ValueError]
C --> G[Read and write per-shape offset attributes]
D --> H[Map offsets to Newton geometry properties]
E --> I[Use PhysX root-view offset accessors]
Reviews (1): Last reviewed commit: "Support OVPhysX in randomize_rigid_body_..." | Re-trigger Greptile |
There was a problem hiding this comment.
Isaac Lab Review Bot
The OVPhysX backend and explicit dispatch extend randomize_rigid_body_collider_offsets as intended, but the new implementation can silently fail to apply a valid rest/contact target pair because it always writes the rest offset first.
- Design and architecture: The backend-specific class follows the existing dispatch and implementation pattern. The remaining concern is confined to OVPhysX write sequencing rather than the overall backend separation.
- API: The public term signature and existing PhysX/Newton paths remain unchanged, and OVPhysX support is documented. However, callers cannot rely on both requested offsets being applied when the target rest offset exceeds the currently authored contact offset, even if the final sampled pair is valid.
- Implementation: The CPU tensor routing, articulation-versus-rigid-object tensor selection, indexed full-buffer writes, and public-path tests support the implementation. The rest offset is nevertheless written before the contact offset; OVPhysX only logs rejection when the intermediate state violates
rest < contact, so the rest write can be silently dropped. The writes should be sequenced according to current and target values so valid final pairs are applied reliably.
Minor fixes needed. Posted 1 actionable finding inline.
Automated review; human maintainers own approval decisions.
| distribution=distribution, | ||
| ) | ||
| # the wheel requires a full-shaped source buffer even for indexed writes | ||
| self.asset.root_view.set_attribute( |
There was a problem hiding this comment.
🔵 Suggestion · Implementation — Rest offset written before contact offset
This new path writes the sampled rest offset before the contact offset. As the added test comment records, PhysX requires rest < contact and OVPhysX only logs a violating setRestOffset, so raising both above a small authored contact offset silently drops the rest write while contact succeeds, leaving a stale rest offset with no error. Sequencing the two writes based on current and target values (or writing contact first when it increases) would make every valid target pair land.
|
run-ci |
|
Backported to |
…7569) # Description > **Stacked on #7563.** This branch needs the `REST_OFFSET` / `CONTACT_OFFSET` / `RIGID_BODY_*_OFFSET` aliases and the CPU-only routing for those tensor types that #7563 adds. Review/merge that first; this diff collapses to a single commit once it lands, at which point the base should be retargeted to `develop`. `randomize_rigid_body_collider_offsets` had no OVPhysX implementation. Its backend dispatch tested only for `"newton"` and fell through a bare `else` to `_RandomizeRigidBodyColliderOffsetsPhysx`, which calls `get_rest_offsets` / `get_contact_offsets` / `set_rest_offsets` / `set_contact_offsets` on `asset.root_view`. On OVPhysX that view is an `OvPhysxView`, which defines none of them, so adding the term to a config raised `AttributeError` during `OvPhysxManager.reset()` (via `PHYSICS_READY`) and the environment never built. The error surfaced from inside the PhysX implementation, so it did not name the unsupported backend either. Found by the OVQA agent harness on Isaac-Cartpole (release/3.0.0, ovphysx 0.5.11). No shipped task uses the term today, so this is latent rather than a live regression. **Fix** - New `_RandomizeRigidBodyColliderOffsetsOvPhysx`, mirroring the PhysX variant. OVPhysX runs the PhysX solver, so rest/contact offsets are written directly, per collision shape, through the asset's `OvPhysxView`: `REST_OFFSET` / `CONTACT_OFFSET` for articulations, `RIGID_BODY_REST_OFFSET` / `RIGID_BODY_CONTACT_OFFSET` for rigid objects. Both bindings are CPU-resident `[N, S]` buffers, so the full tensor is read-modify-written on the host with the selected envs as write indices. - Dispatch now matches `randomize_rigid_body_material` in the same file: `ovphysxmanager` first (it contains the substring `physx`), then Newton, then PhysX, and a `ValueError` naming the manager for anything else instead of silently selecting PhysX. - Docstring lists OVPhysX as a supported backend. **Note on write order** PhysX enforces `restOffset < contactOffset` and on OVPhysX a violating `setRestOffset` is only logged, not raised. The term writes rest before contact, same as the PhysX variant, so raising both above a small authored contact offset can silently skip the rest write. Kept for PhysX parity; flagging in case we want to reorder in both backends. **Verification** New `source/isaaclab_ov/test/test_randomize_rigid_body_collider_offsets_mdp.py` drives the public term (stubbed `cfg` / `env` / `asset_cfg`) against a real OVPhysX `RigidObject` and `Articulation`, so the dispatch itself is covered. It reproduced the reported `AttributeError` before the fix. Assertions: selected envs land in the sampled range, unselected envs are untouched, and omitting one distribution leaves that offset alone. Passes on `cuda:0` and `cpu` (separate processes, ovphysx device lock). PhysX and Newton paths are unchanged. Dependencies: #7563. Fixes # (no tracking issue; reported by the OVQA agent harness) ## Type of change - Bug fix (non-breaking change which fixes an issue) ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Screenshots Not applicable: no visual change. ## Checklist Docker and GPU tests run on demand. Push the commits you want tested, then comment `run-ci` on the pull request. - [x] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] I have added a changelog fragment under `source/<pkg>/changelog.d/` for every touched package (do **not** edit `CHANGELOG.rst` or bump `extension.toml` — CI handles that) - [x] I have added my name to the `CONTRIBUTORS.md` or my name already exists there --------- Co-authored-by: Kelly Guo <kellyg@nvidia.com> (cherry picked from commit 1b182e7)
Description
randomize_rigid_body_collider_offsetshad no OVPhysX implementation. Its backend dispatch tested only for"newton"and fell through a bareelseto_RandomizeRigidBodyColliderOffsetsPhysx, which callsget_rest_offsets/get_contact_offsets/set_rest_offsets/set_contact_offsetsonasset.root_view. On OVPhysX that view is anOvPhysxView, which defines none of them, so adding the term to a config raisedAttributeErrorduringOvPhysxManager.reset()(viaPHYSICS_READY) and the environment never built. The error surfaced from inside the PhysX implementation, so it did not name the unsupported backend either.Found by the OVQA agent harness on Isaac-Cartpole (release/3.0.0, ovphysx 0.5.11). No shipped task uses the term today, so this is latent rather than a live regression.
Fix
_RandomizeRigidBodyColliderOffsetsOvPhysx, mirroring the PhysX variant. OVPhysX runs the PhysX solver, so rest/contact offsets are written directly, per collision shape, through the asset'sOvPhysxView:REST_OFFSET/CONTACT_OFFSETfor articulations,RIGID_BODY_REST_OFFSET/RIGID_BODY_CONTACT_OFFSETfor rigid objects. Both bindings are CPU-resident[N, S]buffers, so the full tensor is read-modify-written on the host with the selected envs as write indices.randomize_rigid_body_materialin the same file:ovphysxmanagerfirst (it contains the substringphysx), then Newton, then PhysX, and aValueErrornaming the manager for anything else instead of silently selecting PhysX.Note on write order
PhysX enforces
restOffset < contactOffsetand on OVPhysX a violatingsetRestOffsetis only logged, not raised. The term writes rest before contact, same as the PhysX variant, so raising both above a small authored contact offset can silently skip the rest write. Kept for PhysX parity; flagging in case we want to reorder in both backends.Verification
New
source/isaaclab_ov/test/test_randomize_rigid_body_collider_offsets_mdp.pydrives the public term (stubbedcfg/env/asset_cfg) against a real OVPhysXRigidObjectandArticulation, so the dispatch itself is covered. It reproduced the reportedAttributeErrorbefore the fix. Assertions: selected envs land in the sampled range, unselected envs are untouched, and omitting one distribution leaves that offset alone. Passes oncuda:0andcpu(separate processes, ovphysx device lock). PhysX and Newton paths are unchanged.Dependencies: #7563.
Fixes # (no tracking issue; reported by the OVQA agent harness)
Type of change
Release backport
developScreenshots
Not applicable: no visual change.
Checklist
Docker and GPU tests run on demand. Push the commits you want tested, then
comment
run-cion the pull request.pre-commitchecks with./isaaclab.sh --formatsource/<pkg>/changelog.d/for every touched package (do not editCHANGELOG.rstor bumpextension.toml— CI handles that)CONTRIBUTORS.mdor my name already exists there