Rigid Object#

The RigidObject class represents non-deformable (rigid) physical objects in EmbodiChain. Rigid objects are characterized by a single pose (position + orientation), collision and visual shapes, and standard rigid-body physical properties.

Configuration#

Configured via the RigidObjectCfg class.

Parameter

Type

Default

Description

shape

ShapeCfg

ShapeCfg()

Geometry configuration for visual and collision shapes. Use MeshCfg for mesh files or primitive cfgs (e.g., CubeCfg).

body_type

Literal["dynamic","kinematic","static"]

"dynamic"

Actor type for the rigid body. See {class}~cfg.RigidObjectCfg.to_dexsim_body_type` for conversion.

attrs

RigidBodyPhysicsCfg

empty groups

Grouped physical attributes (mass, damping, friction, restitution, collision offsets, CCD, etc.).

init_pos

Sequence[float]

(0,0,0)

Initial root position (x, y, z).

init_rot

Sequence[float]

(0,0,0) (Euler degrees)

Initial root orientation (Euler angles in degrees) or provide init_local_pose.

asset_physics_mode

AssetPhysicsMode

"preserve"

Preserve source-authored physics or overlay explicitly configured values.

uid

str

None

Optional unique identifier for the object; manager will assign one if omitted.

Rigid Body Physics (RigidBodyPhysicsCfg)#

Physical properties are grouped by intent. Every field is optional: None means that a source asset or the active backend keeps ownership of that value.

Group

Example fields

mass_props

mass, density, inertia, com_position, com_quaternion

rigid_props

linear_damping, angular_damping, enable_ccd

collision_props

collision_enabled, contact_offset, rest_offset

material_props

dynamic_friction, static_friction, restitution

COM quaternions are authored in xyzw order. With three principal moments, EmbodiChain converts them to R diag(I) R.T before creating a DexSim descriptor. A full 3-by-3 inertia is already in body axes; supplying a quaternion with it emits a warning and leaves the matrix unchanged. A quaternion without explicit inertia is rejected. Both backends receive the same mat33 contract.

Native engine attributes are an internal adapter detail. Backend-specific values use the concrete type in the corresponding property slot rather than a second backend block.

Setup & Initialization#

import torch
from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
from embodichain.lab.sim.objects import RigidObject, RigidObjectCfg
from embodichain.lab.sim.shapes import CubeCfg
from embodichain.lab.sim.cfg import (
    MassPropertiesCfg,
    RigidBodyMaterialCfg,
    RigidBodyPhysicsCfg,
)

# 1. Initialize Simulation
device = "cuda" if torch.cuda.is_available() else "cpu"
sim_cfg = SimulationManagerCfg(device=device)
sim = SimulationManager(sim_cfg)

# 2. Configure a rigid object (cube)
physics_attrs = RigidBodyPhysicsCfg(
    mass_props=MassPropertiesCfg(mass=1.0),
    material_props=RigidBodyMaterialCfg(
        dynamic_friction=0.5,
        static_friction=0.5,
        restitution=0.1,
    ),
)

cfg = RigidObjectCfg(
    uid="cube",
    shape=CubeCfg(size=[0.1, 0.1, 0.1]),
    body_type="dynamic",
    attrs=physics_attrs,
    init_pos=(0.0, 0.0, 1.0),
)

# 3. Spawn Rigid Object
cube: RigidObject = sim.add_rigid_object(cfg=cfg)

# 4. Commit the complete scene, then optionally open a window and run
sim.prepare()
if not sim.sim_config.headless:
    sim.open_window()
sim.update()

Note: scripts/tutorials/sim/create_scene.py provides a minimal working example of adding a rigid cube and running the simulation loop.

USD Import#

You can import USD files (.usd, .usda, .usdc) as rigid objects:

from embodichain.data import get_data_path

# Import USD with properties from file
usd_cfg = RigidObjectCfg(
    shape=MeshCfg(fpath=get_data_path("path/to/object.usd")),
    body_type="dynamic",
    asset_physics_mode="preserve",  # Keep USD properties
)
obj = sim.add_rigid_object(cfg=usd_cfg)

# Or override USD properties with config
usd_cfg_override = RigidObjectCfg(
    shape=MeshCfg(fpath=get_data_path("path/to/object.usd")),
    body_type="dynamic",
    asset_physics_mode="overlay",
    attrs=RigidBodyPhysicsCfg(mass_props=MassPropertiesCfg(mass=2.0)),
)
obj2 = sim.add_rigid_object(cfg=usd_cfg_override)

Rigid Object Class — Common Methods & Attributes#

Rigid objects are observed and controlled via single poses and linear/angular velocities. Key APIs include:

Pose & State#

Method / Property

Return / Args

Description

get_local_pose(to_matrix=False)

(N, 7) or (N, 4, 4)

Get object local pose as (x, y, z, qx, qy, qz, qw) or 4x4 matrix per environment.

set_local_pose(pose, env_ids=None)

pose: (N, 7) or (N, 4, 4)

Teleport object to given pose (requires calling sim.update() to apply).

body_data.pose

(N, 7)

Access object pose as [x, y, z, qx, qy, qz, qw] (for dynamic/kinematic bodies).

body_data.lin_vel

(N, 3)

Access linear velocity of object root (for dynamic bodies).

body_data.ang_vel

(N, 3)

Access angular velocity of object root (for dynamic bodies).

body_data.vel

(N, 6)

Concatenated linear and angular velocities.

body_data.lin_acc

(N, 3)

Access linear acceleration of object root (for dynamic bodies).

body_data.ang_acc

(N, 3)

Access angular acceleration of object root (for dynamic bodies).

body_data.acc

(N, 6)

Concatenated linear and angular accelerations.

body_data.com_pose

(N, 7)

Get center of mass pose as [x, y, z, qx, qy, qz, qw].

body_data.default_com_pose

(N, 7)

Default center of mass pose as [x, y, z, qx, qy, qz, qw].

body_state

(N, 13)

Get full body state: [x, y, z, qx, qy, qz, qw, lin_x, lin_y, lin_z, ang_x, ang_y, ang_z].

Dynamics Control#

Method / Property

Return / Args

Description

add_force_torque(force, torque, pos, env_ids)

force: (N, 3), torque: (N, 3)

Apply continuous force and/or torque to object.

set_velocity(lin_vel, ang_vel, env_ids)

lin_vel: (N, 3), ang_vel: (N, 3)

Set linear and/or angular velocity directly.

clear_dynamics(env_ids=None)

-

Reset velocities and clear all forces/torques.

Physical Properties#

Method / Property

Return / Args

Description

set_attrs(attrs, env_ids=None)

attrs: RigidBodyPhysicsCfg

Set grouped physical attributes (mass, friction, damping, etc.).

set_mass(mass, env_ids=None)

mass: (N,)

Set mass for rigid object.

get_mass(env_ids=None)

(N,)

Get mass for rigid object.

set_friction(friction, env_ids=None)

friction: (N,)

Set dynamic and static friction.

get_friction(env_ids=None)

(N,)

Get friction (dynamic friction value).

set_damping(damping, env_ids=None)

damping: (N, 2)

Set linear and angular damping.

get_damping(env_ids=None)

(N, 2)

Get linear and angular damping.

set_inertia(inertia, env_ids=None)

inertia: (N, 3)

Set inertia tensor diagonal values.

get_inertia(env_ids=None)

(N, 3)

Get inertia tensor diagonal values.

set_com_pose(com_pose, env_ids=None)

com_pose: (N, 7)

Set center of mass pose (dynamic/kinematic only).

Geometry & Body Type#

Method / Property

Return / Args

Description

get_vertices(env_ids=None)

(N, num_verts, 3)

Get mesh vertices of the rigid objects.

get_body_scale(env_ids=None)

(N, 3)

Get the body scale.

set_body_scale(scale, env_ids=None)

scale: (N, 3)

Set scale of rigid body (CPU only).

set_body_type(body_type)

body_type: str

Change body type between ‘dynamic’ and ‘kinematic’.

is_static

bool

Check if the rigid object is static.

is_non_dynamic

bool

Check if the rigid object is non-dynamic (static or kinematic).

Collision & Filtering#

Method / Property

Return / Args

Description

enable_collision(enable, env_ids=None)

enable: (N,)

Enable/disable collision for specific instances.

set_collision_filter(filter_data, env_ids=None)

filter_data: (N, 4)

Set collision filter data (arena id, collision flag, …).

Visual & Appearance#

Method / Property

Return / Args

Description

set_visual_material(mat, env_ids=None, shared=False)

mat: VisualMaterial

Change visual appearance at runtime.

restore_visual_material(env_ids=None)

-

Restore the asset materials captured at construction, including per-segment assignments.

get_visual_material_inst(env_ids=None)

List[VisualMaterialInst | None]

Get the existing or explicitly assigned representative material for each environment.

get_existing_visual_material(env_ids=None, shared=False)

List[List[ReuseSegmentState]]

Retain each original segment instance and create a working instance from its existing material template.

share_visual_material_inst(mat_insts)

mat_insts: List[VisualMaterialInst]

Share material instances between objects.

set_visible(visible)

visible: bool

Set visibility of the rigid object.

set_physical_visible(visible, rgba=None)

visible: bool, rgba: (4,)

Set collision body render visibility.

When a rigid object is loaded, its material assignment is captured without replacing the underlying dexsim instances. If a render body has multiple mesh segments, get_visual_material_inst() returns the first valid material; use get_existing_visual_material() when every segment must be addressed independently. All segments in one returned environment state share the same working instance, while their original instances remain distinct. shared=True builds the state from the first environment for reuse across the batch. reset() calls restore_visual_material() for the selected environments before resetting their physical state.

Utility & Identification#

Method / Property

Return / Args

Description

get_user_ids()

(N,)

Get the user IDs of the rigid bodies.

reset(env_ids=None)

-

Restore original materials and reset objects to their initial configuration.

destroy()

-

Destroy and remove the rigid object from simulation.

Observation Shapes#

  • Pose: (N, 7) per-object pose [x, y, z, qx, qy, qz, qw].

  • Velocities: (N, 3) for linear and angular velocities respectively.

N denotes the number of parallel environments when using vectorized simulation (SimulationManagerCfg.num_envs).

Notes & Best Practices#

  • When moving objects programmatically via set_local_pose, call sim.update() (or step the sim) to ensure transforms and collision state are synchronized.

  • Use static body type for fixed obstacles or environment pieces (they do not consume dynamic simulation resources).

  • Use kinematic for objects whose pose is driven by code (teleporting or animation) but still interact with dynamic objects.

  • For complex meshes, configure MeshCfg.collision with approximation="convex_decomposition" and a bounded max_hulls, or provide a simplified collision mesh.

  • For large GPU batches, select an indexed CUDA device and call the same backend-neutral sim.prepare() boundary after all initial assets are added.

Example: Applying Force and Torque#

import torch

# Apply force to the cube
force = torch.tensor([[0.0, 0.0, 100.0]], device=sim.device)  # (N, 3) upward force
cube.add_force_torque(force=force, torque=None)
sim.update()

# Apply torque to the cube
torque = torch.tensor([[0.0, 0.0, 10.0]], device=sim.device)  # (N, 3) torque around z-axis
cube.add_force_torque(force=None, torque=torque)
sim.update()

# Access velocity data
linear_vel = cube.body_data.lin_vel  # (N, 3)
angular_vel = cube.body_data.ang_vel  # (N, 3)

Integration with Sensors & Scenes#

Rigid objects integrate with sensors (cameras, contact sensors) and gizmos. You can attach sensors referencing object uids or query contacts for collision-based events.