Skip to content

Commit c318019

Browse files
authored
[Backport] Fix ray caster path matching regressions (#7516) (#7577)
# Description Backports #7516 to `release/3.0.0`. The automatic backport workflow completed successfully but skipped the backport because the source PR body did not retain the hidden `<!-- backport-active-release -->` selection marker. This branch manually cherry-picks the canonical merged commit `167b6b15538bc6ec23554ec1b69f45ac34ae35bd` with `-x` provenance. The cherry-pick applied without conflicts or release-specific edits. Its stable patch ID is identical to the source commit, and all seven source paths are preserved exactly. ## Type of change - Bug fix (non-breaking change which fixes an issue) ## Release backport - This PR already targets the active release branch. ## Validation - Stable source/backport patch IDs match: `b30f8378be6d764298eb95b92d8f5e03ffb97b51`. - `uv run python -m pytest source/isaaclab_newton/test/sensors/test_newton_raycast_sensor.py -vv` — 18 passed. - `uv run python -m pytest source/isaaclab/test/app/test_standalone_scripts.py::test_commands_respect_script_launcher_capabilities -vv` — 1 passed. - `ISAACLAB_CHANGELOG_BASE_REF=release/3.0.0 uv run isaaclab -f` — all hooks passed. - `git diff --check upstream/release/3.0.0..HEAD` — passed. ## Checklist - [x] I have read and understood the contribution guidelines - [x] I have run the pre-commit checks - [x] I have made corresponding changes to the tutorial and smoke configuration - [x] My changes generate no new warnings - [x] I have added tests that prove the fix is effective - [x] I have added changelog fragments for the touched source packages - [x] My name already exists in `CONTRIBUTORS.md`
1 parent 355dc9b commit c318019

7 files changed

Lines changed: 54 additions & 10 deletions

File tree

scripts/tutorials/04_sensors/run_ray_caster_camera.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def define_sensor() -> RayCasterCamera:
5757

5858
# Setup camera sensor
5959
camera_cfg = RayCasterCameraCfg(
60-
prim_path="/World/Origin_.*/CameraSensor",
60+
prim_path="/World/Origin_[^/]+/CameraSensor",
6161
mesh_prim_paths=["/World/ground"],
6262
update_period=0.1,
6363
offset=RayCasterCameraCfg.OffsetCfg(pos=(0.0, 0.0, 0.0), rot=(1.0, 0.0, 0.0, 0.0)),

source/isaaclab/changelog.d/fix-ray-caster-regex-paths.skip

Whitespace-only changes.

source/isaaclab/test/app/standalone_script_cases.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,7 @@ class SmokeResult:
265265
"scripts/tutorials/03_envs/run_cartpole_rl_env.py": ScriptOverride(readiness_pattern=r"Resetting environment"),
266266
"scripts/tutorials/04_sensors/add_sensors_on_robot.py": ScriptOverride(args=("--enable_cameras",)),
267267
"scripts/tutorials/04_sensors/run_ray_caster.py": ScriptOverride(visualizers=("none", "kit")),
268-
"scripts/tutorials/04_sensors/run_ray_caster_camera.py": ScriptOverride(
269-
args=("--enable_cameras",), visualizers=("none", "kit")
270-
),
268+
"scripts/tutorials/04_sensors/run_ray_caster_camera.py": ScriptOverride(visualizers=("none", "kit")),
271269
"scripts/tutorials/04_sensors/run_usd_camera.py": ScriptOverride(visualizers=("none", "kit")),
272270
"scripts/tutorials/07_visualizers/run_tiled_camera_visualizer.py": ScriptOverride(
273271
readiness_pattern=r"Gym action space",

source/isaaclab/test/app/test_standalone_scripts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ def test_commands_respect_script_launcher_capabilities():
232232
if case.spec.relative_path == "scripts/tutorials/04_sensors/run_ray_caster_camera.py"
233233
and case.visualizer == "none"
234234
)
235-
assert "--enable_cameras" in ray_camera_case.command()
235+
assert "--enable_cameras" not in ray_camera_case.command()
236236

237237
usd_camera_case = next(
238238
case
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fixed
2+
^^^^^
3+
4+
* Fixed legacy Newton multi-mesh ray casters failing to associate tracked target sites when target discovery
5+
produced a different path expression than site registration.

source/isaaclab_newton/isaaclab_newton/sensors/ray_caster/legacy_ray_caster.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@ class _LegacyNewtonRayCasterMixin(_NewtonRayCasterPoseMixin):
3737

3838
def __init__(self: Any, cfg):
3939
super().__init__(cfg)
40-
self._tracked_site_labels_by_target: dict[tuple[str, ...], list[str]] = {}
40+
self._tracked_site_labels: list[list[str]] = []
41+
self._tracked_target_index = 0
4142
for target_cfg in getattr(self, "_raycast_targets_cfg", []):
4243
if target_cfg.track_mesh_transforms:
4344
owner_exprs = self._resolve_target_owner_exprs(target_cfg.prim_expr)
4445
labels = self._register_target_sites_for_exprs(owner_exprs)
45-
self._tracked_site_labels_by_target[tuple(owner_exprs)] = labels
46+
self._tracked_site_labels.append(labels)
47+
48+
def _initialize_warp_meshes(self: Any) -> None:
49+
"""Reset tracked-target association before creating mesh views."""
50+
self._tracked_target_index = 0
51+
super()._initialize_warp_meshes()
4652

4753
def _resolve_target_owner_exprs(self, prim_expr: str) -> list[str]:
4854
"""Resolve mesh target expressions to owning rigid-body expressions."""
@@ -71,8 +77,8 @@ def _register_target_sites_for_exprs(self, owner_exprs: list[str]) -> list[str]:
7177

7278
def _create_tracked_target_view(self: Any, target_prim_path: str | list[str]) -> wp.array:
7379
"""Resolve dynamic multi-mesh target sites to Newton site indices."""
74-
target_exprs = target_prim_path if isinstance(target_prim_path, list) else [target_prim_path]
75-
labels = self._tracked_site_labels_by_target[tuple(target_exprs)]
80+
labels = self._tracked_site_labels[self._tracked_target_index]
81+
self._tracked_target_index += 1
7682
site_indices = self._resolve_site_indices(labels, str(target_prim_path), self._num_envs)
7783
return wp.array(site_indices, dtype=wp.int32, device=self._device)
7884

source/isaaclab_newton/test/sensors/test_newton_raycast_sensor.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@
2727
from isaaclab.assets import RigidObject, RigidObjectCfg
2828
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
2929
from isaaclab.sensors.camera import CameraCfg
30-
from isaaclab.sensors.ray_caster import MultiMeshRayCaster, MultiMeshRayCasterCamera, RayCasterCamera, RayCasterCfg
30+
from isaaclab.sensors.ray_caster import (
31+
MultiMeshRayCaster,
32+
MultiMeshRayCasterCamera,
33+
MultiMeshRayCasterCfg,
34+
RayCasterCamera,
35+
RayCasterCfg,
36+
)
3137
from isaaclab.sensors.ray_caster.patterns import GridPatternCfg
3238
from isaaclab.sim import SimulationCfg
3339
from isaaclab.terrains import TerrainImporterCfg
@@ -162,6 +168,35 @@ def test_remaining_warp_mesh_factories_select_legacy_newton_adapters(sim):
162168
assert MultiMeshRayCasterCamera.resolve_class() is LegacyMultiMeshRayCasterCamera
163169

164170

171+
def test_legacy_multi_mesh_tracks_ad_hoc_regex_target(sim):
172+
"""Tracked target registration remains valid when discovery returns concrete owner paths."""
173+
obstacle_cfg = sim_utils.CuboidCfg(
174+
size=(1.0, 1.0, 1.0),
175+
rigid_props=sim_utils.RigidBodyBaseCfg(kinematic_enabled=True),
176+
mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
177+
collision_props=sim_utils.CollisionBaseCfg(),
178+
)
179+
obstacle_cfg.func("/World/Origin_00/Obstacle", obstacle_cfg)
180+
181+
sensor_cfg = MultiMeshRayCasterCfg(
182+
prim_path="/World/Origin_[^/]+/Obstacle",
183+
mesh_prim_paths=[
184+
MultiMeshRayCasterCfg.RaycastTargetCfg(
185+
prim_expr="/World/Origin_[^/]+/Obstacle",
186+
track_mesh_transforms=True,
187+
)
188+
],
189+
pattern_cfg=GridPatternCfg(resolution=1.0, size=(0.0, 0.0)),
190+
)
191+
sensor = MultiMeshRayCaster(sensor_cfg)
192+
193+
sim.reset()
194+
sensor.update(sim.get_physics_dt(), force_recompute=True)
195+
196+
assert sensor.num_instances == 1
197+
assert sensor.data.ray_hits_w.shape[0] == 1
198+
199+
165200
def test_bvh_refit_tracks_moving_geometry(sim):
166201
"""Sliding a box under the sensor changes the hits, proving the BVH refits live."""
167202
scene = InteractiveScene(RaycastTestSceneCfg(num_envs=1))

0 commit comments

Comments
 (0)