Skip to content

Commit 7ed94ce

Browse files
authored
Fixes infinite loop in repeated_objects_terrain: respawn only wrong object samples (#1612)
# Description Currently, the [`repeated_objects_terrain`](https://github.com/isaac-sim/IsaacLab/blob/v1.4.0/source/extensions/omni.isaac.lab/omni/isaac/lab/terrains/trimesh/mesh_terrains.py#L721) function attempts to respawn all *N* required objects if even a single object lies within the central platform. However, the probability of successfully spawning *all objects* outside the central platform depends on the object density (i.e., the number of required objects relative to the terrain size) and the size of the central platform. For high object densities, this probability quickly approaches zero, causing the function to enter an infinite respawn loop. This PR addresses the issue by respawning only the objects that lie within the central platform during each loop, while leaving objects outside the platform untouched. This leads to faster terrain generation and prevents the worst-case scenario of getting stuck in an infinite respawn loop when object density is high. ## 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) ## Checklist - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [ ] 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: Nicola Loi <[email protected]>
1 parent b5078de commit 7ed94ce

File tree

3 files changed

+26
-12
lines changed

3 files changed

+26
-12
lines changed

source/extensions/omni.isaac.lab/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.30.4"
4+
version = "0.30.5"
55

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

source/extensions/omni.isaac.lab/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.30.5 (2025-01-14)
5+
~~~~~~~~~~~~~~~~~~~
6+
7+
Fixed
8+
^^^^^
9+
10+
* Fixed the respawn of only wrong object samples in :func:`repeated_objects_terrain` of :mod:`omni.isaac.lab.terrains.trimesh` module. Previously, the function was respawning all objects in the scene instead of only the wrong object samples, which in worst case could lead to infinite respawn loop.
11+
12+
413
0.30.4 (2025-01-08)
514
~~~~~~~~~~~~~~~~~~~
615

source/extensions/omni.isaac.lab/omni/isaac/lab/terrains/trimesh/mesh_terrains.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -815,22 +815,27 @@ def repeated_objects_terrain(
815815
])
816816
platform_corners[0, :] *= 1 - platform_clearance
817817
platform_corners[1, :] *= 1 + platform_clearance
818-
# sample center for objects
819-
while True:
820-
object_centers = np.zeros((num_objects, 3))
821-
object_centers[:, 0] = np.random.uniform(0, cfg.size[0], num_objects)
822-
object_centers[:, 1] = np.random.uniform(0, cfg.size[1], num_objects)
818+
# sample valid center for objects
819+
object_centers = np.zeros((num_objects, 3))
820+
# use a mask to track invalid objects that still require sampling
821+
mask_objects_left = np.ones((num_objects,), dtype=bool)
822+
# loop until no objects are left to sample
823+
while np.any(mask_objects_left):
824+
# only sample the centers of the remaining invalid objects
825+
num_objects_left = mask_objects_left.sum()
826+
object_centers[mask_objects_left, 0] = np.random.uniform(0, cfg.size[0], num_objects_left)
827+
object_centers[mask_objects_left, 1] = np.random.uniform(0, cfg.size[1], num_objects_left)
823828
# filter out the centers that are on the platform
824829
is_within_platform_x = np.logical_and(
825-
object_centers[:, 0] >= platform_corners[0, 0], object_centers[:, 0] <= platform_corners[1, 0]
830+
object_centers[mask_objects_left, 0] >= platform_corners[0, 0],
831+
object_centers[mask_objects_left, 0] <= platform_corners[1, 0],
826832
)
827833
is_within_platform_y = np.logical_and(
828-
object_centers[:, 1] >= platform_corners[0, 1], object_centers[:, 1] <= platform_corners[1, 1]
834+
object_centers[mask_objects_left, 1] >= platform_corners[0, 1],
835+
object_centers[mask_objects_left, 1] <= platform_corners[1, 1],
829836
)
830-
masks = np.logical_and(is_within_platform_x, is_within_platform_y)
831-
# if there are no objects on the platform, break
832-
if not np.any(masks):
833-
break
837+
# update the mask to track the validity of the objects sampled in this iteration
838+
mask_objects_left[mask_objects_left] = np.logical_and(is_within_platform_x, is_within_platform_y)
834839

835840
# generate obstacles (but keep platform clean)
836841
for index in range(len(object_centers)):

0 commit comments

Comments
 (0)