diff --git a/scripts/benchmarks/benchmark_non_rl.py b/scripts/benchmarks/benchmark_non_rl.py index 295436e75f3..14cfa5af0d9 100644 --- a/scripts/benchmarks/benchmark_non_rl.py +++ b/scripts/benchmarks/benchmark_non_rl.py @@ -113,6 +113,7 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen # override configurations with non-hydra CLI arguments env_cfg.scene.num_envs = args_cli.num_envs if args_cli.num_envs is not None else env_cfg.scene.num_envs env_cfg.sim.device = args_cli.device if args_cli.device is not None else env_cfg.sim.device + env_cfg.seed = args_cli.seed if args_cli.seed is not None else env_cfg.sim.seed # process distributed world_size = 1 diff --git a/source/isaaclab/config/extension.toml b/source/isaaclab/config/extension.toml index 731d14c2941..346de847199 100644 --- a/source/isaaclab/config/extension.toml +++ b/source/isaaclab/config/extension.toml @@ -1,7 +1,7 @@ [package] # Note: Semantic Versioning is used: https://semver.org/ -version = "0.46.3" +version = "0.46.4" # Description title = "Isaac Lab framework for Robot Learning" diff --git a/source/isaaclab/docs/CHANGELOG.rst b/source/isaaclab/docs/CHANGELOG.rst index 1e1a61ed67e..fa251c8bb30 100644 --- a/source/isaaclab/docs/CHANGELOG.rst +++ b/source/isaaclab/docs/CHANGELOG.rst @@ -1,6 +1,16 @@ Changelog --------- +0.46.4 (2025-10-06) +~~~~~~~~~~~~~~~~~~~ + +Changed +^^^^^^^ + +* Fixed :attr:`~isaaclab.sim.simulation_context.SimulationContext.device` to return the device from the configuration. + Previously, it was returning the device from the simulation manager, which was causing a performance overhead. + + 0.46.3 (2025-09-17) ~~~~~~~~~~~~~~~~~~~ @@ -10,6 +20,7 @@ Added * Modified setter to support for viscous and dynamic joint friction coefficients in articulation based on IsaacSim 5.0. * Added randomization of viscous and dynamic joint friction coefficients in event term. + 0.46.2 (2025-09-13) ~~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab/isaaclab/sim/simulation_context.py b/source/isaaclab/isaaclab/sim/simulation_context.py index fbd7f0043e9..5f306ec2a2d 100644 --- a/source/isaaclab/isaaclab/sim/simulation_context.py +++ b/source/isaaclab/isaaclab/sim/simulation_context.py @@ -26,6 +26,7 @@ import omni.physx import omni.usd from isaacsim.core.api.simulation_context import SimulationContext as _SimulationContext +from isaacsim.core.simulation_manager import SimulationManager from isaacsim.core.utils.carb import get_carb_setting, set_carb_setting from isaacsim.core.utils.viewports import set_camera_view from isaacsim.core.version import get_version @@ -259,6 +260,19 @@ def __init__(self, cfg: SimulationCfg | None = None): " simulation step size if you run into physics issues." ) + # set simulation device + # note: Although Isaac Sim sets the physics device in the init function, + # it does a render call which gets the wrong device. + SimulationManager.set_physics_sim_device(self.cfg.device) + + # obtain the parsed device + # This device should be the same as "self.cfg.device". However, for cases, where users specify the device + # as "cuda" and not "cuda:X", then it fetches the current device from SimulationManager. + # Note: Since we fix the device from the configuration and don't expect users to change it at runtime, + # we can obtain the device once from the SimulationManager.get_physics_sim_device() function. + # This reduces the overhead of calling the function. + self._physics_device = SimulationManager.get_physics_sim_device() + # create a simulation context to control the simulator if float(".".join(self._isaacsim_version[2])) < 5: # stage arg is not supported before isaac sim 5.0 @@ -283,126 +297,19 @@ def __init__(self, cfg: SimulationCfg | None = None): stage=self._initial_stage, ) - def _apply_physics_settings(self): - """Sets various carb physics settings.""" - # enable hydra scene-graph instancing - # note: this allows rendering of instanceable assets on the GUI - set_carb_setting(self.carb_settings, "/persistent/omnihydra/useSceneGraphInstancing", True) - # change dispatcher to use the default dispatcher in PhysX SDK instead of carb tasking - # note: dispatcher handles how threads are launched for multi-threaded physics - set_carb_setting(self.carb_settings, "/physics/physxDispatcher", True) - # disable contact processing in omni.physx - # note: we disable it by default to avoid the overhead of contact processing when it isn't needed. - # The physics flag gets enabled when a contact sensor is created. - if hasattr(self.cfg, "disable_contact_processing"): - omni.log.warn( - "The `disable_contact_processing` attribute is deprecated and always set to True" - " to avoid unnecessary overhead. Contact processing is automatically enabled when" - " a contact sensor is created, so manual configuration is no longer required." - ) - # FIXME: From investigation, it seems this flag only affects CPU physics. For GPU physics, contacts - # are always processed. The issue is reported to the PhysX team by @mmittal. - set_carb_setting(self.carb_settings, "/physics/disableContactProcessing", True) - # disable custom geometry for cylinder and cone collision shapes to allow contact reporting for them - # reason: cylinders and cones aren't natively supported by PhysX so we need to use custom geometry flags - # reference: https://nvidia-omniverse.github.io/PhysX/physx/5.4.1/docs/Geometry.html?highlight=capsule#geometry - set_carb_setting(self.carb_settings, "/physics/collisionConeCustomGeometry", False) - set_carb_setting(self.carb_settings, "/physics/collisionCylinderCustomGeometry", False) - # hide the Simulation Settings window - set_carb_setting(self.carb_settings, "/physics/autoPopupSimulationOutputWindow", False) - - def _apply_render_settings_from_cfg(self): - """Sets rtx settings specified in the RenderCfg.""" - - # define mapping of user-friendly RenderCfg names to native carb names - rendering_setting_name_mapping = { - "enable_translucency": "/rtx/translucency/enabled", - "enable_reflections": "/rtx/reflections/enabled", - "enable_global_illumination": "/rtx/indirectDiffuse/enabled", - "enable_dlssg": "/rtx-transient/dlssg/enabled", - "enable_dl_denoiser": "/rtx-transient/dldenoiser/enabled", - "dlss_mode": "/rtx/post/dlss/execMode", - "enable_direct_lighting": "/rtx/directLighting/enabled", - "samples_per_pixel": "/rtx/directLighting/sampledLighting/samplesPerPixel", - "enable_shadows": "/rtx/shadows/enabled", - "enable_ambient_occlusion": "/rtx/ambientOcclusion/enabled", - } - - not_carb_settings = ["rendering_mode", "carb_settings", "antialiasing_mode"] - - # grab the rendering mode using the following priority: - # 1. command line argument --rendering_mode, if provided - # 2. rendering_mode from Render Config, if set - # 3. lastly, default to "balanced" mode, if neither is specified - rendering_mode = get_carb_setting(self.carb_settings, "/isaaclab/rendering/rendering_mode") - if not rendering_mode: - rendering_mode = self.cfg.render.rendering_mode - if not rendering_mode: - rendering_mode = "balanced" - - # set preset settings (same behavior as the CLI arg --rendering_mode) - if rendering_mode is not None: - # check if preset is supported - supported_rendering_modes = ["performance", "balanced", "quality"] - if rendering_mode not in supported_rendering_modes: - raise ValueError( - f"RenderCfg rendering mode '{rendering_mode}' not in supported modes {supported_rendering_modes}." - ) - - # grab isaac lab apps path - isaaclab_app_exp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), *[".."] * 4, "apps") - # for Isaac Sim 4.5 compatibility, we use the 4.5 rendering mode app files in a different folder - if float(".".join(self._isaacsim_version[2])) < 5: - isaaclab_app_exp_path = os.path.join(isaaclab_app_exp_path, "isaacsim_4_5") - - # grab preset settings - preset_filename = os.path.join(isaaclab_app_exp_path, f"rendering_modes/{rendering_mode}.kit") - with open(preset_filename) as file: - preset_dict = toml.load(file) - preset_dict = dict(flatdict.FlatDict(preset_dict, delimiter=".")) - - # set presets - for key, value in preset_dict.items(): - key = "/" + key.replace(".", "/") # convert to carb setting format - set_carb_setting(self.carb_settings, key, value) - - # set user-friendly named settings - for key, value in vars(self.cfg.render).items(): - if value is None or key in not_carb_settings: - # skip unset settings and non-carb settings - continue - if key not in rendering_setting_name_mapping: - raise ValueError( - f"'{key}' in RenderCfg not found. Note: internal 'rendering_setting_name_mapping' dictionary might" - " need to be updated." - ) - key = rendering_setting_name_mapping[key] - set_carb_setting(self.carb_settings, key, value) - - # set general carb settings - carb_settings = self.cfg.render.carb_settings - if carb_settings is not None: - for key, value in carb_settings.items(): - if "_" in key: - key = "/" + key.replace("_", "/") # convert from python variable style string - elif "." in key: - key = "/" + key.replace(".", "/") # convert from .kit file style string - if get_carb_setting(self.carb_settings, key) is None: - raise ValueError(f"'{key}' in RenderCfg.general_parameters does not map to a carb setting.") - set_carb_setting(self.carb_settings, key, value) + """ + Properties - Override. + """ - # set denoiser mode - if self.cfg.render.antialiasing_mode is not None: - try: - import omni.replicator.core as rep + @property + def device(self) -> str: + """Device used by the simulation. - rep.settings.set_render_rtx_realtime(antialiasing=self.cfg.render.antialiasing_mode) - except Exception: - pass - - # WAR: Ensure /rtx/renderMode RaytracedLighting is correctly cased. - if get_carb_setting(self.carb_settings, "/rtx/rendermode").lower() == "raytracedlighting": - set_carb_setting(self.carb_settings, "/rtx/rendermode", "RaytracedLighting") + Note: + In Omniverse, it is possible to configure multiple GPUs for rendering, while physics engine + operates on a single GPU. This function returns the device that is used for physics simulation. + """ + return self._physics_device """ Operations - New. @@ -742,6 +649,127 @@ def clear_instance(cls): Helper Functions """ + def _apply_physics_settings(self): + """Sets various carb physics settings.""" + # enable hydra scene-graph instancing + # note: this allows rendering of instanceable assets on the GUI + set_carb_setting(self.carb_settings, "/persistent/omnihydra/useSceneGraphInstancing", True) + # change dispatcher to use the default dispatcher in PhysX SDK instead of carb tasking + # note: dispatcher handles how threads are launched for multi-threaded physics + set_carb_setting(self.carb_settings, "/physics/physxDispatcher", True) + # disable contact processing in omni.physx + # note: we disable it by default to avoid the overhead of contact processing when it isn't needed. + # The physics flag gets enabled when a contact sensor is created. + if hasattr(self.cfg, "disable_contact_processing"): + omni.log.warn( + "The `disable_contact_processing` attribute is deprecated and always set to True" + " to avoid unnecessary overhead. Contact processing is automatically enabled when" + " a contact sensor is created, so manual configuration is no longer required." + ) + # FIXME: From investigation, it seems this flag only affects CPU physics. For GPU physics, contacts + # are always processed. The issue is reported to the PhysX team by @mmittal. + set_carb_setting(self.carb_settings, "/physics/disableContactProcessing", True) + # disable custom geometry for cylinder and cone collision shapes to allow contact reporting for them + # reason: cylinders and cones aren't natively supported by PhysX so we need to use custom geometry flags + # reference: https://nvidia-omniverse.github.io/PhysX/physx/5.4.1/docs/Geometry.html?highlight=capsule#geometry + set_carb_setting(self.carb_settings, "/physics/collisionConeCustomGeometry", False) + set_carb_setting(self.carb_settings, "/physics/collisionCylinderCustomGeometry", False) + # hide the Simulation Settings window + set_carb_setting(self.carb_settings, "/physics/autoPopupSimulationOutputWindow", False) + + def _apply_render_settings_from_cfg(self): + """Sets rtx settings specified in the RenderCfg.""" + + # define mapping of user-friendly RenderCfg names to native carb names + rendering_setting_name_mapping = { + "enable_translucency": "/rtx/translucency/enabled", + "enable_reflections": "/rtx/reflections/enabled", + "enable_global_illumination": "/rtx/indirectDiffuse/enabled", + "enable_dlssg": "/rtx-transient/dlssg/enabled", + "enable_dl_denoiser": "/rtx-transient/dldenoiser/enabled", + "dlss_mode": "/rtx/post/dlss/execMode", + "enable_direct_lighting": "/rtx/directLighting/enabled", + "samples_per_pixel": "/rtx/directLighting/sampledLighting/samplesPerPixel", + "enable_shadows": "/rtx/shadows/enabled", + "enable_ambient_occlusion": "/rtx/ambientOcclusion/enabled", + } + + not_carb_settings = ["rendering_mode", "carb_settings", "antialiasing_mode"] + + # grab the rendering mode using the following priority: + # 1. command line argument --rendering_mode, if provided + # 2. rendering_mode from Render Config, if set + # 3. lastly, default to "balanced" mode, if neither is specified + rendering_mode = get_carb_setting(self.carb_settings, "/isaaclab/rendering/rendering_mode") + if not rendering_mode: + rendering_mode = self.cfg.render.rendering_mode + if not rendering_mode: + rendering_mode = "balanced" + + # set preset settings (same behavior as the CLI arg --rendering_mode) + if rendering_mode is not None: + # check if preset is supported + supported_rendering_modes = ["performance", "balanced", "quality"] + if rendering_mode not in supported_rendering_modes: + raise ValueError( + f"RenderCfg rendering mode '{rendering_mode}' not in supported modes {supported_rendering_modes}." + ) + + # grab isaac lab apps path + isaaclab_app_exp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), *[".."] * 4, "apps") + # for Isaac Sim 4.5 compatibility, we use the 4.5 rendering mode app files in a different folder + if float(".".join(self._isaacsim_version[2])) < 5: + isaaclab_app_exp_path = os.path.join(isaaclab_app_exp_path, "isaacsim_4_5") + + # grab preset settings + preset_filename = os.path.join(isaaclab_app_exp_path, f"rendering_modes/{rendering_mode}.kit") + with open(preset_filename) as file: + preset_dict = toml.load(file) + preset_dict = dict(flatdict.FlatDict(preset_dict, delimiter=".")) + + # set presets + for key, value in preset_dict.items(): + key = "/" + key.replace(".", "/") # convert to carb setting format + set_carb_setting(self.carb_settings, key, value) + + # set user-friendly named settings + for key, value in vars(self.cfg.render).items(): + if value is None or key in not_carb_settings: + # skip unset settings and non-carb settings + continue + if key not in rendering_setting_name_mapping: + raise ValueError( + f"'{key}' in RenderCfg not found. Note: internal 'rendering_setting_name_mapping' dictionary might" + " need to be updated." + ) + key = rendering_setting_name_mapping[key] + set_carb_setting(self.carb_settings, key, value) + + # set general carb settings + carb_settings = self.cfg.render.carb_settings + if carb_settings is not None: + for key, value in carb_settings.items(): + if "_" in key: + key = "/" + key.replace("_", "/") # convert from python variable style string + elif "." in key: + key = "/" + key.replace(".", "/") # convert from .kit file style string + if get_carb_setting(self.carb_settings, key) is None: + raise ValueError(f"'{key}' in RenderCfg.general_parameters does not map to a carb setting.") + set_carb_setting(self.carb_settings, key, value) + + # set denoiser mode + if self.cfg.render.antialiasing_mode is not None: + try: + import omni.replicator.core as rep + + rep.settings.set_render_rtx_realtime(antialiasing=self.cfg.render.antialiasing_mode) + except Exception: + pass + + # WAR: Ensure /rtx/renderMode RaytracedLighting is correctly cased. + if get_carb_setting(self.carb_settings, "/rtx/rendermode").lower() == "raytracedlighting": + set_carb_setting(self.carb_settings, "/rtx/rendermode", "RaytracedLighting") + def _set_additional_physx_params(self): """Sets additional PhysX parameters that are not directly supported by the parent class.""" # obtain the physics scene api