Skip to content

Commit ba3af1a

Browse files
committed
remove attach_stage_to_usd_context, and simply attach in sim context
1 parent fb088fa commit ba3af1a

File tree

6 files changed

+30
-127
lines changed

6 files changed

+30
-127
lines changed

docs/source/how-to/optimize_stage_creation.rst

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,23 @@ Stage in memory can be toggled by setting the :attr:`isaaclab.sim.SimulationCfg.
4747
# create env with stage in memory
4848
env = ManagerBasedRLEnv(cfg=cfg)
4949
50-
Note, if stage in memory is enabled without using an existing RL environment class, a few more steps are need.
51-
The stage creation steps should be wrapped in a :py:keyword:`with` statement to set the stage context.
52-
If the stage needs to be attached, the :meth:`~isaaclab.sim.utils.attach_stage_to_usd_context` function should
53-
be called after the stage is created.
50+
When using stage in memory without an existing RL environment class, wrap the stage creation steps
51+
in a :py:keyword:`with` statement to set the stage context. The stage is automatically attached
52+
to the USD context when ``SimulationContext`` is created with ``create_stage_in_memory=True``.
5453

5554
**Using Stage in Memory with a manual scene setup**
5655

5756
.. code-block:: python
5857
5958
# init simulation context with stage in memory
59+
# Note: stage is automatically attached to USD context
6060
sim = SimulationContext(cfg=SimulationCfg(create_stage_in_memory=True))
6161
62-
# grab stage in memory and set stage context
62+
# grab stage and set stage context
6363
with stage_utils.use_stage(sim.stage):
6464
# create cartpole scene
6565
scene_cfg = CartpoleSceneCfg(num_envs=1024)
6666
scene = InteractiveScene(scene_cfg)
67-
# attach stage to memory after stage is created
68-
sim_utils.attach_stage_to_usd_context()
6967
7068
sim.play()
7169
@@ -117,13 +115,11 @@ Limitations
117115

118116
- Cannot be currently enabled at the same time as **Fabric Cloning**.
119117

120-
- Attaching stage in memory to the USD context can be slow, offsetting some or all of the performance benefits.
121-
122-
- Note, attaching is only necessary when rendering is enabled. For example, in headless mode, attachment is not required.
118+
- The stage is automatically attached to the USD context at ``SimulationContext`` creation, ensuring proper
119+
lifecycle events for viewport and physics systems.
123120

124121
- Certain low-level Kit APIs do not yet support stage in memory.
125122

126-
- In most cases, when these APIs are hit, existing scripts will automatically early attach the stage and print a warning message.
127123
- In one particular case, for some environments, the API call to color the ground plane is skipped, when stage in memory is enabled.
128124

129125

source/isaaclab/isaaclab/envs/direct_marl_env.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from isaaclab.managers import EventManager
2626
from isaaclab.scene import InteractiveScene
2727
from isaaclab.sim import SimulationContext
28-
from isaaclab.sim.utils.stage import attach_stage_to_usd_context, use_stage
28+
from isaaclab.sim.utils.stage import use_stage
2929
from isaaclab.utils.noise import NoiseModel
3030
from isaaclab.utils.seed import configure_seed
3131
from isaaclab.utils.timer import Timer
@@ -125,7 +125,6 @@ def __init__(self, cfg: DirectMARLEnvCfg, render_mode: str | None = None, **kwar
125125
with use_stage(self.sim.stage):
126126
self.scene = InteractiveScene(self.cfg.scene)
127127
self._setup_scene()
128-
attach_stage_to_usd_context()
129128
print("[INFO]: Scene manager: ", self.scene)
130129

131130
# set up camera viewport controller

source/isaaclab/isaaclab/envs/direct_rl_env.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from isaaclab.managers import EventManager
2727
from isaaclab.scene import InteractiveScene
2828
from isaaclab.sim import SimulationContext
29-
from isaaclab.sim.utils.stage import attach_stage_to_usd_context, use_stage
29+
from isaaclab.sim.utils.stage import use_stage
3030
from isaaclab.utils.noise import NoiseModel
3131
from isaaclab.utils.seed import configure_seed
3232
from isaaclab.utils.timer import Timer
@@ -131,7 +131,6 @@ def __init__(self, cfg: DirectRLEnvCfg, render_mode: str | None = None, **kwargs
131131
with use_stage(self.sim.stage):
132132
self.scene = InteractiveScene(self.cfg.scene)
133133
self._setup_scene()
134-
attach_stage_to_usd_context()
135134
print("[INFO]: Scene manager: ", self.scene)
136135

137136
# set up camera viewport controller

source/isaaclab/isaaclab/envs/manager_based_env.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from isaaclab.managers import ActionManager, EventManager, ObservationManager, RecorderManager
1717
from isaaclab.scene import InteractiveScene
1818
from isaaclab.sim import SimulationContext
19-
from isaaclab.sim.utils.stage import attach_stage_to_usd_context, use_stage
19+
from isaaclab.sim.utils.stage import use_stage
2020
from isaaclab.ui.widgets import ManagerLiveVisualizer
2121
from isaaclab.utils.seed import configure_seed
2222
from isaaclab.utils.timer import Timer
@@ -138,7 +138,6 @@ def __init__(self, cfg: ManagerBasedEnvCfg):
138138
# set the stage context for scene creation steps which use the stage
139139
with use_stage(self.sim.stage):
140140
self.scene = InteractiveScene(self.cfg.scene)
141-
attach_stage_to_usd_context()
142141
print("[INFO]: Scene manager: ", self.scene)
143142

144143
# set up camera viewport controller

source/isaaclab/isaaclab/sim/utils/stage.py

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ def get_context_stage() -> Usd.Stage | None:
9393
* Most Isaac Sim/Omniverse systems operate on by default
9494
9595
This is different from an "in-memory stage" created via
96-
:func:`create_new_stage_in_memory`, which exists only in RAM and is not
97-
attached to the context (invisible to viewport/UI until explicitly attached
98-
via :func:`attach_stage_to_usd_context`).
96+
:func:`create_new_stage_in_memory`, which exists only in RAM. Note that when
97+
using ``SimulationCfg(create_stage_in_memory=True)``, the in-memory stage is
98+
automatically attached to the USD context at ``SimulationContext`` creation.
9999
100100
Returns:
101101
The stage attached to the USD context, or None if no stage is attached.
@@ -513,56 +513,3 @@ def get_current_stage_id() -> int:
513513
stage_id = stage_cache.Insert(stage).ToLongInt()
514514
# return stage ID
515515
return stage_id
516-
517-
518-
def attach_stage_to_usd_context(attaching_early: bool = False):
519-
"""Attaches the current USD stage in memory to the USD context.
520-
521-
This function should be called during or after scene is created and before stage is simulated or rendered.
522-
If the stage is not in memory or rendering is not enabled, this function will return without attaching.
523-
524-
.. versionadded:: 2.3.0
525-
This function is available in Isaac Sim 5.0 and later. For backwards
526-
compatibility, it returns without attaching to the USD context.
527-
528-
Args:
529-
attaching_early: Whether to attach the stage to the usd context before stage is created. Defaults to False.
530-
"""
531-
532-
import carb
533-
import omni.physx
534-
import omni.usd
535-
536-
from isaaclab.sim.simulation_context import SimulationContext
537-
538-
# if Isaac Sim version is less than 5.0, stage in memory is not supported
539-
if get_isaac_sim_version().major < 5:
540-
return
541-
542-
# if stage is not in memory, we can return early
543-
if not is_current_stage_in_memory():
544-
return
545-
546-
# attach stage to physx
547-
stage_id = get_current_stage_id()
548-
physx_sim_interface = omni.physx.get_physx_simulation_interface()
549-
physx_sim_interface.attach_stage(stage_id)
550-
551-
# this carb flag is equivalent to if rendering is enabled
552-
carb_setting = carb.settings.get_settings() # type: ignore
553-
is_rendering_enabled = carb_setting.get("/physics/fabricUpdateTransformations")
554-
555-
# if rendering is not enabled, we don't need to attach it
556-
if not is_rendering_enabled:
557-
return
558-
559-
# early attach warning msg
560-
if attaching_early:
561-
logger.warning(
562-
"Attaching stage in memory to USD context early to support an operation which"
563-
" does not support stage in memory."
564-
)
565-
566-
# Enable physics fabric and attach stage to usd context for rendering
567-
SimulationContext.instance().set_setting("/isaaclab/fabric_enabled", True)
568-
omni.usd.get_context().attach_stage_with_callback(stage_id)

source/isaaclab/test/sim/test_simulation_stage_in_memory.py

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ def test_stage_in_memory_with_shapes(sim):
5555
# define parameters
5656
num_clones = 10
5757

58-
# grab stage in memory and set as current stage via the with statement
58+
# verify stage is attached to USD context (happens automatically now with create_stage_in_memory)
59+
assert not sim_utils.is_current_stage_in_memory()
60+
61+
# grab stage and set as current stage via the with statement
5962
stage_in_memory = sim.stage
6063
with sim_utils.use_stage(stage_in_memory):
6164
# create cloned cone stage
@@ -108,27 +111,11 @@ def test_stage_in_memory_with_shapes(sim):
108111
prim_path_regex = "/World/env_.*/Cone"
109112
cfg.func(prim_path_regex, cfg)
110113

111-
# verify stage is in memory
112-
assert sim_utils.is_current_stage_in_memory()
113-
114-
# verify prims exist in stage in memory
114+
# verify prims exist in stage
115115
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
116116
assert len(prims) == num_clones
117117

118-
# verify prims do not exist in context stage (if one exists)
119-
context_stage = sim_utils.get_context_stage()
120-
if context_stage is not None:
121-
with sim_utils.use_stage(context_stage):
122-
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
123-
assert len(prims) != num_clones
124-
125-
# attach stage to context
126-
sim_utils.attach_stage_to_usd_context()
127-
128-
# verify stage is no longer in memory
129-
assert not sim_utils.is_current_stage_in_memory()
130-
131-
# verify prims now exist in context stage
118+
# verify prims exist in context stage
132119
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
133120
assert len(prims) == num_clones
134121

@@ -147,7 +134,10 @@ def test_stage_in_memory_with_usds(sim):
147134
f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-D/anymal_d.usd",
148135
]
149136

150-
# grab stage in memory and set as current stage via the with statement
137+
# verify stage is attached to USD context (happens automatically now with create_stage_in_memory)
138+
assert not sim_utils.is_current_stage_in_memory()
139+
140+
# grab stage and set as current stage via the with statement
151141
stage_in_memory = sim.stage
152142
with sim_utils.use_stage(stage_in_memory):
153143
# create cloned robot stage
@@ -174,27 +164,11 @@ def test_stage_in_memory_with_usds(sim):
174164
prim_path_regex = "/World/env_.*/Robot"
175165
cfg.func(prim_path_regex, cfg)
176166

177-
# verify stage is in memory
178-
assert sim_utils.is_current_stage_in_memory()
179-
180-
# verify prims exist in stage in memory
167+
# verify prims exist in stage
181168
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
182169
assert len(prims) == num_clones
183170

184-
# verify prims do not exist in context stage (if one exists)
185-
context_stage = sim_utils.get_context_stage()
186-
if context_stage is not None:
187-
with sim_utils.use_stage(context_stage):
188-
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
189-
assert len(prims) != num_clones
190-
191-
# attach stage to context
192-
sim_utils.attach_stage_to_usd_context()
193-
194-
# verify stage is no longer in memory
195-
assert not sim_utils.is_current_stage_in_memory()
196-
197-
# verify prims now exist in context stage
171+
# verify prims exist in context stage
198172
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
199173
assert len(prims) == num_clones
200174

@@ -210,7 +184,10 @@ def test_stage_in_memory_with_clone_in_fabric(sim):
210184
usd_path = f"{ISAACLAB_NUCLEUS_DIR}/Robots/ANYbotics/ANYmal-C/anymal_c.usd"
211185
num_clones = 100
212186

213-
# grab stage in memory and set as current stage via the with statement
187+
# verify stage is attached to USD context (happens automatically now with create_stage_in_memory)
188+
assert not sim_utils.is_current_stage_in_memory()
189+
190+
# grab stage and set as current stage via the with statement
214191
stage_in_memory = sim.stage
215192
with sim_utils.use_stage(stage_in_memory):
216193
# set up paths
@@ -235,22 +212,8 @@ def test_stage_in_memory_with_clone_in_fabric(sim):
235212
replicate_physics=True,
236213
clone_in_fabric=True,
237214
)
238-
prim_path_regex = "/World/envs/env_.*"
239-
240-
# verify prims do not exist in context stage (if one exists)
241-
context_stage = sim_utils.get_context_stage()
242-
if context_stage is not None:
243-
with sim_utils.use_stage(context_stage):
244-
prims = sim_utils.find_matching_prim_paths(prim_path_regex)
245-
assert len(prims) != num_clones
246-
247-
# attach stage to context
248-
sim_utils.attach_stage_to_usd_context()
249-
250-
# verify stage is no longer in memory
251-
assert not sim_utils.is_current_stage_in_memory()
252215

253-
# verify prims now exist in fabric stage using usdrt apis
216+
# verify prims exist in fabric stage using usdrt apis
254217
stage_id = sim_utils.get_current_stage_id()
255218
usdrt_stage = usdrt.Usd.Stage.Attach(stage_id)
256219
for i in range(num_clones):

0 commit comments

Comments
 (0)