Repository navigation
[Core] Decide visualizers and the device once in launch_simulation - #8125
Conversation
launch_simulation resolves the final visualizer list (--viz none, an explicit --viz selection, the config's visualizers, livestream's Kit visualizer, --max_visible_envs) and the device (--device or the distributed rank, then the launcher's refinement, then cuda:N) once, and writes both into the config. SimulationContext reads cfg.visualizer_cfgs instead of re-applying the rule from settings, apply_env_overrides no longer writes the device, and the RL run summary reads the resolved config after launch instead of scanning it again. This fixes the summary listing configured visualizers under --viz none and the default device on distributed runs.
|
run-ci |
|
| sim_cfg.visualizer_cfgs = _resolve_visualizer_cfgs( | ||
| sim_cfg.visualizer_cfgs, _parse_visualizer_csv(visualizers) | ||
| ) |
There was a problem hiding this comment.
Pending visualizers override builder choice A launch with a bare physics config leaves its visualizer selection in process-wide settings. If
build_simulation_context(visualizers=["kit"]) runs afterward, this code selects Kit, but SimulationContext.__init__ then reapplies the earlier selection. The builder can therefore create the wrong visualizer instead of the one explicitly requested.
Knowledge Base Used: Core simulation framework
There was a problem hiding this comment.
Isaac Lab Review Bot
Reviewed the centralization of visualizer and device resolution in launch_simulation, including the SimulationCfg mutation path, the fallback for launches without a simulation config, RL summary ordering, and mimic config reuse. No candidate findings were supplied or supported as merge-blocking issues.
- Design and architecture: The patch establishes
launch_simulationas the primary owner of resolved device and visualizer state while retaining a documented settings-based compatibility path for callers that constructSimulationCfgafter launch. The producer and consumer paths are internally consistent, though the process-global fallback remains a transitional state-management tradeoff. - API: The documented breaking removals and call-order requirement are reflected in changelog fragments, and the shown in-repository callers are migrated. The additive
setup_env_config(env_cfg=...)parameter preserves the existing parse-on-None behavior. - Implementation: Traced device precedence through CLI, distributed rank, config fallback, launcher refinement, and CUDA index normalization. Also checked visualizer list normalization, stale-setting clearing for config-owning launches, summary reads after resolution, and the mimic hand-off of the launched config. The fallback settings path and pre-launch optional-backend imports remain areas worth monitoring, but the supplied patch does not demonstrate a concrete failure requiring action.
No blocking issues. No inline issue met the actionable-evidence threshold; the assessment above records the review feedback.
Automated review; human maintainers own approval decisions.
- Move function-local imports to module top wherever measuring shows they load no pxr/omni/carb/isaacsim/usdrt before Kit starts; the rest stay local with the reason (Kit-only, optional dependency, or kept cheap on purpose, such as isaaclab.test.utils, which many Kit-free tests import). - SimulationContext turns visualizer_cfgs into a list once, drops the helper and getattr guards around it, and builds default visualizer configs without a catch-all try/except. - Video recording is wired after launch everywhere and reads the resolved visualizer list; pre_launch_video_config is the only place that adds a headless Kit visualizer, before launch.
|
run-ci |
Core must not import a backend package at module level, and sim_launcher loads every backend's configs, so both imports stay inside the functions that need them. The PhysX articulation kernel tests stub isaaclab_physx.physics and failed on the module-level import.
|
run-ci |
launch_simulation writes the two visualizer settings itself instead of through a single-caller helper, and the export backends stop re-applying a device the launch already set.
| from ..utils.string import string_to_callable | ||
| from ..visualizers.visualizer_cfg import _VISUALIZER_ALIASES, _VISUALIZER_TYPES, VisualizerCfg | ||
| from ..visualizers.visualizer_cfg import ( | ||
| _VISUALIZER_ALIASES, |
There was a problem hiding this comment.
Let's avoid importing _ prefixes into another module, _ means its private to that file
There was a problem hiding this comment.
Fixed in ad03700: the --viz parser, resolve_visualizer_cfgs, the install hint and the type table are now public names in isaaclab.visualizers.visualizer_cfg, and sim_launcher imports them from there.
| if max_visible_envs is not None and int(max_visible_envs) < 0: | ||
| raise ValueError(f"Invalid value for --max_visible_envs: {max_visible_envs}. Expected non-negative int.") | ||
| visualizers = args.get("visualizer") | ||
| def _make_visualizer_cfg(visualizer_type: str) -> VisualizerCfg: |
There was a problem hiding this comment.
Would this be useful to users outside this file? Maybe we can expose and remove the _?
| visualizers = args.get("visualizer") | ||
| def _make_visualizer_cfg(visualizer_type: str) -> VisualizerCfg: | ||
| """Construct the default config of a visualizer type, importing only its backend package.""" | ||
| module = {"newton_gl": "newton", "newton_rtx": "newton"}.get(visualizer_type, visualizer_type) |
There was a problem hiding this comment.
this is the aliasing right? this is not looking good like this
There was a problem hiding this comment.
Fixed in ad03700: replaced the two dicts with one VISUALIZER_TYPES table of "module:Class" strings. It is also the list of valid types, so the separate tuple is gone.
| "viser": "ViserVisualizerCfg", | ||
| }[visualizer_type] | ||
| try: | ||
| return getattr(importlib.import_module(f"isaaclab_visualizers.{module}"), class_name)() |
There was a problem hiding this comment.
can we remove getattr? (in this case it might be better to keep it but always want to consider the alternative)
There was a problem hiding this comment.
Removed in ad03700: the lookup now goes through string_to_callable(VISUALIZER_TYPES[visualizer_type]).
| _resolve_distributed_device(effective_cfg, args) | ||
| # The SimulationCfg the simulation is built from: an env config holds it in ``sim``; a physics config or | ||
| # None holds none. | ||
| sim_cfg = getattr(effective_cfg, "sim", effective_cfg if hasattr(effective_cfg, "visualizer_cfgs") else None) |
There was a problem hiding this comment.
Removed in ad03700: scan() now records the first SimulationCfg it walks (Scan.sim_cfg), so launch_simulation reads a typed config instead of probing with getattr.
| args["device"] = sim_cfg.device | ||
|
|
||
| # Decide the visualizers once, into the SimulationCfg. | ||
| has_visualizer_cfgs = hasattr(sim_cfg, "visualizer_cfgs") |
There was a problem hiding this comment.
Removed in ad03700: this is now if sim_cfg is not None: on the typed Scan.sim_cfg.
| from ..utils.version import has_kit | ||
| from ..visualizers.base_visualizer import BaseVisualizer | ||
| from ..visualizers.visualizer_cfg import _VISUALIZER_TYPES, _get_visualizer_install_hint | ||
| from ..visualizers.visualizer_cfg import _get_visualizer_install_hint |
There was a problem hiding this comment.
more _ stuff being imported
There was a problem hiding this comment.
Fixed in ad03700: SimulationContext imports the public helpers from visualizer_cfg, which depends only on isaaclab.utils, so its two local imports from sim_launcher are gone too.
| device = getattr(args_cli, "device", None) | ||
| if device is not None: | ||
| env_cfg.sim.device = device | ||
| if getattr(args_cli, "disable_fabric", False): |
There was a problem hiding this comment.
Partly done in ad03700. Every parser that reaches this function defines --num_envs, so it's plain attribute access now. The other two stay as getattr on purpose: --disable_fabric exists only on the play parsers, and --export_io_descriptors only on the train parsers, so each parser lacks one of them. The docstring now says this.
- A newton_rtx or Kit visualizer that an explicit --viz selection drops no longer starts OVRTX, trips the Kit/OVRTX conflict check, or turns on the Kit streaming view. - XR auto-starts only when the run has no Kit visualizer from the config or --viz. - Drop validate_distributed_device, which the per-rank cuda:N device made dead, and the unused caller-supplied has_kit_streaming_view intent.
|
run-ci |
|
Split for review: this PR now covers deciding visualizers and the device once (the commits Mustafa reviewed, plus the device-test fix and the |
| return list(dict.fromkeys(names)) | ||
|
|
||
|
|
||
| def _normalize_launcher_args(args: dict) -> None: |
There was a problem hiding this comment.
the function name normalize does not give too much info on what this function does, would _resolve be better to match the other _resolve_xxx functions?
There was a problem hiding this comment.
Renamed to _resolve_launcher_args in d3435b7.
| ) | ||
|
|
||
|
|
||
| def _resolve_device(sim_cfg, args: dict, launchers: list[SimulationLauncher]) -> None: |
There was a problem hiding this comment.
so device is getting resolved, see this other PR: #8188. If we know device from the initial resolution, then it should be passed to all further configs in the argument. (please leave a comment in that PR once this PR is merged)
There was a problem hiding this comment.
Agreed. Once this merges, the launch-resolved device is always on env_cfg.sim.device, so the agent/runner can take it from there instead of agent_cfg.device. I'll leave that note on #8188 after this PR merges.
| _VISUALIZER_TYPES = ("kit", "newton_gl", "newton_rtx", "rerun", "viser") | ||
| """Canonical visualizer type names, for ``--visualizer`` and :attr:`VisualizerCfg.visualizer_type`.""" | ||
| VISUALIZER_TYPES = { | ||
| "kit": "isaaclab_visualizers.kit:KitVisualizerCfg", |
There was a problem hiding this comment.
I guess the goal here is to not import from the subpackages, still it looks a bit sad when written this way
There was a problem hiding this comment.
Shortened in d3435b7: the entries are now "kit:KitVisualizerCfg" etc., and the isaaclab_visualizers. prefix is added in the one place that resolves them. The string form stays because core isaaclab must not import isaaclab_visualizers subpackages until one is requested. A lazy top-level export in isaaclab_visualizers (lazy_export()) would also work, but it needs a .pyi stub, so I kept this PR to the table.
| _MISSING = object() | ||
| _PHYSICS_BACKEND_NAMES = {"PhysxCfg": "isaacsim_physx", "OvPhysxCfg": "ovphysx", "PhysxAutoCfg": "physx"} | ||
| _RENDERER_BACKEND_NAMES = {"isaac_rtx": "isaacsim_rtx", "newton_warp": "newton_renderer", "auto_rtx": "rtx"} | ||
| _PHYSICS_BACKEND_NAMES = {"PhysxCfg": "isaacsim_physx", "OvPhysxCfg": "ovphysx"} |
There was a problem hiding this comment.
it seems some backends are missing here, is this correct? is it used for another purpose?
There was a problem hiding this comment.
Yes, this is correct. The table only maps names that can't be derived from the class. Newton configs get theirs from the class plus the solver (NewtonCfg + MJWarpSolverCfg becomes newton_mjwarp) in _physics_backend_name, so they aren't listed. It's only used for the run summary.
| _PHYSICS_BACKEND_NAMES = {"PhysxCfg": "isaacsim_physx", "OvPhysxCfg": "ovphysx", "PhysxAutoCfg": "physx"} | ||
| _RENDERER_BACKEND_NAMES = {"isaac_rtx": "isaacsim_rtx", "newton_warp": "newton_renderer", "auto_rtx": "rtx"} | ||
| _PHYSICS_BACKEND_NAMES = {"PhysxCfg": "isaacsim_physx", "OvPhysxCfg": "ovphysx"} | ||
| _RENDERER_BACKEND_NAMES = {"isaac_rtx": "isaacsim_rtx", "newton_warp": "newton_renderer"} |
There was a problem hiding this comment.
I wonder if we should make the available backends something global/universal, is it defined like this elsewhere in the repo?
There was a problem hiding this comment.
Not yet. These two maps predate this PR, and there are similar ones in benchmark/capture.py (renderer names) and preset_target.py (renderer aliases). The next PR in the series turns --physics into physics= presets, which is the natural single home for backend preset names, so I'd consolidate them there rather than here.
| assert env_cfg.sim.device == "cuda:1" | ||
| mock_set_device.assert_called_once_with("cuda:1") | ||
|
|
||
| @pytest.mark.parametrize("device, expected", [("cuda:1", "cuda:1"), ("cuda", "cuda:0"), ("cpu", "cpu")]) |
There was a problem hiding this comment.
Can these tests be combined with other tests?
There was a problem hiding this comment.
Yes. In 50f95cd the file's 6 classes and 13 test functions (342 lines) became two parametrized tests (164 lines) with the same 15 cases: one table for _resolve_distributed_device (multi-GPU, restricted devices, JAX rank, dict args, missing env, multi-node, two no-op cases) and one for launch_simulation device precedence (Kit refines, Kit gets the config device, kitless distributed rank 0/1, --device cuda:1/cuda/cpu). I also dropped the spy on the internal call and now assert the resulting device and set_cuda_device instead.
|
run-ci |
|
run-ci |
|
run-ci |
## Description Fixes the Kit startup crash introduced by #8125 when MoviePy is installed. Importing the RL entrypoints pulled in the environment runtime and `moviepy.editor`, including unrelated editing dependencies, before Kit launched. - Import the MARL wrapper only when constructing the wrapped environment, after simulation launch. - Import `ImageSequenceClip` directly in the recorder instead of loading `moviepy.editor`. This preserves recording without importing SciPy, OpenCV, or matplotlib. - Add one case to the existing subprocess import test. It catches eager environment imports even without MoviePy installed. There are no launcher or distributed-device changes. Torch remains available before Kit; moving one import did not change that boundary. ## Validation - 121 tests passed across the entrypoint, distributed-device, and video-recorder suites, with MoviePy installed. - The added regression failed when the original eager MARL import was restored and passed with the fix. - The recorder wrote and decoded a three-frame MP4 using the direct import. - GPU 0: `Isaac-Cartpole-Direct`, Isaac PhysX, 16 environments, one RSL-RL training iteration completed. A second run with the environment/video recorder deliberately imported before Kit also completed. - Formatting, lint, and changelog checks passed. ## Release backport - [ ] <!-- 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 tests that prove my fix is effective - [x] I have added changelog fragments for every touched package
## Description Follows #8125. **`--visualizer` decides which visualizers run; the config only holds their settings. `--video` says what to record.** ### `--visualizer` | Command line | Before | After | |---|---|---| | no flag | the config's visualizers run | **nothing runs** | | `--viz kit` | Kit | Kit, using the config's Kit settings (e.g. camera) if it lists one | - Tasks and tools (`zero_agent`, `random_agent`, `run_cartpole_rl_env`, ...) no longer open a viewer by default. Demos, examples and visualizer tutorials keep theirs via `parser.set_defaults(visualizer=[...])`. - Kit opens a window only when `--viz kit` is selected (`HEADLESS=1` still forces headless). The internal `headless` and `visualizer_intent` launcher arguments are removed. ### `--video [SOURCE]` | Command line | Records from | |---|---| | `--video` | the `--viz` window, else a headless newton_gl | | `--video viz:newton_rtx` | newton_rtx (headless unless `--viz` opened it) | | `--video sensor:wrist_camera` | that camera sensor | - `VideoRecorderCfg.source` uses the same format; `visualizer:kit` and `viz:kit` are equivalent. - `--video presets=newton_mjwarp` still applies the preset: `--video` never takes a Hydra override as its value. ### Migration | Before | Now | |---|---| | config lists a visualizer, no flag | add `--viz <type>` | | `zero_agent.py --task X` to watch | add `--viz newton_gl` | | `--video` recording from headless Kit | `--video viz:kit` | ## Type of change - Breaking change (see Migration) ## Validation - Unit tests for the tables above (selection, recorder source, headless flags, which launchers start, Hydra overrides). - Cartpole training on Newton and Isaac Sim PhysX without `--viz`: headless, no Kit on Newton. - `--video` on Newton and PhysX, `--video viz:kit`, and `--video presets=newton_mjwarp`: each writes clips. - Not run: windowed cases (no display on the test machine; unit-tested), XR, livestream. ## Release backport - [ ] <!-- 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 tests that prove my fix is effective - [x] I have added changelog fragments for every touched package
# Description `--device` defaults to `cuda:0`. On macOS, which has no CUDA, every command without an explicit `--device cpu` fails at simulation start (`Torch not compiled with CUDA enabled` in `SimulationContext._init_usd_physics_scene`). The default is now `cpu` on macOS and stays `cuda:0` elsewhere. It checks `sys.platform` rather than `torch.cuda.is_available()` because the launcher defers importing torch until after Kit starts (see the comment in `_resolve_device_settings`). An explicit `--device` still wins, and `device_explicit` is untouched, so the XR device logic is unaffected. `launch_simulation` logs a warning when it applies this default (`No --device given; using 'cpu' because macOS has no CUDA.`), so the switch is visible. Passing `--device` explicitly suppresses it. Hosts that request a CUDA device without having CUDA are handled separately by #8188, which falls back to the CPU with its own warning. Part of the experimental macOS (Apple silicon, CPU-only) support series. ## Type of change - New feature (non-breaking change which adds functionality) ## Validation - On macOS arm64, rebased on `develop` with #8125: `isaaclab train --rl_library rsl_rl --task Isaac-Cartpole-Direct physics=newton_mjwarp --max_iterations 2` (no `--device`) logs the warning, reports `Device cpu`, and trains to completion. This also needs #8188. - With `--device cpu`, no warning is logged. ## 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 `uv run isaaclab --format` (all hooks pass except `check-git-lfs-pointers`, which needs git-lfs installed locally) - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have validated the changed behavior with focused coverage and applied the [test-audit criteria](https://github.com/isaac-sim/IsaacLab/blob/develop/skills/developer/test-audit/SKILL.md) to any test changes - [x] I have added a changelog fragment under `source/<pkg>/changelog.d/` for every touched package (do **not** edit `CHANGELOG.rst` or bump package versions — CI handles that) - [x] I have added my name to the `CONTRIBUTORS.md` or my name already exists there
…t CUDA (#8188) # Description Hosts without CUDA, such as macOS, could not train with RSL-RL even with `--device cpu`. The agent configuration's device (`cuda:0` by default) was used to build the policy, so the run failed with `AssertionError: Torch not compiled with CUDA enabled`. This PR uses the device `launch_simulation` already resolves (since #8125), and sets it in each RL library's shared agent-config setup: - **Clear error without CUDA.** `_resolve_device` in `isaaclab.app.sim_launcher` raises `RuntimeError: Device 'cuda:0' requires CUDA, which is not available; pass --device cpu.` when the resolved device is a CUDA device and CUDA is unavailable. Before, the run failed later inside PyTorch. On macOS, #8190 defaults `--device` to `cpu`. - **The agent runs on the resolved device, set in one shared setup per library.** Each library's config setup takes the device (`args_cli.device`, which `launch_simulation` resolves) as an explicit argument. Every workflow calls it after launch, before the agent is built or its config is saved. This is unconditional, not only for `--distributed`: - **RSL-RL:** the existing `update_rsl_rl_cfg(agent_cfg, args_cli)` sets `agent_cfg.device = args_cli.device`, for train, play, and benchmark train. Export and benchmark play, whose CLIs don't define the RSL-RL training arguments, set the device directly. - **RL-Games:** the new `update_rl_games_cfg(agent_cfg, args_cli)` mirrors `update_rsl_rl_cfg`: it sets `device` / `device_name` and the seed for train, play, export, and both benchmarks. RL-Games export gains `--seed`, matching RSL-RL export, so every RL-Games workflow can call it. - **Stable-Baselines3:** the new `update_sb3_cfg(agent_cfg, args_cli)` mirrors `update_rsl_rl_cfg`: it sets the device and seed for train, play, and both benchmarks. Both `PPO.load()` calls pass `device=agent_cfg["device"]`, so checkpoint loading follows the same setup. skrl and TorchRL already used the simulation's device. The saved agent config records the device actually used, which addresses the bot findings. Closes #8193. Part of the experimental macOS (Apple silicon, CPU-only) support series. ## Type of change - Bug fix (non-breaking change which fixes an issue) - Breaking change (existing functionality will not work without user modification) **Breaking:** outside distributed runs, the RSL-RL, RL-Games and SB3 CLI workflows used to ignore `--device` for the agent: | Command | Before | After | |---|---|---| | `--device cpu` | Simulation on CPU, agent on `cuda:0` | Both on the CPU | | `--device cuda:1` | Simulation on GPU 1, agent on GPU 0 (see #2148) | Both on GPU 1 | The agent configuration's `device` is now overwritten by these workflows. The wrappers still support running the simulation and the agent on different devices for custom scripts; `source/isaaclab_tasks/test/core/test_rl_device_separation.py` covers that and is unaffected. `isaaclab_rl` gets a `.major` fragment. ## Validation On macOS arm64, CPU-only: | Run | Result | |---|---| | RSL-RL train, `--device cpu` | Trains | | SB3 train, `--device cpu` | Trains (`Using cpu device`) | | RL-Games train, `--device cpu` (512 envs) | Completes 2 epochs | | RSL-RL train, `--device cuda:0` | Stops with `RuntimeError: Device 'cuda:0' requires CUDA, which is not available; pass --device cpu.` | `source/isaaclab_rl/test/test_entrypoints.py`, `test_entrypoints_common.py`, and `source/isaaclab/test/app/test_launch_simulation_require_kit.py`: 83 passed. The one failure is `test_skrl_training_parser_leaves_algorithm_implicit`, which needs `skrl`, not installed locally. `test_run_summary_reports_the_launch_resolved_visualizers_and_device` now launches on `cpu`: it only used `cuda:0` as a label and still checks the device resolved after launch. ## 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 `uv run isaaclab --format` (all hooks pass except `check-git-lfs-pointers`, which needs git-lfs installed locally) - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have validated the changed behavior with focused coverage and applied the [test-audit criteria](https://github.com/isaac-sim/IsaacLab/blob/develop/skills/developer/test-audit/SKILL.md) to any test changes - [x] I have added a changelog fragment under `source/<pkg>/changelog.d/` for every touched package (do **not** edit `CHANGELOG.rst` or bump package versions — CI handles that) - [x] I have added my name to the `CONTRIBUTORS.md` or my name already exists there
Description
This is step 2 of the launch-consistency series, after #8111 and #8112: each run-time choice is decided once, in
launch_simulation, and consumers read the resolved config instead of re-deciding it.Visualizers
launch_simulationresolves the final visualizer list:--viz nonegives none; an explicit--viz a,bgives exactly those, reusing a configured visualizer of the same type (with its settings) or else a default; with no--viz, the config's own list; livestreaming adds Kit; and--max_visible_envsapplies to the result. The list is written into the config'ssim.visualizer_cfgsbefore any launcher starts, so a missing visualizer package fails before Kit starts.--vizgoverns everything derived from visualizers. A configurednewton_rtxor Kit visualizer that--vizdrops no longer starts OVRTX, trips the Kit/OVRTX conflict check, or turns on the Kit streaming view. XR auto-starts only when the run has no Kit visualizer.SimulationContextreadscfg.visualizer_cfgs. Its settings-based re-resolution and the/isaaclab/visualizer/explicitand/disable_allsettings are gone. Code that builds aSimulationContextdirectly gets its config's visualizers.build_simulation_context(visualizers=...)is removed. It had no callers and on develop only set a settings key without creating the visualizers.parse_visualizer_csv,resolve_visualizer_cfgs,get_visualizer_install_hint,VISUALIZER_TYPESandVISUALIZER_ALIASESlive inisaaclab.visualizers.visualizer_cfg.VISUALIZER_TYPESmaps each type to its default config as a"module:Class"string, andscan()returns the typedSimulationCfgit found, solaunch_simulationno longer probes withgetattr/hasattr.SimulationCfgto write into (a physics config orNone, as in several tutorials) still passes the selection through/isaaclab/visualizer/types, whichSimulationContextapplies once with the same function. It goes away when those entry points launch with their real config.The command-line convention changes (
--viz noneremoval, no visualizer without--viz,--video [SOURCE]) are split out into the follow-up PR.Device
--device, or this rank's GPU in a distributed run, falling back to the config's device when--deviceis not given, then the launcher's refinement (for example XR picks the CPU), thencudanormalized tocuda:N. The result is written once to the config and to the launcher args.validate_distributed_deviceand its six callers are removed, since each rank now resolves its owncuda:N.apply_env_overridesno longer writes the device (itsapply_deviceargument is removed), andsimple_agentsno longer overwrites--devicewith the task's device.One config scan per run
scan(). The RL backends print it insidelaunch_simulation, from the resolved config.generate_dataset.pylaunches with its real config instead of a throwaway one.Follow-up in this PR
pxr,omni,carb,isaacsim, orusdrtbefore Kit starts: 100 → 71 local imports across the launch stack,SimulationContext, the RL entrypoints, and mimic. The rest stay local for a stated reason: Kit-only, an optional dependency, or kept cheap on purpose (for exampleisaaclab.test.utils, which many Kit-free tests import, and the benchmark dispatcher).SimulationContextvisualizer list.visualizer_cfgsis turned into a list once (direct users now see[]instead ofNone), and default visualizer configs are built without a catch-alltry/except.apply_video_recordingis wired after launch everywhere and reads the resolved visualizer list.pre_launch_video_configis the only place that adds a headless Kit visualizer, before launch, so a Kit visualizer is never injected too late to start Kit. A config with only streaming visualizers now errors on--videoinstead of picking a source that cannot capture.Bugs fixed
--viz none: the run summary listed the config's visualizers although none ran; it now showsnone (headless).The summary now names the concrete backend (for example
ovphysx) rather thanphysx (ovphysx), because the resolved config no longer records which automatic selector chose it.Net: +667 / −853.
Type of change
/isaaclab/visualizer/explicitand/disable_allsettings, thehas_kit_streaming_viewkey ofvisualizer_intent,build_simulation_context(visualizers=...),apply_env_overrides(apply_device=...)andvalidate_distributed_device; dropped the leading underscore from the visualizer selection helpers, andshow_run_summarymust be called inside the launchValidation
All runs on GPU 0 except the multi-GPU check.
--viz nonesummary;--device cuda:1,cuda, andcpu, and Kit starting on the config's device without--device;--vizthat drops a configurednewton_rtxor Kit streaming view starts neither.test_kit_launcher(86),test_simulation_context(26),test_simulation_context_kit(4).physics=isaacsim_physxandphysics=newton_mjwarpeach run 2 iterations; the summaries show the right backend andcuda:0.train.py ... physics=isaacsim_physx --video --video_length 20 --video_interval 20writes two mp4 clips headless.torch.distributed.run --nproc_per_node=2 train.py --task Isaac-Cartpole --distributedon GPUs 0 and 1, withphysics=newton_mjwarpandphysics=isaacsim_physx(Kit in each rank): both exit 0, and rank 0 and rank 1 each report and run on their owncuda:0/cuda:1.pxr,omni,carb,isaacsim, orusdrt, and the env-config import-purity tests pass.Release backport
developChecklist