Skip to content

[Core] Move scripts, examples, and docs to launch_simulation (2/3) - #8090

Merged
ooctipus merged 2 commits into
isaac-sim:developfrom
ooctipus:octi/launch-simulation-migration
Sep 28, 2026
Merged

ooctipus merged 2 commits into
isaac-sim:developfrom
ooctipus:octi/launch-simulation-migration

Conversation

@ooctipus

@ooctipus ooctipus commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

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.

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 (Use function-style configuration operations across the repository #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

  • Backport this pull request to the active release branch after it merges into develop

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks
  • I have made corresponding changes to the documentation (tutorials and how-to guides)
  • My changes generate no new warnings
  • I have added changelog fragments for every touched package

@ooctipus
ooctipus requested a review from a team September 27, 2026 21:05
@ooctipus ooctipus changed the title Move scripts and tests to launch_simulation (2/2, depends on #8068) [Core] Move scripts and tests to launch_simulation (2/2, depends on #8068) Sep 27, 2026
@ooctipus

Copy link
Copy Markdown
Collaborator Author

run-ci

@github-actions github-actions Bot added documentation Improvements or additions to documentation asset New asset feature or request isaac-sim Related to Isaac Sim team isaac-mimic Related to Isaac Mimic team infrastructure labels Sep 27, 2026
@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 27, 2026
@greptile-apps

greptile-apps Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Reorganizes simulation launcher classes across extension modules.

The PR should not merge until migrated simulation loops stop when their Kit runtime stops.

Findings

  1. P1 Loop outlives stopped Kit ▶
  2. P2 Depth and normals are discarded ▶
  3. P2 Snippet endpoint does not match ▶

Summary

The top commit migrates scripts and tests to configuration-driven simulation launch, retains a minimal AppLauncher shim, and replaces several Kit-specific output paths. Review attention is needed for loop termination after Kit shutdown, preservation of camera data when saving, and one broken documentation excerpt.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  C[Simulation configuration and CLI] --> L[launch_simulation]
  L --> K[Kit runtime when required]
  L --> N[Kitless runtime otherwise]
  K --> S[Simulation context]
  N --> S
  S --> E[Environment or scene]
  E --> R[Step, render, and save outputs]
Loading

Reviews (1) · Last reviewed commit: "Move scripts and tests to launch_simulat..."

@ooctipus
ooctipus force-pushed the octi/launch-simulation-migration branch from d6a53e7 to e53df5b Compare September 28, 2026 02:46
@ooctipus

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 28, 2026
@ooctipus

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 28, 2026
ooctipus added a commit that referenced this pull request Sep 28, 2026
…he config (1/2) (#8068)

## Description

**Part 1 of 2: the design.** The migration of every script and test is
in the stacked follow-up, #8090. This PR keeps existing scripts running
unchanged, so the two halves can be reviewed separately.

`launch_simulation` now starts each simulation runtime through the
launcher that the runtime's own backend package provides. The resolved
config says which launcher is needed, so core never imports one.

```python
# isaaclab.app: the interface every backend runtime implements
class SimulationLauncher:
    device: str | None = None                 # optional device the runtime picked
    def __init__(self, launcher_args): ...    # constructing it starts the runtime
    def close(self, exit_code: int = 0): ...  # stops it

# backend configs name their launcher, resolved lazily like ``class_type``
class PhysxCfg(PhysicsCfg):
    launcher_type: ClassVar[str] = "isaaclab_physx.app:KitLauncher"
class OVRTXRendererCfg(RendererCfg):
    launcher_type: ClassVar[str] = "isaaclab_ov.app:OvrtxLauncher"
```

`launch_simulation(cfg, args)` scans the resolved config as it already
did and collects `launcher_type` from the physics and renderer config
instances it resolved. It constructs each launcher once and closes them
in reverse order when the block exits. Kit needs that no config names
(`require_kit`, no physics config, a Kit visualizer requested only on
the CLI) fall back to `KitLauncher`.

- **`isaaclab_physx.app.KitLauncher`** is the old `AppLauncher` body,
minus dead code:
- removed: argument-collision bookkeeping, the Isaac Sim 5 branch, and
the hidden `--cpu` flag;
- moved in from `launch_simulation`: the Isaac Sim availability check
and the "Kit already running" guard.
- **`isaaclab_ov.app.OvrtxLauncher`** registers the OVRTX USD schemas,
which `launch_simulation` used to do inline.
- **Moved into `sim_launcher.py`** because kitless launches need them
too: argv fusing, visualizer argument normalization, and the
visualizer-settings sync (no longer wrapped in a blanket
`suppress(Exception)`).

### Kit stays in `isaaclab_physx`

Core code no longer imports `carb`, `omni`, or `omni.replicator`. Kit
concerns go through one of two owners, and no new global hook is added.

- **The `SimulationContext` backend registry** owns anything tied to a
simulation's lifetime:
- `isaaclab_physx.app.KitStageBackend` is registered through
`get_or_create_backend` when Kit runs;
- it attaches the stage to Kit's USD context and closes Kit's context
stage when `clear_instance()` closes the other backends;
- core stage utilities never touch Kit: `clear_stage()`/`close_stage()`
are Kit-free, and Kit's own consumers (PhysX reset/step, RTX render, the
Kit visualizer) run the app updates they need.
- **No defensive `None` handling on invariants:** a `SimulationContext`
always has a stage, so consumers read
`SimulationContext.instance().stage` directly
(`SceneDataProvider.usd_stage` / `get_usd_stage` are removed).
- **`KitLauncher`** owns one-time process setup:
- `SettingsManager.set_backend(carb.settings)`, replacing
`initialize_carb_settings` and `is_omniverse_mode`;
  - sharing Isaac Sim's stage-helper context;
  - one app update in `close()`, so scripts no longer need their own.
- **Replicator** is enabled by the Isaac RTX renderer and seeded by the
Replicator event terms that use it. The env classes no longer import it.
- **`show_stage_in_viewport`** moves to `isaaclab_physx.app`, since it
only works under Kit.
- **Gravity:** tasks set it through `PhysxManager.set_gravity` instead
of `carb.Float3`.

### Exit handling

The ~110-line `_SimulationAppLifecycle` class from #6636 is gone. I
measured a real Kit process with no handlers installed, and only two
exit paths needed help. Both are now handled by two lines in
`KitLauncher`:

- An unhandled exception exits with 1. Kit's exit path reported 0.
- `SIGINT` raises `KeyboardInterrupt`. Kit's own handler exited 0.

`SIGTERM`, `SIGABRT`, and `SIGSEGV` keep their default actions. Fixes
#7774, supersedes #7775 and #6531.

### Constructing runtime objects after launch

Importing `pxr.Usd` before Kit starts makes Kit fail to start. Scripts
therefore import only config classes and construct runtime objects with
`instantiate(cfg)` (#8085), which resolves the config's lazy
`class_type` after the runtime is up.

- `ManagerBasedEnvCfg` and `ManagerBasedRLEnvCfg` gain `class_type`.
- The 21 task configs with a custom env class name it. A registry test
checks that all 126 match their registered entry point.
- **Fixed:** `{DIR}` in an inherited `class_type` resolved against the
module of a subclass missing `@configclass`, so the call failed with
`ModuleNotFoundError`.

### Compatibility in this PR

`isaaclab.app.AppLauncher` is deprecated. It now starts Kit through
`launch_simulation`, so develop's scripts and tests run unchanged here.
It still offers `is_available`, `has_gui`, and `has_window`, which
unmigrated scripts use. The migration PR moves every caller and reduces
it to an init-only shim.

`isaaclab.test.utils.launch_test_simulation(**launcher_args)` starts Kit
for a test module through `launch_simulation`. It picks the test device
by default.

### Behavior changes

- **Removed** (breaking; each only restated an invariant or forwarded
elsewhere):
- `sim_utils.update_stage`: the simulation's reset, step, and render
process stage changes;
- `sim_utils.is_current_stage_in_memory`: compare against
`SimulationContext.instance().stage`;
- `sim_utils.show_stage_in_viewport`: use
`isaaclab_physx.app.show_stage_in_viewport`;
- `SettingsManager.initialize_carb_settings` (and the module-level
function) and `is_omniverse_mode`: `KitLauncher` sets the settings
backend, and `has_kit()` checks for Kit;
  - `SceneDataProvider.usd_stage` / `get_usd_stage`;
  - the hidden `--cpu` flag: use `--device cpu`.
- **Replicator seeding:** the Replicator event terms seed it with
`env.cfg.seed` when they are built; `_get_replicator()` only loads it.
Calling `env.seed(x)` later no longer reseeds Replicator.
- **Kit startup marker** is now `[ISAACLAB] KitLauncher initialization
complete`, and `tools/conftest.py` is updated to match.
- **SIGTERM** ends the process immediately, without a Kit teardown.
- **Warp environments:** `render_mode="rgb_array"` now warns and returns
`None`, matching the core environments.

Net: +2,326 / −3,045 across 154 files.

## Type of change

- Breaking change (`AppLauncher` deprecated; Kit-coupled helpers
removed; Kit exit and seeding behavior changed)

## Validation

All runs on the display GPU (GPU 0), with develop's scripts and tests
unchanged unless listed here.

- **Launcher, app, and config tests:**
  - `isaaclab/test/app` (26) and `isaaclab_physx/test/app` (88);
- `test_runtime_compatibility` (27), visualizer intent (8), distributed
device (13), `test_preset_kit_decision` (6), `test_preset_cli` (11);
- `test_configclass` (37), `test_sb3_leapp_export`, and the CLI tests
(234).
- **Kit tests through the deprecated adapter:**
- `test_simulation_context` (30), PhysX `test_rigid_object` (44),
`test_camera` (21);
- stage utils (15), stage in memory (3), `test_events` (4), texture
randomization (2), `test_manager_based_env` (4).
- **Training:** `train.py --task Isaac-Cartpole --max_iterations 2`
exits 0 with `isaacsim_physx` and `newton_mjwarp`.
- `physics=physx` (kitless ovphysx) fails with an observation batch
mismatch.
- Develop `93b6e7432` fails the same way, so it is unrelated to this PR.
- **Every script under `scripts/` and `examples/`**, compared against
develop with the same invocation:
- **Scripts outside the standalone matrix (78):** same outcome on
develop and here. 52 run, 19 are blocked by an external resource
(datasets, XR, Ray, gr00t, robomimic, moviepy), and 7 fail identically
on develop.
- **Standalone matrix (361 cases):** no regressions. The only case that
first looked new was an old-style script with `--visualizer newton_rtx`.
Kit and OVRTX cannot share a process, so the adapter now skips that
visualizer with a warning, as Kit did on develop.
- **Newton-based visualizers next to Kit PhysX:** those cases fail on
develop too, when Newton builds its model from USD.
- **After rebasing onto the latest develop:** the state machines,
`bin_packing`, and Cartpole training still run.
- **Known pre-existing failure:** `test_visualizer_integration_newton`
has a flat-frame check that fails identically on develop.
- Pre-commit passes. The changelog check only flags fragments from other
PRs, because it compares against the fork's stale `develop`.

## 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 (API pages
for `isaaclab.app`, `isaaclab_physx.app`, `isaaclab_ov.app`)
- [x] My changes generate no new warnings
- [x] I have added changelog fragments for every touched package
isaaclab-bot Bot pushed a commit that referenced this pull request Sep 28, 2026
…he config (1/2) (#8068)

## Description

**Part 1 of 2: the design.** The migration of every script and test is
in the stacked follow-up, #8090. This PR keeps existing scripts running
unchanged, so the two halves can be reviewed separately.

`launch_simulation` now starts each simulation runtime through the
launcher that the runtime's own backend package provides. The resolved
config says which launcher is needed, so core never imports one.

```python
# isaaclab.app: the interface every backend runtime implements
class SimulationLauncher:
    device: str | None = None                 # optional device the runtime picked
    def __init__(self, launcher_args): ...    # constructing it starts the runtime
    def close(self, exit_code: int = 0): ...  # stops it

# backend configs name their launcher, resolved lazily like ``class_type``
class PhysxCfg(PhysicsCfg):
    launcher_type: ClassVar[str] = "isaaclab_physx.app:KitLauncher"
class OVRTXRendererCfg(RendererCfg):
    launcher_type: ClassVar[str] = "isaaclab_ov.app:OvrtxLauncher"
```

`launch_simulation(cfg, args)` scans the resolved config as it already
did and collects `launcher_type` from the physics and renderer config
instances it resolved. It constructs each launcher once and closes them
in reverse order when the block exits. Kit needs that no config names
(`require_kit`, no physics config, a Kit visualizer requested only on
the CLI) fall back to `KitLauncher`.

- **`isaaclab_physx.app.KitLauncher`** is the old `AppLauncher` body,
minus dead code:
- removed: argument-collision bookkeeping, the Isaac Sim 5 branch, and
the hidden `--cpu` flag;
- moved in from `launch_simulation`: the Isaac Sim availability check
and the "Kit already running" guard.
- **`isaaclab_ov.app.OvrtxLauncher`** registers the OVRTX USD schemas,
which `launch_simulation` used to do inline.
- **Moved into `sim_launcher.py`** because kitless launches need them
too: argv fusing, visualizer argument normalization, and the
visualizer-settings sync (no longer wrapped in a blanket
`suppress(Exception)`).

### Kit stays in `isaaclab_physx`

Core code no longer imports `carb`, `omni`, or `omni.replicator`. Kit
concerns go through one of two owners, and no new global hook is added.

- **The `SimulationContext` backend registry** owns anything tied to a
simulation's lifetime:
- `isaaclab_physx.app.KitStageBackend` is registered through
`get_or_create_backend` when Kit runs;
- it attaches the stage to Kit's USD context and closes Kit's context
stage when `clear_instance()` closes the other backends;
- core stage utilities never touch Kit: `clear_stage()`/`close_stage()`
are Kit-free, and Kit's own consumers (PhysX reset/step, RTX render, the
Kit visualizer) run the app updates they need.
- **No defensive `None` handling on invariants:** a `SimulationContext`
always has a stage, so consumers read
`SimulationContext.instance().stage` directly
(`SceneDataProvider.usd_stage` / `get_usd_stage` are removed).
- **`KitLauncher`** owns one-time process setup:
- `SettingsManager.set_backend(carb.settings)`, replacing
`initialize_carb_settings` and `is_omniverse_mode`;
  - sharing Isaac Sim's stage-helper context;
  - one app update in `close()`, so scripts no longer need their own.
- **Replicator** is enabled by the Isaac RTX renderer and seeded by the
Replicator event terms that use it. The env classes no longer import it.
- **`show_stage_in_viewport`** moves to `isaaclab_physx.app`, since it
only works under Kit.
- **Gravity:** tasks set it through `PhysxManager.set_gravity` instead
of `carb.Float3`.

### Exit handling

The ~110-line `_SimulationAppLifecycle` class from #6636 is gone. I
measured a real Kit process with no handlers installed, and only two
exit paths needed help. Both are now handled by two lines in
`KitLauncher`:

- An unhandled exception exits with 1. Kit's exit path reported 0.
- `SIGINT` raises `KeyboardInterrupt`. Kit's own handler exited 0.

`SIGTERM`, `SIGABRT`, and `SIGSEGV` keep their default actions. Fixes
#7774, supersedes #7775 and #6531.

### Constructing runtime objects after launch

Importing `pxr.Usd` before Kit starts makes Kit fail to start. Scripts
therefore import only config classes and construct runtime objects with
`instantiate(cfg)` (#8085), which resolves the config's lazy
`class_type` after the runtime is up.

- `ManagerBasedEnvCfg` and `ManagerBasedRLEnvCfg` gain `class_type`.
- The 21 task configs with a custom env class name it. A registry test
checks that all 126 match their registered entry point.
- **Fixed:** `{DIR}` in an inherited `class_type` resolved against the
module of a subclass missing `@configclass`, so the call failed with
`ModuleNotFoundError`.

### Compatibility in this PR

`isaaclab.app.AppLauncher` is deprecated. It now starts Kit through
`launch_simulation`, so develop's scripts and tests run unchanged here.
It still offers `is_available`, `has_gui`, and `has_window`, which
unmigrated scripts use. The migration PR moves every caller and reduces
it to an init-only shim.

`isaaclab.test.utils.launch_test_simulation(**launcher_args)` starts Kit
for a test module through `launch_simulation`. It picks the test device
by default.

### Behavior changes

- **Removed** (breaking; each only restated an invariant or forwarded
elsewhere):
- `sim_utils.update_stage`: the simulation's reset, step, and render
process stage changes;
- `sim_utils.is_current_stage_in_memory`: compare against
`SimulationContext.instance().stage`;
- `sim_utils.show_stage_in_viewport`: use
`isaaclab_physx.app.show_stage_in_viewport`;
- `SettingsManager.initialize_carb_settings` (and the module-level
function) and `is_omniverse_mode`: `KitLauncher` sets the settings
backend, and `has_kit()` checks for Kit;
  - `SceneDataProvider.usd_stage` / `get_usd_stage`;
  - the hidden `--cpu` flag: use `--device cpu`.
- **Replicator seeding:** the Replicator event terms seed it with
`env.cfg.seed` when they are built; `_get_replicator()` only loads it.
Calling `env.seed(x)` later no longer reseeds Replicator.
- **Kit startup marker** is now `[ISAACLAB] KitLauncher initialization
complete`, and `tools/conftest.py` is updated to match.
- **SIGTERM** ends the process immediately, without a Kit teardown.
- **Warp environments:** `render_mode="rgb_array"` now warns and returns
`None`, matching the core environments.

Net: +2,326 / −3,045 across 154 files.

## Type of change

- Breaking change (`AppLauncher` deprecated; Kit-coupled helpers
removed; Kit exit and seeding behavior changed)

## Validation

All runs on the display GPU (GPU 0), with develop's scripts and tests
unchanged unless listed here.

- **Launcher, app, and config tests:**
  - `isaaclab/test/app` (26) and `isaaclab_physx/test/app` (88);
- `test_runtime_compatibility` (27), visualizer intent (8), distributed
device (13), `test_preset_kit_decision` (6), `test_preset_cli` (11);
- `test_configclass` (37), `test_sb3_leapp_export`, and the CLI tests
(234).
- **Kit tests through the deprecated adapter:**
- `test_simulation_context` (30), PhysX `test_rigid_object` (44),
`test_camera` (21);
- stage utils (15), stage in memory (3), `test_events` (4), texture
randomization (2), `test_manager_based_env` (4).
- **Training:** `train.py --task Isaac-Cartpole --max_iterations 2`
exits 0 with `isaacsim_physx` and `newton_mjwarp`.
- `physics=physx` (kitless ovphysx) fails with an observation batch
mismatch.
- Develop `93b6e7432` fails the same way, so it is unrelated to this PR.
- **Every script under `scripts/` and `examples/`**, compared against
develop with the same invocation:
- **Scripts outside the standalone matrix (78):** same outcome on
develop and here. 52 run, 19 are blocked by an external resource
(datasets, XR, Ray, gr00t, robomimic, moviepy), and 7 fail identically
on develop.
- **Standalone matrix (361 cases):** no regressions. The only case that
first looked new was an old-style script with `--visualizer newton_rtx`.
Kit and OVRTX cannot share a process, so the adapter now skips that
visualizer with a warning, as Kit did on develop.
- **Newton-based visualizers next to Kit PhysX:** those cases fail on
develop too, when Newton builds its model from USD.
- **After rebasing onto the latest develop:** the state machines,
`bin_packing`, and Cartpole training still run.
- **Known pre-existing failure:** `test_visualizer_integration_newton`
has a flat-frame check that fails identically on develop.
- Pre-commit passes. The changelog check only flags fragments from other
PRs, because it compares against the fork's stale `develop`.

## 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 (API pages
for `isaaclab.app`, `isaaclab_physx.app`, `isaaclab_ov.app`)
- [x] My changes generate no new warnings
- [x] I have added changelog fragments for every touched package

(cherry picked from commit c9f9e22)
@ooctipus
ooctipus force-pushed the octi/launch-simulation-migration branch from 2e74354 to 4761397 Compare September 28, 2026 03:16
@ooctipus ooctipus changed the title [Core] Move scripts and tests to launch_simulation (2/2, depends on #8068) [Core] Move scripts and tests to launch_simulation (2/2) Sep 28, 2026
@ooctipus

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 28, 2026
Every script, example, tutorial, and benchmark starts the runtime with
launch_simulation and builds runtime objects with instantiate. Scripts no longer
import carb or omni.replicator, the converter tools preview in the visualizer
chosen with --viz, and the check_* scripts that duplicated pytest coverage are
deleted. AppLauncher shrinks to a shim that keeps old-style scripts running by
starting Kit through launch_simulation, and show_stage_in_viewport has no
callers left.
@ooctipus
ooctipus force-pushed the octi/launch-simulation-migration branch from 4761397 to 0601259 Compare September 28, 2026 03:31
@ooctipus ooctipus changed the title [Core] Move scripts and tests to launch_simulation (2/2) [Core] Move scripts, examples, and docs to launch_simulation (2/3) Sep 28, 2026
@ooctipus

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 28, 2026
.
# Simulate physics
while simulation_app.is_running():
while sim.is_headless_or_exist_active_visualizer():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a long function name, and also why are we still checking for headless?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, both points. Renamed SimulationContext.is_headless_or_exist_active_visualizer() to is_running() everywhere (90ee058). The headless case is now an internal detail: is_running() stays true while no visualizer was started, and once visualizers were started it is true while one is still open. That also fixes a real bug the old name hid: after the last visualizer closed, render() dropped it from the list and the empty list read as "headless", so the loop kept going.

Comment thread docs/source/how-to/wrap_rl_env.rst Outdated
}
env = gym.wrappers.RecordVideo(env, **video_kwargs)
# start the runtime with off-screen rendering enabled for the video frames
with launch_simulation(env_cfg, {"enable_cameras": True}):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we removed/deprecated enable_cameras?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enable_cameras is still a Kit launcher argument, but it is no longer something users pass: launch_simulation turns it on automatically when the resolved config contains an RTX camera (or a Kit visualizer streaming view), and the --enable_cameras CLI flag is gone. This doc passed it only because its recipe used render_mode="rgb_array", which is itself deprecated (it warns and returns None). I rewrote the section to record with VideoRecorderCfg on env_cfg.video_recorders from a Kit visualizer, which needs no enable_cameras and no RecordVideo wrapper (90ee058).

step_count += 1
finally:
pick_and_place.close()
with launch_simulation(env_cfg, args_cli):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we allow args_cli like this? It would be better if arguments are explicit, and then users can unpack if they choose to (**args_cli)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept as is for now, on purpose: launch_simulation(cfg, launcher_args) takes the parsed launcher namespace (or a dict) by design, because the launcher reads many optional flags that add_launcher_args adds (--viz, --device, --livestream, --kit_args, --xr, ...), and a script usually just forwards them. Code that builds its own arguments already passes an explicit dict, e.g. launch_simulation(env_cfg, {"device": "cpu"}). Changing the signature to keyword arguments would touch all 83 call sites and the API that just merged in #8068, so if we want that, I'd do it as a separate PR.

Comment thread examples/sensors/cameras.py Outdated
args_cli.output_dir.mkdir(parents=True, exist_ok=True)

while simulation_app.is_running() and (args_cli.max_steps < 0 or count < args_cli.max_steps):
while sim.is_headless_or_exist_active_visualizer() and (args_cli.max_steps < 0 or count < args_cli.max_steps):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_headless_or_exist_active_visualizer seems like an odd choice, what was wrong with is_running(), I think is_running is very standard for app/game lifecycle terminology

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 90ee058: sim.is_running() replaces is_headless_or_exist_active_visualizer() in all scripts, docs, and library callers (no alias kept). See the reply on the ray_caster doc thread for the semantics.

- Rename SimulationContext.is_headless_or_exist_active_visualizer to
  is_running(), which also ends once every started visualizer has closed
  instead of treating the emptied visualizer list as a headless run.
- launch_simulation keeps the status of sys.exit(n) raised in its block, and
  the AppLauncher shim's app.close(exit_code=n) ends the process with n.
- run_usd_camera --save also writes depth and normals as .npy files.
- The wrap_rl_env guide records video with VideoRecorderCfg instead of the
  deprecated rgb_array render mode, so it no longer passes enable_cameras.
@ooctipus

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 28, 2026
ooctipus added a commit that referenced this pull request Sep 28, 2026
…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
@isaaclab-bot

isaaclab-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Backported to release/3.0.0 as 752fa80.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset New asset feature or request documentation Improvements or additions to documentation infrastructure isaac-mimic Related to Isaac Mimic team isaac-sim Related to Isaac Sim team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants