diff --git a/source/extensions/isaacsim.ros2.sim_control/python/impl/entity_utils.py b/source/extensions/isaacsim.ros2.sim_control/python/impl/entity_utils.py index 66cf0ad2cf..49906277b0 100644 --- a/source/extensions/isaacsim.ros2.sim_control/python/impl/entity_utils.py +++ b/source/extensions/isaacsim.ros2.sim_control/python/impl/entity_utils.py @@ -68,10 +68,9 @@ def get_filtered_entities(usdrt_stage: object, filter_pattern: str | None = None if not usdrt_stage: return [], "usdrt Stage not available for traversing" - # Get all prim paths from the usdrt stage - + # Get all prim paths from the usdrt stage. Stage.Traverse() already excludes the pseudo-root. all_prim_paths = [] - for prim in list(usdrt_stage.Traverse())[1:]: + for prim in usdrt_stage.Traverse(): if not prim.GetPrimPath().pathString.startswith("/Render"): all_prim_paths.append(prim.GetPrimPath().pathString) @@ -250,4 +249,4 @@ def create_empty_entity_state() -> object: empty_state.twist = Twist(linear=Vector3(x=0.0, y=0.0, z=0.0), angular=Vector3(x=0.0, y=0.0, z=0.0)) empty_state.acceleration = Accel(linear=Vector3(x=0.0, y=0.0, z=0.0), angular=Vector3(x=0.0, y=0.0, z=0.0)) - return empty_state + return empty_state \ No newline at end of file diff --git a/source/extensions/isaacsim.ros2.sim_control/python/tests/test_entity_utils.py b/source/extensions/isaacsim.ros2.sim_control/python/tests/test_entity_utils.py new file mode 100644 index 0000000000..df86de3d67 --- /dev/null +++ b/source/extensions/isaacsim.ros2.sim_control/python/tests/test_entity_utils.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Regression tests for ROS 2 simulation-control entity utilities.""" + +import omni.kit.test +from isaacsim.ros2.sim_control.impl.entity_utils import get_filtered_entities + + +class _FakePath: + def __init__(self, path: str) -> None: + self.pathString = path + + +class _FakePrim: + def __init__(self, path: str) -> None: + self._path = _FakePath(path) + + def GetPrimPath(self) -> _FakePath: + return self._path + + +class _FakeStage: + def __init__(self, paths: list[str]) -> None: + self._prims = [_FakePrim(path) for path in paths] + + def Traverse(self) -> list[_FakePrim]: + return self._prims + + +class TestEntityUtils(omni.kit.test.TestCase): + def test_get_filtered_entities_keeps_first_traversed_prim(self) -> None: + stage = _FakeStage(["/First", "/Second", "/Render/Products"]) + + entities, error = get_filtered_entities(stage) + + self.assertEqual(error, "") + self.assertEqual(entities, ["/First", "/Second"]) + + def test_get_filtered_entities_applies_regex_to_all_prims(self) -> None: + stage = _FakeStage(["/RobotA", "/RobotB", "/Sensor"]) + + entities, error = get_filtered_entities(stage, r"Robot") + + self.assertEqual(error, "") + self.assertEqual(entities, ["/RobotA", "/RobotB"])