[WARP] Cleanup Part 4: Open the warp frontend to the OVPhysX backend#6580
Draft
hujc7 wants to merge 42 commits into
Draft
[WARP] Cleanup Part 4: Open the warp frontend to the OVPhysX backend#6580hujc7 wants to merge 42 commits into
hujc7 wants to merge 42 commits into
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).
Replace the frontend's hardcoded stable-to-experimental module table with a registry that experimental task packages populate at import time via register_mdp_route(), so adding a task family no longer requires editing the frontend module. Twin lookup previously keyed only off the symbol's defining module, which missed every twin that overrides a symbol defined in a core or shared package: the stable reach rewards live in isaaclab.envs.mdp and the humanoid observations in the shared locomotion package, so their task-specific warp twins were never consulted and the stable Humanoid, Ant, and Reach tasks could not adapt at all. Resolution now consults the warp mirror of the cfg's own task MDP namespace first (routed from the cfg class hierarchy), then the mirror of the symbol's package, then the shared fallback — mirroring how a stable cfg consumes its mdp namespace. This makes the stable Ant, Humanoid, and Reach joint-pos tasks adapt cleanly under --frontend=warp. Also convert test_frontend.py to pytest style and cover the new registry (longest-prefix match, conflict rejection, broken-target error, cfg-hierarchy resolution).
Every manager-based *-Warp-v0 task duplicated its stable environment configuration file-for-file, so each stable task rewrite had to be mirrored by hand (as happened with the Cartpole rewrite). ManagerBasedRLEnvWarp now adapts its cfg in __init__, so warp env construction accepts stable-derived cfgs directly. On top of that: - Drop the Cartpole, Humanoid, Ant, and Reach-Franka warp registrations and their duplicated cfgs; the stable ids run on warp via --frontend warp presets=newton_mjwarp. Their packages keep only the warp MDP twins and the route registration. - Rewrite the velocity *-Warp-v0 variants as thin subclasses of the stable flat cfgs that only disable the rigid-body material/mass randomization events, which have no warp twins yet. The duplicated velocity base cfg, per-robot cfgs, and unregistered rough cfgs are removed; the variants now select Newton via presets=newton_mjwarp like every other task. - Cover both paths in test_frontend_cfg_conversion.py: the stable ids with full twin coverage adapt cleanly, and every registered warp variant still adapts. - Update the warp environments documentation and the generated environment list accordingly.
Direct warp tasks duplicated their stable task configuration in a parallel *-Direct-Warp-v0 registration, so every stable cfg change had to be mirrored by hand. A stable direct registration can now declare its warp implementation with a warp_entry_point kwarg (mirroring env_cfg_entry_point); --frontend warp constructs that class with the stable cfg and swaps nothing else. Declared for Isaac-Cartpole-Direct, Isaac-Ant-Direct, and Isaac-Humanoid-Direct, whose warp cfgs matched the stable ones field-for-field; their *-Direct-Warp-v0 registrations and duplicated cfgs are removed and the env classes annotate the stable cfg types. The Allegro reorient warp task keeps its own registration: its cube is modeled as an articulation, unlike the stable task's rigid object, so the configurations genuinely differ.
Extract the --frontend flag into add_frontend_args so other entrypoints (e.g. play) can reuse it without pulling in all training arguments; add_common_train_args keeps calling it so every train and benchmark CLI registers the flag. Also derive SceneEntityCfg.from_stable from the stable dataclass fields instead of a hand-maintained list, drop single-use aliases in the wrench observation twin, and trim render comments to one line.
The experimental task package still used the manager_based/direct split
that the stable package left behind when it consolidated each task under
core/<task>. That mismatch was the only reason the warp MDP routing
needed non-obvious mappings.
Move the warp task packages to the same layout — core/cartpole,
core/locomotion/{ant,humanoid}, core/velocity, core/reach, and
core/reorient for the Allegro task — with each task package holding both
its manager-based MDP twins and its direct warp env class, exactly like
its stable counterpart. Routes and warp_entry_point declarations now
read as the mechanical mirror they are.
Group the warp-side machinery — route registry, cfg adaptation steps, twin resolution, and both env build paths — under a WarpFrontend class instead of a flat set of module functions. The module-level build(), adapt_cfg_for_warp(), and register_mdp_route() API is unchanged for callers; the class gives the machinery one named owner, keeps the route registry as explicit class state, and leaves room for future frontends to subclass or replace it.
The shared RL CLI already peels off the torch path before importing the optional isaaclab_experimental package, so the frontend's own torch branch (module-level build() with a Frontend enum) was dead code that duplicated the gym.make dispatch. Remove it: create_isaaclab_env owns the torch/warp dispatch and calls WarpFrontend.build_env directly, and the module's public surface shrinks to WarpFrontend, Workflow, register_mdp_route, and the error type. Callers use WarpFrontend.adapt_cfg in place of the adapt_cfg_for_warp alias.
The experimental tree now mirrors the stable tree exactly, so twin routing needs no declarations: mirror the module root (isaaclab -> isaaclab_experimental, isaaclab_tasks -> isaaclab_tasks_experimental) and look the symbol up on the nearest .mdp package of the mirrored path — the cfg's own task namespace first, then the symbol's defining package. Resolution is a pure function of the installed package tree; misses accumulate across the whole cfg and are reported in a single hard failure listing every missing twin and all searched modules. This deletes register_mdp_route, the route registry, the twin-provider side-effect import, and all five task-package registration calls. The humanoid MDP twins move to core/locomotion/mdp — the true mirror of the stable shared locomotion package — which also removes the Ant special case (both tasks now resolve mechanically).
Add warp adapters for the two stable startup randomization events (randomize_rigid_body_material, randomize_rigid_body_mass): the stable terms already dispatch to the active physics backend, so the adapters only convert the warp event manager's env-mask calling convention to the stable env-ids one and inherit the warp ManagerTermBase so the managers accept them as class terms. With those twins in place the stable flat velocity tasks adapt cleanly, so the 18 velocity *-Warp-v0 registrations and their delta configs are deleted — no manager-based warp registration remains, and the conversion test pins that end state. The Allegro reorient task id drops its stale -v0 suffix (Isaac-Reorient-Cube-Allegro-Direct-Warp).
Add one-line comments at the dense decision points of WarpFrontend (twin lookup order, mirror walk, collect-all-misses reporting). Replace the removed -Warp-v0 ids in the benchmarking guide with a same-task A/B that differs only in --frontend, with identical Newton physics on both runs. Add the missing changelog entry for the RewardManager merging class-term reset() extras into its episode logs.
The stable cfg already resolves its cube to an articulation under the newton_mjwarp preset, so the duplicated warp cfg diverged only by pinning ls_iterations=15; the stable preset values now apply. Isaac-Reorient-Cube-Allegro-Direct declares the warp env class via warp_entry_point; the separate -Warp registration and its cfg package are deleted. A new end-state pin asserts no -Warp task ids remain, and the frontend stub-task fixture now unregisters its ids so later test modules see the real registry.
Move the body-frame state helpers from isaaclab_newton.kernels to a new backend-neutral isaaclab.utils.warp.state_math module (they are pure frame math; a deprecation shim remains), widen the frontend physics gate to accept OvPhysxCfg alongside NewtonCfg, and add a backend data-parity test pinning that every data.<field>.warp view the warp MDP twins read exists on each warp-capable backend. With this, the twins carry no Newton dependency and warp-frontend tasks accept presets=ovphysx.
This was referenced Jul 21, 2026
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
1. Summary
--frontend warpnow accepts OVPhysX: the physics gate takesNewtonCfg | OvPhysxCfg, so warp-frontend tasks run withpresets=ovphysxas well aspresets=newton_mjwarp.isaaclab.utils.warp.state_math— pure frame math with no Newton dependency;isaaclab_newton.kernels.state_kernelsremains as a deprecation shim.data.<field>.warpview the warp MDP twins read (articulation, contact-sensor, and joint-wrench fields) exists on both the Newton and OVPhysX data classes.2. Dependencies
3. Test plan
./isaaclab.sh -fclean on all files.Isaac-Cartpole --frontend warp presets=ovphysx): pending — the pinnedovphysx==0.5.2wheel is not yet installable in the dev environment; will attach the run before marking ready for review.