Skip to content

Commit b82fd8a

Browse files
Fix headless visualizer bug related to parser defaults
1 parent c647d39 commit b82fd8a

3 files changed

Lines changed: 55 additions & 8 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixed
2+
^^^^^
3+
4+
* Fixed an issue where script-defined default visualizers were incorrectly promoted to explicit user intent, causing ``RuntimeError`` during headless execution.

source/isaaclab/isaaclab/app/app_launcher.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ def add_app_launcher_args(parser: argparse.ArgumentParser) -> None:
583583
default=AppLauncher._APPLAUNCHER_CFG_INFO["device"][1],
584584
help='The device to run the simulation on. Can be "cpu", "cuda", "cuda:N", where N is the device ID',
585585
)
586+
parser.set_defaults(visualizer_explicit=False)
586587
arg_group.add_argument(
587588
"--visualizer",
588589
"--viz",
@@ -962,9 +963,11 @@ def _resolve_visualizer_settings(self, launcher_args: dict) -> None:
962963
)
963964
self._cfg_has_any_visualizers = cfg_has_any
964965
self._cfg_has_kit_visualizer = cfg_has_kit
965-
visualizer_explicit = bool(launcher_args.pop("visualizer_explicit", False))
966-
if not visualizer_explicit and "visualizer" in launcher_args:
967-
visualizer_explicit = raw_visualizers is not None
966+
visualizer_explicit = launcher_args.pop("visualizer_explicit", None)
967+
if visualizer_explicit is None:
968+
visualizer_explicit = "visualizer" in launcher_args and raw_visualizers is not None
969+
else:
970+
visualizer_explicit = bool(visualizer_explicit)
968971

969972
visualizer_types: list[str] = []
970973
if raw_visualizers is not None:
@@ -1010,6 +1013,11 @@ def _resolve_visualizer_settings(self, launcher_args: dict) -> None:
10101013
raw_visualizers is None or "none" in visualizer_types
10111014
)
10121015
self._cli_visualizer_types = [] if self._cli_visualizer_disable_all else visualizer_types
1016+
1017+
if not self._cli_visualizer_explicit and self._cli_visualizer_types:
1018+
self._cfg_has_any_visualizers = True
1019+
if "kit" in self._cli_visualizer_types:
1020+
self._cfg_has_kit_visualizer = True
10131021
launcher_args["visualizer"] = self._cli_visualizer_types
10141022

10151023
def _resolve_camera_settings(self, launcher_args: dict):

source/isaaclab/test/app/test_kwarg_launch.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ def _raise_settings_error():
356356

357357
def test_parse_visualizer_csv_accepts_comma_delimited_values():
358358
parsed = app_launcher_module.AppLauncher._parse_visualizer_csv("kit,newton,rerun,viser")
359-
assert parsed == ["kit", "newton", "rerun", "viser"]
359+
assert parsed == ["kit", "newton_gl", "rerun", "viser"]
360360

361361

362362
def test_parse_visualizer_csv_rejects_spaces_between_entries():
@@ -380,7 +380,7 @@ def test_visualizer_csv_does_not_swallow_hydra_overrides():
380380
["--visualizer", "kit,newton,rerun", "presets=newton_mjwarp", "env.episode_length=10"]
381381
)
382382

383-
assert args.visualizer == ["kit", "newton", "rerun"]
383+
assert args.visualizer == ["kit", "newton_gl", "rerun"]
384384
assert hydra_args == ["presets=newton_mjwarp", "env.episode_length=10"]
385385

386386

@@ -403,7 +403,7 @@ def test_matrix_cli_kit_newton_with_custom_kit_cfg_intent_non_headless(monkeypat
403403
},
404404
)
405405
assert headless is False
406-
assert launcher._cli_visualizer_types == ["kit", "newton"]
406+
assert launcher._cli_visualizer_types == ["kit", "newton_gl"]
407407

408408

409409
def test_matrix_cli_rerun_with_custom_kit_cfg_intent_headless(monkeypatch: pytest.MonkeyPatch):
@@ -483,8 +483,8 @@ def test_matrix_headless_with_viz_names_takes_precedence(monkeypatch: pytest.Mon
483483
},
484484
)
485485
assert headless is True
486-
assert launcher._cli_visualizer_disable_all is True
487-
assert launcher._cli_visualizer_types == []
486+
assert launcher._cli_visualizer_disable_all is False
487+
assert launcher._cli_visualizer_types == ["kit", "newton_gl"]
488488

489489

490490
def test_no_cli_and_no_cfg_visualizers_defaults_headless(monkeypatch: pytest.MonkeyPatch):
@@ -581,3 +581,38 @@ def test_has_gui_reads_published_setting():
581581
assert AppLauncher.has_gui() is False
582582
finally:
583583
settings.set_bool("/isaaclab/has_gui", bool(original))
584+
585+
586+
def test_visualizer_argparse_set_defaults_is_not_explicit():
587+
parser = argparse.ArgumentParser(add_help=False)
588+
app_launcher_module.AppLauncher.add_app_launcher_args(parser)
589+
parser.set_defaults(visualizer=["kit"])
590+
591+
args, _ = parser.parse_known_args([])
592+
launcher = AppLauncher.__new__(AppLauncher)
593+
launcher._resolve_visualizer_settings(vars(args))
594+
595+
assert launcher._cli_visualizer_explicit is False
596+
assert launcher._cfg_has_any_visualizers is True
597+
assert launcher._cfg_has_kit_visualizer is True
598+
599+
600+
def test_visualizer_direct_kwargs_is_explicit():
601+
launcher = AppLauncher.__new__(AppLauncher)
602+
launcher._resolve_visualizer_settings({"visualizer": ["kit"]})
603+
604+
assert launcher._cli_visualizer_explicit is True
605+
606+
607+
def test_matrix_headless_env_with_kit_visualizer(monkeypatch: pytest.MonkeyPatch):
608+
monkeypatch.setenv("HEADLESS", "1")
609+
launcher = AppLauncher.__new__(AppLauncher)
610+
launcher._livestream = 0
611+
launcher._resolve_visualizer_settings({"visualizer": ["kit"], "visualizer_explicit": True})
612+
launcher._resolve_headless_settings(
613+
{"visualizer": ["kit"], "visualizer_explicit": True}, livestream_arg=-1, livestream_env=0
614+
)
615+
616+
assert launcher._headless is True
617+
# Kit visualizer shouldn't be disabled just because of HEADLESS=1
618+
assert launcher._cli_visualizer_disable_all is False

0 commit comments

Comments
 (0)