Skip to content
Merged
2 changes: 1 addition & 1 deletion source/isaaclab/config/extension.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

# Note: Semantic Versioning is used: https://semver.org/
version = "0.45.12"
version = "0.46.0"

# Description
title = "Isaac Lab framework for Robot Learning"
Expand Down
11 changes: 11 additions & 0 deletions source/isaaclab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Changelog
---------

0.46.0 (2025-09-06)
~~~~~~~~~~~~~~~~~~~

Changed
^^^^^^^

* Added parsing of instanced prims in :meth:`~isaaclab.sim.utils.get_all_matching_child_prims` and :meth:`~isaaclab.sim.utils.get_first_matching_child_prim`.
Earlier, instanced prims were skipped since :meth:`Usd.Prim.GetChildren` does not return instanced prims.
* Added parsing of instanced prims in :meth:`~isaaclab.sim.utils.make_uninstanceable` to make all prims uninstanceable.


0.45.12 (2025-09-05)
~~~~~~~~~~~~~~~~~~~~

Expand Down
6 changes: 3 additions & 3 deletions source/isaaclab/isaaclab/sim/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ def make_uninstanceable(prim_path: str | Sdf.Path, stage: Usd.Stage | None = Non
# make the prim uninstanceable
child_prim.SetInstanceable(False)
# add children to list
all_prims += child_prim.GetChildren()
all_prims += child_prim.GetFilteredChildren(Usd.TraverseInstanceProxies())


"""
Expand Down Expand Up @@ -617,7 +617,7 @@ def get_first_matching_child_prim(
if predicate(child_prim):
return child_prim
# add children to list
all_prims += child_prim.GetChildren()
all_prims += child_prim.GetFilteredChildren(Usd.TraverseInstanceProxies())
return None


Expand Down Expand Up @@ -673,7 +673,7 @@ def get_all_matching_child_prims(
output_prims.append(child_prim)
# add children to list
if depth is None or current_depth < depth:
all_prims_queue += [(child, current_depth + 1) for child in child_prim.GetChildren()]
all_prims_queue += [(child, current_depth + 1) for child in child_prim.GetFilteredChildren(Usd.TraverseInstanceProxies())]

return output_prims

Expand Down
48 changes: 45 additions & 3 deletions source/isaaclab/test/sim/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import isaacsim.core.utils.prims as prim_utils
import isaacsim.core.utils.stage as stage_utils
import pytest
from pxr import Sdf, Usd, UsdGeom
from pxr import Sdf, Usd, UsdGeom, UsdPhysics

import isaaclab.sim as sim_utils
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR
Expand All @@ -42,20 +42,62 @@ def test_get_all_matching_child_prims():
# create scene
prim_utils.create_prim("/World/Floor")
prim_utils.create_prim(
"/World/Floor/thefloor", "Cube", position=np.array([75, 75, -150.1]), attributes={"size": 300}
"/World/Floor/Box", "Cube", position=np.array([75, 75, -150.1]), attributes={"size": 300}
)
prim_utils.create_prim("/World/Room", "Sphere", attributes={"radius": 1e3})
prim_utils.create_prim("/World/Wall", "Sphere", attributes={"radius": 1e3})

# test
isaac_sim_result = prim_utils.get_all_matching_child_prims("/World")
isaaclab_result = sim_utils.get_all_matching_child_prims("/World")
assert isaac_sim_result == isaaclab_result

# add articulation root prim -- this asset has instanced prims
# note: isaac sim function does not support instanced prims so we add it here
# after the above test for the above test to still pass.
prim_utils.create_prim(
"/World/Franka", "Xform", usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/FrankaEmika/panda_instanceable.usd"
)

# test with predicate
isaaclab_result = sim_utils.get_all_matching_child_prims("/World", predicate=lambda x: x.GetTypeName() == "Cube")
assert len(isaaclab_result) == 1
assert isaaclab_result[0].GetPrimPath() == "/World/Floor/Box"

# test with predicate and instanced prims
isaaclab_result = sim_utils.get_all_matching_child_prims("/World/Franka/panda_hand/visuals", predicate=lambda x: x.GetTypeName() == "Mesh")
assert len(isaaclab_result) == 1
assert isaaclab_result[0].GetPrimPath() == "/World/Franka/panda_hand/visuals/panda_hand"

# test valid path
with pytest.raises(ValueError):
sim_utils.get_all_matching_child_prims("World/Room")


def test_get_first_matching_child_prim():
"""Test get_first_matching_child_prim() function."""
# create scene
prim_utils.create_prim("/World/Floor")
prim_utils.create_prim(
"/World/env_1/Franka", "Xform", usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/FrankaEmika/panda_instanceable.usd"
)
prim_utils.create_prim(
"/World/env_2/Franka", "Xform", usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/FrankaEmika/panda_instanceable.usd"
)
prim_utils.create_prim(
"/World/env_0/Franka", "Xform", usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/FrankaEmika/panda_instanceable.usd"
)

# test
isaaclab_result = sim_utils.get_first_matching_child_prim("/World", predicate=lambda prim: prim.HasAPI(UsdPhysics.ArticulationRootAPI))
assert isaaclab_result is not None
assert isaaclab_result.GetPrimPath() == "/World/env_1/Franka"

# test with instanced prims
isaaclab_result = sim_utils.get_first_matching_child_prim("/World/env_1/Franka", predicate=lambda prim: prim.GetTypeName() == "Mesh")
assert isaaclab_result is not None
assert isaaclab_result.GetPrimPath() == "/World/env_1/Franka/panda_link0/visuals/panda_link0"


def test_find_matching_prim_paths():
"""Test find_matching_prim_paths() function."""
# create scene
Expand Down
4 changes: 0 additions & 4 deletions source/isaaclab/utils/assets.py

This file was deleted.

Loading