Repository navigation
[Core] Make tests backend-agnostic and start them with launch_test_simulation (3/3) - #8102
Conversation
Test modules start the runtime with a single launch_test_simulation(...) call, which now takes an optional config and starts the runtime that config needs instead of forcing Kit. Core isaaclab tests no longer import omni, carb, or isaacsim; tests of Kit, PhysX, or Isaac Sim behavior move to isaaclab_physx.
|
run-ci |
|
| cfg = SimulationCfg() if cfg is None else cfg | ||
| _RUNTIME.enter_context(launch_simulation(cfg, {"headless": True, **launcher_args})) |
There was a problem hiding this comment.
Explicit config path untested. The new
cfg parameter lets tests select a runtime, but the migrated tests all call this helper without a config. They exercise only the default Kit path, so a regression that starts Kit for a Newton or other kitless config could go unnoticed. A focused test with an explicit non-Kit config would cover the new behavior.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Isaac Lab Review Bot
The backend-agnostic test-launch migration and relocation of Kit/PhysX-specific coverage are coherent. One API maintainability fix remains: annotate the newly added public cfg parameter on launch_test_simulation.
- Design and architecture: The shared launcher remains in
isaaclab.test.utils, while Kit-, PhysX-, and Isaac Sim-specific tests move intoisaaclab_physx, preserving the intended dependency direction. Deferred runtime imports also retain the pre-launch import boundary. - API: The return-value and configuration-driven behavior changes are documented with migration guidance, and in-repository callers were updated. However, the new public
cfgparameter is untyped; add a concreteSimulationCfg | Noneannotation using a deferred orTYPE_CHECKINGimport. - Implementation: The migrated callers preserve relevant launcher arguments, and tests requiring direct Kit app access now obtain it explicitly. No additional material implementation issue from the candidate findings is supported by the patch.
Minor fixes needed. Posted 1 actionable finding inline.
Automated review; human maintainers own approval decisions.
|
|
||
| def launch_test_simulation(**launcher_args): | ||
| """Start Isaac Sim / Kit for the rest of the test process through :func:`~isaaclab.app.launch_simulation`. | ||
| def launch_test_simulation(cfg=None, **launcher_args) -> None: |
There was a problem hiding this comment.
🔵 Suggestion · Api — Annotate the new public cfg parameter
launch_test_simulation is referenced as a public helper in the changelog and its return is annotated, but the new first positional parameter cfg has no type. The module already uses from __future__ import annotations, so cfg: SimulationCfg | None = None with a TYPE_CHECKING import documents the contract while keeping the runtime import deferred.
The Kit-visualizer paths in visualizer_integration_utils update the running Kit app directly, so the five visualizer test modules no longer import omni.kit.app or register an app object.
|
run-ci |
|
run-ci |
…mulation (3/3) (#8102) ## Description **Part 3 of 3.** #8068 (merged) added the launcher design, and #8090 moves the scripts onto it. This PR does the same for the tests. It is independent of #8090, so they can merge in either order. ### What changes - **One-line launch:** test modules start the runtime with a single `launch_test_simulation(...)` call. It replaces the `"""Launch Isaac Sim Simulator first."""` preamble in about 125 modules. - **`launch_test_simulation(cfg=None, **launcher_args)` is config-driven.** It starts whatever runtime the test's simulation config needs (the default `SimulationCfg()` when none is given) instead of forcing Kit, and it returns `None`. It still picks the test device from the multi-GPU mask by default. Every existing test gets the same runtime as before, because the default config uses PhysX, which starts Kit; the config makes that choice now, not the helper. - **Core `isaaclab` tests no longer import `omni`, `carb`, or `isaacsim`:** - camera tests rely on the simulation's own cleanup instead of Replicator's `destroy_hydra_textures`; - tests that check Kit, PhysX, or Isaac Sim behavior move to `isaaclab_physx`: the Isaac Sim `XformPrim` comparison, the Kit timeline and app-update tests, stage-in-memory, the UI window, Kit startup performance, and three Isaac Sim extension-path tests. No coverage is deleted. - **Tests that need the Kit app object** get it from `omni.kit.app` in their own package: Newton fabric sync, teleop XR, and the visualizer tests. The remaining Kit mentions in core tests are the `isaacsim_ci` CI markers, the `install_ci` installer checks, `omni.client`, and tests that stub `omni` to exercise core code's own Kit branches without starting Kit. Net: +856 / −1,260 across 169 files. ## Type of change - Breaking change (`launch_test_simulation` signature and return value) ## Validation All runs on the display GPU (GPU 0). - **Every changed or moved module passes,** including the app tests (43), simulation context (26), the moved Kit context tests (4), camera (21), Newton fabric sync (9), views, controllers, the other camera tests, pink IK, and teleop XR. - **Visualizer tests:** the integration and golden-image tests fail on this machine exactly as they do without this PR (a known flat-frame issue); CI is the check for those. ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the pre-commit checks - [x] My changes generate no new warnings - [x] I have added changelog fragments for every touched package (cherry picked from commit c7775bc)
|
Backported to |
…8090) ## Description **Part 2 of 3.** #8068 (merged) added the launcher design; this PR moves every script, example, tutorial, benchmark, and doc page onto it. The tests are in #8102. The two PRs are independent and can merge in either order. ```python from isaaclab.app import add_launcher_args, launch_simulation from isaaclab.utils import instantiate add_launcher_args(parser) args_cli = parser.parse_args() ... with launch_simulation(env_cfg, args_cli): # the runtime follows the config env = instantiate(env_cfg) ``` ### What changes - **Every script, example, tutorial, and benchmark** starts the runtime with `launch_simulation` and builds runtime objects with `instantiate` (#8085). Nothing outside the shim below uses `AppLauncher` any more. - **Kit calls leave the scripts:** - the teleop, record, and replay scripts no longer load Replicator or update the app after closing the env; - `pick_and_place.py` uses `Se3Keyboard` instead of raw `carb.input` (W/S/A/D move, Q/E height, K gripper, N/M aim). On develop it died before stepping; - the camera tutorials save PNGs with `save_images_to_file` instead of Replicator writers. - **The converter tools** (`convert_mesh`, `convert_urdf`, `convert_mjcf`) preview the converted asset in the visualizer chosen with `--viz`, Kit included, instead of a Kit-only viewport. `isaaclab_physx.app.show_stage_in_viewport` has no callers left and is removed. - **The 14 `check_*` scripts** under the core and PhysX test folders, which duplicated pytest coverage, are deleted. - **`AppLauncher` shrinks to an init-only shim**, so scripts written against the old API keep running: - `AppLauncher.add_app_launcher_args(parser)` adds the launcher arguments; - `AppLauncher(args).app` starts Kit through `launch_simulation`, and `app.close()` stops it; - `is_available`, `has_gui`, `has_window`, and `device` are removed. The runtime is held for the process, so a script that drops the launcher keeps Kit running. `test_app_launcher_shim.py` covers both a kept and a dropped launcher; the dropped case fails without the fix. - **Moved with their scripts:** the two converter tests and the replay-loop test, which read script code, and `wait_for_stage_load`, used by the teleop replay script. Net: +2,367 / −4,334 across 121 files. ## Type of change - Breaking change (`AppLauncher` reduced to a shim) ## Validation All runs on the display GPU (GPU 0). - **Every script under `scripts/` and `examples/`** was run on develop and with these changes, using the same invocation. No script that runs on develop fails here. - Of the 78 scripts outside the standalone matrix, 52 run, 19 are blocked by the same missing resource on both (datasets, XR, a Ray cluster, gr00t, robomimic, moviepy), and 7 fail the same way on both. - The standalone matrix (361 cases) shows no new failures. - **Converter tools:** each writes its USD. `--viz kit` and `--viz newton_gl` keep rendering the asset until the window closes. - **Tests:** the shim test (2), URDF converter (17), replay loop (1), and RTX utils (10) pass. - **Training:** Cartpole on `isaacsim_physx` runs 2 iterations. ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the pre-commit checks - [x] I have made corresponding changes to the documentation (tutorials and how-to guides) - [x] My changes generate no new warnings - [x] I have added changelog fragments for every touched package
…8090) ## Description **Part 2 of 3.** #8068 (merged) added the launcher design; this PR moves every script, example, tutorial, benchmark, and doc page onto it. The tests are in #8102. The two PRs are independent and can merge in either order. ```python from isaaclab.app import add_launcher_args, launch_simulation from isaaclab.utils import instantiate add_launcher_args(parser) args_cli = parser.parse_args() ... with launch_simulation(env_cfg, args_cli): # the runtime follows the config env = instantiate(env_cfg) ``` ### What changes - **Every script, example, tutorial, and benchmark** starts the runtime with `launch_simulation` and builds runtime objects with `instantiate` (#8085). Nothing outside the shim below uses `AppLauncher` any more. - **Kit calls leave the scripts:** - the teleop, record, and replay scripts no longer load Replicator or update the app after closing the env; - `pick_and_place.py` uses `Se3Keyboard` instead of raw `carb.input` (W/S/A/D move, Q/E height, K gripper, N/M aim). On develop it died before stepping; - the camera tutorials save PNGs with `save_images_to_file` instead of Replicator writers. - **The converter tools** (`convert_mesh`, `convert_urdf`, `convert_mjcf`) preview the converted asset in the visualizer chosen with `--viz`, Kit included, instead of a Kit-only viewport. `isaaclab_physx.app.show_stage_in_viewport` has no callers left and is removed. - **The 14 `check_*` scripts** under the core and PhysX test folders, which duplicated pytest coverage, are deleted. - **`AppLauncher` shrinks to an init-only shim**, so scripts written against the old API keep running: - `AppLauncher.add_app_launcher_args(parser)` adds the launcher arguments; - `AppLauncher(args).app` starts Kit through `launch_simulation`, and `app.close()` stops it; - `is_available`, `has_gui`, `has_window`, and `device` are removed. The runtime is held for the process, so a script that drops the launcher keeps Kit running. `test_app_launcher_shim.py` covers both a kept and a dropped launcher; the dropped case fails without the fix. - **Moved with their scripts:** the two converter tests and the replay-loop test, which read script code, and `wait_for_stage_load`, used by the teleop replay script. Net: +2,367 / −4,334 across 121 files. ## Type of change - Breaking change (`AppLauncher` reduced to a shim) ## Validation All runs on the display GPU (GPU 0). - **Every script under `scripts/` and `examples/`** was run on develop and with these changes, using the same invocation. No script that runs on develop fails here. - Of the 78 scripts outside the standalone matrix, 52 run, 19 are blocked by the same missing resource on both (datasets, XR, a Ray cluster, gr00t, robomimic, moviepy), and 7 fail the same way on both. - The standalone matrix (361 cases) shows no new failures. - **Converter tools:** each writes its USD. `--viz kit` and `--viz newton_gl` keep rendering the asset until the window closes. - **Tests:** the shim test (2), URDF converter (17), replay loop (1), and RTX utils (10) pass. - **Training:** Cartpole on `isaacsim_physx` runs 2 iterations. ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the pre-commit checks - [x] I have made corresponding changes to the documentation (tutorials and how-to guides) - [x] My changes generate no new warnings - [x] I have added changelog fragments for every touched package (cherry picked from commit 443dc47)
# Description Part 14 of the split of #7949. This PR cleans up sim authoring: the schema writers in `isaaclab.sim.schemas`, the spawners, and the mesh converter. It is rebased onto the current `develop` and ports only the parts of #7949 that still apply there. The authored USD is unchanged, and no public API changes. **Spawners and mesh converter** - `spawners.utils` (renamed from `spawners._utils`, see below) adds a helper: - `apply_schema_props` writes a spawner schema slot. It sends a fragment mapping to the fragment writer, one entry at a time and anchored at the spawned prim, and sends a legacy cfg to the legacy writer. The mesh and shape spawners, `spawn_from_mesh`, and `MeshConverter` repeated this branch for their collision, mass, and rigid-body slots; they now call the helper. - Material paths are resolved inline at each call site (absolute paths are kept; relative names go under the spawned prim), replacing `from_files._resolve_material_path`. - Existing-prim checks are left to `create_prim`, which already raises the same `ValueError`. The spawner bodies are shorter, and `spawn_geom_from_prim_type` / `_spawn_mesh_geom_from_mesh` return the prim they create. - Mesh spawners share `_axis_transform` for the cylinder, capsule, and cone axis rotation. - Light, sensor, ground plane, and multi-USD spawners: - The ground plane hides its light with `set_prim_visibility`. - `spawn_multi_usd_file` builds `MultiAssetSpawnerCfg` in one call and no longer runs a `hasattr` check that was always true. - `AssetConverterBase` has a shorter USD-extension and hash-file check, and writes the `config.yaml` generation stamp with a single `datetime.now()` call. The stamp format is the same. **Schema writers** - `apply_rigid_body_properties`, `apply_collision_properties`, and `apply_mass_properties` now share `_apply_api_fragments`. Target matching, `create_if_missing`, the zero-target warning, and result aggregation are unchanged. - The joint-drive writers share `_write_drive_attributes`, which converts angular stiffness and damping from per-radian to per-degree and maps `drive_type` to the USD `type` attribute. It is used by `apply_drive`, `_ensure_drive_exists`, `apply_joint_drive_properties`, and `modify_joint_drive_properties`. Joint-type detection reuses `drive_instance_name`, including in `schemas_actuators`. - Other shared helpers: - `_write_mesh_approximation` writes and validates the `physics:approximation` token. - `_tetrahedralize_surface` holds the pytetwild call and the tet-winding fix, moved out of `define_deformable_body_properties`. - Smaller cleanups: - `activate_contact_sensors` counts descendants with `Usd.PrimRange`. - `schemas_actuators` uses `to_camel_case` instead of a private camel-case regex. - Redundant `pass` statements are removed from the fragment marker classes. - Fragment appliers are called directly as `cfg.func(cfg, prim_path, stage)`. `@configclass` already turns the `func` import string into a callable `ResolvableString`, so the `callable(...) else string_to_callable(...)` fallback (four schema writers and the physics-material spawner) never ran. **Reflection** - Replaced avoidable `getattr`/`setattr`/`hasattr` with direct attribute access or an `isinstance` check wherever the attribute is always defined for the configs that reach that code (actuator authoring, the USD-file and shape spawners, the camera spawner's intrinsics, the fragment annotation lookup). The remaining uses are dynamic by design: iterating dataclass fields, the deprecated alias forwarding, optional class metadata, and mixed config types in the multi-asset wrapper. **No underscore module names or cross-file private helpers in core** - Renamed the underscore modules: `sim/spawners/_utils.py` → `utils.py`, `sim/schemas/_backend_hooks.py` → `backend_hooks.py`, `actuators/_compat.py` → `actuator_compat.py`, `benchmark/_cli.py` → `cli.py`, `cloner/_fabric_notices.py` → `fabric_notices.py`, `utils/_device.py` → `device.py`. All importers in `isaaclab`, `isaaclab_physx`, `isaaclab_newton`, `isaaclab_ov`, the benchmark scripts, tests, and docs are updated. - Dropped the `_` prefix from module-level functions used from other files: `limits_equal`, `resolve_limit_aliases`, `skip_joint_drive`, `articulation_root_companion_namespace`, `apply_namespaced_schemas`, `drive_instance_name`, `validate_newton_native_actuator_cfgs`, `author_actuator_prims`, `resave_checkpoint_with_metadata`, `deprecate_field_alias`, `deprecated_schema_cfg`, `spawn_from_usd_file`, `spawn_geom_from_prim_type`. They are not added to the package exports. **Not ported from #7949** - The forwarding-shim refactors in `schemas/__init__.py` and `schemas_cfg.py`, the `usd_api` / `physx_api` deprecation properties, and the empty `_usd_*` metadata on deprecated cfgs. These are deprecation-only and will be removed. - The `_OVERRIDABLE_PROPS` constant in the wrappers, a single-use constant. - The import-only edits. `develop` already uses relative imports. ## Type of change - Refactor (no functional change). The only visible difference is that the `ValueError` for an unsupported deformable type is now one line, instead of a triple-quoted string with embedded indentation. ## Verification - USD authoring equivalence, comparing `develop` sources with this branch in Kit, one fresh stage per case. All 57 cases produce identical exported USDA, return values, and raised errors: - Sphere, cuboid, cylinder, capsule, and cone shapes; and sphere, cuboid, cylinder, capsule, cone, and rectangle meshes. Each is spawned plain, with legacy cfgs, and with fragments (including dict targets and absolute material paths). - The cable spawner, `MeshFileCfg` from a trimesh object and from an `.obj` file, and all five lights. - Pinhole and fisheye cameras, and the sensor frame. - `UsdFileCfg` with legacy cfgs and with fragments (articulation root, joint drives, contact sensors, semantics, materials), the compliant-contact spawner, and a ground plane asset. - `MultiAssetSpawnerCfg` and `MultiUsdFileCfg`, and a surface deformable. - The legacy `define_`/`modify_` writers and the fragment `apply_*` writers, including `ensure_drives_exist`, the no-target case, mesh collision with an invalid approximation name, and fixed tendons. - A `MeshConverter` run with collision, mesh-collision, mass, and rigid props and `make_instanceable`, comparing the generated USD layers and `config.yaml`. - Tests, run one file at a time; all pass: - Spawners: `test_spawn_shapes`, `test_spawn_meshes`, `test_spawn_lights`, `test_spawn_sensors`, `test_spawn_from_files`, `test_spawn_wrappers`, `test_spawn_cable`, `test_spawn_materials`, `test_default_ground_plane`, `test_visual_materials_kitless`. - Schemas: `test_schemas`, `test_schemas_deprecation`, `test_schemas_shim`, `test_schemas_kitless_fixed_joint`, `test_schema_fragments`, `test_schema_fragment_parity`, `test_schema_writer_nested_targets`, `test_joint_drive_fragments`, `test_collision_fragments`, `test_mass_fragments`, `test_mesh_collision_fragments`, `test_articulation_fragments`, `test_material_fragments`, `test_tendon_fragments`, `test_tendon_fragments_codeless`, `test_deformable_backend_split`. - Converter: `test_mesh_converter`. - Actuator authoring: `source/isaaclab/test/actuators`, `test_newton_actuator_manager_authoring`, `test_newton_actuators_newton`, `test_newton_actuators_physx`. - After the renames, reflection pass, and review fixes, the 57-case USD comparison was rerun against the latest `develop` (0 differences), and the spawner, schema, fragment, converter, cloner (`isaaclab` and `isaaclab_physx`), benchmark CLI, device, Newton schema, and actuator authoring tests were rerun; all pass. Every renamed module and its importers in `isaaclab_physx`, `isaaclab_newton`, and `isaaclab_ov` import cleanly. - One-line helpers are kept inline rather than wrapped in functions (e.g. the drive get-or-apply, the passive-drive check, the dataclass-field dict, material paths). - After merging the latest `develop` (including #8102), the tests above were rerun and pass. `isaaclab_physx/test/sim/test_spawn_meshes.py` was run with the `tetrahedralization` extra, which covers `_tetrahedralize_surface`; it passes on this branch and on `develop`. - `ruff check` and `ruff format` are clean. ## Checklist - [x] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] I have added a changelog fragment under `source/<package>/changelog.d/` for each changed package (see [Changelog](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html#changelog)) - [x] If this is a user-visible change, the fragment clearly describes it ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop`
# Description Part 14 of the split of #7949. This PR cleans up sim authoring: the schema writers in `isaaclab.sim.schemas`, the spawners, and the mesh converter. It is rebased onto the current `develop` and ports only the parts of #7949 that still apply there. The authored USD is unchanged, and no public API changes. **Spawners and mesh converter** - `spawners.utils` (renamed from `spawners._utils`, see below) adds a helper: - `apply_schema_props` writes a spawner schema slot. It sends a fragment mapping to the fragment writer, one entry at a time and anchored at the spawned prim, and sends a legacy cfg to the legacy writer. The mesh and shape spawners, `spawn_from_mesh`, and `MeshConverter` repeated this branch for their collision, mass, and rigid-body slots; they now call the helper. - Material paths are resolved inline at each call site (absolute paths are kept; relative names go under the spawned prim), replacing `from_files._resolve_material_path`. - Existing-prim checks are left to `create_prim`, which already raises the same `ValueError`. The spawner bodies are shorter, and `spawn_geom_from_prim_type` / `_spawn_mesh_geom_from_mesh` return the prim they create. - Mesh spawners share `_axis_transform` for the cylinder, capsule, and cone axis rotation. - Light, sensor, ground plane, and multi-USD spawners: - The ground plane hides its light with `set_prim_visibility`. - `spawn_multi_usd_file` builds `MultiAssetSpawnerCfg` in one call and no longer runs a `hasattr` check that was always true. - `AssetConverterBase` has a shorter USD-extension and hash-file check, and writes the `config.yaml` generation stamp with a single `datetime.now()` call. The stamp format is the same. **Schema writers** - `apply_rigid_body_properties`, `apply_collision_properties`, and `apply_mass_properties` now share `_apply_api_fragments`. Target matching, `create_if_missing`, the zero-target warning, and result aggregation are unchanged. - The joint-drive writers share `_write_drive_attributes`, which converts angular stiffness and damping from per-radian to per-degree and maps `drive_type` to the USD `type` attribute. It is used by `apply_drive`, `_ensure_drive_exists`, `apply_joint_drive_properties`, and `modify_joint_drive_properties`. Joint-type detection reuses `drive_instance_name`, including in `schemas_actuators`. - Other shared helpers: - `_write_mesh_approximation` writes and validates the `physics:approximation` token. - `_tetrahedralize_surface` holds the pytetwild call and the tet-winding fix, moved out of `define_deformable_body_properties`. - Smaller cleanups: - `activate_contact_sensors` counts descendants with `Usd.PrimRange`. - `schemas_actuators` uses `to_camel_case` instead of a private camel-case regex. - Redundant `pass` statements are removed from the fragment marker classes. - Fragment appliers are called directly as `cfg.func(cfg, prim_path, stage)`. `@configclass` already turns the `func` import string into a callable `ResolvableString`, so the `callable(...) else string_to_callable(...)` fallback (four schema writers and the physics-material spawner) never ran. **Reflection** - Replaced avoidable `getattr`/`setattr`/`hasattr` with direct attribute access or an `isinstance` check wherever the attribute is always defined for the configs that reach that code (actuator authoring, the USD-file and shape spawners, the camera spawner's intrinsics, the fragment annotation lookup). The remaining uses are dynamic by design: iterating dataclass fields, the deprecated alias forwarding, optional class metadata, and mixed config types in the multi-asset wrapper. **No underscore module names or cross-file private helpers in core** - Renamed the underscore modules: `sim/spawners/_utils.py` → `utils.py`, `sim/schemas/_backend_hooks.py` → `backend_hooks.py`, `actuators/_compat.py` → `actuator_compat.py`, `benchmark/_cli.py` → `cli.py`, `cloner/_fabric_notices.py` → `fabric_notices.py`, `utils/_device.py` → `device.py`. All importers in `isaaclab`, `isaaclab_physx`, `isaaclab_newton`, `isaaclab_ov`, the benchmark scripts, tests, and docs are updated. - Dropped the `_` prefix from module-level functions used from other files: `limits_equal`, `resolve_limit_aliases`, `skip_joint_drive`, `articulation_root_companion_namespace`, `apply_namespaced_schemas`, `drive_instance_name`, `validate_newton_native_actuator_cfgs`, `author_actuator_prims`, `resave_checkpoint_with_metadata`, `deprecate_field_alias`, `deprecated_schema_cfg`, `spawn_from_usd_file`, `spawn_geom_from_prim_type`. They are not added to the package exports. **Not ported from #7949** - The forwarding-shim refactors in `schemas/__init__.py` and `schemas_cfg.py`, the `usd_api` / `physx_api` deprecation properties, and the empty `_usd_*` metadata on deprecated cfgs. These are deprecation-only and will be removed. - The `_OVERRIDABLE_PROPS` constant in the wrappers, a single-use constant. - The import-only edits. `develop` already uses relative imports. ## Type of change - Refactor (no functional change). The only visible difference is that the `ValueError` for an unsupported deformable type is now one line, instead of a triple-quoted string with embedded indentation. ## Verification - USD authoring equivalence, comparing `develop` sources with this branch in Kit, one fresh stage per case. All 57 cases produce identical exported USDA, return values, and raised errors: - Sphere, cuboid, cylinder, capsule, and cone shapes; and sphere, cuboid, cylinder, capsule, cone, and rectangle meshes. Each is spawned plain, with legacy cfgs, and with fragments (including dict targets and absolute material paths). - The cable spawner, `MeshFileCfg` from a trimesh object and from an `.obj` file, and all five lights. - Pinhole and fisheye cameras, and the sensor frame. - `UsdFileCfg` with legacy cfgs and with fragments (articulation root, joint drives, contact sensors, semantics, materials), the compliant-contact spawner, and a ground plane asset. - `MultiAssetSpawnerCfg` and `MultiUsdFileCfg`, and a surface deformable. - The legacy `define_`/`modify_` writers and the fragment `apply_*` writers, including `ensure_drives_exist`, the no-target case, mesh collision with an invalid approximation name, and fixed tendons. - A `MeshConverter` run with collision, mesh-collision, mass, and rigid props and `make_instanceable`, comparing the generated USD layers and `config.yaml`. - Tests, run one file at a time; all pass: - Spawners: `test_spawn_shapes`, `test_spawn_meshes`, `test_spawn_lights`, `test_spawn_sensors`, `test_spawn_from_files`, `test_spawn_wrappers`, `test_spawn_cable`, `test_spawn_materials`, `test_default_ground_plane`, `test_visual_materials_kitless`. - Schemas: `test_schemas`, `test_schemas_deprecation`, `test_schemas_shim`, `test_schemas_kitless_fixed_joint`, `test_schema_fragments`, `test_schema_fragment_parity`, `test_schema_writer_nested_targets`, `test_joint_drive_fragments`, `test_collision_fragments`, `test_mass_fragments`, `test_mesh_collision_fragments`, `test_articulation_fragments`, `test_material_fragments`, `test_tendon_fragments`, `test_tendon_fragments_codeless`, `test_deformable_backend_split`. - Converter: `test_mesh_converter`. - Actuator authoring: `source/isaaclab/test/actuators`, `test_newton_actuator_manager_authoring`, `test_newton_actuators_newton`, `test_newton_actuators_physx`. - After the renames, reflection pass, and review fixes, the 57-case USD comparison was rerun against the latest `develop` (0 differences), and the spawner, schema, fragment, converter, cloner (`isaaclab` and `isaaclab_physx`), benchmark CLI, device, Newton schema, and actuator authoring tests were rerun; all pass. Every renamed module and its importers in `isaaclab_physx`, `isaaclab_newton`, and `isaaclab_ov` import cleanly. - One-line helpers are kept inline rather than wrapped in functions (e.g. the drive get-or-apply, the passive-drive check, the dataclass-field dict, material paths). - After merging the latest `develop` (including #8102), the tests above were rerun and pass. `isaaclab_physx/test/sim/test_spawn_meshes.py` was run with the `tetrahedralization` extra, which covers `_tetrahedralize_surface`; it passes on this branch and on `develop`. - `ruff check` and `ruff format` are clean. ## Checklist - [x] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] I have added a changelog fragment under `source/<package>/changelog.d/` for each changed package (see [Changelog](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html#changelog)) - [x] If this is a user-visible change, the fragment clearly describes it ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` (cherry picked from commit d11f811)
## Description A follow-up to #8068, #8090, and #8102: it inlines or removes launch-stack helpers whose names cost the reader more than their bodies do. This PR is pure cleanup with no behavior change; every public removal is listed below with its replacement. ### Launcher (`isaaclab.app.sim_launcher`) - **Arguments become a dict once.** `launch_simulation` and `scan` convert launcher args with `vars(args_cli)`, the namespace's live `__dict__`, so values resolved at launch (for example `args_cli.headless`) still reach the caller. That removes `_get_arg` / `_set_arg` and their three-way Namespace/dict/None branching on every read. - **Resolved once instead of twice:** - the livestream mode is resolved during argument normalization and read back afterwards; - the "explicit `--viz` overrides the config" rule for the Kit visualizer is part of the scan's visualizer intent. - **Inlined:** the logging-level resolver (now private here), the one-line `_is_*` config predicates, and the Kit-source list formatter. - **`make_physics_cfg` is private** (`_make_physics_cfg`); only `scan` used it. ### Settings (`isaaclab.app.settings_manager`) - **One accessor:** `SettingsManager.instance()` is removed. It was identical to `get_settings_manager()`. - **One setter:** `set_bool` / `set_int` / `set_float` / `set_string` are removed. They only called `set()`, which already dispatches on the value's type. Only calls on Isaac Lab's settings manager changed; calls on carb's settings interface are untouched. ### Kit launcher (`isaaclab_physx.app.KitLauncher`) - **Inlined:** three single-use helpers (spectator-view check, experience dependency check, deferred CUDA device). - **Merged:** the stop-button and play-button toolbar helpers become one `_set_toolbar_button_visible`, with each button's current behavior kept. - **Renamed:** `add_app_launcher_args` → `add_launcher_args`, and `ExplicitAction` → `_ExplicitAction` (internal). Net: +239 / −405 (about −165 lines). ## Type of change - Breaking change (removed `SettingsManager.instance`, the typed `SettingsManager.set_*` forwarders, and `isaaclab.app.make_physics_cfg`; renamed `KitLauncher.add_app_launcher_args`) ## Validation All runs on GPU 0. - **Launcher and runtime tests:** - Kit launcher (84), visualizer intent (8), distributed device resolution (11), runtime compatibility (27), `require_kit` (10); - preset Kit decision (6), preset CLI (11), RL entrypoints (44), CLI tests (234); - app tests, including the `AppLauncher` shim, exit status, and Kit startup; - simulation context (26), Isaac RTX renderer contract (26), and the changed contact-sensor and OvPhysX scene-data tests. - **`test_simulation_context_visualizers`:** 44 passed, 1 failed. The failing test needs `carb`, which only CI's image has, and it fails identically on develop. - **Training:** Cartpole runs 2 iterations with `isaacsim_physx` (Kit starts) and with `newton_mjwarp` (no Kit). - **Tutorial:** `create_empty.py` reaches setup and runs. - **Not run:** the toolbar-button and livestream `isaacsim.exp.full` paths need a GUI or a livestream. - **Removed test:** `test_deferred_cuda_device_synchronizes_torch_and_warp`. Its helper is now inlined into Kit-only startup code. ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the pre-commit checks - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added changelog fragments for every touched package
## Description A follow-up to #8068, #8090, and #8102: it inlines or removes launch-stack helpers whose names cost the reader more than their bodies do. This PR is pure cleanup with no behavior change; every public removal is listed below with its replacement. ### Launcher (`isaaclab.app.sim_launcher`) - **Arguments become a dict once.** `launch_simulation` and `scan` convert launcher args with `vars(args_cli)`, the namespace's live `__dict__`, so values resolved at launch (for example `args_cli.headless`) still reach the caller. That removes `_get_arg` / `_set_arg` and their three-way Namespace/dict/None branching on every read. - **Resolved once instead of twice:** - the livestream mode is resolved during argument normalization and read back afterwards; - the "explicit `--viz` overrides the config" rule for the Kit visualizer is part of the scan's visualizer intent. - **Inlined:** the logging-level resolver (now private here), the one-line `_is_*` config predicates, and the Kit-source list formatter. - **`make_physics_cfg` is private** (`_make_physics_cfg`); only `scan` used it. ### Settings (`isaaclab.app.settings_manager`) - **One accessor:** `SettingsManager.instance()` is removed. It was identical to `get_settings_manager()`. - **One setter:** `set_bool` / `set_int` / `set_float` / `set_string` are removed. They only called `set()`, which already dispatches on the value's type. Only calls on Isaac Lab's settings manager changed; calls on carb's settings interface are untouched. ### Kit launcher (`isaaclab_physx.app.KitLauncher`) - **Inlined:** three single-use helpers (spectator-view check, experience dependency check, deferred CUDA device). - **Merged:** the stop-button and play-button toolbar helpers become one `_set_toolbar_button_visible`, with each button's current behavior kept. - **Renamed:** `add_app_launcher_args` → `add_launcher_args`, and `ExplicitAction` → `_ExplicitAction` (internal). Net: +239 / −405 (about −165 lines). ## Type of change - Breaking change (removed `SettingsManager.instance`, the typed `SettingsManager.set_*` forwarders, and `isaaclab.app.make_physics_cfg`; renamed `KitLauncher.add_app_launcher_args`) ## Validation All runs on GPU 0. - **Launcher and runtime tests:** - Kit launcher (84), visualizer intent (8), distributed device resolution (11), runtime compatibility (27), `require_kit` (10); - preset Kit decision (6), preset CLI (11), RL entrypoints (44), CLI tests (234); - app tests, including the `AppLauncher` shim, exit status, and Kit startup; - simulation context (26), Isaac RTX renderer contract (26), and the changed contact-sensor and OvPhysX scene-data tests. - **`test_simulation_context_visualizers`:** 44 passed, 1 failed. The failing test needs `carb`, which only CI's image has, and it fails identically on develop. - **Training:** Cartpole runs 2 iterations with `isaacsim_physx` (Kit starts) and with `newton_mjwarp` (no Kit). - **Tutorial:** `create_empty.py` reaches setup and runs. - **Not run:** the toolbar-button and livestream `isaacsim.exp.full` paths need a GUI or a livestream. - **Removed test:** `test_deferred_cuda_device_synchronizes_torch_and_warp`. Its helper is now inlined into Kit-only startup code. ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the pre-commit checks - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added changelog fragments for every touched package (cherry picked from commit 24e1b46)
) # Description Part 7B of the camera performance series, based on the latest `develop` (including #8039, #8042, and #8087). A sweep of the per-step hot path found remaining host-device synchronizations and code that costs more than it gives. This PR fixes the verified findings: it removes the synchronizations, launch overhead, and dead or over-defensive code, and fixes the verified bugs. Profiling on `develop` motivated this. The GPU sat idle 20–27% of each step, because the CPU blocked on synchronizations and then launched hundreds of small kernels. On `Isaac-Velocity-Rough-AnymalD` (4096 environments), for example, the CPU was blocked 12.8 ms of a 25.4 ms step. ## Changes ### Host synchronizations removed - **Episode logging:** the command, termination, and curriculum managers, `survival_success_rate`, the pose commands, and task success rates (Cabinet, Locomotion, Lift deformable/cable, Fourbar) log 0-d device tensors instead of reading back `.item()`/`.cpu()` on every reset. `RewardManager` already logged tensors, and the RL wrappers accept them. Curriculum states are logged as copies, because rsl_rl keeps episode infos for a whole rollout. The inspection accessor `get_active_iterable_terms()` still returns Python scalars. - **Velocity command:** heading control is branchless (`torch.where`) instead of `is_heading_env.nonzero()` every step. Output is identical. - **Event ranges:** core and Lift event terms use `sample_uniform_from_ranges()` to draw named components directly. One private, bounded bounds cache replaces both sets of tensor-building helpers; it is keyed by values, resolved device, and dtype. Curriculum edits take effect on the next call, and every call draws fresh samples in the existing order. - **Ray caster:** `reset()` no longer uploads its range tensor or samples drift when the drift ranges are zero (the default). In rough locomotion this reset runs almost every step. When drift is disabled after sampling, reset clears the selected environments’ old drift. - **DiffIK:** the `if ee_quat.norm() != 0` guard in `apply_actions`, which synchronized every physics substep, is now a `torch.where` with the same all-or-nothing behavior. - **Direct tasks:** Reorient (about 14 host-list indexes per substep), Cabinet, and Locomotion store joint and body indices as device tensors, precompute static joint limits and default positions, and use the non-deprecated `actuators.target_command` API. - **Other task terms:** - Locomotion `walk_target_w` caches its device target (it synchronized 4 times per step). - Reorient's `EpisodeErrorRecorder` uses `torch.where` with NaN reductions instead of boolean masks. - Lift reset events share the named-range sampler with the core event terms. - **Joint limits:** Newton, PhysX, and OvPhysX position-limit writes reuse the clamping counter and read it back only when the resulting message would be logged. ### Launch overhead - **`RewardManager`:** each term writes its weighted value into a step-reward matrix column, followed by one sum and one batched episode-sum update. Reset is one mean and one fill. With 20 terms at 4096 environments, compute drops from 121 to 23 kernels (471 → 152 µs) and reset from 80 to 4 kernels (504 → 49 µs). - **`ObservationManager`:** the built-in noise functions (`constant_noise`, `gaussian_noise`, `uniform_noise`) are out-of-place, so the pre-noise clone and the second clone are skipped. Safe built-in noise functions are identified during `_prepare_terms`; custom noise functions, noise models, and modifiers still clone, including when a caller replaces a noise function after setup. The noise sampling order is unchanged. - **`CircularBuffer`:** one staged shift replaces K−1 slot copies for frames up to 2 MiB. Image-sized frames keep the slot loop, which is faster for them. - **Lift contacts:** one stacked norm replaces per-sensor norms. `contacts()` runs 5 times per step in Kuka Allegro, and this removes about 80 kernels per step. - **ANYmal symmetry augmentation:** one cached permutation and sign tensor per transform, bitwise-equal to the original, is 1.56 → 0.15 ms per call at 4096 environments. - **RTX renderer:** normals, motion vectors, `rgb_hdr`, and simple shading no longer copy each frame into a contiguous channel slice before reshaping. - **Smaller changes:** - Reorient reads its command slices directly instead of concatenating them. - sb3 computes `dones` on the host side. ### Overengineered code removed - **`NewtonManager.step()`** ran the solver-internals reset every physics step. `forward()` already performs it when kinematics are dirty, so the extra call only launched with an all-False mask. - **`WrenchComposer.reset()`** returns early when inactive. Its buffers are already zero, and this removes about 7 memsets per rigid object per physics step (21 µs → 0.07 µs per call). - **`SensorBase`:** sensors with `debug_vis=True` no longer refresh on every physics substep. That refresh existed because debug callbacks once read private data. The callbacks now refresh the outdated buffers themselves. The original eager update was introduced in commit `4565902f5` to make visualization work without a `data` read; it did not pump rendering. - **`VisualizationMarkers.visualize()`** returns early when no backend is active. - **Dead code:** removed the Newton Warp renderer's output copy loop (every output is a zero-copy alias), the impossible PhysX ray-caster guard, and the redundant Lift `body_state_b` index conversion (redundant since #8087). ### Bug fixes - **Newton `body_com_acc_w`:** the finite difference divided by the physics timestep even when an update spans several physics steps (Newton owning the decimation loop). That made the acceleration, and `body_lin_acc_l2`, `decimation`× too large. It now uses the elapsed time, matching `joint_acc`. The OvPhysX rigid-object implementation uses the same elapsed-time formula. PhysX and OvPhysX articulations read acceleration from the backend, so they do not need this finite-difference change. - **`reset_root_state_uniform`** built its range tensors in `__init__` and ignored call-time `pose_range`/`velocity_range`, so curriculum updates were silently dropped. ### Investigated and not included - **Step reset, command resample, and interval-event `nonzero`:** these are now the only synchronizations left in `Isaac-Velocity-Rough-AnymalD`. Each converts a mask into variable-length environment IDs consumed across the reset, command, and event APIs. Removing them requires a mask-based API redesign and is left for a separate design. - **Needs a Kit trace before changing:** the PhysX IMU/PVA per-update COM upload, PhysX contact-sensor per-substep fetches, and the Fabric render synchronizations. They rely on PhysX/Fabric semantics we have not measured. A similar "pageable upload synchronizes" assumption proved false for the Newton sensor flags. - **Deferring the MPM sparse-grid status check:** a solver reset clears the status, so a deferred check could lose capacity errors, and no test covers this path. - **RMPflow guard:** it already runs on the host, so removing the guard gains nothing. The `joint_actions` allocation is needed for LEAPP export tracing. - **Lower confidence, left out:** collection mask-write kernels and batching model-change notifications. ## Type of change - Bug fix (non-breaking change which fixes an issue) - Behavior changes with migration notes in the changelog fragments: - Episode log values are 0-d tensors; use `float()` or `.item()` where a Python number is needed. - Reorient direct index attributes (`actuated_dof_indices`, `finger_bodies`, `finger_wrench_bodies`) and `resolve_actuated_tendons` ids are tensors. - `EpisodeErrorRecorder` reports NaN for an empty selection after its first update. - Custom sensors should refresh their buffers inside `_debug_vis_callback`. ## Performance RTX PRO 6000 Blackwell Workstation Edition (driver 595.91.07); PyTorch 2.12.0+cu130; Warp 1.17.0; Newton 1.6.0; GPU otherwise idle. `develop` at `60bc09f17` compared with this PR on that base, with the same `uv.lock`. The branch has since merged `develop` at `f25d3f09b` (#8042, #8090, #8102). The numbers below were measured before that merge; #8042 changes the Kuka camera observations and #8090 touches the simulation context, so they have not been re-measured on the merged branch or after review fixes. Static Lift success markers now resend positions to support late backend activation; the earlier marker-index-only optimization is not included. Runtime benchmark (`isaaclab benchmark runtime`), Newton/MJWarp, seed 42, no visualizer. Three fresh processes per revision, run in alternating order. Figures are the mean step time across processes; every workload's per-process ranges are disjoint. | Workload | `develop` | This PR | Change | | --- | ---: | ---: | ---: | | `Isaac-Ant`, 4096 envs | 3.369 ms | 2.629 ms | **−22.0%** (+28.1% throughput) | | `Isaac-Open-Drawer-Franka-Direct`, 4096 envs | 11.106 ms | 10.100 ms | **−9.1%** (+10.0%) | | `Isaac-Reorient-Cube-Allegro-Direct`, 4096 envs | 27.114 ms | 25.221 ms | **−7.0%** (+7.5%) | | `Isaac-Velocity-Rough-AnymalD`, 4096 envs | 23.078 ms | 22.573 ms | −2.2% (+2.2%) | | `Isaac-Lift-KukaAllegro-Camera`, 256 envs, `presets=duo_camera,rgb128`, Newton renderer | 12.396 ms | 12.202 ms | −1.6% (+1.6%) | Per-process step times (`develop` → PR): - Ant: `3.367, 3.359, 3.382` → `2.639, 2.638, 2.611` ms. - Drawer: `11.113, 11.102, 11.104` → `10.099, 10.100, 10.100` ms. - Reorient: `27.136, 27.136, 27.070` → `25.217, 25.250, 25.197` ms. - AnymalD: `23.081, 23.050, 23.103` → `22.551, 22.568, 22.599` ms. - Camera: `12.389, 12.374, 12.424` → `12.373, 12.119, 12.113` ms. Host synchronizations per `env.step()`, attributed to call sites with PyTorch sync-debug mode over 170 steps: | Task | `develop` | This PR | Remaining | | --- | ---: | ---: | --- | | `Isaac-Velocity-Rough-AnymalD` | 6.75 | 3.00 | step reset, command resample, and interval-event `nonzero` | | `Isaac-Lift-KukaAllegro-Camera` | 2.11 | 2.04 | step reset and command resample `nonzero`; curriculum difficulty `.item()` (0.04 per step) | PyTorch labels sync-debug mode a prototype that does not detect every synchronization, and it does not see synchronizations issued by Warp, so these counts are lower bounds. ## Validation - The shared sampling refactor passed 257 tests across the existing math, root-state event, and Lift configuration suites. The existing event test now checks exact seeded samples, key order, missing axes, fresh draws, range edits, and warm-cache CUDA synchronization. Eight standalone equivalence checks also passed across CPU/CUDA, float32/float64, and flat/nodal batch shapes. No new tests or test files were added. - Before the shared-sampler refactor, 205 focused tests passed, with each file run in its own process: curriculum, observation, reward, and termination managers; heading commands and mutable event ranges; DiffIK; wrench composition; ray-caster and sensor-base behavior; marker visualization; Lift and reorientation helpers; and the existing joint-limit tests on both PhysX and OvPhysX, on CPU and CUDA. Kit tests used the `isaacsim` extra, and OvPhysX used `ovphysx` with separate CPU/GPU processes. - Regression checks fail with the old curriculum accessor, stale drift, and static marker behavior restored. Mutations also turn the retained tests red for custom-noise aliasing, eager debug-visualization refreshes, partial reward reset corruption, and missing reorientation NaN statistics. - Applied the test-audit skill: seven standalone tests were consolidated into existing reward, wrench, reorientation, marker, ray-caster, sensor-update, and Lift tests. Synchronization tests run on CUDA instead of repeating the same bookkeeping on CPU. No new test functions or files were added in the review-fix commit. - Retained unique heading, curriculum snapshot, mutable-range, and ANYmal symmetry coverage: there is no equivalent existing owner test. The symmetry test checks the new permutation tables against the previous independent index-assignment formulation. - `uv run isaaclab -f` passed, including changelog checks against the actual PR base, and `git diff --check` passed. - The full test suite and training smoke runs have not been repeated on this revision; benchmark figures above describe the earlier measured revision. ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` ## Checklist - [x] I have read and understood the contribution guidelines. - [x] I have run the pre-commit checks with `uv run --frozen isaaclab -f`. - [x] I have made corresponding changes to the documentation. - [x] I have added tests that prove the behavior and checked the regressions against the unfixed code. - [x] I have added a changelog fragment for every touched source package. - [x] My name already exists in `CONTRIBUTORS.md`.
Description
Part 3 of 3. #8068 (merged) added the launcher design, and #8090 moves the scripts onto it. This PR does the same for the tests. It is independent of #8090, so they can merge in either order.
What changes
launch_test_simulation(...)call. It replaces the"""Launch Isaac Sim Simulator first."""preamble in about 125 modules.launch_test_simulation(cfg=None, **launcher_args)is config-driven. It starts whatever runtime the test's simulation config needs (the defaultSimulationCfg()when none is given) instead of forcing Kit, and it returnsNone. It still picks the test device from the multi-GPU mask by default. Every existing test gets the same runtime as before, because the default config uses PhysX, which starts Kit; the config makes that choice now, not the helper.isaaclabtests no longer importomni,carb, orisaacsim:destroy_hydra_textures;isaaclab_physx: the Isaac SimXformPrimcomparison, the Kit timeline and app-update tests, stage-in-memory, the UI window, Kit startup performance, and three Isaac Sim extension-path tests. No coverage is deleted.omni.kit.appin their own package: Newton fabric sync, teleop XR, and the visualizer tests.The remaining Kit mentions in core tests are the
isaacsim_ciCI markers, theinstall_ciinstaller checks,omni.client, and tests that stubomnito exercise core code's own Kit branches without starting Kit.Net: +856 / −1,260 across 169 files.
Type of change
launch_test_simulationsignature and return value)Validation
All runs on the display GPU (GPU 0).
Release backport
developChecklist