Skip to content

Commit 91ad494

Browse files
authored
Fixes visual prims handling during texture randomization. (#2476)
# Description <!-- 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 --> Fixed potential issues in :func:`~isaaclab.envs.mdp.events.randomize_visual_texture_material` related to handling visual prims during texture randomization. Fixes # (issue) <!-- 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. --> ## Type of change <!-- As you go through the list, delete the ones that are not applicable. --> - Bug fix (non-breaking change which fixes an issue) ## Screenshots Please attach before and after screenshots of the change if applicable. <!-- 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. --> ## Checklist - [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 - [x] My changes generate no new warnings - [ ] 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: YunLiu <55491388+KumoLiu@users.noreply.github.com>
1 parent 33e6865 commit 91ad494

File tree

4 files changed

+123
-4
lines changed

4 files changed

+123
-4
lines changed

source/isaaclab/config/extension.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
# Note: Semantic Versioning is used: https://semver.org/
4-
version = "0.40.5"
4+
version = "0.40.6"
55

66
# Description
77
title = "Isaac Lab framework for Robot Learning"

source/isaaclab/docs/CHANGELOG.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Changelog
22
---------
33

4+
0.40.6 (2025-06-12)
5+
~~~~~~~~~~~~~~~~~~~
6+
7+
Fixed
8+
^^^^^
9+
10+
* Fixed potential issues in :func:`~isaaclab.envs.mdp.events.randomize_visual_texture_material` related to handling visual prims during texture randomization.
11+
12+
413
0.40.5 (2025-05-22)
514
~~~~~~~~~~~~~~~~~~~
615

source/isaaclab/isaaclab/envs/mdp/events.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,8 +1229,25 @@ def __init__(self, cfg: EventTermCfg, env: ManagerBasedEnv):
12291229
body_names_regex = ".*"
12301230

12311231
# create the affected prim path
1232-
# TODO: Remove the hard-coded "/visuals" part.
1233-
prim_path = f"{asset.cfg.prim_path}/{body_names_regex}/visuals"
1232+
# Check if the pattern with '/visuals' yields results when matching `body_names_regex`.
1233+
# If not, fall back to a broader pattern without '/visuals'.
1234+
asset_main_prim_path = asset.cfg.prim_path
1235+
# Try the pattern with '/visuals' first for the generic case
1236+
pattern_with_visuals = f"{asset_main_prim_path}/{body_names_regex}/visuals"
1237+
# Use sim_utils to check if any prims currently match this pattern
1238+
matching_prims = sim_utils.find_matching_prim_paths(pattern_with_visuals)
1239+
if matching_prims:
1240+
# If matches are found, use the pattern with /visuals
1241+
prim_path = pattern_with_visuals
1242+
else:
1243+
# If no matches found, fall back to the broader pattern without /visuals
1244+
# This pattern (e.g., /World/envs/env_.*/Table/.*) should match visual prims
1245+
# whether they end in /visuals or have other structures.
1246+
prim_path = f"{asset_main_prim_path}/.*"
1247+
carb.log_info(
1248+
f"Pattern '{pattern_with_visuals}' found no prims. Falling back to '{prim_path}' for texture"
1249+
" randomization."
1250+
)
12341251

12351252
# Create the omni-graph node for the randomization term
12361253
def rep_texture_randomization():
@@ -1240,7 +1257,6 @@ def rep_texture_randomization():
12401257
rep.randomizer.texture(
12411258
textures=texture_paths, project_uvw=True, texture_rotate=rep.distribution.uniform(*texture_rotation)
12421259
)
1243-
12441260
return prims_group.node
12451261

12461262
# Register the event to the replicator

source/isaaclab/test/envs/test_texture_randomization.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import math
2121
import torch
2222
import unittest
23+
from unittest.mock import patch
2324

2425
import omni.usd
2526

@@ -127,6 +128,36 @@ class EventCfg:
127128
)
128129

129130

131+
@configclass
132+
class EventCfgFallback:
133+
"""Configuration for events that tests the fallback mechanism."""
134+
135+
# Test fallback when /visuals pattern doesn't match
136+
test_fallback_texture_randomizer = EventTerm(
137+
func=mdp.randomize_visual_texture_material,
138+
mode="reset",
139+
params={
140+
"asset_cfg": SceneEntityCfg("robot", body_names=["slider"]),
141+
"texture_paths": [
142+
f"{NVIDIA_NUCLEUS_DIR}/Materials/Base/Wood/Bamboo_Planks/Bamboo_Planks_BaseColor.png",
143+
f"{NVIDIA_NUCLEUS_DIR}/Materials/Base/Wood/Cherry/Cherry_BaseColor.png",
144+
],
145+
"event_name": "test_fallback_texture_randomizer",
146+
"texture_rotation": (0.0, 0.0),
147+
},
148+
)
149+
150+
reset_cart_position = EventTerm(
151+
func=mdp.reset_joints_by_offset,
152+
mode="reset",
153+
params={
154+
"asset_cfg": SceneEntityCfg("robot", joint_names=["slider_to_cart"]),
155+
"position_range": (-1.0, 1.0),
156+
"velocity_range": (-0.1, 0.1),
157+
},
158+
)
159+
160+
130161
@configclass
131162
class CartpoleEnvCfg(ManagerBasedEnvCfg):
132163
"""Configuration for the cartpole environment."""
@@ -150,6 +181,29 @@ def __post_init__(self):
150181
self.sim.dt = 0.005 # sim step every 5ms: 200Hz
151182

152183

184+
@configclass
185+
class CartpoleEnvCfgFallback(ManagerBasedEnvCfg):
186+
"""Configuration for the cartpole environment that tests fallback mechanism."""
187+
188+
# Scene settings
189+
scene = CartpoleSceneCfg(env_spacing=2.5)
190+
191+
# Basic settings
192+
actions = ActionsCfg()
193+
observations = ObservationsCfg()
194+
events = EventCfgFallback()
195+
196+
def __post_init__(self):
197+
"""Post initialization."""
198+
# viewer settings
199+
self.viewer.eye = (4.5, 0.0, 6.0)
200+
self.viewer.lookat = (0.0, 0.0, 2.0)
201+
# step settings
202+
self.decimation = 4 # env step every 4 sim steps: 200Hz / 4 = 50Hz
203+
# simulation settings
204+
self.sim.dt = 0.005 # sim step every 5ms: 200Hz
205+
206+
153207
class TestTextureRandomization(unittest.TestCase):
154208
"""Test for texture randomization"""
155209

@@ -186,6 +240,46 @@ def test_texture_randomization(self):
186240

187241
env.close()
188242

243+
def test_texture_randomization_fallback(self):
244+
"""Test texture randomization fallback mechanism when /visuals pattern doesn't match."""
245+
246+
def mock_find_matching_prim_paths(pattern):
247+
"""Mock function that simulates a case where /visuals pattern doesn't match."""
248+
# If the pattern contains '/visuals', return empty list to trigger fallback
249+
if pattern.endswith("/visuals"):
250+
return []
251+
return None
252+
253+
for device in ["cpu", "cuda"]:
254+
with self.subTest(device=device):
255+
# create a new stage
256+
omni.usd.get_context().new_stage()
257+
258+
# set the arguments - use fallback config
259+
env_cfg = CartpoleEnvCfgFallback()
260+
env_cfg.scene.num_envs = 16
261+
env_cfg.scene.replicate_physics = False
262+
env_cfg.sim.device = device
263+
264+
with patch.object(
265+
mdp.events.sim_utils, "find_matching_prim_paths", side_effect=mock_find_matching_prim_paths
266+
):
267+
# This should trigger the fallback mechanism and log the fallback message
268+
env = ManagerBasedEnv(cfg=env_cfg)
269+
270+
# simulate physics
271+
with torch.inference_mode():
272+
for count in range(20): # shorter test for fallback
273+
# reset every few steps to check nothing breaks
274+
if count % 10 == 0:
275+
env.reset()
276+
# sample random actions
277+
joint_efforts = torch.randn_like(env.action_manager.action)
278+
# step the environment
279+
env.step(joint_efforts)
280+
281+
env.close()
282+
189283
def test_texture_randomization_failure_replicate_physics(self):
190284
"""Test texture randomization failure when replicate physics is set to True."""
191285
# create a new stage

0 commit comments

Comments
 (0)