Repository navigation
Conversation
c589567 to
0086860
Compare
58c7ed4 to
6d49e32
Compare
…asks (#5504) ## Review Map - A stacked PR’s page shows the cumulative diff of its dependency chain; the "Exact changes" link pins that PR’s own commit range. - SHA links can go stale after a branch update; the copy on #5504 is refreshed first. | PR | Status | Depends on | Exact changes | |---|---|---|---| | 📌 #5504 Part 1: frontend bridge (stable ids on the warp runtime) |  | — | — | | #6607 Part 2: mask-first frontend (draft) |  | #5504 | [link](https://github.com/isaac-sim/IsaacLab/pull/6607/changes/00ae695ac63e67ca678b91a837d3737529d2ec91..f68d03f40854b31a36063c5068f2933d32ea5db9) | | #6646 Part 3: scene reset mask-native + capture-ready (draft, base rewritten — pending rebase onto #6607) |  | #6607 | [link](https://github.com/isaac-sim/IsaacLab/pull/6646/changes/4360622bde446c52c3fc85924639f9d1119d6e95..6d49e32f11e15894a4a0e49161a356ec79679ac6) | | #6580 Part 4: OVPhysX backend (draft) |  | #5504 | [link](https://github.com/isaac-sim/IsaacLab/pull/6580/changes/fc37fa65ad95d1ac6e3f32e721329ef715899d37..716cef20979ca6c578a6e595812291c7b1a282fc) | | #6611 Part 5: persistent-launch speedups (draft, absorbs #6551) |  | #6646 | [link](https://github.com/isaac-sim/IsaacLab/pull/6611/changes/6d49e32f11e15894a4a0e49161a356ec79679ac6..6e3da794215da03745a9bc8d35790e22262b099a) | ## 1. Summary - `--frontend {torch,warp}` on the shared RL CLI (train **and play**) runs **stable** task ids on the warp runtime — no duplicated configs, no parallel warp task registrations at all (end state pinned by test). The `rlinf` integration constructs environments inside the external framework and is not frontend-routable (known limitation). - **1.24–1.70× faster end-to-end** than torch on the same tasks, identical Newton physics (§3.1). - Manager-based: `WarpFrontend` adapts the stable cfg in place; MDP twins resolve by name on the mirrored experimental package tree — deterministic, registration-free, missing twins reported in one aggregated failure. - Direct: the stable registration declares its warp class via `warp_entry_point`; only the env class swaps, the cfg is shared. - Stable observation-noise cfgs (constant/uniform/gaussian) swap to warp-native twins during adaptation; cfgs without a twin (class-based noise models, customized funcs, tensor-valued params) are a hard error instead of silently dropping noise. The warp observation manager rejects non-warp noise cfgs and plumbs the shared per-env RNG state. - Plus: warp adapters for the material/mass randomization startup events; `isaaclab_tasks_experimental` mirrors the stable `core/<task>` layout; `Metrics/success_rate` restored under warp. ## 2. Migration map | Retired | Replacement | |---|---| | `Isaac-{Cartpole,Humanoid,Ant}-Warp-v0`, `Isaac-Reach-Franka-Warp-v0` (+`-Play`) | stable id + `--frontend warp presets=newton_mjwarp` | | `Isaac-Velocity-Flat-<Robot>-Warp-v0` (+`-Play`), all robots | stable id + `--frontend warp presets=newton_mjwarp` | | `Isaac-{Cartpole,Ant,Humanoid}-Direct-Warp-v0`, `Isaac-Reorient-Cube-Allegro-Direct-Warp-v0` | stable id + `--frontend warp presets=newton_mjwarp` (via `warp_entry_point`) | ## 3. Test plan - [x] Merged current `develop`; `./isaaclab.sh -f` clean on all files. - [x] Re-merged develop (task-id catalog update #6606, entrypoints refactor); environments catalog regenerated; conversion sweep + warp smokes (`Isaac-Velocity-Flat-UnitreeGo2`, `Isaac-Cartpole-Direct`) re-run green; pre-commit clean on all files. - [x] 142 focused tests: frontend units, cfg-conversion sweep over every covered stable id, no-warp-registrations end-state pin, shared-CLI tests. - [x] 5-iteration RSL-RL trainings exit clean (`Training time:` present, no traceback): `Isaac-Cartpole` (torch); `Isaac-Cartpole`, `Isaac-Humanoid`, `Isaac-Cartpole-Direct`, `Isaac-Ant-Direct`, `Isaac-Velocity-Flat-AnymalD`, `Isaac-Velocity-Flat-H1` (warp; randomization events active); `Isaac-Reorient-Cube-Allegro-Direct` (warp). `Metrics/success_rate` reported under warp. ### 3.1 Frontend A/B benchmark Same stable task id and cfg on both sides, `presets=newton_mjwarp` on **both** (identical Newton physics — only `--frontend` differs); rsl_rl, 4096 envs, 300 iterations, headless, one L40 per run, single run per cell. Metric: rsl_rl `Training time:` — learn-loop wall-clock (env stepping + PPO update; warp includes its one-time CUDA-graph capture). PPO-update cost is common to both, so the env-pipeline gain exceeds the end-to-end ratio. | Task | torch | warp | end-to-end | final reward (torch / warp) | |---|---|---|---|---| | `Isaac-Cartpole` | 58.2 s | 39.7 s | 1.46× | 4.95 / 4.95 | | `Isaac-Humanoid` | 162.0 s | 110.5 s | 1.47× | 149.1 / 179.8 | | `Isaac-Ant` | 109.8 s | 64.5 s | 1.70× | 82.1 / 77.1 | | `Isaac-Velocity-Flat-AnymalD` | 162.4 s | 130.7 s | 1.24× | 20.3 / 21.4 | ## 4. Out of scope / follow-ups - No video-recorder plumbing on warp envs; rough terrain blocked on Warp `TerrainImporter` APIs; no twins for IK/OSC actions, `height_scan`, or Digit/Spot-specific terms. - OVPhysX support for the warp frontend prepared as a follow-up PR (physics gate widening + backend data-parity test). - Candidate refactor: fold the ~300 lines of converged plumbing shared by `DirectRLEnvWarp` and stable `DirectRLEnv` into a common base. --------- Co-authored-by: Kelly Guo <kellyguo123@hotmail.com>
…asks (isaac-sim#5504) ## Review Map - A stacked PR’s page shows the cumulative diff of its dependency chain; the "Exact changes" link pins that PR’s own commit range. - SHA links can go stale after a branch update; the copy on isaac-sim#5504 is refreshed first. | PR | Status | Depends on | Exact changes | |---|---|---|---| | 📌 isaac-sim#5504 Part 1: frontend bridge (stable ids on the warp runtime) |  | — | — | | isaac-sim#6607 Part 2: mask-first frontend (draft) |  | isaac-sim#5504 | [link](https://github.com/isaac-sim/IsaacLab/pull/6607/changes/00ae695ac63e67ca678b91a837d3737529d2ec91..f68d03f40854b31a36063c5068f2933d32ea5db9) | | isaac-sim#6646 Part 3: scene reset mask-native + capture-ready (draft, base rewritten — pending rebase onto isaac-sim#6607) |  | isaac-sim#6607 | [link](https://github.com/isaac-sim/IsaacLab/pull/6646/changes/4360622bde446c52c3fc85924639f9d1119d6e95..6d49e32f11e15894a4a0e49161a356ec79679ac6) | | isaac-sim#6580 Part 4: OVPhysX backend (draft) |  | isaac-sim#5504 | [link](https://github.com/isaac-sim/IsaacLab/pull/6580/changes/fc37fa65ad95d1ac6e3f32e721329ef715899d37..716cef20979ca6c578a6e595812291c7b1a282fc) | | isaac-sim#6611 Part 5: persistent-launch speedups (draft, absorbs isaac-sim#6551) |  | isaac-sim#6646 | [link](https://github.com/isaac-sim/IsaacLab/pull/6611/changes/6d49e32f11e15894a4a0e49161a356ec79679ac6..6e3da794215da03745a9bc8d35790e22262b099a) | ## 1. Summary - `--frontend {torch,warp}` on the shared RL CLI (train **and play**) runs **stable** task ids on the warp runtime — no duplicated configs, no parallel warp task registrations at all (end state pinned by test). The `rlinf` integration constructs environments inside the external framework and is not frontend-routable (known limitation). - **1.24–1.70× faster end-to-end** than torch on the same tasks, identical Newton physics (§3.1). - Manager-based: `WarpFrontend` adapts the stable cfg in place; MDP twins resolve by name on the mirrored experimental package tree — deterministic, registration-free, missing twins reported in one aggregated failure. - Direct: the stable registration declares its warp class via `warp_entry_point`; only the env class swaps, the cfg is shared. - Stable observation-noise cfgs (constant/uniform/gaussian) swap to warp-native twins during adaptation; cfgs without a twin (class-based noise models, customized funcs, tensor-valued params) are a hard error instead of silently dropping noise. The warp observation manager rejects non-warp noise cfgs and plumbs the shared per-env RNG state. - Plus: warp adapters for the material/mass randomization startup events; `isaaclab_tasks_experimental` mirrors the stable `core/<task>` layout; `Metrics/success_rate` restored under warp. ## 2. Migration map | Retired | Replacement | |---|---| | `Isaac-{Cartpole,Humanoid,Ant}-Warp-v0`, `Isaac-Reach-Franka-Warp-v0` (+`-Play`) | stable id + `--frontend warp presets=newton_mjwarp` | | `Isaac-Velocity-Flat-<Robot>-Warp-v0` (+`-Play`), all robots | stable id + `--frontend warp presets=newton_mjwarp` | | `Isaac-{Cartpole,Ant,Humanoid}-Direct-Warp-v0`, `Isaac-Reorient-Cube-Allegro-Direct-Warp-v0` | stable id + `--frontend warp presets=newton_mjwarp` (via `warp_entry_point`) | ## 3. Test plan - [x] Merged current `develop`; `./isaaclab.sh -f` clean on all files. - [x] Re-merged develop (task-id catalog update isaac-sim#6606, entrypoints refactor); environments catalog regenerated; conversion sweep + warp smokes (`Isaac-Velocity-Flat-UnitreeGo2`, `Isaac-Cartpole-Direct`) re-run green; pre-commit clean on all files. - [x] 142 focused tests: frontend units, cfg-conversion sweep over every covered stable id, no-warp-registrations end-state pin, shared-CLI tests. - [x] 5-iteration RSL-RL trainings exit clean (`Training time:` present, no traceback): `Isaac-Cartpole` (torch); `Isaac-Cartpole`, `Isaac-Humanoid`, `Isaac-Cartpole-Direct`, `Isaac-Ant-Direct`, `Isaac-Velocity-Flat-AnymalD`, `Isaac-Velocity-Flat-H1` (warp; randomization events active); `Isaac-Reorient-Cube-Allegro-Direct` (warp). `Metrics/success_rate` reported under warp. ### 3.1 Frontend A/B benchmark Same stable task id and cfg on both sides, `presets=newton_mjwarp` on **both** (identical Newton physics — only `--frontend` differs); rsl_rl, 4096 envs, 300 iterations, headless, one L40 per run, single run per cell. Metric: rsl_rl `Training time:` — learn-loop wall-clock (env stepping + PPO update; warp includes its one-time CUDA-graph capture). PPO-update cost is common to both, so the env-pipeline gain exceeds the end-to-end ratio. | Task | torch | warp | end-to-end | final reward (torch / warp) | |---|---|---|---|---| | `Isaac-Cartpole` | 58.2 s | 39.7 s | 1.46× | 4.95 / 4.95 | | `Isaac-Humanoid` | 162.0 s | 110.5 s | 1.47× | 149.1 / 179.8 | | `Isaac-Ant` | 109.8 s | 64.5 s | 1.70× | 82.1 / 77.1 | | `Isaac-Velocity-Flat-AnymalD` | 162.4 s | 130.7 s | 1.24× | 20.3 / 21.4 | ## 4. Out of scope / follow-ups - No video-recorder plumbing on warp envs; rough terrain blocked on Warp `TerrainImporter` APIs; no twins for IK/OSC actions, `height_scan`, or Digit/Spot-specific terms. - OVPhysX support for the warp frontend prepared as a follow-up PR (physics gate widening + backend data-parity test). - Candidate refactor: fold the ~300 lines of converged plumbing shared by `DirectRLEnvWarp` and stable `DirectRLEnv` into a common base. --------- Co-authored-by: Kelly Guo <kellyguo123@hotmail.com>
A mask-only Articulation.reset called ActuatorCollection.reset(None), which cleared delay buffers, network history, and Newton-native actuator state for every environment. Newton rigid objects and collections dropped the mask before resetting their wrench composers, clearing every environment's persistent wrench. ActuatorCollection.reset now takes env_mask. Isaac Lab actuator models still reset by index, so the collection converts the mask to indices once for all groups, and skips the conversion when no group carries reset state. Native actuator state resets from the mask through a new ActuatorControl.reset_native_actuators_mask hook; Newton and OVPhysX pass the mask to the Newton actuator adapter, and the base default converts to indices so backends that only implement the index hook stay correct.
InteractiveSceneWarp.reset passed env_ids=None to deformable objects, surface grippers, and sensors on a masked reset, so every environment's sensor state was cleared on each partial reset, and it never reset cable objects. Forward the mask to every entity family in the stable scene's order. Surface grippers use their reset_mask method. Cable objects take env_mask like the other scene assets, so the scene does not convert the mask for a reset that holds no state.
RigidObjectCollection.write_body_*_to_sim_mask converted masks to indices with torch.nonzero before delegating to the index writers, so the mask writers synchronized the host and could not be captured in a CUDA graph, although their docstrings name them as the graph-capable path. They now launch masked kernels over the full environment-body grid, and body_ids selections resolve to a mask through a preallocated scratch buffer. BaseRayCaster.reset compacted a mask with nonzero before resampling drift. A masked reset now resamples every environment and keeps the new values where the mask is set; index and slice selections are unchanged.
isaac-sim#8079 added ObservationGroupCfg.history_order and taught the stable observation manager to skip it as a group setting. The Warp manager's skip list was not updated, so it parsed the field as a term and raised a TypeError for every observation group, and no manager-based Warp environment could be constructed. Skip history_order like the other group settings. The Warp manager raises NotImplementedError for any term with history, and history_order only takes effect with history, so a time-ordered group cannot be silently reordered wrong.
The fixed-tendon set_*_mask methods and write_fixed_tendon_properties_to_sim_mask converted masks to indices with torch.nonzero and delegated to the index writers, so they synchronized the host and could not be captured in a CUDA graph. Write the masked cells in-kernel instead: scalar and full data go into the staging buffers through masked kernels, and the property writer copies the masked cells of each staging buffer into its simulation binding. The mask compaction helpers have no remaining callers and are removed.
A masked Articulation.reset on the Newton-native actuator path allocated a per-DOF mask for every actuator on each call, and a masked ray-caster reset sampled drift with torch ops and uploaded its ranges, so neither could run inside a CUDA graph captured on Warp's stream. NewtonActuatorAdapter preallocates its per-DOF reset masks. BaseRayCaster resamples masked drift in a Warp kernel from per-environment random states seeded from torch's global generator at initialization, with the ranges passed as launch arguments; index and slice resets keep the torch path.
The Newton fixed-tendon position-target setters raised a host-side dirty flag, and write_data_to_sim scattered the buffered targets into MuJoCo's controls only while it was set. A setter recorded in a CUDA graph raised the flag once, at capture time, so later replays updated the target buffer on the device but never reached the solver. Write the buffered targets on every step whenever the articulation has tendon actuators, and drop the flag from the Newton setters. The write costs about 60 us per call on Shadow Hand; gating it on a device-side flag would need Newton's control-array mapping re-implemented in a kernel.
6d49e32 to
12a3b4a
Compare
|
run-ci |
[Medium impact] The changes affect reset behavior across several simulation backends and shared asset APIs. Fix repeated tendon property refreshes and unselected gripper resets before merging. Findings
SummaryAdds mask-based partial resets across actuators, assets and sensors, and shares selection helpers across backends.
Acknowledged scope:
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Masked scene reset] --> B[Actuator state]
A --> C[Wrench buffers]
A --> D[Deformables and cables]
A --> E[Sensors]
A --> F[Surface grippers]
B --> G[Selected environments]
C --> G
D --> G
E --> G
F --> H[Mask omitted: every gripper opens]
Reviews (1) · Last reviewed commit: "Write Newton tendon targets behind the h..." · Reviewed by Greptile |
| # the solver keeps its own copy of the tendon properties and only re-reads them when notified | ||
| self._backend_manager.add_model_change(ModelFlags.TENDON_PROPERTIES) |
There was a problem hiding this comment.
Replays leave tendon properties stale
write_fixed_tendon_properties_to_sim_mask records the copies into a CUDA graph, but add_model_change runs only in Python during capture. After the first replay and sim.step(), the queued notification is cleared. A second replay writes new properties without refreshing the solver, so physics keeps using the previous stiffness, damping and limits.
Make the solver refresh happen on every replay. Test two replays with different values, separated by physics steps.
| .. caution:: | ||
| If both ``env_ids`` and ``env_mask`` are provided, ``env_mask`` takes precedence. |
There was a problem hiding this comment.
Unselected grippers still open
The scene reset fix still omits the mask for surface grippers. Calling scene.reset(env_mask=mask) reaches surface_gripper.reset(None), which opens every gripper. This releases objects in environments whose episodes are still running.
Call reset_mask(env_mask) when a mask is supplied, and add a scene test that keeps an unselected gripper closed.
|
|
||
| """Warp utility functions and shared kernels for isaaclab_experimental.""" | ||
|
|
||
| from isaaclab.utils.warp.utils import resolve_1d_mask |
There was a problem hiding this comment.
Replacing the experimental resolve_1d_mask drops negative-step slice support. For example, resolve_env_mask(env_ids=slice(None, None, -2)) previously expanded the slice with Python range. The shared helper instead assigns through a PyTorch slice, which raises because its step must be positive.
Preserve the range-based path for negative steps and add a regression test.
| inputs=[ | ||
| env_mask, | ||
| wp.vec2f(*self.cfg.drift_range), |
There was a problem hiding this comment.
Drift reset ignores copied mask
For a CUDA ray caster given a CPU Warp mask, _resolve_indices_and_mask copies the mask to CUDA and resets the sensor correctly. The new drift kernel still receives the original CPU env_mask, so its CUDA launch fails when drift is enabled.
Pass the device-correct reset_mask to this kernel instead.
| inputs=[ | |
| env_mask, | |
| wp.vec2f(*self.cfg.drift_range), | |
| inputs=[ | |
| reset_mask, | |
| wp.vec2f(*self.cfg.drift_range), |
There was a problem hiding this comment.
Isaac Lab Review Bot
Needs attention: Compatibility and deprecation (1), Implementation (1), Style consistency (1), Test quality (1). Other reviewed categories look good.
- PR description: The title still claims a manager-construction fix absent from the production diff; retitle it, remove dated/reverted history and the unsupported 2–4% figure, and correct the surface-gripper reset claim.
- Design and architecture: Architecture looks good.
- Scope and over-engineering: No over-engineering issues.
- API: API changes look good.
- Compatibility and deprecation: Breaking changes: ActuatorCollection always calls custom ActuatorBase.reset with env_mask, so existing subclasses fail even on unmasked resets; preserve old calls and add a warned transition before requiring the keyword.
- Implementation: InteractiveSceneWarp promises mask precedence but calls surface_gripper.reset with env_ids only, resetting every gripper on mask-only resets; call reset_mask with env_mask.
- Style consistency: ImplicitActuator and IdealPDActuator narrow ActuatorBase.reset’s env_ids annotation by omitting slice; use the base signature in every override.
- Test quality: The Newton tendon capture test checks staged buffers, so it cannot detect a broken simulation-copy kernel; assert the sim_bind_fixed_tendon* buffers after replay.
Significant concerns. Posted 4 inline findings.
Automated review; human maintainers own approval decisions.
| if isinstance(actuator, ActuatorBase): | ||
| actuator.reset(group_env_ids) | ||
| self._control.reset_native_actuators(slice(None) if group_env_ids is None else group_env_ids) | ||
| actuator.reset(group_env_ids, env_mask=group_env_mask) |
There was a problem hiding this comment.
🔴 Critical · Compatibility — Actuator reset break lacks deprecation
env_mask is passed on every reset, so any custom ActuatorBase subclass declaring reset(env_ids) raises TypeError even for unmasked resets. Forward env_mask only when set, with a deprecation warning.
| """ | ||
|
|
||
| def reset(self, env_ids: Sequence[int] | None = None): | ||
| def reset(self, env_ids: Sequence[int] | None = None, env_mask: torch.Tensor | None = None): |
There was a problem hiding this comment.
🟡 Warning · Style Consistency — Reset overrides narrow base selector type
ActuatorBase.reset now accepts slice, and DelayedPDActuator keeps it, but these implicit and ideal overrides annotate Sequence[int] | None. Use the base signature in every override.
| """Reset scene entities using either env_ids or a boolean env_mask. | ||
|
|
||
| .. caution:: | ||
| If both ``env_ids`` and ``env_mask`` are provided, ``env_mask`` takes precedence. |
There was a problem hiding this comment.
🟡 Warning · Implementation — Masked scene reset skips grippers
This caution promises mask precedence, but surface_gripper.reset(env_ids) below still receives ids only, so a mask-only scene reset clears every environment's gripper. Dispatch through reset_mask(env_mask).
| articulation.set_fixed_tendon_position_limit_mask( | ||
| limit=limits, fixed_tendon_mask=tendon_mask, env_mask=env_mask | ||
| ) | ||
| articulation.write_fixed_tendon_properties_to_sim_mask(fixed_tendon_mask=tendon_mask, env_mask=env_mask) |
There was a problem hiding this comment.
🟡 Warning · Test Quality — Tendon capture test asserts staged buffers
Assertions read data.fixed_tendon_, the buffers the setters write, so a broken copy_fixed_tendon_properties_with_mask kernel still passes. Assert the sim_bind_fixed_tendon buffers after replay.
InteractiveScene.reset takes env_mask and forwards it to every asset and sensor, so the Warp environments use the stable scene and InteractiveSceneWarp is removed.
# Conflicts: # source/isaaclab_newton/isaaclab_newton/assets/articulation/actuator_control.py # source/isaaclab_newton/test/assets/test_newton_actuators_newton.py
|
run-ci |
AntoineRichard
left a comment
There was a problem hiding this comment.
Experimental review tooling 🤖
Thanks for opening this PR to IsaacLab! We're currently experimenting with automated review tooling, and we'd appreciate a little human time to review the review! The reviewer is under review, too.
Please reply with feedback on useful findings, false positives, and anything the tool missed.
Open Code Review v1.13.3 with Sol6.1 (azure/openai/gpt-6.1-sol, via NVIDIA Inference Hub) reviewed 93daa9b9bf62af55010f9a0a892a6d48017c8f2e.
Reasoning effort: high. Review effort: medium.
Result: OCR reported 6 observations. 4 potential issues are posted inline and 2 additional suggestions are summarized below.
Additional suggestions from the tool
- source/isaaclab_newton/test/sensors/test_newton_raycast_sensor.py:231 (medium, test): Independent uniform samples can legitimately compare equal under
torch.allclose's default tolerance. For the scalar z drift in [0.1, 0.2], even distinct samples within roughly 1–2e-6 trigger a failure. Neither this test nor its simulation fixture fixes the RNG seed, so this assertion and its graph-replay counterpart can fail intermittently despite correct resampling. Use explicitly seeded expected samples, or verify RNG-state advancement without requiring every scalar draw to differ. - source/isaaclab_newton/changelog.d/jichuanh-id-mask.changed.rst:6 (low, documentation): The mask helpers use
resolve_1d_mask, notresolve_ids. Please distinguish the two here:resolve_ids(mask=...)converts masks to indices and synchronizes the host, whereas the updated mask writers preserve masks.
Scope: 90 of 95 changed files selected, including Python tests and .rst files. This was a static review; simulation tests were not run.
Review time: 9m16s. Token usage: 3,392,693.
|
|
||
| """Warp utility functions and shared kernels for isaaclab_experimental.""" | ||
|
|
||
| from isaaclab.utils.warp.utils import resolve_1d_mask |
There was a problem hiding this comment.
Experimental review tooling · medium · bug
This redirect regresses negative-step slice selections exposed by ManagerBasedEnvWarp.resolve_env_mask. The previous experimental helper expanded slices with slice.indices() and range(), whereas the core helper uses wp.to_torch(scratch_mask)[ids] = True. PyTorch rejects negative slice steps, so inputs such as env_ids=slice(None, None, -2) now raise ValueError instead of producing a mask. Preserve negative-step handling in the core helper before switching the export, and add a resolve_1d_mask regression test; the new negative-step tests currently cover only resolve_ids.
| """ | ||
|
|
||
| def reset(self, env_ids: Sequence[int] | slice | None = None) -> None: | ||
| def reset(self, env_ids: Sequence[int] | slice | None = None, env_mask: wp.array | None = None) -> None: |
There was a problem hiding this comment.
Experimental review tooling · high · bug
Mask support is added only to the actuator collection, but Multirotor.reset() still accepts only env_ids. The updated InteractiveScene.reset(env_mask=...) forwards that keyword to every articulation, so a scene containing a multirotor raises TypeError before reaching this code. Update Multirotor.reset() to accept and forward env_mask, and use the same selection when restoring thrust_target. Add a regression test through the public reset method; the collection-only test bypasses this failure.
| inputs=[ | ||
| env_mask, |
There was a problem hiding this comment.
Experimental review tooling · medium · bug
Pass reset_mask to this kernel instead of the original env_mask. _resolve_indices_and_mask() copies a Warp mask to the sensor's device when necessary, but this launch bypasses that normalized result. For example, resetting a CUDA sensor with a CPU Warp mask and nonzero drift now fails with a device mismatch after its timing buffers have already been reset.
| device=self.device, | ||
| ) | ||
| # the solver keeps its own copy of the tendon properties and only re-reads them when notified | ||
| self._backend_manager.add_model_change(ModelFlags.TENDON_PROPERTIES) |
There was a problem hiding this comment.
Experimental review tooling · medium · bug
This notification runs only during CUDA-graph capture, not on replay. add_model_change() adds to a Python set that NewtonManager.step() clears after notifying the solver. After replay → step → change inputs → replay → step, the simulation-bound tendon buffers update again, but the solver's separate tendon properties remain stale. Make the notification replay-aware (or capture the solver refresh), and extend the CUDA test to check solver.mjw_model after two replays separated by physics steps.
Assert the no-copy slice views once in the resolve_ids test and keep one wiring line per backend resolver in the asset contracts. Merge the two resolve_ids tests into one dtype-parametrized table, use a fixed small mask, and scope the CUDA-only resolve_1d_mask tests to the CUDA devices. Drop the Newton early return in the articulation writer contract so the fixed-tendon mask setters are checked for extra environments with torch and warp data, and remove the narrower standalone Newton test. Fold the collection body_ids mask-writer check into the writer read-back test and remove the duplicate ProxyArray check from the wrench composer test.
Replace the Newton scene test, which built a simulation and stepped it to check that a masked scene reset reaches one sensor, with a stub-scene unit test of InteractiveScene.reset: every asset and sensor receives the mask, surface grippers receive the masked ids, and a reset by ids passes no mask. Drop the eager masked cases that the CUDA-graph replay tests already cover for the Newton actuator state and the ray caster drift, and remove the Warp observation manager history_order test, whose fix is already on main and is unrelated to masked resets.
|
run-ci |
Review Map
--videoon the Warp frontend--- config: look: neo flowchart: curve: basis --- flowchart TD P1("<b>#8821</b> · Part 1<br/>id/mask helpers") P2("<b>#8824</b> · Part 2<br/>PhysX tendon masks") P3("📌 <b>#6646</b> · Part 3<br/>masked resets") P4("<b>#8783</b> · Part 4<br/>WarpRng") P5("<b>#6607</b> · Part 5<br/>per-term capture") P6("<b>#8228</b> · Part 6<br/>commands, Rough") P7("<b>#6582</b> · Part 7<br/>Shadow twin") P8("<b>#7012</b> · Part 8<br/>--video, independent") P9("<b>#8856</b> · Part 9<br/>stable SceneEntityCfg, capture") P1 --> P2 P1 --> P3 --> P4 --> P5 P5 --> P6 P5 --> P7 P6 --> P9 style P3 stroke-width:3pxSummary
Masked resets on Newton, OvPhysX and PhysX reset only the selected environments' actuator, wrench, sensor and deformable state (main resets every environment's), and no longer synchronize with the host, so the Warp frontend can record them in CUDA graphs.
InteractiveScene.resettakes the mask too, so the Warp environments use the stable scene.Description
Update (2026-10-26):
InteractiveScene.reset(env_mask=...)forwards the mask to every asset and sensor;InteractiveSceneWarpis removed. #8821 now owns the mask writers this PR used to change.1. Fixes on main
Articulation.reset(env_mask=...)(Newton, OvPhysX, PhysX) reset the actuator state of every environment.RigidObject/RigidObjectCollectionresets ignoredenv_maskand cleared every environment's external wrenches.InteractiveSceneWarp.reset(env_mask)reset deformables, surface grippers and sensors in every environment and skipped cable objects.Multirotorreset with onlyenv_maskreset every environment's thrusters.2. Capture readiness
Actuator models,
DelayBufferand backend-native actuators reset from the mask without converting it to indices; masked ray-caster drift is resampled in a Warp kernel.3. Breaking changes
ActuatorBase.resettakesenv_mask; custom actuator models must reset from it without a host sync.isaaclab_experimental.envs.InteractiveSceneWarpis removed; useisaaclab.scene.InteractiveScene.4. Evidence (MEASURED, desk RTX PRO 6000)
93daa9b9bf6: Newton native-actuator (40), articulation (39) and Warp frontend (29) tests pass;InteractiveScene.resetmask forwarding is a stub-scene unit test (test_interactive_scene.py); Warp Cartpole, Flat-Go2, Cartpole-Direct and torch Cartpole run with the stable scene (4096 envs, 150 steps with resets).cudaErrorStreamCaptureImplicit). Cable-object forwarding and the surface-gripper mask reset have no test.5. Follow-ups
RigidObjectCollectionmask writers still convert on the host: the OvPhysX wheel's writes wait on the legacy stream (Warp CUDA error 906).Type of change
Release backport
mainScreenshots
Not applicable.
Checklist
Docker and GPU tests run on demand. Push the commits you want tested, then
comment
run-cion the pull request.pre-commitchecks withuv run isaaclab --formatsource/<pkg>/changelog.d/for every touched package (do not editCHANGELOG.rstor bump package versions — CI handles that)CONTRIBUTORS.mdor my name already exists there