Skip to content

Commit

Permalink
Adds clearer initialization errors for asset classes (isaac-sim#509)
Browse files Browse the repository at this point in the history
# Description

Earlier, the error message for initializing asset classes (with invalid
prims) only checked "length != 1". However, the error messages are
clearer if we separate them for the null and many cases, respectively.
This MR fixes this for better error messages.

## Type of change

- New feature (non-breaking change which adds functionality)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.sh --format`
- [ ] 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
- [ ] 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
  • Loading branch information
Mayankm96 authored Apr 17, 2024
1 parent 779107f commit 952498c
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -546,15 +546,23 @@ def _initialize_impl(self):
if template_prim is None:
raise RuntimeError(f"Failed to find prim for expression: '{self.cfg.prim_path}'.")
template_prim_path = template_prim.GetPath().pathString

# find articulation root prims
root_prims = sim_utils.get_all_matching_child_prims(
template_prim_path, predicate=lambda prim: prim.HasAPI(UsdPhysics.ArticulationRootAPI)
)
if len(root_prims) != 1:
if len(root_prims) == 0:
raise RuntimeError(
f"Failed to find an articulation when resolving '{self.cfg.prim_path}'."
" Please ensure that the prim has 'USD ArticulationRootAPI' applied."
)
if len(root_prims) > 1:
raise RuntimeError(
f"Failed to find a single articulation root when resolving '{self.cfg.prim_path}'."
f" Found roots '{root_prims}' under '{template_prim_path}'."
f"Failed to find a single articulation when resolving '{self.cfg.prim_path}'."
f" Found multiple '{root_prims}' under '{template_prim_path}'."
" Please ensure that there is only one articulation in the prim path tree."
)

# resolve articulation root prim back into regex expression
root_prim_path = root_prims[0].GetPath().pathString
root_prim_path_expr = self.cfg.prim_path + root_prim_path[len(template_prim_path) :]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,25 +300,35 @@ def _initialize_impl(self):
if template_prim is None:
raise RuntimeError(f"Failed to find prim for expression: '{self.cfg.prim_path}'.")
template_prim_path = template_prim.GetPath().pathString

# find rigid root prims
root_prims = sim_utils.get_all_matching_child_prims(
template_prim_path, predicate=lambda prim: prim.HasAPI(UsdPhysics.RigidBodyAPI)
)
if len(root_prims) != 1:
if len(root_prims) == 0:
raise RuntimeError(
f"Failed to find a rigid body when resolving '{self.cfg.prim_path}'."
" Please ensure that the prim has 'USD RigidBodyAPI' applied."
)
if len(root_prims) > 1:
raise RuntimeError(
f"Failed to find a single rigid body when resolving '{self.cfg.prim_path}'."
f" Found multiple '{root_prims}' under '{template_prim_path}'."
" Please ensure that there is only one rigid body in the prim path tree."
)

# resolve root prim back into regex expression
root_prim_path = root_prims[0].GetPath().pathString
root_prim_path_expr = self.cfg.prim_path + root_prim_path[len(template_prim_path) :]
# -- object view
self._root_physx_view = self._physics_sim_view.create_rigid_body_view(root_prim_path_expr.replace(".*", "*"))

# log information about the articulation
carb.log_info(f"Rigid body initialized at: {self.cfg.prim_path} with root '{root_prim_path_expr}'.")
carb.log_info(f"Number of instances: {self.num_instances}")
carb.log_info(f"Number of bodies: {self.num_bodies}")
carb.log_info(f"Body names: {self.body_names}")

# create buffers
self._create_buffers()
# process configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@
from omni.isaac.orbit.utils.math import default_orientation, random_orientation


def generate_cubes_scene(num_cubes: int = 1, height=1.0) -> tuple[RigidObject, torch.Tensor]:
def generate_cubes_scene(num_cubes: int = 1, height=1.0, has_api: bool = True) -> tuple[RigidObject, torch.Tensor]:
"""Generate a scene with the provided number of cubes.
Args:
num_cubes: Number of cubes to generate.
height: Height of the cubes.
has_api: Whether the cubes have a rigid body API on them.
Returns:
RigidObject: The rigid object representing the cubes.
Expand All @@ -52,10 +53,21 @@ def generate_cubes_scene(num_cubes: int = 1, height=1.0) -> tuple[RigidObject, t
for i, origin in enumerate(origins):
prim_utils.create_prim(f"/World/Table_{i}", "Xform", translation=origin)

# Resolve spawn configuration
if has_api:
spawn_cfg = sim_utils.UsdFileCfg(
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
)
else:
# since no rigid body properties defined, this is just a static collider
spawn_cfg = sim_utils.CuboidCfg(
size=(0.1, 0.1, 0.1),
collision_props=sim_utils.CollisionPropertiesCfg(),
)
# Create rigid object
cube_object_cfg = RigidObjectCfg(
prim_path="/World/Table_.*/Object",
spawn=sim_utils.UsdFileCfg(usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd"),
spawn=spawn_cfg,
init_state=RigidObjectCfg.InitialStateCfg(pos=(0.0, 0.0, height)),
)
cube_object = RigidObject(cfg=cube_object_cfg)
Expand Down Expand Up @@ -99,6 +111,23 @@ def test_initialization(self):
# update object
cube_object.update(sim.cfg.dt)

def test_initialization_with_no_rigid_body(self):
"""Test that initialization fails when no rigid body is found at the provided prim path."""
for num_cubes in (1, 2):
for device in ("cuda:0", "cpu"):
with self.subTest(num_cubes=num_cubes, device=device):
with build_simulation_context(device=device, auto_add_lighting=True) as sim:
cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, has_api=False)

# Check that boundedness of rigid object is correct
self.assertEqual(ctypes.c_long.from_address(id(cube_object)).value, 1)

# Play sim
sim.reset()

# Check if object is initialized
self.assertFalse(cube_object._is_initialized)

def test_external_force_on_single_body(self):
"""Test application of external force on the base of the object.
Expand Down

0 comments on commit 952498c

Please sign in to comment.