Commit 33bcf660 authored by matthewtrepte's avatar matthewtrepte Committed by Kelly Guo

Adds support for Stage in Memory (#375)

<!--
Thank you for your interest in sending a pull request. Please make sure
to check the contribution guidelines.

Link:
https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html
-->

Support using a stage in memory, rather the default stage attached to a
usd context, for faster operations during stage initialization and
cloning.

The feature requires a change on Isaac Sim which is tracked separately.

<!-- As a practice, it is recommended to open an issue to have
discussions on the proposed pull request.
This makes it easier for the community to keep track of what is being
developed or added, and if a given feature
is demanded by more than one party. -->

<!-- As you go through the list, delete the ones that are not
applicable. -->

- New feature (non-breaking change which adds functionality)

<!--
Example:

| Before | After |
| ------ | ----- |
| _gif/png before_ | _gif/png after_ |

To upload images to a PR -- simply drag and drop an image while in edit
mode and it should upload the image directly. You can then paste that
source into the above before/after sections.
-->

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [x] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

<!--
As you go through the checklist above, you can mark something as done by
putting an x character in it

For example,
- [x] I have done this task
- [ ] I have not done this task
-->

---------
Signed-off-by: 's avatarKelly Guo <kellyguo123@hotmail.com>
Signed-off-by: 's avatarrwiltz <165190220+rwiltz@users.noreply.github.com>
Signed-off-by: 's avatarAshwin Varghese Kuruttukulam <123109010+ashwinvkNV@users.noreply.github.com>
Signed-off-by: 's avatarKelly Guo <kellyg@nvidia.com>
Signed-off-by: 's avatarMichael Gussert <michael@gussert.com>
Co-authored-by: 's avatarpeterd-NV <peterd@nvidia.com>
Co-authored-by: 's avatarKelly Guo <kellyg@nvidia.com>
Co-authored-by: 's avatarcosmith-nvidia <141183495+cosmith-nvidia@users.noreply.github.com>
Co-authored-by: 's avatarjaczhangnv <jaczhang@nvidia.com>
Co-authored-by: 's avatarrwiltz <165190220+rwiltz@users.noreply.github.com>
Co-authored-by: 's avatarYanzi Zhu <yanziz@nvidia.com>
Co-authored-by: 's avatarnv-mhaselton <mhaselton@nvidia.com>
Co-authored-by: 's avatarCY Chen <cyc@nvidia.com>
Co-authored-by: 's avataroahmednv <oahmed@Nvidia.com>
Co-authored-by: 's avatarAshwin Varghese Kuruttukulam <123109010+ashwinvkNV@users.noreply.github.com>
Co-authored-by: 's avatarRafael Wiltz <rwiltz@nvidia.com>
Co-authored-by: 's avatarMichael Gussert <michael@gussert.com>
Co-authored-by: 's avatarKelly Guo <kellyguo123@hotmail.com>
Co-authored-by: 's avatarchengronglai <chengrongl@nvidia.com>
Co-authored-by: 's avatarpulkitg01 <pulkitg@nvidia.com>
Co-authored-by: 's avatarConnor Smith <cosmith@nvidia.com>
Co-authored-by: 's avatarAshwin Varghese Kuruttukulam <ashwinvk@nvidia.com>
Co-authored-by: 's avatarlotusl-code <lotusl@nvidia.com>
parent fd805c27
...@@ -45,6 +45,7 @@ import torch ...@@ -45,6 +45,7 @@ import torch
import carb import carb
import omni import omni
from isaacsim.core.utils.stage import get_current_stage
from omni.kit.viewport.utility import get_viewport_from_window_name from omni.kit.viewport.utility import get_viewport_from_window_name
from omni.kit.viewport.utility.camera_state import ViewportCameraState from omni.kit.viewport.utility.camera_state import ViewportCameraState
from pxr import Gf, Sdf from pxr import Gf, Sdf
...@@ -110,7 +111,7 @@ class H1RoughDemo: ...@@ -110,7 +111,7 @@ class H1RoughDemo:
def create_camera(self): def create_camera(self):
"""Creates a camera to be used for third-person view.""" """Creates a camera to be used for third-person view."""
stage = omni.usd.get_context().get_stage() stage = get_current_stage()
self.viewport = get_viewport_from_window_name("Viewport") self.viewport = get_viewport_from_window_name("Viewport")
# Create camera # Create camera
self.camera_path = "/World/Camera" self.camera_path = "/World/Camera"
......
...@@ -19,6 +19,8 @@ from __future__ import annotations ...@@ -19,6 +19,8 @@ from __future__ import annotations
import argparse import argparse
from isaacsim.core.utils.stage import get_current_stage
from isaaclab.app import AppLauncher from isaaclab.app import AppLauncher
# add argparse arguments # add argparse arguments
...@@ -37,7 +39,6 @@ simulation_app = app_launcher.app ...@@ -37,7 +39,6 @@ simulation_app = app_launcher.app
import random import random
import omni.usd
from pxr import Gf, Sdf from pxr import Gf, Sdf
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -69,8 +70,8 @@ from isaaclab_assets.robots.anymal import ANYDRIVE_3_LSTM_ACTUATOR_CFG # isort: ...@@ -69,8 +70,8 @@ from isaaclab_assets.robots.anymal import ANYDRIVE_3_LSTM_ACTUATOR_CFG # isort:
def randomize_shape_color(prim_path_expr: str): def randomize_shape_color(prim_path_expr: str):
"""Randomize the color of the geometry.""" """Randomize the color of the geometry."""
# acquire stage # get stage handle
stage = omni.usd.get_context().get_stage() stage = get_current_stage()
# resolve prim paths for spawning and cloning # resolve prim paths for spawning and cloning
prim_paths = sim_utils.find_matching_prim_paths(prim_path_expr) prim_paths = sim_utils.find_matching_prim_paths(prim_path_expr)
# manually clone prims if the source prim path is a regex expression # manually clone prims if the source prim path is a regex expression
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The Isaac Lab Project Developers. # Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
...@@ -68,6 +68,7 @@ import isaacsim.core.utils.prims as prim_utils ...@@ -68,6 +68,7 @@ import isaacsim.core.utils.prims as prim_utils
from isaacsim.core.api.simulation_context import SimulationContext from isaacsim.core.api.simulation_context import SimulationContext
from isaacsim.core.cloner import GridCloner from isaacsim.core.cloner import GridCloner
from isaacsim.core.utils.carb import set_carb_setting from isaacsim.core.utils.carb import set_carb_setting
from isaacsim.core.utils.stage import get_current_stage
from isaaclab.utils import Timer from isaaclab.utils import Timer
from isaaclab.utils.assets import check_file_path from isaaclab.utils.assets import check_file_path
...@@ -82,6 +83,10 @@ def main(): ...@@ -82,6 +83,10 @@ def main():
sim = SimulationContext( sim = SimulationContext(
stage_units_in_meters=1.0, physics_dt=0.01, rendering_dt=0.01, backend="torch", device="cuda:0" stage_units_in_meters=1.0, physics_dt=0.01, rendering_dt=0.01, backend="torch", device="cuda:0"
) )
# get stage handle
stage = get_current_stage()
# enable fabric which avoids passing data over to USD structure # enable fabric which avoids passing data over to USD structure
# this speeds up the read-write operation of GPU buffers # this speeds up the read-write operation of GPU buffers
if sim.get_physics_context().use_gpu_pipeline: if sim.get_physics_context().use_gpu_pipeline:
...@@ -94,7 +99,7 @@ def main(): ...@@ -94,7 +99,7 @@ def main():
set_carb_setting(sim._settings, "/persistent/omnihydra/useSceneGraphInstancing", True) set_carb_setting(sim._settings, "/persistent/omnihydra/useSceneGraphInstancing", True)
# Create interface to clone the scene # Create interface to clone the scene
cloner = GridCloner(spacing=args_cli.spacing) cloner = GridCloner(spacing=args_cli.spacing, stage=stage)
cloner.define_base_env("/World/envs") cloner.define_base_env("/World/envs")
prim_utils.define_prim("/World/envs/env_0") prim_utils.define_prim("/World/envs/env_0")
# Spawn things into stage # Spawn things into stage
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers. # Copyright (c) 2024-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers. # Copyright (c) 2024-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers. # Copyright (c) 2024-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers. # Copyright (c) 2024-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers. # Copyright (c) 2024-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers. # Copyright (c) 2024-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
...@@ -24,11 +24,14 @@ simulation_app = app_launcher.app ...@@ -24,11 +24,14 @@ simulation_app = app_launcher.app
import numpy as np import numpy as np
import torch import torch
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.actuators import ImplicitActuatorCfg from isaaclab.actuators import ImplicitActuatorCfg
from isaaclab.assets import AssetBaseCfg from isaaclab.assets import AssetBaseCfg
from isaaclab.assets.articulation import ArticulationCfg from isaaclab.assets.articulation import ArticulationCfg
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
JETBOT_CONFIG = ArticulationCfg( JETBOT_CONFIG = ArticulationCfg(
...@@ -160,13 +163,16 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene): ...@@ -160,13 +163,16 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
def main(): def main():
"""Main function.""" """Main function."""
# Initialize the simulation context # Initialize the simulation context
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg) sim = sim_utils.SimulationContext(sim_cfg)
sim.set_camera_view([3.5, 0.0, 3.2], [0.0, 0.0, 0.5]) sim.set_camera_view([3.5, 0.0, 3.2], [0.0, 0.0, 0.5])
# design scene # Design scene
scene_cfg = NewRobotsSceneCfg(args_cli.num_envs, env_spacing=2.0) scene_cfg = NewRobotsSceneCfg(args_cli.num_envs, env_spacing=2.0)
# Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene = InteractiveScene(scene_cfg) scene = InteractiveScene(scene_cfg)
attach_stage_to_usd_context()
# Play the simulator # Play the simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -35,10 +35,12 @@ simulation_app = app_launcher.app ...@@ -35,10 +35,12 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import Articulation from isaaclab.assets import Articulation
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
## ##
# Pre-defined configs # Pre-defined configs
...@@ -121,12 +123,14 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Articula ...@@ -121,12 +123,14 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Articula
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = SimulationContext(sim_cfg) sim = SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0]) sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0])
# Design scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities, scene_origins = design_scene() scene_entities, scene_origins = design_scene()
attach_stage_to_usd_context()
scene_origins = torch.tensor(scene_origins, device=sim.device) scene_origins = torch.tensor(scene_origins, device=sim.device)
# Play the simulator # Play the simulator
sim.reset() sim.reset()
......
...@@ -36,11 +36,13 @@ simulation_app = app_launcher.app ...@@ -36,11 +36,13 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
import isaaclab.utils.math as math_utils import isaaclab.utils.math as math_utils
from isaaclab.assets import DeformableObject, DeformableObjectCfg from isaaclab.assets import DeformableObject, DeformableObjectCfg
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
def design_scene(): def design_scene():
...@@ -146,12 +148,14 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Deformab ...@@ -146,12 +148,14 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Deformab
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = SimulationContext(sim_cfg) sim = SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view(eye=[3.0, 0.0, 1.0], target=[0.0, 0.0, 0.5]) sim.set_camera_view(eye=[3.0, 0.0, 1.0], target=[0.0, 0.0, 0.5])
# Design scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities, scene_origins = design_scene() scene_entities, scene_origins = design_scene()
attach_stage_to_usd_context()
scene_origins = torch.tensor(scene_origins, device=sim.device) scene_origins = torch.tensor(scene_origins, device=sim.device)
# Play the simulator # Play the simulator
sim.reset() sim.reset()
......
...@@ -36,11 +36,13 @@ simulation_app = app_launcher.app ...@@ -36,11 +36,13 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
import isaaclab.utils.math as math_utils import isaaclab.utils.math as math_utils
from isaaclab.assets import RigidObject, RigidObjectCfg from isaaclab.assets import RigidObject, RigidObjectCfg
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
def design_scene(): def design_scene():
...@@ -126,12 +128,14 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, RigidObj ...@@ -126,12 +128,14 @@ def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, RigidObj
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = SimulationContext(sim_cfg) sim = SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view(eye=[1.5, 0.0, 1.0], target=[0.0, 0.0, 0.0]) sim.set_camera_view(eye=[1.5, 0.0, 1.0], target=[0.0, 0.0, 0.0])
# Design scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities, scene_origins = design_scene() scene_entities, scene_origins = design_scene()
attach_stage_to_usd_context()
scene_origins = torch.tensor(scene_origins, device=sim.device) scene_origins = torch.tensor(scene_origins, device=sim.device)
# Play the simulator # Play the simulator
sim.reset() sim.reset()
......
...@@ -35,10 +35,13 @@ simulation_app = app_launcher.app ...@@ -35,10 +35,13 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import ArticulationCfg, AssetBaseCfg from isaaclab.assets import ArticulationCfg, AssetBaseCfg
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils import configclass from isaaclab.utils import configclass
## ##
...@@ -110,13 +113,16 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene): ...@@ -110,13 +113,16 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = SimulationContext(sim_cfg) sim = SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0]) sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.0])
# Design scene # Design scene
scene_cfg = CartpoleSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0) scene_cfg = CartpoleSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
# Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene = InteractiveScene(scene_cfg) scene = InteractiveScene(scene_cfg)
attach_stage_to_usd_context()
# Play the simulator # Play the simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -141,6 +141,7 @@ def main(): ...@@ -141,6 +141,7 @@ def main():
env_cfg = CartpoleEnvCfg() env_cfg = CartpoleEnvCfg()
env_cfg.scene.num_envs = args_cli.num_envs env_cfg.scene.num_envs = args_cli.num_envs
env_cfg.sim.device = args_cli.device env_cfg.sim.device = args_cli.device
env_cfg.sim.create_stage_in_memory = True
# setup base environment # setup base environment
env = ManagerBasedEnv(cfg=env_cfg) env = ManagerBasedEnv(cfg=env_cfg)
......
...@@ -314,7 +314,9 @@ def main(): ...@@ -314,7 +314,9 @@ def main():
"""Main function.""" """Main function."""
# setup base environment # setup base environment
env = ManagerBasedEnv(cfg=CubeEnvCfg()) env_cfg = CubeEnvCfg()
env_cfg.sim.create_stage_in_memory = True
env = ManagerBasedEnv(cfg=env_cfg)
# setup target position commands # setup target position commands
target_position = torch.rand(env.num_envs, 3, device=env.device) * 2 target_position = torch.rand(env.num_envs, 3, device=env.device) * 2
......
...@@ -205,6 +205,7 @@ def main(): ...@@ -205,6 +205,7 @@ def main():
"""Main function.""" """Main function."""
# setup base environment # setup base environment
env_cfg = QuadrupedEnvCfg() env_cfg = QuadrupedEnvCfg()
env_cfg.sim.create_stage_in_memory = True
env = ManagerBasedEnv(cfg=env_cfg) env = ManagerBasedEnv(cfg=env_cfg)
# load level policy # load level policy
......
...@@ -70,6 +70,7 @@ def main(): ...@@ -70,6 +70,7 @@ def main():
env_cfg.sim.device = args_cli.device env_cfg.sim.device = args_cli.device
if args_cli.device == "cpu": if args_cli.device == "cpu":
env_cfg.sim.use_fabric = False env_cfg.sim.use_fabric = False
env_cfg.sim.create_stage_in_memory = True
# create environment # create environment
env = ManagerBasedRLEnv(cfg=env_cfg) env = ManagerBasedRLEnv(cfg=env_cfg)
......
...@@ -46,6 +46,7 @@ def main(): ...@@ -46,6 +46,7 @@ def main():
env_cfg = CartpoleEnvCfg() env_cfg = CartpoleEnvCfg()
env_cfg.scene.num_envs = args_cli.num_envs env_cfg.scene.num_envs = args_cli.num_envs
env_cfg.sim.device = args_cli.device env_cfg.sim.device = args_cli.device
env_cfg.sim.create_stage_in_memory = True
# setup RL environment # setup RL environment
env = ManagerBasedRLEnv(cfg=env_cfg) env = ManagerBasedRLEnv(cfg=env_cfg)
......
...@@ -41,10 +41,13 @@ simulation_app = app_launcher.app ...@@ -41,10 +41,13 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import ArticulationCfg, AssetBaseCfg from isaaclab.assets import ArticulationCfg, AssetBaseCfg
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sensors import CameraCfg, ContactSensorCfg, RayCasterCfg, patterns from isaaclab.sensors import CameraCfg, ContactSensorCfg, RayCasterCfg, patterns
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils import configclass from isaaclab.utils import configclass
## ##
...@@ -157,13 +160,16 @@ def main(): ...@@ -157,13 +160,16 @@ def main():
"""Main function.""" """Main function."""
# Initialize the simulation context # Initialize the simulation context
sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device, create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg) sim = sim_utils.SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view(eye=[3.5, 3.5, 3.5], target=[0.0, 0.0, 0.0]) sim.set_camera_view(eye=[3.5, 3.5, 3.5], target=[0.0, 0.0, 0.0])
# design scene # Design scene
scene_cfg = SensorsSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0) scene_cfg = SensorsSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
# Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene = InteractiveScene(scene_cfg) scene = InteractiveScene(scene_cfg)
attach_stage_to_usd_context()
# Play the simulator # Play the simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -35,6 +35,7 @@ simulation_app = app_launcher.app ...@@ -35,6 +35,7 @@ simulation_app = app_launcher.app
import math import math
import torch import torch
import isaacsim.core.utils.stage as stage_utils
import isaacsim.util.debug_draw._debug_draw as omni_debug_draw import isaacsim.util.debug_draw._debug_draw as omni_debug_draw
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -44,6 +45,7 @@ from isaaclab.markers import VisualizationMarkers ...@@ -44,6 +45,7 @@ from isaaclab.markers import VisualizationMarkers
from isaaclab.markers.config import FRAME_MARKER_CFG from isaaclab.markers.config import FRAME_MARKER_CFG
from isaaclab.sensors import FrameTransformer, FrameTransformerCfg, OffsetCfg from isaaclab.sensors import FrameTransformer, FrameTransformerCfg, OffsetCfg
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
## ##
# Pre-defined configs # Pre-defined configs
...@@ -164,12 +166,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict): ...@@ -164,12 +166,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict):
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device, create_stage_in_memory=True)
sim = SimulationContext(sim_cfg) sim = SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view(eye=[2.5, 2.5, 2.5], target=[0.0, 0.0, 0.0]) sim.set_camera_view(eye=[2.5, 2.5, 2.5], target=[0.0, 0.0, 0.0])
# Design the scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities = design_scene() scene_entities = design_scene()
attach_stage_to_usd_context()
# Play the simulator # Play the simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -34,10 +34,12 @@ simulation_app = app_launcher.app ...@@ -34,10 +34,12 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import RigidObject, RigidObjectCfg from isaaclab.assets import RigidObject, RigidObjectCfg
from isaaclab.sensors.ray_caster import RayCaster, RayCasterCfg, patterns from isaaclab.sensors.ray_caster import RayCaster, RayCasterCfg, patterns
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
from isaaclab.utils.timer import Timer from isaaclab.utils.timer import Timer
...@@ -130,12 +132,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict): ...@@ -130,12 +132,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict):
def main(): def main():
"""Main function.""" """Main function."""
# Load simulation context # Load simulation context
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg) sim = sim_utils.SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([0.0, 15.0, 15.0], [0.0, 0.0, -2.5]) sim.set_camera_view([0.0, 15.0, 15.0], [0.0, 0.0, -2.5])
# Design the scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities = design_scene() scene_entities = design_scene()
attach_stage_to_usd_context()
# Play simulator # Play simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -39,10 +39,12 @@ import os ...@@ -39,10 +39,12 @@ import os
import torch import torch
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import omni.replicator.core as rep import omni.replicator.core as rep
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.sensors.ray_caster import RayCasterCamera, RayCasterCameraCfg, patterns from isaaclab.sensors.ray_caster import RayCasterCamera, RayCasterCameraCfg, patterns
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils import convert_dict_to_backend from isaaclab.utils import convert_dict_to_backend
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
from isaaclab.utils.math import project_points, unproject_depth from isaaclab.utils.math import project_points, unproject_depth
...@@ -163,11 +165,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict): ...@@ -163,11 +165,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict):
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim = sim_utils.SimulationContext() sim_cfg = sim_utils.SimulationCfg(create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([2.5, 2.5, 3.5], [0.0, 0.0, 0.0]) sim.set_camera_view([2.5, 2.5, 3.5], [0.0, 0.0, 0.0])
# design the scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities = design_scene() scene_entities = design_scene()
attach_stage_to_usd_context()
# Play simulator # Play simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -66,6 +66,7 @@ import random ...@@ -66,6 +66,7 @@ import random
import torch import torch
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import omni.replicator.core as rep import omni.replicator.core as rep
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -74,6 +75,7 @@ from isaaclab.markers import VisualizationMarkers ...@@ -74,6 +75,7 @@ from isaaclab.markers import VisualizationMarkers
from isaaclab.markers.config import RAY_CASTER_MARKER_CFG from isaaclab.markers.config import RAY_CASTER_MARKER_CFG
from isaaclab.sensors.camera import Camera, CameraCfg from isaaclab.sensors.camera import Camera, CameraCfg
from isaaclab.sensors.camera.utils import create_pointcloud_from_depth from isaaclab.sensors.camera.utils import create_pointcloud_from_depth
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils import convert_dict_to_backend from isaaclab.utils import convert_dict_to_backend
...@@ -268,12 +270,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict): ...@@ -268,12 +270,14 @@ def run_simulator(sim: sim_utils.SimulationContext, scene_entities: dict):
def main(): def main():
"""Main function.""" """Main function."""
# Load simulation context # Load simulation context
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(device=args_cli.device, create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg) sim = sim_utils.SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0]) sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
# design the scene # Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene_entities = design_scene() scene_entities = design_scene()
attach_stage_to_usd_context()
# Play simulator # Play simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -39,6 +39,8 @@ simulation_app = app_launcher.app ...@@ -39,6 +39,8 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import AssetBaseCfg from isaaclab.assets import AssetBaseCfg
from isaaclab.controllers import DifferentialIKController, DifferentialIKControllerCfg from isaaclab.controllers import DifferentialIKController, DifferentialIKControllerCfg
...@@ -46,6 +48,7 @@ from isaaclab.managers import SceneEntityCfg ...@@ -46,6 +48,7 @@ from isaaclab.managers import SceneEntityCfg
from isaaclab.markers import VisualizationMarkers from isaaclab.markers import VisualizationMarkers
from isaaclab.markers.config import FRAME_MARKER_CFG from isaaclab.markers.config import FRAME_MARKER_CFG
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils import configclass from isaaclab.utils import configclass
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
from isaaclab.utils.math import subtract_frame_transforms from isaaclab.utils.math import subtract_frame_transforms
...@@ -190,13 +193,16 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene): ...@@ -190,13 +193,16 @@ def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene):
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg) sim = sim_utils.SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0]) sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
# Design scene # Design scene
scene_cfg = TableTopSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0) scene_cfg = TableTopSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
# Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene = InteractiveScene(scene_cfg) scene = InteractiveScene(scene_cfg)
attach_stage_to_usd_context()
# Play the simulator # Play the simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
...@@ -38,6 +38,8 @@ simulation_app = app_launcher.app ...@@ -38,6 +38,8 @@ simulation_app = app_launcher.app
import torch import torch
import isaacsim.core.utils.stage as stage_utils
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import Articulation, AssetBaseCfg from isaaclab.assets import Articulation, AssetBaseCfg
from isaaclab.controllers import OperationalSpaceController, OperationalSpaceControllerCfg from isaaclab.controllers import OperationalSpaceController, OperationalSpaceControllerCfg
...@@ -45,6 +47,7 @@ from isaaclab.markers import VisualizationMarkers ...@@ -45,6 +47,7 @@ from isaaclab.markers import VisualizationMarkers
from isaaclab.markers.config import FRAME_MARKER_CFG from isaaclab.markers.config import FRAME_MARKER_CFG
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
from isaaclab.sensors import ContactSensorCfg from isaaclab.sensors import ContactSensorCfg
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils import configclass from isaaclab.utils import configclass
from isaaclab.utils.math import ( from isaaclab.utils.math import (
combine_frame_transforms, combine_frame_transforms,
...@@ -462,13 +465,16 @@ def convert_to_task_frame(osc: OperationalSpaceController, command: torch.tensor ...@@ -462,13 +465,16 @@ def convert_to_task_frame(osc: OperationalSpaceController, command: torch.tensor
def main(): def main():
"""Main function.""" """Main function."""
# Load kit helper # Load kit helper
sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device) sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device, create_stage_in_memory=True)
sim = sim_utils.SimulationContext(sim_cfg) sim = sim_utils.SimulationContext(sim_cfg)
# Set main camera # Set main camera
sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0]) sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
# Design scene # Design scene
scene_cfg = SceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0) scene_cfg = SceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
# Create scene with stage in memory and then attach to USD context
with stage_utils.use_stage(sim.get_initial_stage()):
scene = InteractiveScene(scene_cfg) scene = InteractiveScene(scene_cfg)
attach_stage_to_usd_context()
# Play the simulator # Play the simulator
sim.reset() sim.reset()
# Now we are ready! # Now we are ready!
......
[package] [package]
# Note: Semantic Versioning is used: https://semver.org/ # Note: Semantic Versioning is used: https://semver.org/
version = "0.41.21" version = "0.42.21"
# Description # Description
title = "Isaac Lab framework for Robot Learning" title = "Isaac Lab framework for Robot Learning"
......
Changelog Changelog
--------- ---------
0.41.21 (2025-06-25) 0.42.21 (2025-06-25)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -12,7 +12,7 @@ Added ...@@ -12,7 +12,7 @@ Added
env instance env instance
0.41.20 (2025-07-11) 0.42.20 (2025-07-11)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -22,7 +22,7 @@ Fixed ...@@ -22,7 +22,7 @@ Fixed
restricting the resetting joint indices be that user defined joint indices. restricting the resetting joint indices be that user defined joint indices.
0.41.19 (2025-07-11) 0.42.19 (2025-07-11)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -32,7 +32,7 @@ Fixed ...@@ -32,7 +32,7 @@ Fixed
env_ids are passed. env_ids are passed.
0.41.18 (2025-07-09) 0.42.18 (2025-07-09)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -49,7 +49,7 @@ Fixed ...@@ -49,7 +49,7 @@ Fixed
buffer on recording. buffer on recording.
0.41.17 (2025-07-10) 0.42.17 (2025-07-10)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -80,7 +80,7 @@ Changed ...@@ -80,7 +80,7 @@ Changed
* Changed the implementation of :func:`~isaaclab.utils.math.copysign` to better reflect the documented functionality. * Changed the implementation of :func:`~isaaclab.utils.math.copysign` to better reflect the documented functionality.
0.41.16 (2025-07-08) 0.42.16 (2025-07-08)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -90,7 +90,7 @@ Fixed ...@@ -90,7 +90,7 @@ Fixed
:class:`~isaaclab.assets.articulation.RigidObjectCollectionData` :class:`~isaaclab.assets.articulation.RigidObjectCollectionData`
0.41.15 (2025-07-08) 0.42.15 (2025-07-08)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -99,7 +99,7 @@ Added ...@@ -99,7 +99,7 @@ Added
* Added ability to set platform height independent of object height for trimesh terrains. * Added ability to set platform height independent of object height for trimesh terrains.
0.41.14 (2025-07-01) 0.42.14 (2025-07-01)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -110,7 +110,7 @@ Added ...@@ -110,7 +110,7 @@ Added
* Added deprecation warnings to the existing :attr:`max_height_noise` but still functions. * Added deprecation warnings to the existing :attr:`max_height_noise` but still functions.
0.41.13 (2025-07-03) 0.42.13 (2025-07-03)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -119,7 +119,7 @@ Fixed ...@@ -119,7 +119,7 @@ Fixed
* Fixed unittest tests that are floating inside pytests for articulation and rendering * Fixed unittest tests that are floating inside pytests for articulation and rendering
0.41.12 (2025-07-03) 0.42.12 (2025-07-03)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Changed Changed
...@@ -129,7 +129,7 @@ Changed ...@@ -129,7 +129,7 @@ Changed
videos with the ``--video`` flag. videos with the ``--video`` flag.
0.41.11 (2025-06-27) 0.42.11 (2025-06-27)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -144,7 +144,7 @@ Fixed ...@@ -144,7 +144,7 @@ Fixed
* Fixed the implementation mistake in :func:`~isaaclab.utils.math.quat_inv`. * Fixed the implementation mistake in :func:`~isaaclab.utils.math.quat_inv`.
0.41.10 (2025-06-25) 0.42.10 (2025-06-25)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -153,7 +153,7 @@ Fixed ...@@ -153,7 +153,7 @@ Fixed
* Fixed :func:`~isaaclab.utils.dict.update_class_from_dict` preventing setting flat Iterables with different lengths. * Fixed :func:`~isaaclab.utils.dict.update_class_from_dict` preventing setting flat Iterables with different lengths.
0.41.9 (2025-06-25) 0.42.9 (2025-06-25)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -163,7 +163,7 @@ Added ...@@ -163,7 +163,7 @@ Added
sampling, which is now the default behavior. If set to False, the previous behavior of sharing the same bias value across all components is retained. sampling, which is now the default behavior. If set to False, the previous behavior of sharing the same bias value across all components is retained.
0.41.8 (2025-06-18) 0.42.8 (2025-06-18)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -175,7 +175,7 @@ Fixed ...@@ -175,7 +175,7 @@ Fixed
* added pytest that check against these data consistencies * added pytest that check against these data consistencies
0.41.7 (2025-06-24) 0.42.7 (2025-06-24)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -189,12 +189,16 @@ Changed ...@@ -189,12 +189,16 @@ Changed
* Renamed :func:`~isaaclab.utils.noise.NoiseModel.apply` method to :func:`~isaaclab.utils.noise.NoiseModel.__call__`. * Renamed :func:`~isaaclab.utils.noise.NoiseModel.apply` method to :func:`~isaaclab.utils.noise.NoiseModel.__call__`.
<<<<<<< HEAD
<<<<<<< HEAD <<<<<<< HEAD
0.40.6 (2025-06-12) 0.40.6 (2025-06-12)
======= =======
0.41.6 (2025-06-12) 0.41.6 (2025-06-12)
>>>>>>> cf094c211f (Updates to Isaac Sim 5.0 (#379)) >>>>>>> cf094c211f (Updates to Isaac Sim 5.0 (#379))
=======
0.42.6 (2025-06-12)
>>>>>>> b048c33739 (Adds support for Stage in Memory (#375))
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -203,7 +207,7 @@ Fixed ...@@ -203,7 +207,7 @@ Fixed
* Fixed potential issues in :func:`~isaaclab.envs.mdp.events.randomize_visual_texture_material` related to handling visual prims during texture randomization. * Fixed potential issues in :func:`~isaaclab.envs.mdp.events.randomize_visual_texture_material` related to handling visual prims during texture randomization.
0.41.5 (2025-05-22) 0.42.5 (2025-05-22)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -213,7 +217,7 @@ Fixed ...@@ -213,7 +217,7 @@ Fixed
currently has limitations for CPU simulation. Collision filtering needs to be manually enabled when using CPU simulation. currently has limitations for CPU simulation. Collision filtering needs to be manually enabled when using CPU simulation.
0.41.4 (2025-06-03) 0.42.4 (2025-06-03)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Changed Changed
...@@ -224,7 +228,7 @@ Changed ...@@ -224,7 +228,7 @@ Changed
passed in the ``TerrainGeneratorCfg``. passed in the ``TerrainGeneratorCfg``.
0.41.3 (2025-03-20) 0.42.3 (2025-03-20)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Changed Changed
...@@ -239,7 +243,7 @@ Changed ...@@ -239,7 +243,7 @@ Changed
more readable. more readable.
0.41.2 (2025-05-10) 0.42.2 (2025-05-31)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -249,7 +253,7 @@ Added ...@@ -249,7 +253,7 @@ Added
* Added support for specifying module:task_name as task name to avoid module import for ``gym.make`` * Added support for specifying module:task_name as task name to avoid module import for ``gym.make``
0.41.1 (2025-06-02) 0.42.1 (2025-06-02)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -265,6 +269,16 @@ Changed ...@@ -265,6 +269,16 @@ Changed
to make it available for mdp functions. to make it available for mdp functions.
0.42.0 (2025-06-02)
~~~~~~~~~~~~~~~~~~~
Added
^^^^^
* Added support for stage in memory and cloning in fabric. This will help improve performance for scene setup and lower
overall startup time.
0.41.0 (2025-05-19) 0.41.0 (2025-05-19)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
......
...@@ -13,7 +13,6 @@ from collections.abc import Sequence ...@@ -13,7 +13,6 @@ from collections.abc import Sequence
from prettytable import PrettyTable from prettytable import PrettyTable
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import isaacsim.core.utils.stage as stage_utils
import omni.log import omni.log
import omni.physics.tensors.impl.api as physx import omni.physics.tensors.impl.api as physx
from isaacsim.core.simulation_manager import SimulationManager from isaacsim.core.simulation_manager import SimulationManager
...@@ -1578,14 +1577,13 @@ class Articulation(AssetBase): ...@@ -1578,14 +1577,13 @@ class Articulation(AssetBase):
self._spatial_tendon_names = list() self._spatial_tendon_names = list()
# parse fixed tendons properties if they exist # parse fixed tendons properties if they exist
if self.num_fixed_tendons > 0 or self.num_spatial_tendons > 0: if self.num_fixed_tendons > 0 or self.num_spatial_tendons > 0:
stage = stage_utils.get_current_stage()
joint_paths = self.root_physx_view.dof_paths[0] joint_paths = self.root_physx_view.dof_paths[0]
# iterate over all joints to find tendons attached to them # iterate over all joints to find tendons attached to them
for j in range(self.num_joints): for j in range(self.num_joints):
usd_joint_path = joint_paths[j] usd_joint_path = joint_paths[j]
# check whether joint has tendons - tendon name follows the joint name it is attached to # check whether joint has tendons - tendon name follows the joint name it is attached to
joint = UsdPhysics.Joint.Get(stage, usd_joint_path) joint = UsdPhysics.Joint.Get(self.stage, usd_joint_path)
if joint.GetPrim().HasAPI(PhysxSchema.PhysxTendonAxisRootAPI): if joint.GetPrim().HasAPI(PhysxSchema.PhysxTendonAxisRootAPI):
joint_name = usd_joint_path.split("/")[-1] joint_name = usd_joint_path.split("/")[-1]
self._fixed_tendon_names.append(joint_name) self._fixed_tendon_names.append(joint_name)
......
...@@ -18,6 +18,7 @@ import isaacsim.core.utils.prims as prim_utils ...@@ -18,6 +18,7 @@ import isaacsim.core.utils.prims as prim_utils
import omni.kit.app import omni.kit.app
import omni.timeline import omni.timeline
from isaacsim.core.simulation_manager import IsaacEvents, SimulationManager from isaacsim.core.simulation_manager import IsaacEvents, SimulationManager
from isaacsim.core.utils.stage import get_current_stage
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -69,6 +70,8 @@ class AssetBase(ABC): ...@@ -69,6 +70,8 @@ class AssetBase(ABC):
self.cfg = cfg.copy() self.cfg = cfg.copy()
# flag for whether the asset is initialized # flag for whether the asset is initialized
self._is_initialized = False self._is_initialized = False
# get stage handle
self.stage = get_current_stage()
# check if base asset path is valid # check if base asset path is valid
# note: currently the spawner does not work if there is a regex pattern in the leaf # note: currently the spawner does not work if there is a regex pattern in the leaf
......
...@@ -7,6 +7,7 @@ import torch ...@@ -7,6 +7,7 @@ import torch
import weakref import weakref
import omni.physics.tensors.impl.api as physx import omni.physics.tensors.impl.api as physx
from isaacsim.core.utils.stage import get_current_stage_id
import isaaclab.utils.math as math_utils import isaaclab.utils.math as math_utils
from isaaclab.utils.buffers import TimestampedBuffer from isaaclab.utils.buffers import TimestampedBuffer
...@@ -51,7 +52,8 @@ class RigidObjectData: ...@@ -51,7 +52,8 @@ class RigidObjectData:
self._sim_timestamp = 0.0 self._sim_timestamp = 0.0
# Obtain global physics sim view # Obtain global physics sim view
physics_sim_view = physx.create_simulation_view("torch") stage_id = get_current_stage_id()
physics_sim_view = physx.create_simulation_view("torch", stage_id)
physics_sim_view.set_subspace_roots("/") physics_sim_view.set_subspace_roots("/")
gravity = physics_sim_view.get_gravity() gravity = physics_sim_view.get_gravity()
# Convert to direction vector # Convert to direction vector
......
...@@ -7,6 +7,7 @@ import torch ...@@ -7,6 +7,7 @@ import torch
import weakref import weakref
import omni.physics.tensors.impl.api as physx import omni.physics.tensors.impl.api as physx
from isaacsim.core.utils.stage import get_current_stage_id
import isaaclab.utils.math as math_utils import isaaclab.utils.math as math_utils
from isaaclab.utils.buffers import TimestampedBuffer from isaaclab.utils.buffers import TimestampedBuffer
...@@ -54,7 +55,8 @@ class RigidObjectCollectionData: ...@@ -54,7 +55,8 @@ class RigidObjectCollectionData:
self._sim_timestamp = 0.0 self._sim_timestamp = 0.0
# Obtain global physics sim view # Obtain global physics sim view
physics_sim_view = physx.create_simulation_view("torch") stage_id = get_current_stage_id()
physics_sim_view = physx.create_simulation_view("torch", stage_id)
physics_sim_view.set_subspace_roots("/") physics_sim_view.set_subspace_roots("/")
gravity = physics_sim_view.get_gravity() gravity = physics_sim_view.get_gravity()
# Convert to direction vector # Convert to direction vector
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The Isaac Lab Project Developers. # Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
...@@ -17,6 +17,7 @@ from collections.abc import Sequence ...@@ -17,6 +17,7 @@ from collections.abc import Sequence
from dataclasses import MISSING from dataclasses import MISSING
from typing import Any, ClassVar from typing import Any, ClassVar
import isaacsim.core.utils.stage as stage_utils
import isaacsim.core.utils.torch as torch_utils import isaacsim.core.utils.torch as torch_utils
import omni.kit.app import omni.kit.app
import omni.log import omni.log
...@@ -25,6 +26,7 @@ from isaacsim.core.version import get_version ...@@ -25,6 +26,7 @@ from isaacsim.core.version import get_version
from isaaclab.managers import EventManager from isaaclab.managers import EventManager
from isaaclab.scene import InteractiveScene from isaaclab.scene import InteractiveScene
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils.noise import NoiseModel from isaaclab.utils.noise import NoiseModel
from isaaclab.utils.timer import Timer from isaaclab.utils.timer import Timer
...@@ -117,8 +119,10 @@ class DirectMARLEnv(gym.Env): ...@@ -117,8 +119,10 @@ class DirectMARLEnv(gym.Env):
# generate scene # generate scene
with Timer("[INFO]: Time taken for scene creation", "scene_creation"): with Timer("[INFO]: Time taken for scene creation", "scene_creation"):
with stage_utils.use_stage(self.sim.get_initial_stage()):
self.scene = InteractiveScene(self.cfg.scene) self.scene = InteractiveScene(self.cfg.scene)
self._setup_scene() self._setup_scene()
attach_stage_to_usd_context()
print("[INFO]: Scene manager: ", self.scene) print("[INFO]: Scene manager: ", self.scene)
# set up camera viewport controller # set up camera viewport controller
......
...@@ -17,6 +17,7 @@ from collections.abc import Sequence ...@@ -17,6 +17,7 @@ from collections.abc import Sequence
from dataclasses import MISSING from dataclasses import MISSING
from typing import Any, ClassVar from typing import Any, ClassVar
import isaacsim.core.utils.stage as stage_utils
import isaacsim.core.utils.torch as torch_utils import isaacsim.core.utils.torch as torch_utils
import omni.kit.app import omni.kit.app
import omni.log import omni.log
...@@ -26,6 +27,7 @@ from isaacsim.core.version import get_version ...@@ -26,6 +27,7 @@ from isaacsim.core.version import get_version
from isaaclab.managers import EventManager from isaaclab.managers import EventManager
from isaaclab.scene import InteractiveScene from isaaclab.scene import InteractiveScene
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.utils.noise import NoiseModel from isaaclab.utils.noise import NoiseModel
from isaaclab.utils.timer import Timer from isaaclab.utils.timer import Timer
...@@ -123,8 +125,10 @@ class DirectRLEnv(gym.Env): ...@@ -123,8 +125,10 @@ class DirectRLEnv(gym.Env):
# generate scene # generate scene
with Timer("[INFO]: Time taken for scene creation", "scene_creation"): with Timer("[INFO]: Time taken for scene creation", "scene_creation"):
with stage_utils.use_stage(self.sim.get_initial_stage()):
self.scene = InteractiveScene(self.cfg.scene) self.scene = InteractiveScene(self.cfg.scene)
self._setup_scene() self._setup_scene()
attach_stage_to_usd_context()
print("[INFO]: Scene manager: ", self.scene) print("[INFO]: Scene manager: ", self.scene)
# set up camera viewport controller # set up camera viewport controller
......
...@@ -8,6 +8,7 @@ import torch ...@@ -8,6 +8,7 @@ import torch
from collections.abc import Sequence from collections.abc import Sequence
from typing import Any from typing import Any
import isaacsim.core.utils.stage as stage_utils
import isaacsim.core.utils.torch as torch_utils import isaacsim.core.utils.torch as torch_utils
import omni.log import omni.log
from isaacsim.core.simulation_manager import SimulationManager from isaacsim.core.simulation_manager import SimulationManager
...@@ -15,6 +16,7 @@ from isaacsim.core.simulation_manager import SimulationManager ...@@ -15,6 +16,7 @@ from isaacsim.core.simulation_manager import SimulationManager
from isaaclab.managers import ActionManager, EventManager, ObservationManager, RecorderManager from isaaclab.managers import ActionManager, EventManager, ObservationManager, RecorderManager
from isaaclab.scene import InteractiveScene from isaaclab.scene import InteractiveScene
from isaaclab.sim import SimulationContext from isaaclab.sim import SimulationContext
from isaaclab.sim.utils import attach_stage_to_usd_context
from isaaclab.ui.widgets import ManagerLiveVisualizer from isaaclab.ui.widgets import ManagerLiveVisualizer
from isaaclab.utils.timer import Timer from isaaclab.utils.timer import Timer
...@@ -127,7 +129,10 @@ class ManagerBasedEnv: ...@@ -127,7 +129,10 @@ class ManagerBasedEnv:
# generate scene # generate scene
with Timer("[INFO]: Time taken for scene creation", "scene_creation"): with Timer("[INFO]: Time taken for scene creation", "scene_creation"):
# get stage handle and set stage context
with stage_utils.use_stage(self.sim.get_initial_stage()):
self.scene = InteractiveScene(self.cfg.scene) self.scene = InteractiveScene(self.cfg.scene)
attach_stage_to_usd_context()
print("[INFO]: Scene manager: ", self.scene) print("[INFO]: Scene manager: ", self.scene)
# set up camera viewport controller # set up camera viewport controller
......
...@@ -20,8 +20,8 @@ from typing import TYPE_CHECKING, Literal ...@@ -20,8 +20,8 @@ from typing import TYPE_CHECKING, Literal
import carb import carb
import omni.physics.tensors.impl.api as physx import omni.physics.tensors.impl.api as physx
import omni.usd
from isaacsim.core.utils.extensions import enable_extension from isaacsim.core.utils.extensions import enable_extension
from isaacsim.core.utils.stage import get_current_stage
from pxr import Gf, Sdf, UsdGeom, Vt from pxr import Gf, Sdf, UsdGeom, Vt
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -92,7 +92,7 @@ def randomize_rigid_body_scale( ...@@ -92,7 +92,7 @@ def randomize_rigid_body_scale(
env_ids = env_ids.cpu() env_ids = env_ids.cpu()
# acquire stage # acquire stage
stage = omni.usd.get_context().get_stage() stage = get_current_stage()
# resolve prim paths for spawning and cloning # resolve prim paths for spawning and cloning
prim_paths = sim_utils.find_matching_prim_paths(asset.cfg.prim_path) prim_paths = sim_utils.find_matching_prim_paths(asset.cfg.prim_path)
......
...@@ -15,6 +15,7 @@ import isaacsim ...@@ -15,6 +15,7 @@ import isaacsim
import omni.kit.app import omni.kit.app
import omni.kit.commands import omni.kit.commands
import omni.usd import omni.usd
from isaacsim.core.utils.stage import get_current_stage
from pxr import PhysxSchema, Sdf, Usd, UsdGeom, UsdPhysics from pxr import PhysxSchema, Sdf, Usd, UsdGeom, UsdPhysics
from isaaclab.ui.widgets import ManagerLiveVisualizer from isaaclab.ui.widgets import ManagerLiveVisualizer
...@@ -60,6 +61,9 @@ class BaseEnvWindow: ...@@ -60,6 +61,9 @@ class BaseEnvWindow:
*self.env.scene.articulations.keys(), *self.env.scene.articulations.keys(),
] ]
# get stage handle
self.stage = get_current_stage()
# Listeners for environment selection changes # Listeners for environment selection changes
self._ui_listeners: list[ManagerLiveVisualizer] = [] self._ui_listeners: list[ManagerLiveVisualizer] = []
...@@ -300,8 +304,7 @@ class BaseEnvWindow: ...@@ -300,8 +304,7 @@ class BaseEnvWindow:
# stop the recording # stop the recording
_ = omni.kit.commands.execute("StopRecording") _ = omni.kit.commands.execute("StopRecording")
# save the current stage # save the current stage
stage = omni.usd.get_context().get_stage() source_layer = self.stage.GetRootLayer()
source_layer = stage.GetRootLayer()
# output the stage to a file # output the stage to a file
stage_usd_path = os.path.join(self.animation_log_dir, "Stage.usd") stage_usd_path = os.path.join(self.animation_log_dir, "Stage.usd")
source_prim_path = "/" source_prim_path = "/"
...@@ -311,8 +314,8 @@ class BaseEnvWindow: ...@@ -311,8 +314,8 @@ class BaseEnvWindow:
temp_layer = Sdf.Layer.CreateNew(stage_usd_path) temp_layer = Sdf.Layer.CreateNew(stage_usd_path)
temp_stage = Usd.Stage.Open(temp_layer) temp_stage = Usd.Stage.Open(temp_layer)
# update stage data # update stage data
UsdGeom.SetStageUpAxis(temp_stage, UsdGeom.GetStageUpAxis(stage)) UsdGeom.SetStageUpAxis(temp_stage, UsdGeom.GetStageUpAxis(self.stage))
UsdGeom.SetStageMetersPerUnit(temp_stage, UsdGeom.GetStageMetersPerUnit(stage)) UsdGeom.SetStageMetersPerUnit(temp_stage, UsdGeom.GetStageMetersPerUnit(self.stage))
# copy the prim # copy the prim
Sdf.CreatePrimInLayer(temp_layer, source_prim_path) Sdf.CreatePrimInLayer(temp_layer, source_prim_path)
Sdf.CopySpec(source_layer, source_prim_path, temp_layer, source_prim_path) Sdf.CopySpec(source_layer, source_prim_path, temp_layer, source_prim_path)
......
...@@ -25,11 +25,14 @@ from dataclasses import MISSING ...@@ -25,11 +25,14 @@ from dataclasses import MISSING
import isaacsim.core.utils.stage as stage_utils import isaacsim.core.utils.stage as stage_utils
import omni.kit.commands import omni.kit.commands
import omni.log
import omni.physx.scripts.utils as physx_utils import omni.physx.scripts.utils as physx_utils
from isaacsim.core.utils.stage import get_current_stage
from pxr import Gf, PhysxSchema, Sdf, Usd, UsdGeom, UsdPhysics, Vt from pxr import Gf, PhysxSchema, Sdf, Usd, UsdGeom, UsdPhysics, Vt
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.sim.spawners import SpawnerCfg from isaaclab.sim.spawners import SpawnerCfg
from isaaclab.sim.utils import attach_stage_to_usd_context, is_current_stage_in_memory
from isaaclab.utils.configclass import configclass from isaaclab.utils.configclass import configclass
from isaaclab.utils.math import convert_quat from isaaclab.utils.math import convert_quat
...@@ -145,8 +148,8 @@ class VisualizationMarkers: ...@@ -145,8 +148,8 @@ class VisualizationMarkers:
# get next free path for the prim # get next free path for the prim
prim_path = stage_utils.get_next_free_path(cfg.prim_path) prim_path = stage_utils.get_next_free_path(cfg.prim_path)
# create a new prim # create a new prim
stage = stage_utils.get_current_stage() self.stage = get_current_stage()
self._instancer_manager = UsdGeom.PointInstancer.Define(stage, prim_path) self._instancer_manager = UsdGeom.PointInstancer.Define(self.stage, prim_path)
# store inputs # store inputs
self.prim_path = prim_path self.prim_path = prim_path
self.cfg = cfg self.cfg = cfg
...@@ -395,6 +398,15 @@ class VisualizationMarkers: ...@@ -395,6 +398,15 @@ class VisualizationMarkers:
child_prim.SetInstanceable(False) child_prim.SetInstanceable(False)
# check if prim is a mesh -> if so, make it invisible to secondary rays # check if prim is a mesh -> if so, make it invisible to secondary rays
if child_prim.IsA(UsdGeom.Gprim): if child_prim.IsA(UsdGeom.Gprim):
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "ChangePropertyCommand" kit command
if is_current_stage_in_memory():
omni.log.warn(
"Attaching stage in memory to USD context early to support omni kit command during stage"
" creation."
)
attach_stage_to_usd_context()
# invisible to secondary rays such as depth images # invisible to secondary rays such as depth images
omni.kit.commands.execute( omni.kit.commands.execute(
"ChangePropertyCommand", "ChangePropertyCommand",
......
...@@ -12,6 +12,7 @@ import omni.log ...@@ -12,6 +12,7 @@ import omni.log
import omni.usd import omni.usd
from isaacsim.core.cloner import GridCloner from isaacsim.core.cloner import GridCloner
from isaacsim.core.prims import XFormPrim from isaacsim.core.prims import XFormPrim
from isaacsim.core.utils.stage import get_current_stage, get_current_stage_id
from pxr import PhysxSchema from pxr import PhysxSchema
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -27,6 +28,7 @@ from isaaclab.assets import ( ...@@ -27,6 +28,7 @@ from isaaclab.assets import (
RigidObjectCollectionCfg, RigidObjectCollectionCfg,
) )
from isaaclab.sensors import ContactSensorCfg, FrameTransformerCfg, SensorBase, SensorBaseCfg from isaaclab.sensors import ContactSensorCfg, FrameTransformerCfg, SensorBase, SensorBaseCfg
from isaaclab.sim import SimulationContext
from isaaclab.terrains import TerrainImporter, TerrainImporterCfg from isaaclab.terrains import TerrainImporter, TerrainImporterCfg
from .interactive_scene_cfg import InteractiveSceneCfg from .interactive_scene_cfg import InteractiveSceneCfg
...@@ -119,12 +121,14 @@ class InteractiveScene: ...@@ -119,12 +121,14 @@ class InteractiveScene:
self._rigid_object_collections = dict() self._rigid_object_collections = dict()
self._sensors = dict() self._sensors = dict()
self._extras = dict() self._extras = dict()
# obtain the current stage # get stage handle
self.stage = omni.usd.get_context().get_stage() self.sim = SimulationContext.instance()
self.stage = get_current_stage()
self.stage_id = get_current_stage_id()
# physics scene path # physics scene path
self._physics_scene_path = None self._physics_scene_path = None
# prepare cloner for environment replication # prepare cloner for environment replication
self.cloner = GridCloner(spacing=self.cfg.env_spacing) self.cloner = GridCloner(spacing=self.cfg.env_spacing, stage=self.stage)
self.cloner.define_base_env(self.env_ns) self.cloner.define_base_env(self.env_ns)
self.env_prim_paths = self.cloner.generate_paths(f"{self.env_ns}/env", self.cfg.num_envs) self.env_prim_paths = self.cloner.generate_paths(f"{self.env_ns}/env", self.cfg.num_envs)
# create source prim # create source prim
......
...@@ -154,9 +154,8 @@ class Camera(SensorBase): ...@@ -154,9 +154,8 @@ class Camera(SensorBase):
" will be disabled in the current workflow and may lead to longer load times and increased memory" " will be disabled in the current workflow and may lead to longer load times and increased memory"
" usage." " usage."
) )
stage = omni.usd.get_context().get_stage()
with Sdf.ChangeBlock(): with Sdf.ChangeBlock():
for prim in stage.Traverse(): for prim in self.stage.Traverse():
prim.SetInstanceable(False) prim.SetInstanceable(False)
def __del__(self): def __del__(self):
...@@ -421,12 +420,10 @@ class Camera(SensorBase): ...@@ -421,12 +420,10 @@ class Camera(SensorBase):
self._render_product_paths: list[str] = list() self._render_product_paths: list[str] = list()
self._rep_registry: dict[str, list[rep.annotators.Annotator]] = {name: list() for name in self.cfg.data_types} self._rep_registry: dict[str, list[rep.annotators.Annotator]] = {name: list() for name in self.cfg.data_types}
# Obtain current stage
stage = omni.usd.get_context().get_stage()
# Convert all encapsulated prims to Camera # Convert all encapsulated prims to Camera
for cam_prim_path in self._view.prim_paths: for cam_prim_path in self._view.prim_paths:
# Get camera prim # Get camera prim
cam_prim = stage.GetPrimAtPath(cam_prim_path) cam_prim = self.stage.GetPrimAtPath(cam_prim_path)
# Check if prim is a camera # Check if prim is a camera
if not cam_prim.IsA(UsdGeom.Camera): if not cam_prim.IsA(UsdGeom.Camera):
raise RuntimeError(f"Prim at path '{cam_prim_path}' is not a Camera.") raise RuntimeError(f"Prim at path '{cam_prim_path}' is not a Camera.")
......
...@@ -13,7 +13,6 @@ from collections.abc import Sequence ...@@ -13,7 +13,6 @@ from collections.abc import Sequence
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
import carb import carb
import omni.usd
import warp as wp import warp as wp
from isaacsim.core.prims import XFormPrim from isaacsim.core.prims import XFormPrim
from isaacsim.core.version import get_version from isaacsim.core.version import get_version
...@@ -173,12 +172,10 @@ class TiledCamera(Camera): ...@@ -173,12 +172,10 @@ class TiledCamera(Camera):
# Create frame count buffer # Create frame count buffer
self._frame = torch.zeros(self._view.count, device=self._device, dtype=torch.long) self._frame = torch.zeros(self._view.count, device=self._device, dtype=torch.long)
# Obtain current stage
stage = omni.usd.get_context().get_stage()
# Convert all encapsulated prims to Camera # Convert all encapsulated prims to Camera
for cam_prim_path in self._view.prim_paths: for cam_prim_path in self._view.prim_paths:
# Get camera prim # Get camera prim
cam_prim = stage.GetPrimAtPath(cam_prim_path) cam_prim = self.stage.GetPrimAtPath(cam_prim_path)
# Check if prim is a camera # Check if prim is a camera
if not cam_prim.IsA(UsdGeom.Camera): if not cam_prim.IsA(UsdGeom.Camera):
raise RuntimeError(f"Prim at path '{cam_prim_path}' is not a Camera.") raise RuntimeError(f"Prim at path '{cam_prim_path}' is not a Camera.")
......
...@@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Any ...@@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Any
import omni.kit.app import omni.kit.app
import omni.timeline import omni.timeline
from isaacsim.core.simulation_manager import IsaacEvents, SimulationManager from isaacsim.core.simulation_manager import IsaacEvents, SimulationManager
from isaacsim.core.utils.stage import get_current_stage
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -59,6 +60,8 @@ class SensorBase(ABC): ...@@ -59,6 +60,8 @@ class SensorBase(ABC):
self._is_initialized = False self._is_initialized = False
# flag for whether the sensor is in visualization mode # flag for whether the sensor is in visualization mode
self._is_visualizing = False self._is_visualizing = False
# get stage handle
self.stage = get_current_stage()
# note: Use weakref on callbacks to ensure that this object can be deleted when its destructor is called. # note: Use weakref on callbacks to ensure that this object can be deleted when its destructor is called.
# add callbacks for stage play/stop # add callbacks for stage play/stop
......
...@@ -8,9 +8,9 @@ from __future__ import annotations ...@@ -8,9 +8,9 @@ from __future__ import annotations
import math import math
import isaacsim.core.utils.stage as stage_utils
import omni.log import omni.log
import omni.physx.scripts.utils as physx_utils import omni.physx.scripts.utils as physx_utils
from isaacsim.core.utils.stage import get_current_stage
from omni.physx.scripts import deformableUtils as deformable_utils from omni.physx.scripts import deformableUtils as deformable_utils
from pxr import PhysxSchema, Usd, UsdPhysics from pxr import PhysxSchema, Usd, UsdPhysics
...@@ -44,9 +44,10 @@ def define_articulation_root_properties( ...@@ -44,9 +44,10 @@ def define_articulation_root_properties(
ValueError: When the prim path is not valid. ValueError: When the prim path is not valid.
TypeError: When the prim already has conflicting API schemas. TypeError: When the prim already has conflicting API schemas.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get articulation USD prim # get articulation USD prim
prim = stage.GetPrimAtPath(prim_path) prim = stage.GetPrimAtPath(prim_path)
# check if prim path is valid # check if prim path is valid
...@@ -102,9 +103,10 @@ def modify_articulation_root_properties( ...@@ -102,9 +103,10 @@ def modify_articulation_root_properties(
Raises: Raises:
NotImplementedError: When the root prim is not a rigid body and a fixed joint is to be created. NotImplementedError: When the root prim is not a rigid body and a fixed joint is to be created.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get articulation USD prim # get articulation USD prim
articulation_prim = stage.GetPrimAtPath(prim_path) articulation_prim = stage.GetPrimAtPath(prim_path)
# check if prim has articulation applied on it # check if prim has articulation applied on it
...@@ -204,9 +206,10 @@ def define_rigid_body_properties( ...@@ -204,9 +206,10 @@ def define_rigid_body_properties(
ValueError: When the prim path is not valid. ValueError: When the prim path is not valid.
TypeError: When the prim already has conflicting API schemas. TypeError: When the prim already has conflicting API schemas.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
prim = stage.GetPrimAtPath(prim_path) prim = stage.GetPrimAtPath(prim_path)
# check if prim path is valid # check if prim path is valid
...@@ -250,9 +253,10 @@ def modify_rigid_body_properties( ...@@ -250,9 +253,10 @@ def modify_rigid_body_properties(
Returns: Returns:
True if the properties were successfully set, False otherwise. True if the properties were successfully set, False otherwise.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get rigid-body USD prim # get rigid-body USD prim
rigid_body_prim = stage.GetPrimAtPath(prim_path) rigid_body_prim = stage.GetPrimAtPath(prim_path)
# check if prim has rigid-body applied on it # check if prim has rigid-body applied on it
...@@ -299,9 +303,10 @@ def define_collision_properties( ...@@ -299,9 +303,10 @@ def define_collision_properties(
Raises: Raises:
ValueError: When the prim path is not valid. ValueError: When the prim path is not valid.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
prim = stage.GetPrimAtPath(prim_path) prim = stage.GetPrimAtPath(prim_path)
# check if prim path is valid # check if prim path is valid
...@@ -343,9 +348,10 @@ def modify_collision_properties( ...@@ -343,9 +348,10 @@ def modify_collision_properties(
Returns: Returns:
True if the properties were successfully set, False otherwise. True if the properties were successfully set, False otherwise.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
collider_prim = stage.GetPrimAtPath(prim_path) collider_prim = stage.GetPrimAtPath(prim_path)
# check if prim has collision applied on it # check if prim has collision applied on it
...@@ -390,9 +396,10 @@ def define_mass_properties(prim_path: str, cfg: schemas_cfg.MassPropertiesCfg, s ...@@ -390,9 +396,10 @@ def define_mass_properties(prim_path: str, cfg: schemas_cfg.MassPropertiesCfg, s
Raises: Raises:
ValueError: When the prim path is not valid. ValueError: When the prim path is not valid.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
prim = stage.GetPrimAtPath(prim_path) prim = stage.GetPrimAtPath(prim_path)
# check if prim path is valid # check if prim path is valid
...@@ -435,9 +442,10 @@ def modify_mass_properties(prim_path: str, cfg: schemas_cfg.MassPropertiesCfg, s ...@@ -435,9 +442,10 @@ def modify_mass_properties(prim_path: str, cfg: schemas_cfg.MassPropertiesCfg, s
Returns: Returns:
True if the properties were successfully set, False otherwise. True if the properties were successfully set, False otherwise.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
rigid_prim = stage.GetPrimAtPath(prim_path) rigid_prim = stage.GetPrimAtPath(prim_path)
# check if prim has mass API applied on it # check if prim has mass API applied on it
...@@ -478,9 +486,10 @@ def activate_contact_sensors(prim_path: str, threshold: float = 0.0, stage: Usd. ...@@ -478,9 +486,10 @@ def activate_contact_sensors(prim_path: str, threshold: float = 0.0, stage: Usd.
ValueError: If the input prim path is not valid. ValueError: If the input prim path is not valid.
ValueError: If there are no rigid bodies under the prim path. ValueError: If there are no rigid bodies under the prim path.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get prim # get prim
prim: Usd.Prim = stage.GetPrimAtPath(prim_path) prim: Usd.Prim = stage.GetPrimAtPath(prim_path)
# check if prim is valid # check if prim is valid
...@@ -564,9 +573,10 @@ def modify_joint_drive_properties( ...@@ -564,9 +573,10 @@ def modify_joint_drive_properties(
Raises: Raises:
ValueError: If the input prim path is not valid. ValueError: If the input prim path is not valid.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
prim = stage.GetPrimAtPath(prim_path) prim = stage.GetPrimAtPath(prim_path)
# check if prim path is valid # check if prim path is valid
...@@ -666,9 +676,10 @@ def modify_fixed_tendon_properties( ...@@ -666,9 +676,10 @@ def modify_fixed_tendon_properties(
Raises: Raises:
ValueError: If the input prim path is not valid. ValueError: If the input prim path is not valid.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
tendon_prim = stage.GetPrimAtPath(prim_path) tendon_prim = stage.GetPrimAtPath(prim_path)
# check if prim has fixed tendon applied on it # check if prim has fixed tendon applied on it
...@@ -734,7 +745,7 @@ def modify_spatial_tendon_properties( ...@@ -734,7 +745,7 @@ def modify_spatial_tendon_properties(
""" """
# obtain stage # obtain stage
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
tendon_prim = stage.GetPrimAtPath(prim_path) tendon_prim = stage.GetPrimAtPath(prim_path)
# check if prim has spatial tendon applied on it # check if prim has spatial tendon applied on it
...@@ -792,9 +803,10 @@ def define_deformable_body_properties( ...@@ -792,9 +803,10 @@ def define_deformable_body_properties(
ValueError: When the prim path is not valid. ValueError: When the prim path is not valid.
ValueError: When the prim has no mesh or multiple meshes. ValueError: When the prim has no mesh or multiple meshes.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get USD prim # get USD prim
prim = stage.GetPrimAtPath(prim_path) prim = stage.GetPrimAtPath(prim_path)
# check if prim path is valid # check if prim path is valid
...@@ -867,9 +879,9 @@ def modify_deformable_body_properties( ...@@ -867,9 +879,9 @@ def modify_deformable_body_properties(
Returns: Returns:
True if the properties were successfully set, False otherwise. True if the properties were successfully set, False otherwise.
""" """
# obtain stage # get stage handle
if stage is None: if stage is None:
stage = stage_utils.get_current_stage() stage = get_current_stage()
# get deformable-body USD prim # get deformable-body USD prim
deformable_body_prim = stage.GetPrimAtPath(prim_path) deformable_body_prim = stage.GetPrimAtPath(prim_path)
......
...@@ -339,3 +339,9 @@ class SimulationCfg: ...@@ -339,3 +339,9 @@ class SimulationCfg:
render: RenderCfg = RenderCfg() render: RenderCfg = RenderCfg()
"""Render settings. Default is RenderCfg().""" """Render settings. Default is RenderCfg()."""
create_stage_in_memory: bool = False
"""If stage is first created in memory and then attached to usd context for simulation and rendering.
Creating the stage in memory can reduce start-up time.
"""
...@@ -24,6 +24,7 @@ import flatdict ...@@ -24,6 +24,7 @@ import flatdict
import isaacsim.core.utils.stage as stage_utils import isaacsim.core.utils.stage as stage_utils
import omni.log import omni.log
import omni.physx import omni.physx
import omni.usd
from isaacsim.core.api.simulation_context import SimulationContext as _SimulationContext from isaacsim.core.api.simulation_context import SimulationContext as _SimulationContext
from isaacsim.core.utils.carb import get_carb_setting, set_carb_setting from isaacsim.core.utils.carb import get_carb_setting, set_carb_setting
from isaacsim.core.utils.viewports import set_camera_view from isaacsim.core.utils.viewports import set_camera_view
...@@ -128,6 +129,12 @@ class SimulationContext(_SimulationContext): ...@@ -128,6 +129,12 @@ class SimulationContext(_SimulationContext):
if stage_utils.get_current_stage() is None: if stage_utils.get_current_stage() is None:
raise RuntimeError("The stage has not been created. Did you run the simulator?") raise RuntimeError("The stage has not been created. Did you run the simulator?")
# create stage in memory if requested
if self.cfg.create_stage_in_memory:
self._initial_stage = stage_utils.create_new_stage_in_memory()
else:
self._initial_stage = omni.usd.get_context().get_stage()
# acquire settings interface # acquire settings interface
self.carb_settings = carb.settings.get_settings() self.carb_settings = carb.settings.get_settings()
...@@ -257,6 +264,7 @@ class SimulationContext(_SimulationContext): ...@@ -257,6 +264,7 @@ class SimulationContext(_SimulationContext):
sim_params=sim_params, sim_params=sim_params,
physics_prim_path=self.cfg.physics_prim_path, physics_prim_path=self.cfg.physics_prim_path,
device=self.cfg.device, device=self.cfg.device,
stage=self._initial_stage,
) )
def _apply_physics_settings(self): def _apply_physics_settings(self):
...@@ -526,6 +534,14 @@ class SimulationContext(_SimulationContext): ...@@ -526,6 +534,14 @@ class SimulationContext(_SimulationContext):
self.physics_sim_view.update_articulations_kinematic() self.physics_sim_view.update_articulations_kinematic()
self._update_fabric(0.0, 0.0) self._update_fabric(0.0, 0.0)
def get_initial_stage(self) -> Usd.Stage:
"""Returns stage handle used during scene creation.
Returns:
The stage used during scene creation.
"""
return self._initial_stage
""" """
Operations - Override (standalone) Operations - Override (standalone)
""" """
...@@ -660,6 +676,7 @@ class SimulationContext(_SimulationContext): ...@@ -660,6 +676,7 @@ class SimulationContext(_SimulationContext):
def _init_stage(self, *args, **kwargs) -> Usd.Stage: def _init_stage(self, *args, **kwargs) -> Usd.Stage:
_ = super()._init_stage(*args, **kwargs) _ = super()._init_stage(*args, **kwargs)
with stage_utils.use_stage(self.get_initial_stage()):
# a stage update here is needed for the case when physics_dt != rendering_dt, otherwise the app crashes # a stage update here is needed for the case when physics_dt != rendering_dt, otherwise the app crashes
# when in headless mode # when in headless mode
self.set_setting("/app/player/playSimulations", False) self.set_setting("/app/player/playSimulations", False)
......
...@@ -8,7 +8,6 @@ from __future__ import annotations ...@@ -8,7 +8,6 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import omni.kit.commands import omni.kit.commands
import omni.log import omni.log
from pxr import Gf, Sdf, Usd from pxr import Gf, Sdf, Usd
...@@ -19,8 +18,16 @@ try: ...@@ -19,8 +18,16 @@ try:
except ModuleNotFoundError: except ModuleNotFoundError:
from pxr import Semantics from pxr import Semantics
from isaacsim.core.utils.stage import get_current_stage
from isaaclab.sim import converters, schemas from isaaclab.sim import converters, schemas
from isaaclab.sim.utils import bind_physics_material, bind_visual_material, clone, select_usd_variants from isaaclab.sim.utils import (
bind_physics_material,
bind_visual_material,
clone,
is_current_stage_in_memory,
select_usd_variants,
)
if TYPE_CHECKING: if TYPE_CHECKING:
from . import from_files_cfg from . import from_files_cfg
...@@ -166,7 +173,16 @@ def spawn_ground_plane( ...@@ -166,7 +173,16 @@ def spawn_ground_plane(
# Change the color of the plane # Change the color of the plane
# Warning: This is specific to the default grid plane asset. # Warning: This is specific to the default grid plane asset.
if cfg.color is not None: if cfg.color is not None:
# avoiding this step if stage is in memory since the "ChangePropertyCommand" kit command
# is not supported in stage in memory
if is_current_stage_in_memory():
omni.log.warn(
"Ground plane color modification is not supported while the stage is in memory. Skipping operation."
)
else:
prop_path = f"{prim_path}/Looks/theGrid/Shader.inputs:diffuse_tint" prop_path = f"{prim_path}/Looks/theGrid/Shader.inputs:diffuse_tint"
# change the color # change the color
omni.kit.commands.execute( omni.kit.commands.execute(
"ChangePropertyCommand", "ChangePropertyCommand",
...@@ -177,7 +193,8 @@ def spawn_ground_plane( ...@@ -177,7 +193,8 @@ def spawn_ground_plane(
) )
# Remove the light from the ground plane # Remove the light from the ground plane
# It isn't bright enough and messes up with the user's lighting settings # It isn't bright enough and messes up with the user's lighting settings
omni.kit.commands.execute("ToggleVisibilitySelectedPrims", selected_paths=[f"{prim_path}/SphereLight"]) stage = get_current_stage()
omni.kit.commands.execute("ToggleVisibilitySelectedPrims", selected_paths=[f"{prim_path}/SphereLight"], stage=stage)
prim = prim_utils.get_prim_at_path(prim_path) prim = prim_utils.get_prim_at_path(prim_path)
# Apply semantic tags # Apply semantic tags
...@@ -231,8 +248,10 @@ def _spawn_from_usd_file( ...@@ -231,8 +248,10 @@ def _spawn_from_usd_file(
Raises: Raises:
FileNotFoundError: If the USD file does not exist at the given path. FileNotFoundError: If the USD file does not exist at the given path.
""" """
# get stage handle
stage = get_current_stage()
# check file path exists # check file path exists
stage: Usd.Stage = stage_utils.get_current_stage()
if not stage.ResolveIdentifierToEditTarget(usd_path): if not stage.ResolveIdentifierToEditTarget(usd_path):
raise FileNotFoundError(f"USD file not found at path: '{usd_path}'.") raise FileNotFoundError(f"USD file not found at path: '{usd_path}'.")
# spawn asset if it doesn't exist. # spawn asset if it doesn't exist.
......
...@@ -8,7 +8,7 @@ from __future__ import annotations ...@@ -8,7 +8,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils from isaacsim.core.utils.stage import get_current_stage
from pxr import PhysxSchema, Usd, UsdPhysics, UsdShade from pxr import PhysxSchema, Usd, UsdPhysics, UsdShade
from isaaclab.sim.utils import clone, safe_set_attribute_on_usd_schema from isaaclab.sim.utils import clone, safe_set_attribute_on_usd_schema
...@@ -41,9 +41,12 @@ def spawn_rigid_body_material(prim_path: str, cfg: physics_materials_cfg.RigidBo ...@@ -41,9 +41,12 @@ def spawn_rigid_body_material(prim_path: str, cfg: physics_materials_cfg.RigidBo
Raises: Raises:
ValueError: When a prim already exists at the specified prim path and is not a material. ValueError: When a prim already exists at the specified prim path and is not a material.
""" """
# get stage handle
stage = get_current_stage()
# create material prim if no prim exists # create material prim if no prim exists
if not prim_utils.is_prim_path_valid(prim_path): if not prim_utils.is_prim_path_valid(prim_path):
_ = UsdShade.Material.Define(stage_utils.get_current_stage(), prim_path) _ = UsdShade.Material.Define(stage, prim_path)
# obtain prim # obtain prim
prim = prim_utils.get_prim_at_path(prim_path) prim = prim_utils.get_prim_at_path(prim_path)
...@@ -99,9 +102,12 @@ def spawn_deformable_body_material(prim_path: str, cfg: physics_materials_cfg.De ...@@ -99,9 +102,12 @@ def spawn_deformable_body_material(prim_path: str, cfg: physics_materials_cfg.De
.. _PxFEMSoftBodyMaterial: https://nvidia-omniverse.github.io/PhysX/physx/5.4.1/_api_build/structPxFEMSoftBodyMaterialModel.html .. _PxFEMSoftBodyMaterial: https://nvidia-omniverse.github.io/PhysX/physx/5.4.1/_api_build/structPxFEMSoftBodyMaterialModel.html
""" """
# get stage handle
stage = get_current_stage()
# create material prim if no prim exists # create material prim if no prim exists
if not prim_utils.is_prim_path_valid(prim_path): if not prim_utils.is_prim_path_valid(prim_path):
_ = UsdShade.Material.Define(stage_utils.get_current_stage(), prim_path) _ = UsdShade.Material.Define(stage, prim_path)
# obtain prim # obtain prim
prim = prim_utils.get_prim_at_path(prim_path) prim = prim_utils.get_prim_at_path(prim_path)
......
...@@ -9,9 +9,15 @@ from typing import TYPE_CHECKING ...@@ -9,9 +9,15 @@ from typing import TYPE_CHECKING
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import omni.kit.commands import omni.kit.commands
import omni.log
from pxr import Usd from pxr import Usd
from isaaclab.sim.utils import clone, safe_set_attribute_on_usd_prim from isaaclab.sim.utils import (
attach_stage_to_usd_context,
clone,
is_current_stage_in_memory,
safe_set_attribute_on_usd_prim,
)
from isaaclab.utils.assets import NVIDIA_NUCLEUS_DIR from isaaclab.utils.assets import NVIDIA_NUCLEUS_DIR
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -48,9 +54,19 @@ def spawn_preview_surface(prim_path: str, cfg: visual_materials_cfg.PreviewSurfa ...@@ -48,9 +54,19 @@ def spawn_preview_surface(prim_path: str, cfg: visual_materials_cfg.PreviewSurfa
""" """
# spawn material if it doesn't exist. # spawn material if it doesn't exist.
if not prim_utils.is_prim_path_valid(prim_path): if not prim_utils.is_prim_path_valid(prim_path):
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "CreatePreviewSurfaceMaterialPrim" kit command
if is_current_stage_in_memory():
omni.log.warn(
"Attaching stage in memory to USD context early to support an operation which doesn't support stage in"
" memory."
)
attach_stage_to_usd_context()
omni.kit.commands.execute("CreatePreviewSurfaceMaterialPrim", mtl_path=prim_path, select_new_prim=False) omni.kit.commands.execute("CreatePreviewSurfaceMaterialPrim", mtl_path=prim_path, select_new_prim=False)
else: else:
raise ValueError(f"A prim already exists at path: '{prim_path}'.") raise ValueError(f"A prim already exists at path: '{prim_path}'.")
# obtain prim # obtain prim
prim = prim_utils.get_prim_at_path(f"{prim_path}/Shader") prim = prim_utils.get_prim_at_path(f"{prim_path}/Shader")
# apply properties # apply properties
...@@ -58,7 +74,7 @@ def spawn_preview_surface(prim_path: str, cfg: visual_materials_cfg.PreviewSurfa ...@@ -58,7 +74,7 @@ def spawn_preview_surface(prim_path: str, cfg: visual_materials_cfg.PreviewSurfa
del cfg["func"] del cfg["func"]
for attr_name, attr_value in cfg.items(): for attr_name, attr_value in cfg.items():
safe_set_attribute_on_usd_prim(prim, f"inputs:{attr_name}", attr_value, camel_case=True) safe_set_attribute_on_usd_prim(prim, f"inputs:{attr_name}", attr_value, camel_case=True)
# return prim
return prim return prim
...@@ -93,6 +109,15 @@ def spawn_from_mdl_file(prim_path: str, cfg: visual_materials_cfg.MdlMaterialCfg ...@@ -93,6 +109,15 @@ def spawn_from_mdl_file(prim_path: str, cfg: visual_materials_cfg.MdlMaterialCfg
""" """
# spawn material if it doesn't exist. # spawn material if it doesn't exist.
if not prim_utils.is_prim_path_valid(prim_path): if not prim_utils.is_prim_path_valid(prim_path):
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "CreateMdlMaterialPrim" kit command
if is_current_stage_in_memory():
omni.log.warn(
"Attaching stage in memory to USD context early to support an operation which doesn't support stage in"
" memory."
)
attach_stage_to_usd_context()
# extract material name from path # extract material name from path
material_name = cfg.mdl_path.split("/")[-1].split(".")[0] material_name = cfg.mdl_path.split("/")[-1].split(".")[0]
omni.kit.commands.execute( omni.kit.commands.execute(
......
...@@ -12,7 +12,7 @@ import omni.kit.commands ...@@ -12,7 +12,7 @@ import omni.kit.commands
import omni.log import omni.log
from pxr import Sdf, Usd from pxr import Sdf, Usd
from isaaclab.sim.utils import clone from isaaclab.sim.utils import attach_stage_to_usd_context, clone, is_current_stage_in_memory
from isaaclab.utils import to_camel_case from isaaclab.utils import to_camel_case
if TYPE_CHECKING: if TYPE_CHECKING:
...@@ -88,6 +88,15 @@ def spawn_camera( ...@@ -88,6 +88,15 @@ def spawn_camera(
# lock camera from viewport (this disables viewport movement for camera) # lock camera from viewport (this disables viewport movement for camera)
if cfg.lock_camera: if cfg.lock_camera:
# early attach stage to usd context if stage is in memory
# since stage in memory is not supported by the "ChangePropertyCommand" kit command
if is_current_stage_in_memory():
omni.log.warn(
"Attaching stage in memory to USD context early to support an operation which doesn't support stage in"
" memory."
)
attach_stage_to_usd_context()
omni.kit.commands.execute( omni.kit.commands.execute(
"ChangePropertyCommand", "ChangePropertyCommand",
prop_path=Sdf.Path(f"{prim_path}.omni:kit:cameraLock"), prop_path=Sdf.Path(f"{prim_path}.omni:kit:cameraLock"),
......
...@@ -12,6 +12,7 @@ from typing import TYPE_CHECKING ...@@ -12,6 +12,7 @@ from typing import TYPE_CHECKING
import carb import carb
import isaacsim.core.utils.prims as prim_utils import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils import isaacsim.core.utils.stage as stage_utils
from isaacsim.core.utils.stage import get_current_stage
from pxr import Sdf, Usd from pxr import Sdf, Usd
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
...@@ -42,6 +43,9 @@ def spawn_multi_asset( ...@@ -42,6 +43,9 @@ def spawn_multi_asset(
Returns: Returns:
The created prim at the first prim path. The created prim at the first prim path.
""" """
# get stage handle
stage = get_current_stage()
# resolve: {SPAWN_NS}/AssetName # resolve: {SPAWN_NS}/AssetName
# note: this assumes that the spawn namespace already exists in the stage # note: this assumes that the spawn namespace already exists in the stage
root_path, asset_path = prim_path.rsplit("/", 1) root_path, asset_path = prim_path.rsplit("/", 1)
...@@ -88,9 +92,6 @@ def spawn_multi_asset( ...@@ -88,9 +92,6 @@ def spawn_multi_asset(
# resolve prim paths for spawning and cloning # resolve prim paths for spawning and cloning
prim_paths = [f"{source_prim_path}/{asset_path}" for source_prim_path in source_prim_paths] prim_paths = [f"{source_prim_path}/{asset_path}" for source_prim_path in source_prim_paths]
# acquire stage
stage = stage_utils.get_current_stage()
# manually clone prims if the source prim path is a regex expression # manually clone prims if the source prim path is a regex expression
# note: unlike in the cloner API from Isaac Sim, we do not "reset" xforms on the copied prims. # note: unlike in the cloner API from Isaac Sim, we do not "reset" xforms on the copied prims.
# This is because the "spawn" calls during the creation of the proto prims already handles this operation. # This is because the "spawn" calls during the creation of the proto prims already handles this operation.
......
This diff is collapsed.
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The Isaac Lab Project Developers. # Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Launch Isaac Sim Simulator first."""
from isaaclab.app import AppLauncher
# launch omniverse app
simulation_app = AppLauncher(headless=True, enable_cameras=True).app
"""Rest everything follows."""
import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import omni
import omni.physx
import omni.usd
import pytest
import usdrt
from isaacsim.core.cloner import GridCloner
import isaaclab.sim as sim_utils
from isaaclab.sim.simulation_context import SimulationCfg, SimulationContext
from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR
@pytest.fixture
def sim():
"""Create a simulation context."""
cfg = SimulationCfg(create_stage_in_memory=True)
sim = SimulationContext(cfg=cfg)
stage_utils.update_stage()
yield sim
omni.physx.get_physx_simulation_interface().detach_stage()
sim.stop()
sim.clear()
sim.clear_all_callbacks()
sim.clear_instance()
"""
Tests
"""
def test_stage_in_memory_with_shapes(sim):
"""Test spawning of shapes with stage in memory."""
# define parameters
num_clones = 10
# grab stage in memory and set as current stage via the with statement
stage_in_memory = sim.get_initial_stage()
with stage_utils.use_stage(stage_in_memory):
# create cloned cone stage
for i in range(num_clones):
prim_utils.create_prim(f"/World/env_{i}", "Xform", translation=(i, i, 0))
cfg = sim_utils.MultiAssetSpawnerCfg(
assets_cfg=[
sim_utils.ConeCfg(
radius=0.3,
height=0.6,
),
sim_utils.CuboidCfg(
size=(0.3, 0.3, 0.3),
),
sim_utils.SphereCfg(
radius=0.3,
),
],
random_choice=True,
rigid_props=sim_utils.RigidBodyPropertiesCfg(
solver_position_iteration_count=4, solver_velocity_iteration_count=0
),
mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
collision_props=sim_utils.CollisionPropertiesCfg(),
)
prim_path_regex = "/World/env_.*/Cone"
cfg.func(prim_path_regex, cfg)
# verify stage is in memory
assert sim_utils.is_current_stage_in_memory()
# verify prims exist in stage in memory
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) == num_clones
# verify prims do not exist in context stage
context_stage = omni.usd.get_context().get_stage()
with stage_utils.use_stage(context_stage):
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) != num_clones
# attach stage to context
sim_utils.attach_stage_to_usd_context()
# verify stage is no longer in memory
assert not sim_utils.is_current_stage_in_memory()
# verify prims now exist in context stage
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) == num_clones
def test_stage_in_memory_with_usds(sim):
"""Test spawning of USDs with stage in memory."""
# define parameters
num_clones = 10
usd_paths = [
f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd",
f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-D/anymal_d.usd",
]
# grab stage in memory and set as current stage via the with statement
stage_in_memory = sim.get_initial_stage()
with stage_utils.use_stage(stage_in_memory):
# create cloned robot stage
for i in range(num_clones):
prim_utils.create_prim(f"/World/env_{i}", "Xform", translation=(i, i, 0))
cfg = sim_utils.MultiUsdFileCfg(
usd_path=usd_paths,
random_choice=True,
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=False,
retain_accelerations=False,
linear_damping=0.0,
angular_damping=0.0,
max_linear_velocity=1000.0,
max_angular_velocity=1000.0,
max_depenetration_velocity=1.0,
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=True, solver_position_iteration_count=4, solver_velocity_iteration_count=0
),
activate_contact_sensors=True,
)
prim_path_regex = "/World/env_.*/Robot"
cfg.func(prim_path_regex, cfg)
# verify stage is in memory
assert sim_utils.is_current_stage_in_memory()
# verify prims exist in stage in memory
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) == num_clones
# verify prims do not exist in context stage
context_stage = omni.usd.get_context().get_stage()
with stage_utils.use_stage(context_stage):
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) != num_clones
# attach stage to context
sim_utils.attach_stage_to_usd_context()
# verify stage is no longer in memory
assert not sim_utils.is_current_stage_in_memory()
# verify prims now exist in context stage
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) == num_clones
def test_stage_in_memory_with_clone_in_fabric(sim):
"""Test cloning in fabric with stage in memory."""
# define parameters
usd_path = f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd"
num_clones = 100
# grab stage in memory and set as current stage via the with statement
stage_in_memory = sim.get_initial_stage()
with stage_utils.use_stage(stage_in_memory):
# set up paths
base_env_path = "/World/envs"
source_prim_path = f"{base_env_path}/env_0"
# create cloner
cloner = GridCloner(spacing=3, stage=stage_in_memory)
cloner.define_base_env(base_env_path)
# create source prim
prim_utils.create_prim(f"{source_prim_path}/Robot", "Xform", usd_path=usd_path)
# generate target paths
target_paths = cloner.generate_paths("/World/envs/env", num_clones)
# clone robots at target paths
cloner.clone(
source_prim_path=source_prim_path,
base_env_path=base_env_path,
prim_paths=target_paths,
replicate_physics=True,
clone_in_fabric=True,
)
prim_path_regex = "/World/envs/env_.*"
# verify prims do not exist in context stage
context_stage = omni.usd.get_context().get_stage()
with stage_utils.use_stage(context_stage):
prims = prim_utils.find_matching_prim_paths(prim_path_regex)
assert len(prims) != num_clones
# attach stage to context
sim_utils.attach_stage_to_usd_context()
# verify stage is no longer in memory
assert not sim_utils.is_current_stage_in_memory()
# verify prims now exist in fabric stage using usdrt apis
stage_id = stage_utils.get_current_stage_id()
usdrt_stage = usdrt.Usd.Stage.Attach(stage_id)
for i in range(num_clones):
prim = usdrt_stage.GetPrimAtPath(f"/World/envs/env_{i}/Robot")
assert prim.IsValid()
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2024-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2024-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
...@@ -8,14 +8,14 @@ from __future__ import annotations ...@@ -8,14 +8,14 @@ from __future__ import annotations
import torch import torch
import omni.usd
# from Isaac Sim 4.2 onwards, pxr.Semantics is deprecated # from Isaac Sim 4.2 onwards, pxr.Semantics is deprecated
try: try:
import Semantics import Semantics
except ModuleNotFoundError: except ModuleNotFoundError:
from pxr import Semantics from pxr import Semantics
from isaacsim.core.utils.stage import get_current_stage
import isaaclab.sim as sim_utils import isaaclab.sim as sim_utils
from isaaclab.assets import Articulation, RigidObject from isaaclab.assets import Articulation, RigidObject
from isaaclab.scene import InteractiveSceneCfg from isaaclab.scene import InteractiveSceneCfg
...@@ -78,7 +78,7 @@ class ShadowHandVisionEnv(InHandManipulationEnv): ...@@ -78,7 +78,7 @@ class ShadowHandVisionEnv(InHandManipulationEnv):
self.object = RigidObject(self.cfg.object_cfg) self.object = RigidObject(self.cfg.object_cfg)
self._tiled_camera = TiledCamera(self.cfg.tiled_camera) self._tiled_camera = TiledCamera(self.cfg.tiled_camera)
# get stage # get stage
stage = omni.usd.get_context().get_stage() stage = get_current_stage()
# add semantics for in-hand cube # add semantics for in-hand cube
prim = stage.GetPrimAtPath("/World/envs/env_0/object") prim = stage.GetPrimAtPath("/World/envs/env_0/object")
sem = Semantics.SemanticsAPI.Apply(prim, "Semantics") sem = Semantics.SemanticsAPI.Apply(prim, "Semantics")
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2025, The Isaac Lab Project Developers. # Copyright (c) 2025, The Isaac Lab Project Developers.
# All rights reserved. # All rights reserved.
# #
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment