Skip to content

Commit 3e7a470

Browse files
shafeef901Mayankm96
andcommitted
Fixes grid origins in TerrainImporter to match Isaac Sim cloner (#300)
The logic for grid cloning in Isaac Sim GridCloner (func: `get_clone_transforms()`) and in TerrainImporter.py (func: `_compute_env_origins_grid()`) are different. Consequently, they give inconsistent values. This PR fixes the TerrainImporter by updating the logic of `_compute_env_origins_grid()` to make it consistent with IsaacSim. Fixes #287 - Bug fix (non-breaking change which fixes an issue) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./orbit.sh --format` - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] I have run all the tests with `./orbit.sh --test` and they pass - [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 --------- Signed-off-by: Shafeef Omar <[email protected]> Co-authored-by: Mayank Mittal <[email protected]>
1 parent c87ffea commit 3e7a470

File tree

6 files changed

+129
-6
lines changed

6 files changed

+129
-6
lines changed

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Guidelines for modifications:
4343
* René Zurbrügg
4444
* Ritvik Singh
4545
* Rosario Scalise
46+
* Shafeef Omar
4647

4748
## Acknowledgements
4849

source/extensions/omni.isaac.orbit/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.15.4"
4+
version = "0.15.5"
55

66
# Description
77
title = "ORBIT framework for Robot Learning"

source/extensions/omni.isaac.orbit/docs/CHANGELOG.rst

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

4+
0.15.5 (2024-03-23)
5+
~~~~~~~~~~~~~~~~~~~
6+
7+
Fixed
8+
^^^^^
9+
10+
* Fixed the env origins in :meth:`_compute_env_origins_grid` of :class:`omni.isaac.orbit.terrain.TerrainImporter`
11+
to match that obtained from the Isaac Sim :class:`omni.isaac.cloner.GridCloner` class.
12+
13+
Added
14+
^^^^^
15+
16+
* Added unit test to ensure consistency between environment origins generated by IsaacSim's Grid Cloner and those
17+
produced by the TerrainImporter.
18+
19+
420
0.15.4 (2024-03-22)
521
~~~~~~~~~~~~~~~~~~~
622

source/extensions/omni.isaac.orbit/omni/isaac/orbit/terrains/terrain_importer.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,12 @@ def _compute_env_origins_grid(self, num_envs: int, env_spacing: float) -> torch.
351351
# create tensor based on number of environments
352352
env_origins = torch.zeros(num_envs, 3, device=self.device)
353353
# create a grid of origins
354-
num_cols = np.floor(np.sqrt(num_envs))
355-
num_rows = np.ceil(num_envs / num_cols)
356-
xx, yy = torch.meshgrid(torch.arange(num_rows), torch.arange(num_cols), indexing="xy")
357-
env_origins[:, 0] = env_spacing * xx.flatten()[:num_envs] - env_spacing * (num_rows - 1) / 2
358-
env_origins[:, 1] = env_spacing * yy.flatten()[:num_envs] - env_spacing * (num_cols - 1) / 2
354+
num_rows = np.ceil(num_envs / int(np.sqrt(num_envs)))
355+
num_cols = np.ceil(num_envs / num_rows)
356+
ii, jj = torch.meshgrid(
357+
torch.arange(num_rows, device=self.device), torch.arange(num_cols, device=self.device), indexing="ij"
358+
)
359+
env_origins[:, 0] = -(ii.flatten()[:num_envs] - (num_rows - 1) / 2) * env_spacing
360+
env_origins[:, 1] = (jj.flatten()[:num_envs] - (num_cols - 1) / 2) * env_spacing
359361
env_origins[:, 2] = 0.0
360362
return env_origins
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright (c) 2022-2024, The ORBIT Project Developers.
2+
# All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
from __future__ import annotations
7+
8+
"""Launch Isaac Sim Simulator first."""
9+
10+
from omni.isaac.orbit.app import AppLauncher
11+
12+
# launch omniverse app
13+
app_launcher = AppLauncher(headless=True)
14+
simulation_app = app_launcher.app
15+
16+
"""Rest everything follows."""
17+
18+
import torch
19+
import unittest
20+
21+
import omni.isaac.core.utils.prims as prim_utils
22+
from omni.isaac.cloner import GridCloner
23+
24+
import omni.isaac.orbit.sim as sim_utils
25+
from omni.isaac.orbit.terrains import TerrainImporter, TerrainImporterCfg
26+
27+
28+
class TestTerrainImporter(unittest.TestCase):
29+
"""Test the terrain importer for different ground and procedural terrains."""
30+
31+
def test_grid_clone_env_origins(self):
32+
"""Tests that env origins are consistent when computed using the TerrainImporter and IsaacSim GridCloner."""
33+
# iterate over different number of environments and environment spacing
34+
for env_spacing in [1.0, 4.325, 8.0]:
35+
for num_envs in [1, 4, 125, 379, 1024]:
36+
with self.subTest(num_envs=num_envs, env_spacing=env_spacing):
37+
with sim_utils.build_simulation_context(auto_add_lighting=True) as sim:
38+
# create terrain importer
39+
terrain_importer_cfg = TerrainImporterCfg(
40+
num_envs=num_envs,
41+
env_spacing=env_spacing,
42+
prim_path="/World/ground",
43+
terrain_type="plane", # for flat ground, origins are in grid
44+
terrain_generator=None,
45+
)
46+
terrain_importer = TerrainImporter(terrain_importer_cfg)
47+
# obtain env origins using terrain importer
48+
terrain_importer_origins = terrain_importer.env_origins
49+
50+
# obtain env origins using grid cloner
51+
grid_cloner_origins = self.obtain_grid_cloner_env_origins(
52+
num_envs, env_spacing, device=sim.device
53+
)
54+
55+
# check if the env origins are the same
56+
torch.testing.assert_close(terrain_importer_origins, grid_cloner_origins, rtol=1e-5, atol=1e-5)
57+
58+
"""
59+
Helper functions.
60+
"""
61+
62+
@staticmethod
63+
def obtain_grid_cloner_env_origins(num_envs: int, env_spacing: float, device: str) -> torch.Tensor:
64+
"""Obtain the env origins generated by IsaacSim GridCloner (grid_cloner.py)."""
65+
# create grid cloner
66+
cloner = GridCloner(spacing=env_spacing)
67+
cloner.define_base_env("/World/envs")
68+
envs_prim_paths = cloner.generate_paths("/World/envs/env", num_paths=num_envs)
69+
prim_utils.define_prim("/World/envs/env_0")
70+
# clone envs using grid cloner
71+
env_origins = cloner.clone(
72+
source_prim_path="/World/envs/env_0", prim_paths=envs_prim_paths, replicate_physics=True
73+
)
74+
# return as tensor
75+
return torch.tensor(env_origins, dtype=torch.float32, device=device)
76+
77+
78+
if __name__ == "__main__":
79+
# run main
80+
runner = unittest.main(verbosity=2, exit=False)
81+
# close sim app
82+
simulation_app.close()
83+
# report success
84+
exit(not runner.result.wasSuccessful())

train_all_envs.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import subprocess
2+
3+
# List of task names
4+
task_names = [
5+
"Isaac-Velocity-Rough-Anymal-B-v0",
6+
"Isaac-Velocity-Rough-Anymal-C-v0",
7+
"Isaac-Velocity-Rough-Anymal-D-v0",
8+
"Isaac-Velocity-Rough-Cassie-v0",
9+
"Isaac-Velocity-Rough-Unitree-A1-v0",
10+
"Isaac-Velocity-Rough-Unitree-Go1-v0",
11+
"Isaac-Velocity-Rough-Unitree-Go2-v0",
12+
]
13+
14+
# Command template
15+
command_template = "./orbit.sh -p source/standalone/workflows/rsl_rl/train.py --task={task_name} --headless"
16+
17+
# Iterate over each task name and run the command
18+
for task_name in task_names:
19+
command = command_template.format(task_name=task_name)
20+
subprocess.run(command, shell=True)

0 commit comments

Comments
 (0)