Assets#
An asset is anything Arena places in a scene, such as a cracker box, a kitchen background,
a robot, or a light. Each asset has a name, which identifies it in the environment:
variation keys such as <name>.mass, its prim path, its contact sensor, and recorded data
use it. Most assets are objects (Object): spawned from a USD file or a spawn configuration
as a rigid, articulated, or static body. A robot (an embodiment) is an asset but not an object.
Arena ships with a library of asset classes, and new ones can be added by registering them.
Each asset class is registered under a registry_name, such as rubiks_cube_hot3d_robolab.
asset_registry.get_asset_by_name() returns the class. Calling the class creates an asset.
A library object such as CrackerBox is named after its registry name unless you pass name,
for example to name it after its role in the task:
CrackerBox = asset_registry.get_asset_by_name("cracker_box") # the class, registry_name "cracker_box"
cracker_box = CrackerBox() # an asset named "cracker_box"
pick_up_object = CrackerBox(name="pick_up_object") # an asset named "pick_up_object"
pick_up_object.registry_name # "cracker_box"
Backgrounds and robots take no name argument. Their name is always their registry name.
Most code does both steps in one line:
background = asset_registry.get_asset_by_name("kitchen")()
cracker_box = asset_registry.get_asset_by_name("cracker_box")()
Registering a new asset#
To add a new object, subclass LibraryObject, set its registry_name, provide the USD path
and object type, and decorate it with @register_asset:
@register_asset
class MyObject(LibraryObject):
registry_name = "my_object"
tags = ["object", "graspable"]
usd_path = "path/to/my_object.usd"
object_type = ObjectType.RIGID
Once registered, the class is available in the registry like any other asset class:
obj = asset_registry.get_asset_by_name("my_object")()
Assets can also be tagged to make them discoverable by category:
# All graspable objects
objects = asset_registry.get_assets_by_tag("graspable")
# A random graspable object
obj = asset_registry.get_random_asset_by_tag("graspable")()
Useful tags include "graspable", "openable", "pressable", and "background".
Assets can have multiple tags — for example, a fruit is tagged both "graspable" and "food".
Object configuration#
An object’s constructor sets its USD source, scale, initial pose, and object type.
asset_cfg_addon configures the Isaac Lab asset (for example, debug_vis or articulation
actuators). spawn_cfg_addon configures how the USD is loaded and which physics properties
are authored during spawning: mass/density, collision settings, and contact materials.
Use prim_physics within the spawn addons for selected bodies, colliders, or joints.
Physics spawn addons#
Use spawn_cfg_addon to override physics parameters:
Addon |
Example parameters |
|---|---|
|
Mass and density. |
|
Gravity, damping, and velocity limits. |
|
Collision enablement, contact offset, and rest offset. |
|
Static/dynamic friction and restitution. |
|
Self-collision and articulation solver settings. |
|
Selected-prim collision, material, mass, joint, or backend-specific settings,
defined by an environment-owned |
For example, override friction on the library red cube’s Cube collider:
import math
from isaaclab.utils.configclass import configclass
from pxr import UsdPhysics, UsdShade
from isaaclab_arena.assets.object_library import RedCube
from isaaclab_arena.assets.physics_config import UsdPrimSpawnPhysicsCfg
@configclass
class ColliderFrictionCfg(UsdPrimSpawnPhysicsCfg):
"""Bind an instance-local contact material to a selected collider."""
friction: float = 0.8
"""Static and dynamic friction coefficient."""
def validate_target(self, prim, root):
"""Require a collider and a finite nonnegative friction coefficient."""
assert prim.HasAPI(UsdPhysics.CollisionAPI)
assert math.isfinite(self.friction) and self.friction >= 0
assert not prim.GetStage().GetPrimAtPath(prim.GetPath().AppendChild("ContactMaterial"))
def apply(self, prim, root):
"""Author and bind a material within the spawned asset."""
# A local material preserves shared source materials and remaps during cloning.
material = UsdShade.Material.Define(prim.GetStage(), prim.GetPath().AppendChild("ContactMaterial"))
physics = UsdPhysics.MaterialAPI.Apply(material.GetPrim())
physics.CreateStaticFrictionAttr(self.friction)
physics.CreateDynamicFrictionAttr(self.friction)
UsdShade.MaterialBindingAPI.Apply(prim).Bind(
material,
bindingStrength=UsdShade.Tokens.strongerThanDescendants,
materialPurpose="physics",
)
class HighFrictionRedCube(RedCube):
spawn_cfg_addon = {
"prim_physics": {"Cube": ColliderFrictionCfg(friction=0.8)},
}
red_cube = HighFrictionRedCube()
prim_physics keys are exact paths relative to the asset root; use "." for the root.
Settings apply after USD loading and before cloning and physics import.
See Physics configuration for configuration order and Embodiment for robot and end-effector physics.
Object types#
Every asset has an object type that determines how it is simulated:
RIGID — a single rigid body (boxes, bottles, tools, furniture).
ARTICULATION — a multi-body scene object with joints (doors, drawers, appliances).
DEFORMABLE — a body represented by deformable simulation nodes (soft cubes, cloth, or other compliant objects).
BASE — no physics; used for static backgrounds and markers.
Deformable and backend-specific spawn configs must match the environment’s resolved physics backend (PhysX or Newton). See Physics backend selection.
Deformable objects#
DeformableObject represents a body whose geometry changes during simulation. Its spawn
configuration selects the physics implementation: PhysxDeformableBodyPropertiesCfg for
PhysX or NewtonDeformableBodyPropertiesCfg for Newton. The selected implementation must
match the environment’s physics backend.
Newton deformables additionally require a Vertex Block Descent (VBD) solver that owns their
particles. DeformableObject.validate_simulation_cfg() accepts either a direct
VBDSolverCfg or a coupled solver with a particle-owning VBD entry. It rejects Newton
configurations that provide only MJWarpSolverCfg or that include a VBD entry without
assigning particles. This validation runs after the environment’s env_cfg_callback, so
an environment can install its coupled rigid-body and deformable solvers before Arena checks
the final simulation configuration.
Arena uses two complementary geometry representations for a deformable:
Before simulation,
get_bounding_box()returns the undeformed, local-frame bounds from the spawn configuration or USD. Relation placement uses these rest bounds to sample an initial pose without requiring a running physics view.During simulation,
ArenaWorldreads the live deformable state. It exposes the current nodal vertices, centroid, world bounds, and mean nodal velocity through the same geometry query interface used by task predicates.
Predicates therefore evaluate the deformed object rather than its rest bounds. For example, pick-and-place checks use the live centroid and velocity, while deformable support checks use the lowest live nodes near the destination geometry. Deformables do not currently provide an Isaac Lab contact sensor, so predicates that support them use these geometry queries.
The following image shows four initial placements sampled from the same On and NextTo
relations. The undeformed cube bounds keep every sample on the table and beside the plate;
the live nodal geometry takes over after simulation starts.
For a complete task and backend-specific commands, see Deformable Pick and Place.
Backgrounds#
Backgrounds are registered as BASE assets, but their composed USDs may contain
dynamic rigid bodies and articulations whose states can change as they interact with
the robot or other objects. Arena resets these nested physics roots by default. Set
reset_nested_physics=False on a Background to opt out.
Arena registers the roots as private Isaac Lab reset views. After simulation and RTX initialization, Arena creates the views and records one environment-local pose and joint configuration. On each episode reset, Arena applies those values to the resetting environments and zeros all root and joint velocities. The private views are not exposed through the Isaac Lab scene entity registries.
Arena discovers nested roots through the composed USD physics APIs.
Included:
Standalone rigid bodies.
Articulation roots, which own their links and joints.
Excluded:
BASEand collision-only prims.Rigid and articulation roots owned by matching
ObjectReferenceentries.Articulation links, which cannot own reset state independently.
Authored roots without a live physics backend object after composition.
BASE object references remain observational and do not transfer reset
ownership away from the background.
Instanceable subtrees that contribute dynamic physics are materialized at spawn time because physics views cannot control dynamic instance proxies.
Object references#
A background asset like a kitchen is a single USD file containing many prims:
countertops, shelves, drawers, and so on. To use one of these internal prims
as a destination or interaction target (e.g. “place the object on the counter”),
you use an ObjectReference.
kitchen = asset_registry.get_asset_by_name("kitchen")()
counter = ObjectReference(
name="kitchen_counter",
prim_path="{ENV_REGEX_NS}/kitchen/counter_right_main_group/top_geometry",
parent_asset=kitchen,
)
task = PickAndPlaceTask(
pick_up_object=cracker_box,
destination_location=counter,
background_scene=kitchen,
)
The parent_asset tells the environment which spawned USD the prim path belongs to.
The prim path uses {ENV_REGEX_NS} so it resolves correctly across parallel environments.
Use ArticulationObjectReference to configure initial joints on a referenced articulation:
from isaaclab_arena.assets.object_reference import ArticulationObjectReference
microwave = ArticulationObjectReference(
name="microwave",
prim_path="{ENV_REGEX_NS}/kitchen/microwave",
parent_asset=kitchen,
initial_joint_positions={"microjoint": -0.5},
)
Joint keys may be exact names or Isaac Lab regex patterns. Values are radians for revolute joints
and metres for prismatic joints. OpenableObjectReference, PressableObjectReference, and
TurnableObjectReference inherit this option. In graph YAML, the existing object_type: articulation and
params.initial_joint_positions fields select the class automatically.
A reference can also name a link of an ARTICULATION object, such as a door or a drawer.
When a revolute or prismatic joint moves the link, the reference is placed where the
parent’s configured initial joint positions put it, and during simulation it follows the link.
Create the articulation reference before its link references so they use that initial joint
state. Links inside a BASE background, such as a kitchen’s cabinet doors, keep their authored
poses.
door = ObjectReference(
name="microwave_door",
prim_path="{ENV_REGEX_NS}/kitchen/microwave/Microwave039_door",
parent_asset=microwave,
)
Rigid object sets#
To fill one scene role with different rigid objects across parallel
environments, wrap the candidates in a RigidObjectSet. See
Rigid Object Sets for motivation, usage, and limitations.