[WARP] Cleanup Part 2: Make the Warp frontend mask-first#6607
Draft
hujc7 wants to merge 66 commits into
Draft
Conversation
PR isaac-sim#5297 (Decouple Renderer from Camera) replaced `sim.get_setting('/isaaclab/visualizer')` (returned a comma-separated string) with `sim.has_active_visualizers()` plus per-type queries; the warp env path was missed, so it crashes with "AttributeError: 'dict' object has no attribute 'split'" during env construction. Mirror the stable env's pattern: - `has_active_visualizers()` for the gating predicate - `has_kit()` so kitless Newton-only runs (`--viz rerun`) skip ViewportCameraController
Warp's ObservationTermCfg / RewardTermCfg / TerminationTermCfg had no behavioural difference from their stable counterparts — same fields, same base class. The override only carried Warp-first docstrings while keeping the classes as siblings of stable's, which broke `isinstance(stable_term, warp.TermCfg)` checks inside the experimental managers when a stable cfg is fed through the warp runtime. Re-export stable's term cfg classes directly. Term funcs still follow the warp-first `func(env, out, **params)` signature at runtime; the type annotation just lives on stable's class instead of warp's.
Lets a stable manager-based RL env cfg run on the experimental warp runtime without a separate warp task registration. Replaces the duplicate per-robot warp env cfgs by adapting the stable cfg in place. Components: - isaaclab_experimental/envs/warp_frontend.py: 'WarpFrontend' walks the stable cfg, swaps each `term.func` to its same-named warp twin (only accepting candidates whose `__module__` lives under the warp packages — the warp mdp module re-exports stable terms via `from … import *`, so a naive `getattr` would silently keep the stable function), swaps each action `class_type`, picks the `newton` field of any PresetCfg, drops sensors with no warp counterpart (`height_scanner`), and in-place class-promotes `SceneEntityCfg` instances so warp kernels see the `joint_mask` / *\_ids_wp` cached fields. A `WarpAdaptReport` records every term that had no warp twin and surfaces them via the logger; `strict=True` makes the same condition raise `LookupError` instead. - scripts/reinforcement_learning/rsl_rl/train.py: '--manager=warp' flag routes the constructed env through `WarpFrontend.build` instead of `gym.make`. The flag also auto-injects `presets=newton` into Hydra's argv so that PresetCfg wrappers resolve to the newton preset (Hydra's preset resolution runs *before* the adapter). Validated: cartpole and Anymal-D Flat both pass a 3-way comparison — - 'Isaac-Cartpole-v0' (stable manager): trains. - 'Isaac-Cartpole-Warp-v0' (existing direct path): reward 0.06 / ep 76. - 'Isaac-Cartpole-v0 --manager=warp': reward 0.06 / ep 76 (matches direct exactly). - 'Isaac-Velocity-Flat-Anymal-D-v0 presets=newton': -8.45 / 191. - 'Isaac-Velocity-Flat-Anymal-D-Warp-v0': -7.47 / 168. - 'Isaac-Velocity-Flat-Anymal-D-v0 --manager=warp': -7.69 / 174 (within run-to-run variance of the direct warp path). Both stable and warp frontends remain functional for every task; this PR adds a flag-based selector without removing the existing direct warp registrations.
Adds the isaaclab_experimental changelog fragment for the WarpFrontend adapter and the --manager flag, and applies the ruff-format pass that the pre-commit hook produced on warp_frontend.py.
The adapter is now a sequence of CompatRule objects (resolve preset, drop sensors, promote SceneEntityCfg, swap mdp funcs, swap action class). New incompatibilities are added by writing a small rule subclass instead of editing the dispatcher. The CLI flag is renamed --manager → --frontend because the dispatch also covers direct envs: a stable manager-based cfg is adapted onto ManagerBasedRLEnvWarp; a direct task is verified to point at a warp env class and dispatched via gym.make. A stable direct cfg + --frontend=warp raises IncompatibleEnvError with the offending entry_point and a hint at the *-Direct-Warp-v0 alternative. Other fixes: - Forward render_mode through build() so --video keeps working. - Attach the CompatReport on env.unwrapped.warp_compat_report so callers can inspect what was dropped or left unresolved. - Assert the warp SceneEntityCfg subclasses the stable one before doing the in-place __class__ promotion; the rule fails loudly if the hierarchy is ever broken. - Narrow the bare except in mdp-module discovery so real ImportErrors from broken cfgs propagate. - presets=newton is now only auto-injected for stable manager-based tasks; direct warp tasks (which don't carry presets) are left alone. - Warn when the user passes presets=<other> with --frontend=warp. - Add the commands group to the rule that promotes SceneEntityCfg.
The earlier check inspected gym.spec(task).entry_point, which for stable
manager-based tasks is "isaaclab.envs:ManagerBasedRLEnv" — the env class
path, not the cfg path. So the startswith("isaaclab_tasks.manager_based")
test always failed and presets=newton was never injected. Hydra then
resolved every PresetCfg in the cfg tree (physics, contact_forces, etc.)
to its default field, leaving the warp runtime with PhysX class_types it
can't load.
Switch to spec.kwargs["env_cfg_entry_point"], which actually points at the
task cfg module (e.g. "isaaclab_tasks.manager_based.locomotion.velocity.
config.anymal_d.flat_env_cfg:AnymalDFlatEnvCfg"), and the prefix check
selects the right tasks.
The single-file warp_frontend.py grew into a real subsystem worth splitting out, so move it into a frontend/ package with explicit abstractions: - frontend/base.py: Frontend ABC, CompatRule (check + transform via a unified run() method), TaskResolver (centralised gym.spec introspection -> TaskMeta), Workflow / Runtime / Severity enums, Issue / Change / Report record types, register_frontend / get_frontend registry. Helpers walk_attrs / resolve_warp_twin / iter_term_attrs are shared utilities used by rules. - frontend/torch.py: TorchFrontend, the default. Pass-through to gym.make with one rule (WarnIfTaskIsWarpRegistered) for the contradiction case. - frontend/warp.py: WarpFrontend with the full rule pipeline. Includes a new CheckPhysicsIsNewton blocking rule that surfaces the PhysX-with-warp incompatibility (asset class_type strings resolve to isaaclab_physx.* classes that depend on omni.physics.tensors.api, which the warp runtime does not initialise). CLI: rename --frontend stable -> torch since the axis is *runtime*, not *stability tier*. The frontend selector now reads cleanly: --frontend torch -> default gym.make path --frontend warp -> experimental warp runtime via WarpFrontend train.py becomes a thin dispatcher: get_frontend(name) gives a Frontend instance, frontend.preprocess_hydra_args(...) handles preset injection, frontend.build(cfg, task) returns the env. No more inline conditional imports; no more inline preset-injection logic. env.unwrapped.frontend_report is the inspection point - callers and tests can read what changed and what was missing without re-running adapt(). To add a new compatibility check, write a CompatRule subclass and append it to the relevant frontend's `rules` tuple. To add a new runtime, subclass Frontend and call register_frontend(name, cls).
- SwapMdpFunctions: skip terms whose ``func.__module__`` is already under the warp prefixes. Without this, running the bridge against a task already registered under ``isaaclab_tasks_experimental`` (e.g. ``Isaac-Cartpole-Warp-v0 --frontend=warp``) would silently drop terms whose warp twin happens not to live in the resolved fallback module. Also tighten ``_mdp_modules`` to require the trailing dot when matching ``isaaclab_tasks`` so we don't double-replace the prefix and end up importing ``isaaclab_tasks_experimental_experimental.*``. - ResolvePhysicsPreset: scope to MANAGER_BASED via ``applies_to``. Direct cfgs aren't expected to carry ``PresetCfg`` wrappers; running this rule on them was a no-op but the scoping makes the contract explicit. - CheckPhysicsIsNewton: positively accept ``isaaclab_newton.*`` modules, block on ``isaaclab_physx.*``, warn on anything else. The previous rule only rejected PhysX, so a custom or third-party physics cfg in an unrelated module would slip through silently. - PromoteSceneEntityCfg: catch ``TypeError`` from the in-place ``__class__`` reassignment and surface it as a blocking issue. ``issubclass`` does not guarantee Python permits the layout change (slots, layout flags); failing loud at this seam is better than a cryptic crash mid-pipeline. - WarpFrontend.preprocess_hydra_args: normalise leading dashes when inspecting ``presets=``, so ``--presets=foo`` is treated the same as ``presets=foo`` (Hydra accepts both forms). - Frontend.resolve: hard-block when ``gym.spec`` returned no spec. Previously ``meta.runtime`` was ``UNKNOWN`` and ``construct`` would fail later with a less specific error; now the block fires before any rule runs. - train.py: import the frontend lazily and tolerate ``ImportError`` when ``--frontend=torch`` (the default). The experimental package is optional, so a missing install used to break the default path; now it falls back to ``gym.make`` for torch and only fails for ``warp``. - frontend/__init__.py: trim ``__all__`` and the wildcard re-export so helpers (``walk_attrs``, ``iter_term_attrs``, ``resolve_warp_twin``, ``WARP_ROOT_PREFIXES``) are no longer advertised as the public framework surface. They remain importable from ``frontend.base`` for users writing their own rules.
- TaskResolver._classify_runtime: also accept class/callable entry points by inspecting __module__. gym.register accepts both ``"module:Class"`` strings and class objects; the old check only handled strings, so a warp-registered task using the class form classified as Runtime.UNKNOWN and the warn / verify rules silently disengaged. - SwapMdpFunctions._mdp_modules: narrow the exception match from ImportError to ModuleNotFoundError where ``exc.name`` matches the module being looked up. Previously a real ImportError raised inside an existing mdp module (broken import inside the package) would be silently swallowed and the rule would fall through to the fallback module, producing misleading "no warp twin" reports.
…ger-bridge # Conflicts: # scripts/reinforcement_learning/rsl_rl/train.py # source/isaaclab_experimental/isaaclab_experimental/managers/manager_term_cfg.py
Collapses the CompatRule / Frontend / Report / Issue / Change framework (509+72+513+95 LOC across base/torch/warp/__init__) into one module (frontend.py, ~370 LOC). Net diff: 1270 → 864 LOC. Behavior changes: - Drop the pre-Hydra presets=newton injection. The warp frontend now hard-checks cfg.sim.physics is NewtonCfg at build time and tells the user to pass presets=newton on the CLI when it isn't. - Drop DropUnsupportedSensors. The Newton RayCaster (isaac-sim#5510) makes the height_scanner case obsolete; any future incompatible sensor should fail loudly with the sensor name rather than silently set None. - Merge SwapMdpFunctions + SwapActionClassType into one pass that swaps term.func or term.class_type uniformly for every group including actions. - Missing warp twin is always a hard failure (no strict / non-strict toggle). Partial swaps would leave torch funcs in a cfg consumed by warp managers, which only accept the kernel-style signature. - Replace SceneEntityCfg.__class__ = WarpSceneEntityCfg with a proper WarpSceneEntityCfg.from_stable() classmethod that copies every selection field through __init__. Train.py is unchanged in shape — two call sites, now using the top-level build(frontend, cfg, task_id) function.
Frontend (envs/frontend.py) - Replace _TERM_PATHS hardcode (with its policy-only observation limitation) with _walk_terms: a recursive ManagerTermBaseCfg discovery that descends any configclass and yields each term with its path. New cfg layouts and observation sub-groups (perception, critic, camera_images, ...) are picked up automatically with no framework change. - _promote_scene_entity_cfgs and _swap_mdp consume the new walker; delete _walk_attrs / _iter_term_attrs / _TERM_PATHS. - Per-promotion log now lists the actual SceneEntityCfg paths. - Rename _require_direct_is_warp_task to _assert_direct_warp_registration. Update _detect_workflow with a note for adding new cfg roots. Manager term cfg contract - Relax stable ObservationTermCfg / RewardTermCfg / TerminationTermCfg func annotation to Callable[..., torch.Tensor | None] so the warp func(env, out) -> None contract type-checks alongside the existing torch return-value contract. - Drop the now-redundant warp-side manager_term_cfg.py shim and redirect the 9 relative imports onto isaaclab.managers.manager_term_cfg. Tests - New TestWalkTerms cases verify the recursive type-driven discovery. - TestPromoteSceneEntityCfgs / TestSwapMdp use real term cfgs and configclass fixtures so they exercise the actual walker contract.
The isaaclab_experimental fragment shrinks from 47 lines of nested narrative to 12 lines per the existing terse-fragment rule. Adds the matching fragments for the two other touched packages: isaaclab (the term-cfg type-hint relax) and isaaclab_tasks_experimental (.skip — the humanoid import redirect is internal).
Two missed-sync fixes carried alongside the manager_based viewport
sync that already landed earlier in this branch:
1. DirectRLEnvWarp viewport controller now mirrors stable
DirectRLEnv: '(has_gui or has_active_visualizers()) and has_kit()'
gate, instantiate ViewportCameraController accordingly. Replaces the
stale get_setting('/isaaclab/has_gui'/'render/offscreen') check and
removes the commented-out instantiation that left
viewport_camera_controller unconditionally None.
2. render(mode='rgb_array') in ManagerBasedRLEnvWarp and
DirectRLEnvWarp now read SimulationContext.has_gui and
has_offscreen_render properties instead of get_setting on keys that
were removed when the simulation manager was refactored. Without
this the gate silently fell through on None values.
The legacy bare 'newton'/'kamino' preset names were renamed on develop to 'newton_mjwarp'/'newton_kamino' to disambiguate from the Newton backend label. Update the warp-frontend hard-check error message, the `_adapt_cfg_for_warp`/`_require_newton_physics` docstrings, the rsl_rl/train.py comment, and the matching test assertion to spell the canonical preset name so users get the right CLI token in errors.
…ger-bridge # Conflicts: # source/isaaclab_experimental/isaaclab_experimental/managers/__init__.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/classic/humanoid/mdp/rewards.py
Move the stable->warp cfg adaptation out of the train.py --frontend path and into ManagerBasedEnvWarp.__init__, so a task registered directly as *-Warp-v0 (with env_cfg_entry_point pointing at the stable cfg) goes through the exact same Newton-physics check, SceneEntityCfg promotion and MDP twin swap. Twin lookup is now keyed off the stable cfg class module (type(cfg).__module__) instead of the gym task id, so it no longer needs a registration to resolve. Adaptation is idempotent. This lets the warp side reuse stable env cfgs instead of carrying parallel copies that drift.
Flatten isaaclab_tasks_experimental from the legacy manager_based/ | direct/ | classic/ trees into core/<task>/ mirroring isaaclab_tasks/core, so the frontend's stable->warp module-path rewrite resolves twins again after the stable migration. Manager-based warp tasks now reuse the stable env cfg (env_cfg_entry_point points at isaaclab_tasks.core...; physics + MDP twins are swapped at construction) instead of carrying parallel copies that drift; the drift cfgs are deleted. Direct warp tasks keep their own env class + cfg. Twin lookup keys off each stable symbol's own module, so ant reusing manager_humanoid's mdp resolves with no per-task shim (mirrors core, which gives manager_ant no mdp/ of its own).
Only observation/reward/termination/action terms are swapped to warp twins and have their SceneEntityCfg promoted; event, curriculum, recorder and command terms run on the stable (torch) managers, so their stable funcs are left in place. This lets the warp env reuse the full stable cfg (domain randomization events, reward curricula, etc.) instead of a trimmed copy. Add a parametrized coverage test that, for every manager-based *-Warp-v0 task, loads its stable cfg and asserts adapt_cfg_for_warp succeeds (all warp-managed twins resolve). Three tasks are xfail(strict) pending warp twins: cartpole survival_success_rate, ant/humanoid body_incoming_wrench. Also add the missing core/__init__.py so the registration walk descends into the migrated package.
Stable cartpole was consolidated to unversioned ids (Isaac-Cartpole, Isaac-Cartpole-Direct); mirror that on the warp side so each warp task pairs 1:1 with its stable counterpart. Other tasks keep -Warp-v0 because their stable ids still carry -v0 on develop.
Implements the two missing warp MDP twins so the full stable cfg adapts for every manager-based *-Warp task (clears the xfails in the conversion test): - cartpole `survival_success_rate`: ManagerTermBase reward mirroring stable — zero reward contribution, logs Metrics/success_rate (time-out rate) on reset. - generic `body_incoming_wrench`: observation reading the Newton joint-wrench sensor and gathering per-body force+torque, following the existing sensor-reading twins (undesired_contacts/illegal_contact). Lives in the shared fallback mdp so it is task-agnostic. Extends the observation manager's `body:N` out_dim resolution to also read `sensor_cfg` (not just `asset_cfg`), since wrench obs select bodies via a sensor entity.
The cfg walker only matched ManagerTermBaseCfg, but ActionTermCfg is a
separate base (not a subclass) carrying a swappable class_type. As a result
action terms kept their stable class and the warp ActionManager rejected
them ("not of type ActionType") when a *-Warp task reused a stable cfg.
Match ActionTermCfg in _walk_terms so action class_type is swapped too, and
guard it in the conversion test.
Also fix the cartpole warp registration agent entry points to the current
stable modules (rsl_rl_ppo_cfg:Cartpole[Direct]PPORunnerCfg, sb3_ppo_cfg)
after the cartpole consolidation renamed them.
The warp EventManager invokes term funcs with a Warp env-mask, so a stable event func breaks at runtime (torch index by wp.array). Add events to the warp-managed groups so their funcs are swapped to warp twins; only curriculum, recorder and command managers fall back to stable. Cartpole (reset_joints_by_offset) and reach now adapt and cartpole trains end-to-end on warp. Rewrite cartpole survival_success_rate as a plain zero-reward term func: its stable form logs a metric on reset via a host readback, which is incompatible with the reward manager's CUDA-graph-captured reset; the warp twin keeps the zero reward and omits the diagnostic metric. Velocity tasks remain xfail in the conversion test pending warp twins for randomize_rigid_body_mass / randomize_rigid_body_material (domain randomization).
Reconcile two conflicts from develop (45 commits): - scripts/reinforcement_learning/rsl_rl/train.py: keep the --frontend=warp lazy-import build path; drop the branch-local fold_preset_tokens() call in favor of develop's verbatim remaining_args. isaac-sim#5944 reworked setup_preset_cli to resolve physics=/presets= tokens during Hydra resolution, so folding is no longer needed and the function was removed upstream. - isaaclab_tasks_experimental .../direct/cartpole/__init__.py: keep the branch deletion (cartpole moved under core/); develop made no substantive change to the old-location file.
Develop's task-cleanup PRs dropped the -v0 suffix from the core Ant, Humanoid, and Reach-Franka torch ids. The warp variants follow a fixed pattern (torch id with -Warp inserted before any -Play/-v0 suffix), so sync the six affected registrations and their doc references: Isaac-Ant-Warp-v0 -> Isaac-Ant-Warp Isaac-Ant-Direct-Warp-v0 -> Isaac-Ant-Direct-Warp Isaac-Humanoid-Warp-v0 -> Isaac-Humanoid-Warp Isaac-Humanoid-Direct-Warp-v0 -> Isaac-Humanoid-Direct-Warp Isaac-Reach-Franka-Warp-v0 -> Isaac-Reach-Franka-Warp Isaac-Reach-Franka-Warp-Play-v0 -> Isaac-Reach-Franka-Warp-Play Cartpole already conformed; contrib and core-velocity tasks kept -v0 upstream, so their warp ids are unchanged.
Retain the current direct and manager-based experimental task layout and move the frontend integration to the unified RSL-RL entrypoint. Align the direct Warp Cartpole with the rewritten stable task.
…nager-bridge # Conflicts: # source/isaaclab/test/test_reinforcement_learning_common.py
Define the flag once in add_common_train_args so every RL library's train and benchmark entrypoint exposes it, instead of registering it per-script for RSL-RL only. create_isaaclab_env now reads the argument directly, so a caller that misses the shared registration fails loudly rather than silently defaulting to the torch runtime. Also drop the frontend dispatch from the deprecated rsl_rl/train.py wrapper; deprecated entrypoints should not grow new features.
The Warp survival_success_rate twin wrote zeros and dropped the Metrics/success_rate value that the stable class-based term flushes into extras on reset, so torch and warp runs of the same task were not comparable on the success metric. Rebuild the twin as a Warp ManagerTermBase class that accumulates the timed-out fraction of just-reset envs in device buffers and exposes it as a persistent tensor view through the reward manager's reset extras. Class reward terms may now return such views from reset(); the reward manager merges them, which keeps the whole reset stage CUDA-graph capturable (no host readback).
8 tasks
Keep Warp-native reset and manager paths mask-based through their host boundaries, and remove unsupported PhysX forwarding. Move frontend-only helpers into the experimental package, make terrain origin buffers dual-access, and keep capture state scoped to its owning environment.
Store terrain origin, level, and type wrappers as importer-owned members. Public properties now return the same persistent objects so ownership and pointer stability are explicit.
Keep the existing Torch terrain API while caching zero-copy Warp views during origin configuration. Route shared origin access through the Warp scene without changing the stable scene API.
Remove the experimental manager routing layer and make Warp managers the direct frontend implementation. Centralize capture eligibility in the environment-owned graph cache while preserving eager fallbacks for unsafe boundaries.
Remove the orphan isaaclab_tasks fragment and move the pose-command quaternion fix entry to isaaclab_experimental. Route surface-gripper mask resets through reset_mask, delegate the scene's Warp origins view to the terrain owner, and make terrain origin reconfiguration pointer-stable. Skip Lab actuator resets in Newton-native mode, share one compact-ID materialization per reset between the recorder and legacy curriculum terms, and downgrade the collection's mask-write docstrings to match their host compaction. Add a static gate that requires a reviewed mask-boundary marker on production nonzero sites.
This was referenced Jul 21, 2026
Split the direct-task step so pure-kernel stages capture as on develop and only the reset stage stays eager, with its rationale registered at the cache. Rename Warp command buffers to own the plain names with _torch view suffixes, section their initialization, and fold the command debug visualization into shared core mixins. Add a mask option to reset_to, rename the manager reset orchestrator to _reset_mask, reuse the action buffer across manager reloads, and drop redundant scalar casts. Add captured-stage introspection, an environment-variable force-eager toggle, curriculum manager section comments, and the mask-first boundary conventions to AGENTS.md.
Rough-terrain tasks need a warp twin for the height_scan observation and command-less tasks need a NullCommand twin once command class_types swap to warp-native implementations. height_scan stays eager (warp_capturable False) until the sensor lazy-update path is audited for graph capture; its output width resolves through a new out_dim='sensor:rays' sentinel.
# Conflicts: # docs/source/overview/environments.rst # source/isaaclab_experimental/isaaclab_experimental/envs/mdp/events.py # source/isaaclab_experimental/isaaclab_experimental/envs/mdp/observations.py # source/isaaclab_experimental/isaaclab_experimental/managers/manager_term_cfg.py # source/isaaclab_experimental/isaaclab_experimental/managers/termination_manager.py # source/isaaclab_rl/test/test_entrypoints_common.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/core/reach/mdp/curriculums.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/locomotion/velocity/config/anymal_b/rough_env_cfg.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/locomotion/velocity/config/anymal_c/rough_env_cfg.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/locomotion/velocity/config/anymal_d/rough_env_cfg.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/locomotion/velocity/config/go1/rough_env_cfg.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/locomotion/velocity/velocity_env_cfg.py # source/isaaclab_tasks_experimental/isaaclab_tasks_experimental/manager_based/manipulation/reach/reach_env_cfg.py
The warp env runs commands on the experimental captured CommandManager, so stable command term class_types must be swapped to their warp twins like every other warp-managed group. Stable CommandTermCfg is a standalone base (like ActionTermCfg), so the term walker must match it explicitly; without this the swap silently skipped command terms and env construction failed with a CommandType TypeError.
The bridge merge moves experimental velocity/reach MDP modules under isaaclab_tasks_experimental.core and retires reach_env_cfg; the curriculum-manager and terrain-out-of-bounds tests import from the new locations.
This was referenced Jul 21, 2026
Every @wp.kernel carries a purpose docstring (domain quantity, units, launch dimensionality where non-trivial) so kernels self-explain instead of reading as bare index math.
Play backends constructed environments with a direct gym.make, so warp-trained policies could not be played through the official CLI: the shared parser accepted --frontend but play ignored it. All four dispatched play backends now build their environment via create_isaaclab_env, mirroring their train twins' MARL-conversion semantics, and a unit test pins the routing. The rlinf integration constructs environments inside the external framework and remains frontend-unroutable (documented in the changelog).
Fix the action-parity mock for origin-less tests, guard the clone-origin warp view against reallocation, accept non-contiguous terrain origins, and pin the reset quaternion composition against the stable math reference. Replace the mask-boundary marker comments with a structural gate: host syncs live in sanctioned functions listed exactly in the gate test, ISAACLAB_SYNC_DEBUG runs warp stages under torch's sync-debug trap as the runtime net, and every @WarpCapturable(False) opt-out is pinned by an inventory test. Consolidate capturability to the class-aware WarpCapturable decorator. The new gate immediately caught a per-step host sync in CircularBuffer.max_length (read on the append path), fixed by caching the host int. Classic-PhysX env_mask behavior is documented on InteractiveScene.reset instead of guarded.
The Warp observation manager applies noise through the experimental noise cfg family, so stable noise cfgs on bridged tasks were silently skipped and training ran without the configured corruption. The frontend now swaps stable constant/uniform/gaussian noise cfgs to their warp-native twins during cfg adaptation (data fields copied, warp func default); cfgs it cannot represent — class-based noise models, customized funcs, tensor-valued parameters — are an aggregated hard error instead of a silent MDP change. The observation manager rejects non-warp noise cfgs at construction and plumbs the shared per-env RNG state to function-style noise kernels, wiring the contract the noise module documented. Audit: every function-style noise cfg in the repo has a swappable warp twin; class-based models are loud unsupported.
Curriculum terms swap to warp twins when one exists, keeping the legacy ID-based fallback for stable terms without twins; the mask-native task classes take their stable functions' names (terrain_levels_vel, modify_reward_weight) so plain name resolution finds them, and the velocity legacy shim is removed with them. The curriculum manager's legacy modes collapse to one (compact IDs, materialized at most once); the unused requires_host_ids cfg knob is removed. Rough-terrain curriculum now runs mask-native and captured; reach's weight curriculum runs mask-native but stays eager by its own declaration (host step counter). The non-capturable inventory detects attribute-style annotations and scans the tasks package.
# Conflicts: # source/isaaclab_experimental/test/envs/test_frontend_cfg_conversion.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_rl_games.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_rsl_rl.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_sb3.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_skrl.py
Both tasks exercise the same converter mechanism (name resolution to a mask-native class twin); one parametrized test covers both data points.
…nager-bridge # Conflicts: # docs/source/overview/environments.rst # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_rl_games.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_rsl_rl.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_sb3.py # source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_skrl.py # source/isaaclab_rl/test/test_entrypoints_common.py
Use the presets= Hydra group name in the PhysX limitation note and drop performance rows for flat-velocity tasks removed by the catalog update (AnymalB, AnymalC, A1, Go1); rename the Go2 row to the UnitreeGo2 task name.
…nd-cleanup # Conflicts: # docs/source/overview/environments.rst
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
Summary
isaaclabreset(env_mask=...)), and mask-based terrain curriculum updates; origin storage stays pointer-stable, including across reconfiguration.reset_mask; scene construction no longer requires a published clone plan.isaaclab_experimentalManagerCallSwitch,MANAGER_CALL_CONFIG, and the duplicateInteractiveSceneWarp; Warp environments instantiate Warp managers directly.WarpGraphCache: eligible CUDA stages warm up, capture, then replay; CPU devices, non-capturable managers, and direct-task stages stay eager.nonzero(compaction must carry a reviewed same-line# mask-boundary:marker.*_torchview suffix), mask-basedreset_to,_reset_maskorchestration, anISAACLAB_WARP_CAPTURE=0force-eager toggle withcaptured_stagesintrospection, and command debug-visualization folded into shared core mixins.isaaclab_newtonandisaaclab_tasks_experimentalWhy
The Warp frontend crossed between Warp masks, Torch index tensors, stable-manager fallbacks, and a runtime dispatcher in high-traffic paths, adding host synchronization and hiding what was safe to optimize. This PR establishes one Warp-first path: direct Warp managers, mask-owned reset state, explicit host boundaries, and one graph cache that owns execution policy.
Design
DirectReset_apply) is intentionally de-captured: develop kept it captured only by silently skipping Python-side actuator resets during replay — that capture was wrong, not merely unvalidated. [WARP] Cleanup Part 5: Speed up persistent Warp frontend launches #6611 restores its speed via record-replay. This is the only stage de-captured relative to develop; the manager-based path is a strict superset (command and curriculum stages are newly captured).Performance
Measurements below used one NVIDIA L40, seed 42, serial execution, Newton MJWarp physics graphs enabled, and the Warp-eager frontend baseline. They characterize the mask-first/Warp-native cleanup; they do not isolate the newly centralized per-manager graph policy.
Develop comparison
developScaling
Cartpole is the upper line and Go2 is the lower line.
xychart-beta title "Warp-eager L40 throughput scaling" x-axis "Environments" [256, 1024, 4096] y-axis "Frames per second" 0 --> 1300000 line [79521, 315642, 1248380] line [58942, 229836, 741682]Cartpole remains launch/CPU-bound across this range. Go2 shows diminishing frontend headroom as GPU utilization rises from 59% to 77%.
Validation
Grid: 300 iterations, 4096 envs, seed 42, rsl_rl,
presets=newton_mjwarp; warp arms via--frontend warp(bridge from #5504, contained in this branch), torch anchors via--frontend torch. L40, solo GPU per run.WarpGraphCache.captured_stages): manager tasks capture 12-16 stages includingCommandManager_compute/reset. On rough terrain the observation group runs eager by design -height_scanis markedwarp_capturable(False)until the sensor lazy-update path is capture-audited (Part 3 scope); the rough terrain-levels curriculum term likewise registers eager.DirectAction_step,DirectEndPre_compute,DirectEndPost_step);DirectReset_applyis deliberately eager - the prior branch captured it only by silently skipping Python-side actuator resets on replay, which was wrong.Limitations and follow-ups
Type of change
Checklist
CONTRIBUTORS.md.