Skip to content
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
16 changes: 16 additions & 0 deletions isaaclab_arena/assets/background_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,22 @@ def __init__(self):
super().__init__()


@register_asset
class OfficeTableBackground(LibraryBackground):
"""
A basic office table.
"""

name = "office_table_background"
tags = ["background"]
usd_path = f"{ISAACLAB_NUCLEUS_DIR}/Mimic/nut_pour_task/nut_pour_assets/table.usd"
object_min_z = -0.05
scale = (1.0, 1.0, 0.7)

def __init__(self):
super().__init__(scale=self.scale)


@register_asset
class LightwheelKitchenBackground(LibraryBackground):
"""
Expand Down
35 changes: 33 additions & 2 deletions isaaclab_arena/environments/arena_env_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,20 @@ def _solve_relations(self) -> None:
placer_params = ObjectPlacerParams(
placement_seed=self.args.placement_seed,
apply_positions_to_objects=False,
solver_params=RelationSolverParams(save_position_history=False, verbose=False),
solver_params=RelationSolverParams(
save_position_history=False,
verbose=False,
no_collision_xy_only=getattr(self.args, "no_collision_xy_only", True),
no_collision_include_anchors=getattr(self.args, "no_collision_include_anchors", False),
),
)
placement_max_attempts = getattr(self.args, "placement_max_attempts", None)
if placement_max_attempts is not None:
placer_params.max_placement_attempts = placement_max_attempts
if cli_resolve is not None:
placer_params.resolve_on_reset = cli_resolve

pool_size = num_envs * placer_params.min_unique_layouts_per_env
pool_size = getattr(self.args, "placement_pool_size", num_envs * placer_params.min_unique_layouts_per_env)

placement_pool = PooledObjectPlacer(
objects=objects_with_relations,
Expand Down Expand Up @@ -412,7 +420,30 @@ def make_registered_and_return_cfg(
) -> tuple[ManagerBasedEnv, IsaacLabArenaManagerBasedRLEnvCfg]:
name, cfg = self.build_registered(env_cfg)
env = gym.make(name, cfg=cfg, render_mode=render_mode)
if self.arena_env.force_convex_hull:
_force_convex_hull(env)
# ViewportCameraController sets the camera before KitVisualizer.initialize() is called,
# so the call is silently ignored. Re-apply here once the visualizers are fully initialized.
reapply_viewer_cfg(env)
return env, cfg


def _force_convex_hull(env: ManagerBasedEnv) -> None:
"""Replace ``convexDecomposition`` with ``convexHull`` on all MeshCollision prims.

``convexDecomposition`` on raw scanned meshes (e.g. robolab assets) creates
irregular contact surfaces that are unstable in multi-object scenarios.
``convexHull`` produces a single convex shape that behaves predictably.
"""
from pxr import UsdPhysics

stage = env.unwrapped.sim.stage
for prim in stage.Traverse():
if not prim.HasAPI(UsdPhysics.MeshCollisionAPI):
continue
mesh_col = UsdPhysics.MeshCollisionAPI(prim)
approx_attr = mesh_col.GetApproximationAttr()
if not approx_attr or not approx_attr.HasValue():
continue
if approx_attr.Get() == "convexDecomposition":
Comment on lines +431 to +448
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 _force_convex_hull modifies all MeshCollision prims including the robot

stage.Traverse() walks the entire USD stage. Every prim carrying UsdPhysics.MeshCollisionAPI with convexDecomposition is patched — including the robot embodiment's collision meshes, the table, and any other scenery that was explicitly authored with convexDecomposition for good reason. If the GR1 joint (or any other articulated body) uses convexDecomposition to correctly approximate its link geometry, silently switching it to convexHull may produce a less accurate (over-approximate) collision shape and change the robot's grasp physics. Scope-filtering by prim path prefix (e.g. skip paths under the embodiment's prim path) would limit the patch to only the placed objects.

approx_attr.Set("convexHull")
6 changes: 6 additions & 0 deletions isaaclab_arena/environments/isaaclab_arena_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def __init__(
env_cfg_callback: Callable[IsaacLabArenaManagerBasedRLEnvCfg] | None = None,
rl_framework_entry_point: str | None = None,
rl_policy_cfg: str | None = None,
force_convex_hull: bool = False,
):
"""
Args:
Expand All @@ -49,6 +50,10 @@ def __init__(
``rl_policy_cfg`` is set.
rl_policy_cfg: Import path to the RL policy config class, e.g.
``"my_module:RLPolicyCfg"``.
force_convex_hull: If True, replace ``convexDecomposition`` with ``convexHull``
on all MeshCollision prims after scene creation. Needed for assets with
raw scanned meshes (e.g. robolab objects) that are unstable with
``convexDecomposition``.
"""
self.name = name
self.scene = scene
Expand All @@ -57,6 +62,7 @@ def __init__(
self.teleop_device = teleop_device
self.orchestrator = orchestrator
self.env_cfg_callback = env_cfg_callback
self.force_convex_hull = force_convex_hull
if (rl_framework_entry_point is None) != (rl_policy_cfg is None):
raise ValueError("rl_framework_entry_point and rl_policy_cfg must both be set or both be None.")
self.rl_framework_entry_point = rl_framework_entry_point
Expand Down
Loading
Loading