Rigid Object Group#

The RigidObjectGroup class represents a logical collection of rigid objects that are created and managed together. It is useful for spawning multiple related rigid bodies (e.g., multi-part props, object sets) and performing batch operations such as resetting, applying transforms, or querying group-level observations.

Configuration#

Configured via the RigidObjectGroupCfg class.

Parameter

Type

Default

Description

uid

str

None

Unique identifier for the group.

rigid_objects

Dict[str, RigidObjectCfg]

MISSING

Mapping from member uid to its RigidObjectCfg. Each entry spawns one rigid object. When folder_path is provided, this acts as a template.

body_type

Literal["dynamic","kinematic"]

"dynamic"

Default body type applied to group members (can be overridden per-member).

folder_path

`str

None`

None

max_num

int

1

When folder_path is used, number of objects to sample/create from the folder.

ext

str

".obj"

File extension filter when loading assets from folder_path.

init_pos / init_rot

Sequence (optional)

group-level transform

Optional transform to apply as a base offset to all members.

Refer to RigidObjectCfg and RigidBodyAttributesCfg for per-member configuration options (mass, friction, restitution, collision options, shapes, etc.).

Folder-based initialization#

If RigidObjectGroupCfg.folder_path is specified, the group can be auto-populated from files under that folder. The from_dict implementation will:

  • list files with extension ext under folder_path,

  • select up to max_num files (wrapping if necessary),

  • copy the template RigidObjectCfg provided in rigid_objects and set each member’s shape.fpath to the selected file path and give each member a generated uid.

This makes it convenient to spawn many similar objects from an asset directory.

Setup & Initialization#

import torch
from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
from embodichain.lab.sim.shapes import CubeCfg
from embodichain.lab.sim.objects import (
    RigidObjectGroup, RigidObjectGroupCfg, RigidObjectCfg
)
from embodichain.lab.sim.cfg import RigidBodyAttributesCfg

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

# 2. Define shared physics attributes
physics_attrs = RigidBodyAttributesCfg(
    mass=1.0,
    dynamic_friction=0.5,
    static_friction=0.5,
    restitution=0.1,
)

# 3. Create group config with multiple members
group_cfg = RigidObjectGroupCfg(
    uid="obj_group",
    rigid_objects={
        "cube_1": RigidObjectCfg(uid="cube_1", shape=CubeCfg(size=[0.1,0.1,0.1]), attrs=physics_attrs, init_pos=[0.0,0.0,1.0]),
        "cube_2": RigidObjectCfg(uid="cube_2", shape=CubeCfg(size=[0.2,0.2,0.2]), attrs=physics_attrs, init_pos=[0.5,0.0,1.0]),
        "cube_3": RigidObjectCfg(uid="cube_3", shape=CubeCfg(size=[0.3,0.3,0.3]), attrs=physics_attrs, init_pos=[-0.5,0.0,1.0]),
    }
)

# 4. Spawn the rigid object group
obj_group: RigidObjectGroup = sim.add_rigid_object_group(cfg=group_cfg)

# 5. Run or step simulation
sim.update()

The example scripts/tutorials/sim/create_rigid_object_group.py demonstrates creating and running a scene with a RigidObjectGroup.

Rigid Object Group — Common Methods & Attributes#

A group provides batch operations on multiple rigid objects. Key APIs include:

Method / Property

Return / Args

Description

num_objects

int

Number of objects in each group instance.

body_data

RigidBodyGroupData

Data manager providing pose, lin_vel, ang_vel properties.

body_state

(N, M, 13)

Full body state of all members: [x, y, z, qw, qx, qy, qz, lin_x, lin_y, lin_z, ang_x, ang_y, ang_z].

get_local_pose(to_matrix=False)

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

Poses of all members across N envs; M = number of members.

set_local_pose(pose, env_ids=None, obj_ids=None)

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

Set poses for specific environments and/or objects; requires sim.update() to apply.

get_user_ids()

(N, M)

Get user IDs tensor for all members in the group.

clear_dynamics(env_ids=None)

-

Reset velocities and clear all forces/torques for the group.

set_visual_material(mat, env_ids=None)

mat: VisualMaterial

Change visual appearance for all members.

set_visible(visible=True)

visible: bool

Set visibility for all members in the group.

set_physical_visible(visible=True, rgba=None)

-

Set collision body visibility for debugging.

reset(env_ids=None)

-

Reset all members to their initial configured transforms.

Observation Shapes#

  • Group member poses (body_data.pose): (N, M, 7) where N is number of environments and M is number of objects in the group.

  • Member linear velocities (body_data.lin_vel): (N, M, 3).

  • Member angular velocities (body_data.ang_vel): (N, M, 3).

  • Full body state (body_state): (N, M, 13) containing [position (3), orientation (4), linear velocity (3), angular velocity (3)].

Use these shapes when collecting vectorized observations for multi-environment training.

Best Practices#

  • Groups are convenient for batch operations: resetting, setting visibility, and applying transforms to multiple objects together.

  • Use obj_ids parameter in set_local_pose() to control specific objects within the group rather than all members.

  • Prefer providing simplified collision meshes or enabling convex decomposition (max_convex_hull_num > 1) for complex visual meshes to improve physics stability.

  • RigidObjectGroup only supports dynamic and kinematic body types (not static).

  • When teleporting many members, batch pose updates and call sim.update() once to avoid synchronization overhead.

  • For GPU physics, set SimulationManagerCfg.sim_device to cuda and call sim.init_gpu_physics() before running simulations.

  • Use clear_dynamics() to reset velocities without changing poses.

Example: Working with Group Poses#

import torch

# Get current poses of all members
poses = obj_group.get_local_pose()  # (N, M, 7) where N=num_envs, M=num_objects

# Move specific objects in the group
# Example: Move only the first object (cube_1) in all environments
new_pose = torch.tensor([[[0.0, 1.0, 0.5, 1, 0, 0, 0]]], device=sim.device)  # (1, 1, 7)
obj_group.set_local_pose(new_pose, env_ids=[0], obj_ids=[0])
sim.update()

# Access velocity data for all members
linear_vels = obj_group.body_data.lin_vel  # (N, M, 3)
angular_vels = obj_group.body_data.ang_vel  # (N, M, 3)

# Reset all objects to initial configuration
obj_group.reset()
sim.update()

Integration with Sensors#

Members in a group behave like normal RigidObjects: they can be observed by cameras, attached to contact sensors. You can operate on individual members or treat the group as a single unit depending on your scenario.