Repository navigation
[Warp] Part 3/6: Capture Warp stages per term without warm-up and step like the stable environments - #6607
Draft
hujc7 wants to merge 51 commits into
Draft
[Warp] Part 3/6: Capture Warp stages per term without warm-up and step like the stable environments#6607hujc7 wants to merge 51 commits into
hujc7 wants to merge 51 commits into
Conversation
8 tasks done
This was referenced Jul 21, 2026
hujc7
force-pushed
the
jichuanh/warp-frontend-cleanup
branch
from
July 23, 2026 23:19
c971364 to
f68d03f
Compare
kellyguo11
added a commit
that referenced
this pull request
Jul 24, 2026
…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>
matthewtrepte
pushed a commit
to matthewtrepte/IsaacLab
that referenced
this pull request
Aug 4, 2026
…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.
Replace ManagerCallSwitch with an environment-owned WarpGraphCache that follows the Newton core capture model: a stage is recorded through NewtonQueries.capture_graph with no eager warm-up, so the first execution is the launch of the new graph; recording starts at the first step; graphs are keyed by the pointers and scalar values of the stage arguments; and every graph is dropped when the physics backend rebinds its buffers or stops, so the next step records against the new buffers. Managers with a non-capturable term keep their stages eager through register_capturability. ISAACLAB_WARP_CAPTURE=0 runs every stage eagerly and ISAACLAB_SYNC_DEBUG=1 traps hidden host synchronizations in eager stages. The direct environment uses the same cache in place of capture_or_replay.
The manager-based Warp environments now reset through one mask-first pipeline: every reset selection is copied into an environment-owned mask that the recorded reset stages read, the scene and the Warp managers reset from that mask, and the episode-length buffer is cleared by a masked kernel. The mask is compacted to environment indices once per reset, and only when a stable command, curriculum or recorder manager has active terms. ManagerBasedEnvWarp.reset accepts env_mask. Each step makes one host check to decide whether any environment terminated: the index compaction when a manager needs indices, otherwise reset_buf.any(). DirectRLEnvWarp moves its reset out of the end-of-step graph into its own stage behind the same predicate. A static gate pins the sanctioned host synchronizations of the mask-first path, which also removes the device read from CircularBuffer.max_length. The Episode_Termination metric keeps averaging over every environment, as the stable manager does.
push_by_setting_velocity, apply_external_force_torque, reset_root_state_uniform and randomize_rigid_body_com kept scratch arrays and parsed ranges as attributes of the module-level function. The first call allocated them, which inside a recorded stage becomes graph-owned memory; the parsed ranges froze the first configuration; and the state was shared by every environment in the process. They are now ManagerTermBase classes that allocate in __init__ and read their ranges on every call. randomize_rigid_body_com offsets the center of mass it finds on its first call instead of accumulating, and apply_external_force_torque with zero ranges leaves the permanent wrench composer untouched. The material and mass adapters reject modes other than startup and are marked non-capturable. Startup terms no longer keep the event stages eager, since they never run inside one, and set_term_cfg re-resolves the term and drops the recorded event stages.
A manager with one non-capturable term used to run every stage eagerly. Managers now describe each stage as ordered steps, one per term plus their own setup and finalize kernels, and WarpGraphCache.call_steps records each run of consecutive capturable steps into one graph while the terms marked @WarpCapturable(False) run eagerly in place. Reward and termination terms write their own output columns and the finalize kernel combines the columns in a fixed order, so these stages evaluate the capturable terms first and need at most one eager group. Observation noise and events draw from the shared per-environment random state, and action terms are applied in order, so those stages keep the configured term order and split into contiguous runs. Observation terms with history run as eager steps instead of raising inside capture. Replacing a reward term rebuilds its steps and drops the recorded reward stages.
A term can be capture-safe for one configuration and not another: a reward that reads a ray-caster refreshes the sensor on the host and launches its query graph, which cannot run inside a recorded stage, while the same reward without a sensor can. WarpCapturable accepts a predicate over the term's parameters, and its guard raises only for the parameters the predicate rejects. The Warp managers resolve capturability with each term's parameters, and a class term may set _warp_capturable in __init__ to decide per instance. The sync gate's opt-out inventory also lists predicate annotations.
Stable environments tell the physics backend their decimation and, when the backend runs the whole decimation loop, apply actions, step the simulation and update the scene once per environment step. The Warp environments still looped once per physics step, so contact sensors sampled four times as often on Go2 and the contact history, air times and the rewards and terminations reading them differed from the stable environment with the same configuration. Mirror the stable loop in the manager-based and direct Warp environments. The per-physics-step loop remains for backends that do not run the decimation loop.
The stable environments honor compute_final_obs: a step that resets environments stores the observations from before the reset in extras["final_obs"] and declares Same-Step autoreset in the metadata. The Warp environments ignored the flag, so torchrl, which sets it, bootstrapped time-outs from the post-reset observation. Compute the observations before the reset stage and keep a copy, because the reset overwrites the persistent observation buffers. Declare Same-Step autoreset in both Warp environment classes.
Warp managers and tasks log persistent buffers that later steps overwrite. Loggers such as the rsl_rl logger keep extras["log"] of every step and average it at the end of an iteration, so every entry showed the latest value. The stable environments log fresh tensors. The manager-based environment copies the tensor values when it builds the reset log. The direct environment keeps the log the task writes and returns a copy of it from every step, so task code that is recorded into a CUDA graph keeps refreshing its own buffers.
ManagerBasedEnvWarp built its reset log from the same persistent manager buffers as the RL environment, so a logged value changed with the next reset. Copy the tensor values like the RL environment does.
Collaborator
Author
|
run-ci |
Collaborator
Author
|
run-ci |
…-mask-native # Conflicts: # docs/source/concepts/warp_environment_migration.rst # source/isaaclab_newton/isaaclab_newton/assets/articulation/actuator_control.py # source/isaaclab_newton/isaaclab_newton/assets/articulation/articulation.py # source/isaaclab_newton/test/assets/test_articulation.py # source/isaaclab_newton/test/assets/test_newton_actuators_newton.py # source/isaaclab_newton/test/assets/test_rigid_object.py # source/isaaclab_newton/test/sensors/test_newton_raycast_sensor.py
… the Warp environments
Collaborator
Author
|
run-ci |
Environments initialize WarpRng once at construction and configure_seed reseeds it in place. The ray caster, experimental managers, events, noise models and Warp tasks read WarpRng.state instead of keeping their own copies; rng_state_wp is removed. Re-applies 6ac6061 and 9328d98, split out of the masked-reset pull request.
6 of 8 tasks
Collaborator
Author
|
run-ci |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review Map
--videoon the Warp frontend (draft)Summary
Warp environments step like the stable ones (physics-owned decimation,
extras["final_obs"], per-stepextras["log"]copies) and record their stages from the first call without an eager warm-up, bitwise equal to eager.Capture is decided per term, so one term that cannot be recorded no longer forces its whole manager stage eager; Go2 Flat steps in 6.96 ms instead of 7.53 ms with Part 1 (8gpu L40, 4096 envs).
Description
Update (2026-10-22): now stacked on #8783 (the shared Warp RNG state, split out of #6646) and merged
main8c9b995cb95; this PR's own diff is unchanged.Update (2026-10-20): merged #6646 and
main2dbb6146d75(the default branch, renamed fromdevelop; "main" below means main without this PR, measured ataa9bafef8a0). The Warp environments reach the physics backend throughsim.backend_manager, since #8711 deprecatedsim.physics_manager. After the merge, the experimental utils, managers and MDP parity tests (85), the frontend, scene, capture, decimation, final-obs, log and reset tests pass; Cartpole, Cartpole-Direct, Ant-Direct, Allegro-Direct and Go2 Flat Warp runs advance 16/16 RNG states, and every Cartpole and Go2 stage records one graph.Update (2026-10-02): merged #6646 and develop
772358ac3b9, plus one review-round commit (ee9e8adbb9d):CapturedStagereplacesWarpGraphCache, direct environments decide resets on the GPU,process_actiontakes torch actions, and a class term'sresetis judged by its own annotation.1. Changes
CapturedStage,@capturedandeager()replaceWarpGraphCache. A stage records on its first call without a warm-up, as main's physics capture does (Capture Newton CUDA graphs without advancing simulation #8058), replays afterwards, and records again after the simulation is reset or stopped (without this: CUDA error 700 after a rebind). Recordings pause the garbage collector and collect only the youngest generation afterwards.ISAACLAB_SYNC_DEBUG=1raises on a hidden host sync.@WarpCapturable(False)term runs eagerly at its place in the recording;@WarpCapturable(lambda params: ...)decides per configured instance. A class annotation covers the term's call; itsresetis recorded unless theresetmethod is annotated.ActionManager.process_actiontakes a torch action.DirectRLEnvWarpdecides on the GPU whether any environment must reset (a conditional graph node, CUDA 12.4+), so a step no longer synchronizes with the host.push_by_setting_velocity,apply_external_force_torque,reset_root_state_uniform,randomize_rigid_body_com): buffers allocated at creation, ranges read on every call. Fixes main's COM offsets accumulating per call and zero-range wrench events clearing permanent wrenches. An interval range replaced throughEventManager.set_term_cfgnow applies; main kept the old range.undesired_contactsandbase_contactdiffer from stable.extras["final_obs"]and Same-Step autoreset metadata: main ignorescompute_final_obs, which the torchrl entry point sets.extras["log"]copies: main returns views, so rsl_rl logs the last reset's value for every step of an iteration.ManagerCallSwitch,ManagerCallMode,MANAGER_CALL_CONFIG,WarpGraphCache,ManagerBasedRLEnvWarp.step_warp_termination_computeandDirectRLEnvWarp.step_warp_action; direct tasks decorate their methods with@capturedto keep them recorded.ActionManager.process_actiontakes a torch tensor;SceneEntityCfg.joint_maskis renamedjoint_mask_wp.WarpFrontend.build_envswaps in the Warp MDP twins), so removing the switch drops no stable-configuration support.2. Evidence
Validation at
5ad9281530f(desk RTX PRO 6000): the experimental utils, managers, MDP, frontend, configuration-conversion, scene, capture, decimation,final_obs, log and reset suites pass. The capture tests compare eager and captured runs bitwise, including a simulation rebind mid-run. Cartpole, Cartpole-Direct, Ant-Direct, Allegro-Direct and Go2 Flat each step 300 to 1000 times; on Cartpole and Go2 Flat every manager stage records one graph.Step time (8gpu L40, 4096 envs, mean of 3 runs per arm, rotated across GPUs; measured on this PR before the last review fixes, which only change the reset path):
Direct reset decision: resetting unconditionally every step is not slower (Cartpole-Direct 0.531 vs 0.538 ms), but it changes logged metrics on steps where nothing reset (Ant's
Metrics/success_ratewould read 0), so resets stay conditional as in stable.Decimation, Go2 Flat, 200 steps against the stable environment (earlier tip; the decimation tests pass at this tip): contact history, air times,
undesired_contacts,base_contactand physics state are bitwise equal,feet_air_timewithin 3e-8 (reduction order).3. Out of scope / follow-ups
.warphandles that go stale after an explicit hardsim.reset(); training never calls it.obs_buf, the GUI reset button andrender_enabled.4. Merge note
#7012 changes the same lines of
direct_rl_env_warp.pyandmanager_based_env_warp.py(video recorder hooks). Whichever of the two merges second keeps both additions.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