Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds check that no articulation root API is applied on rigid bodies #1358

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions source/extensions/omni.isaac.lab/docs/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
---------

0.27.14 (2024-11-04)
~~~~~~~~~~~~~~~~~~~~

* If a USD that contains an articulation root is loaded using a
:attr:`omni.isaac_lab.assets.RigidBody` we now fail unless the articulation root is explicitly
disabled. Using an articulation root for rigid bodies is not needed and decreases overall performance.


0.27.13 (2024-10-30)
~~~~~~~~~~~~~~~~~~~~

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ def _initialize_impl(self):
" Please ensure that there is only one rigid body in the prim path tree."
)

articulation_prims = sim_utils.get_all_matching_child_prims(
template_prim_path, predicate=lambda prim: prim.HasAPI(UsdPhysics.ArticulationRootAPI)
)
if len(articulation_prims) != 0:
if articulation_prims[0].GetAttribute("physxArticulation:articulationEnabled").Get():
raise RuntimeError(
f"Found an articulation root when resolving '{self.cfg.prim_path}' for rigid objects. These are"
f" located at: '{articulation_prims}' under '{template_prim_path}'. Please disable the articulation"
" root in the USD or from code by setting the parameter"
" 'ArticulationRootPropertiesCfg.articulation_enabled' to False in the spawn configuration."
)

# 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) :]
Expand Down
53 changes: 43 additions & 10 deletions source/extensions/omni.isaac.lab/test/assets/test_rigid_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,31 @@
import ctypes
import torch
import unittest
from typing import Literal

import omni.isaac.core.utils.prims as prim_utils

import omni.isaac.lab.sim as sim_utils
from omni.isaac.lab.assets import RigidObject, RigidObjectCfg
from omni.isaac.lab.sim import build_simulation_context
from omni.isaac.lab.sim.spawners import materials
from omni.isaac.lab.utils.assets import ISAAC_NUCLEUS_DIR
from omni.isaac.lab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR
from omni.isaac.lab.utils.math import default_orientation, random_orientation


def generate_cubes_scene(
num_cubes: int = 1, height=1.0, has_api: bool = True, kinematic_enabled: bool = False, device: str = "cuda:0"
num_cubes: int = 1,
height=1.0,
api: Literal["none", "rigid_body", "articulation_root"] = "rigid_body",
kinematic_enabled: bool = False,
device: str = "cuda:0",
) -> 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.
api: The type of API that the cubes should have.
kinematic_enabled: Whether the cubes are kinematic.
device: Device to use for the simulation.

Expand All @@ -57,17 +62,25 @@ def generate_cubes_scene(
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",
rigid_props=sim_utils.RigidBodyPropertiesCfg(kinematic_enabled=kinematic_enabled),
)
else:
if api == "none":
# 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(),
)
elif api == "rigid_body":
spawn_cfg = sim_utils.UsdFileCfg(
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/DexCube/dex_cube_instanceable.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(kinematic_enabled=kinematic_enabled),
)
elif api == "articulation_root":
spawn_cfg = sim_utils.UsdFileCfg(
usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Tests/RigidObject/Cube/dex_cube_instanceable_with_articulation_root.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(kinematic_enabled=kinematic_enabled),
)
else:
raise ValueError(f"Unknown api: {api}")

# Create rigid object
cube_object_cfg = RigidObjectCfg(
prim_path="/World/Table_.*/Object",
Expand Down Expand Up @@ -161,7 +174,27 @@ def test_initialization_with_no_rigid_body(self):
with self.subTest(num_cubes=num_cubes, device=device):
with build_simulation_context(device=device, auto_add_lighting=True) as sim:
# Generate cubes scene
cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, has_api=False, device=device)
cube_object, _ = generate_cubes_scene(num_cubes=num_cubes, api="none", device=device)

# 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_initialization_with_articulation_root(self):
"""Test that initialization fails when an articulation root 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:
# Generate cubes scene
cube_object, _ = generate_cubes_scene(
num_cubes=num_cubes, api="articulation_root", device=device
)

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