Unverified Commit 7ed94ce5 authored by Nicola Loi's avatar Nicola Loi Committed by GitHub

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: 's avatarNicola Loi <nicolaloi@outlook.com>
parent b5078deb
[package]
# Note: Semantic Versioning is used: https://semver.org/
version = "0.30.4"
version = "0.30.5"
# Description
title = "Isaac Lab framework for Robot Learning"
......
Changelog
---------
0.30.5 (2025-01-14)
~~~~~~~~~~~~~~~~~~~
Fixed
^^^^^
* 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.
0.30.4 (2025-01-08)
~~~~~~~~~~~~~~~~~~~
......
......@@ -815,22 +815,27 @@ def repeated_objects_terrain(
])
platform_corners[0, :] *= 1 - platform_clearance
platform_corners[1, :] *= 1 + platform_clearance
# sample center for objects
while True:
object_centers = np.zeros((num_objects, 3))
object_centers[:, 0] = np.random.uniform(0, cfg.size[0], num_objects)
object_centers[:, 1] = np.random.uniform(0, cfg.size[1], num_objects)
# sample valid center for objects
object_centers = np.zeros((num_objects, 3))
# use a mask to track invalid objects that still require sampling
mask_objects_left = np.ones((num_objects,), dtype=bool)
# loop until no objects are left to sample
while np.any(mask_objects_left):
# only sample the centers of the remaining invalid objects
num_objects_left = mask_objects_left.sum()
object_centers[mask_objects_left, 0] = np.random.uniform(0, cfg.size[0], num_objects_left)
object_centers[mask_objects_left, 1] = np.random.uniform(0, cfg.size[1], num_objects_left)
# filter out the centers that are on the platform
is_within_platform_x = np.logical_and(
object_centers[:, 0] >= platform_corners[0, 0], object_centers[:, 0] <= platform_corners[1, 0]
object_centers[mask_objects_left, 0] >= platform_corners[0, 0],
object_centers[mask_objects_left, 0] <= platform_corners[1, 0],
)
is_within_platform_y = np.logical_and(
object_centers[:, 1] >= platform_corners[0, 1], object_centers[:, 1] <= platform_corners[1, 1]
object_centers[mask_objects_left, 1] >= platform_corners[0, 1],
object_centers[mask_objects_left, 1] <= platform_corners[1, 1],
)
masks = np.logical_and(is_within_platform_x, is_within_platform_y)
# if there are no objects on the platform, break
if not np.any(masks):
break
# update the mask to track the validity of the objects sampled in this iteration
mask_objects_left[mask_objects_left] = np.logical_and(is_within_platform_x, is_within_platform_y)
# generate obstacles (but keep platform clean)
for index in range(len(object_centers)):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment