2323
2424from compass .utils .nurec_utils import PARTICLE_SPG_RUNTIME_USD_FILE
2525from compass .utils .renderer_utils import (
26- apply_isaac_rtx_camera_renderer_settings ,
27- apply_nurec_spg_kit_args ,
26+ apply_camera_renderer_settings ,
27+ configure_renderer_runtime ,
2828 configure_nurec_isaacsim_rtx_viewport ,
2929)
3030from compass .utils .visualizer_utils import (
3535
3636# add argparse arguments
3737parser = argparse .ArgumentParser (description = "COMPASS Mobility Generalist." )
38+ parser .add_argument (
39+ "--camera-renderer" ,
40+ choices = ["isaac_rtx" , "ovrtx" ],
41+ default = "isaac_rtx" ,
42+ help = "Camera renderer. OVRTX runs without Kit; select physics with --physics-backend." ,
43+ )
44+ parser .add_argument (
45+ "--physics-backend" ,
46+ choices = ["physx" , "newton" , "ovphysx" ],
47+ default = None ,
48+ help = "Physics backend. Defaults to physx for Isaac RTX or newton (MJWarp) for OVRTX. "
49+ "Standalone ovphysx requires --camera-renderer ovrtx." ,
50+ )
3851parser .add_argument (
3952 "--config-files" ,
4053 "-c" ,
142155 "--spg-runtime" ,
143156 action = "store_true" ,
144157 default = False ,
145- help = "Force SPG runtime Kit args before Isaac Sim starts. "
158+ help = "Force SPG runtime renderer settings before simulation starts. "
146159 f"This is automatic for { PARTICLE_SPG_RUNTIME_USD_FILE } "
147160 "when --nurec-scene is set." ,
148161)
187200 args_cli .environment = args_cli .nurec_scene
188201elif args_cli .nurec_omap_file is not None :
189202 parser .error ("--nurec-omap-file requires --nurec-scene." )
190- apply_nurec_spg_kit_args (args_cli )
203+ try :
204+ configure_renderer_runtime (args_cli )
205+ except ValueError as exc :
206+ parser .error (str (exc ))
191207
192208if args_cli .video :
193209 # Load the FFmpeg-enabled wheel before Kit prepends its bundled OpenCV to sys.path.
198214 "--video requires FFmpeg-enabled OpenCV. Install requirements.txt and recreate "
199215 f"the Docker container after rebuilding the image. Loaded OpenCV: { cv2 .__file__ } " )
200216
201- # launch omniverse app
202- app_launcher = AppLauncher (args_cli , enable_cameras = True )
203- simulation_app = app_launcher .app
217+ # OVRTX must never construct AppLauncher, even for headless runs.
218+ app_launcher = None
219+ simulation_app = None
220+ if args_cli .camera_renderer == "isaac_rtx" :
221+ app_launcher = AppLauncher (args_cli , enable_cameras = True )
222+ simulation_app = app_launcher .app
223+ else :
224+ try :
225+ import ovrtx
226+ except ModuleNotFoundError as exc :
227+ raise ModuleNotFoundError (
228+ "OVRTX requires Isaac Lab's optional ovrtx dependencies. "
229+ "Install the ovrtx extra and run with the Kit-less Python environment." ) from exc
230+ ovrtx .register_schema_paths ()
231+ AppLauncher .sync_visualizer_cli_settings_to_carb ({
232+ ** vars (args_cli ),
233+ "visualizer_disable_all" :
234+ getattr (args_cli , "visualizer_explicit" , False ) and not args_cli .visualizer ,
235+ })
204236
205237import gin
206238import torch
@@ -302,14 +334,12 @@ def run(
302334 num_rerenders_on_reset = None ,
303335):
304336
305- # Multi-GPU distributed setup. With `--distributed`, AppLauncher (already invoked
306- # at module load) reads LOCAL_RANK / RANK / WORLD_SIZE from torchrun's env, sets
307- # physics/active GPU per rank, and limits CPU threads. We still need to call
308- # init_process_group ourselves before any cross-rank op (param broadcast in
309- # ResidualPPOTrainer.__init__, gradient all-reduce in PPO.update).
337+ # Kit-less runs read torchrun ranks directly because AppLauncher is skipped.
310338 if args_cli .distributed :
311- local_rank = app_launcher .local_rank
312- global_rank = app_launcher .global_rank
339+ local_rank = (app_launcher .local_rank if app_launcher is not None else int (
340+ os .environ .get ("LOCAL_RANK" , "0" )))
341+ global_rank = (app_launcher .global_rank if app_launcher is not None else int (
342+ os .environ .get ("RANK" , "0" )))
313343 # Pin PyTorch's current CUDA device to this rank's GPU BEFORE
314344 # init_process_group / any object-collective. NCCL's object
315345 # collectives (dist.all_gather_object in _save_episode_logs)
@@ -326,7 +356,8 @@ def run(
326356 else :
327357 local_rank = 0
328358 global_rank = 0
329- device = "cuda" if torch .cuda .is_available () else "cpu"
359+ device = (args_cli .device if args_cli .camera_renderer == "ovrtx" else
360+ "cuda" if torch .cuda .is_available () else "cpu" )
330361 is_rank_zero = True
331362
332363 # Setup logger. Only rank 0 writes TensorBoard / W&B / artifacts; other ranks get
@@ -398,21 +429,15 @@ def run(
398429
399430 requested_viz = requested_visualizers (args_cli )
400431 configure_visualizers (env_cfg , requested_viz )
401- apply_isaac_rtx_camera_renderer_settings (
402- env_cfg ,
403- isaac_rtx = True ,
404- spg_runtime = args_cli .spg_runtime ,
405- )
432+ apply_camera_renderer_settings (env_cfg , args_cli )
406433
407434 # Setup seed. Per-rank offset diversifies env initial conditions across GPUs so
408435 # rollouts collected by each rank explore different states (matches Isaac Lab's
409436 # rsl_rl reference pattern).
410437 env_cfg .seed = seed + global_rank
411438
412- # Pin PhysX + Isaac Sim's render device to this rank's GPU. Without this every
413- # rank's env_cfg.sim.device defaults to cuda:0 and all 8 sims pile onto a single
414- # GPU (caught with a Vulkan OOM during material loading on the first attempt).
415- if args_cli .distributed :
439+ # Keep physics and rendering on the policy device for Kit-less and distributed runs.
440+ if args_cli .distributed or args_cli .camera_renderer == "ovrtx" :
416441 env_cfg .sim .device = device
417442
418443 # Set collision distances and max resample trial from gin config
@@ -513,6 +538,7 @@ def run(
513538 logger .log_config (gin_config_to_dictionary (gin .config ._OPERATIVE_CONFIG ))
514539
515540 logger .close ()
541+ env .close ()
516542
517543
518544def main ():
@@ -540,6 +566,8 @@ def main():
540566
541567if __name__ == "__main__" :
542568 # Run the main function.
543- main ()
544- # Close the sim app.
545- simulation_app .close ()
569+ try :
570+ main ()
571+ finally :
572+ if simulation_app is not None :
573+ simulation_app .close ()
0 commit comments