Skip to content

Commit 4027429

Browse files
authored
Merge branch 'main' into yhn/success_before_reset
2 parents 477badc + 6d1b2b2 commit 4027429

File tree

3 files changed

+290
-0
lines changed

3 files changed

+290
-0
lines changed

docs/source/overview/sim/sim_assets.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ Configured via `LightCfg`.
124124
```{toctree}
125125
:maxdepth: 1
126126
127+
sim_rigid_object.md
128+
sim_rigid_object_group.md
127129
sim_soft_object.md
128130
sim_articulation.md
129131
sim_robot.md
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Rigid Object
2+
3+
```{currentmodule} embodichain.lab.sim
4+
```
5+
6+
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.
7+
8+
## Configuration
9+
10+
Configured via the {class}`~cfg.RigidObjectCfg` class.
11+
12+
| Parameter | Type | Default | Description |
13+
| :--- | :--- | :--- | :--- |
14+
| `shape` | {class}`~shapes.ShapeCfg` | `ShapeCfg()` | Geometry configuration for visual and collision shapes. Use `MeshCfg` for mesh files or primitive cfgs (e.g., `CubeCfg`). |
15+
| `body_type` | `Literal["dynamic","kinematic","static"]` | `"dynamic"` | Actor type for the rigid body. See `{class}`~cfg.RigidObjectCfg.to_dexsim_body_type` for conversion. |
16+
| `attrs` | {class}`~cfg.RigidBodyAttributesCfg` | defaults in code | Physical attributes (mass, damping, friction, restitution, collision offsets, CCD, etc.). |
17+
| `init_pos` | `Sequence[float]` | `(0,0,0)` | Initial root position (x, y, z). |
18+
| `init_rot` | `Sequence[float]` | `(0,0,0)` (Euler degrees) | Initial root orientation (Euler angles in degrees) or provide `init_local_pose`. |
19+
| `uid` | `str` | `None` | Optional unique identifier for the object; manager will assign one if omitted. |
20+
21+
### Rigid Body Attributes ({class}`~cfg.RigidBodyAttributesCfg`)
22+
23+
The full attribute set lives in `{class}`~cfg.RigidBodyAttributesCfg`. Common fields shown in code include:
24+
25+
| Parameter | Type | Default (from code) | Description |
26+
| :--- | :--- | :---: | :--- |
27+
| `mass` | `float` | `1.0` | Mass of the rigid body in kilograms (set to 0 to use density). |
28+
| `density` | `float` | `1000.0` | Density used when mass is negative/zero. |
29+
| `linear_damping` | `float` | `0.7` | Linear damping coefficient. |
30+
| `angular_damping` | `float` | `0.7` | Angular damping coefficient. |
31+
| `dynamic_friction` | `float` | `0.5` | Dynamic friction coefficient. |
32+
| `static_friction` | `float` | `0.5` | Static friction coefficient. |
33+
| `restitution` | `float` | `0.0` | Restitution (bounciness). |
34+
| `contact_offset` | `float` | `0.002` | Contact offset for collision detection. |
35+
| `rest_offset` | `float` | `0.001` | Rest offset for collision detection. |
36+
| `enable_ccd` | `bool` | `False` | Enable continuous collision detection. |
37+
38+
Use the `.attr()` helper to convert to `dexsim.PhysicalAttr` when interfacing with the engine.
39+
40+
## Setup & Initialization
41+
42+
```python
43+
import torch
44+
from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
45+
from embodichain.lab.sim.objects import RigidObject, RigidObjectCfg
46+
from embodichain.lab.sim.shapes import CubeCfg
47+
from embodichain.lab.sim.cfg import RigidBodyAttributesCfg
48+
49+
# 1. Initialize Simulation
50+
device = "cuda" if torch.cuda.is_available() else "cpu"
51+
sim_cfg = SimulationManagerCfg(sim_device=device)
52+
sim = SimulationManager(sim_cfg)
53+
54+
# 2. Configure a rigid object (cube)
55+
physics_attrs = RigidBodyAttributesCfg(mass=1.0, dynamic_friction=0.5, static_friction=0.5, restitution=0.1)
56+
57+
cfg = RigidObjectCfg(
58+
uid="cube",
59+
shape=CubeCfg(size=[0.1, 0.1, 0.1]),
60+
body_type="dynamic",
61+
attrs=physics_attrs,
62+
init_pos=(0.0, 0.0, 1.0),
63+
)
64+
65+
# 3. Spawn Rigid Object
66+
cube: RigidObject = sim.add_rigid_object(cfg=cfg)
67+
68+
# 4. (Optional) Open window and run
69+
if not sim.sim_config.headless:
70+
sim.open_window()
71+
sim.update()
72+
```
73+
74+
> Note: `scripts/tutorials/sim/create_scene.py` provides a minimal working example of adding a rigid cube and running the simulation loop.
75+
76+
## Rigid Object Class — Common Methods & Attributes
77+
78+
Rigid objects are observed and controlled via single poses and linear/angular velocities. Key APIs include:
79+
80+
| Method / Property | Return / Args | Description |
81+
| :--- | :--- | :--- |
82+
| `get_local_pose(to_matrix=False)` | `(N, 7)` or `(N, 4, 4)` | Get object local pose as (x, y, z, qw, qx, qy, qz) or 4x4 matrix per environment. |
83+
| `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). |
84+
| `body_data.pose` | `(N, 7)` | Access object pose directly (for dynamic/kinematic bodies). |
85+
| `body_data.lin_vel` | `(N, 3)` | Access linear velocity of object root (for dynamic/kinematic bodies). |
86+
| `body_data.ang_vel` | `(N, 3)` | Access angular velocity of object root (for dynamic/kinematic bodies). |
87+
| `body_state` | `(N, 13)` | Get full body state: [x, y, z, qw, qx, qy, qz, lin_x, lin_y, lin_z, ang_x, ang_y, ang_z]. |
88+
| `add_force_torque(force, torque, pos, env_ids)` | `force: (N, 3)`, `torque: (N, 3)` | Apply continuous force and/or torque to the object. |
89+
| `clear_dynamics(env_ids=None)` | - | Reset velocities and clear all forces/torques. |
90+
| `set_visual_material(mat, env_ids=None)` | `mat: VisualMaterial` | Change visual appearance at runtime. |
91+
| `enable_collision(flag, env_ids=None)` | `flag: torch.Tensor` | Enable/disable collision for specific instances. |
92+
| `reset(env_ids=None)` | - | Reset objects to initial configuration. |
93+
94+
### Observation Shapes
95+
96+
- Pose: `(N, 7)` per-object pose (position + quaternion).
97+
- Velocities: `(N, 3)` for linear and angular velocities respectively.
98+
99+
N denotes the number of parallel environments when using vectorized simulation (`SimulationManagerCfg.num_envs`).
100+
101+
## Notes & Best Practices
102+
103+
- When moving objects programmatically via `set_local_pose`, call `sim.update()` (or step the sim) to ensure transforms and collision state are synchronized.
104+
- Use `static` body type for fixed obstacles or environment pieces (they do not consume dynamic simulation resources).
105+
- Use `kinematic` for objects whose pose is driven by code (teleporting or animation) but still interact with dynamic objects.
106+
- For complex meshes, enabling convex decomposition (`RigidObjectCfg.max_convex_hull_num`) or providing a simplified collision mesh improves stability and performance.
107+
- To use GPU physics, ensure `SimulationManagerCfg.sim_device` is set to `cuda` and call `sim.init_gpu_physics()` before large-batch simulations.
108+
109+
## Example: Applying Force and Torque
110+
111+
```python
112+
import torch
113+
114+
# Apply force to the cube
115+
force = torch.tensor([[0.0, 0.0, 100.0]], device=sim.device) # (N, 3) upward force
116+
cube.add_force_torque(force=force, torque=None)
117+
sim.update()
118+
119+
# Apply torque to the cube
120+
torque = torch.tensor([[0.0, 0.0, 10.0]], device=sim.device) # (N, 3) torque around z-axis
121+
cube.add_force_torque(force=None, torque=torque)
122+
sim.update()
123+
124+
# Access velocity data
125+
linear_vel = cube.body_data.lin_vel # (N, 3)
126+
angular_vel = cube.body_data.ang_vel # (N, 3)
127+
```
128+
129+
## Integration with Sensors & Scenes
130+
131+
Rigid objects integrate with sensors (cameras, contact sensors) and gizmos. You can attach sensors referencing object `uid`s or query contacts for collision-based events.
132+
133+
## Related Topics
134+
135+
- Soft bodies: see the Soft Object documentation for deformable object interfaces. ([Soft Body Simulation Tutorial](https://dexforce.github.io/EmbodiChain/tutorial/create_softbody.html))
136+
- Examples: check `scripts/tutorials/sim/create_scene.py` and `examples/sim` for more usage patterns.
137+
138+
139+
<!-- End of rigid object overview -->
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Rigid Object Group
2+
3+
```{currentmodule} embodichain.lab.sim
4+
```
5+
6+
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.
7+
8+
## Configuration
9+
10+
Configured via the {class}`~cfg.RigidObjectGroupCfg` class.
11+
12+
| Parameter | Type | Default | Description |
13+
| :--- | :--- | :--- | :--- |
14+
| `uid` | `str` | `None` | Unique identifier for the group. |
15+
| `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. |
16+
| `body_type` | `Literal["dynamic","kinematic"]` | `"dynamic"` | Default body type applied to group members (can be overridden per-member). |
17+
| `folder_path` | `str | None` | `None` | Optional folder to initialize many objects from mesh files; if specified, `rigid_objects` should contain a template `RigidObjectCfg`. |
18+
| `max_num` | `int` | `1` | When `folder_path` is used, number of objects to sample/create from the folder. |
19+
| `ext` | `str` | `".obj"` | File extension filter when loading assets from `folder_path`. |
20+
| `init_pos` / `init_rot` | `Sequence` (optional) | group-level transform | Optional transform to apply as a base offset to all members. |
21+
22+
Refer to {class}`~cfg.RigidObjectCfg` and {class}`~cfg.RigidBodyAttributesCfg` for per-member configuration options (mass, friction, restitution, collision options, shapes, etc.).
23+
24+
### Folder-based initialization
25+
26+
If `RigidObjectGroupCfg.folder_path` is specified, the group can be auto-populated from files under that folder. The `from_dict` implementation will:
27+
28+
- list files with extension `ext` under `folder_path`,
29+
- select up to `max_num` files (wrapping if necessary),
30+
- 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.
31+
32+
This makes it convenient to spawn many similar objects from an asset directory.
33+
34+
## Setup & Initialization
35+
36+
```python
37+
import torch
38+
from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
39+
from embodichain.lab.sim.shapes import CubeCfg
40+
from embodichain.lab.sim.objects import (
41+
RigidObjectGroup, RigidObjectGroupCfg, RigidObjectCfg
42+
)
43+
from embodichain.lab.sim.cfg import RigidBodyAttributesCfg
44+
45+
# 1. Initialize Simulation
46+
device = "cuda" if torch.cuda.is_available() else "cpu"
47+
sim_cfg = SimulationManagerCfg(sim_device=device)
48+
sim = SimulationManager(sim_cfg)
49+
50+
# 2. Define shared physics attributes
51+
physics_attrs = RigidBodyAttributesCfg(
52+
mass=1.0,
53+
dynamic_friction=0.5,
54+
static_friction=0.5,
55+
restitution=0.1,
56+
)
57+
58+
# 3. Create group config with multiple members
59+
group_cfg = RigidObjectGroupCfg(
60+
uid="obj_group",
61+
rigid_objects={
62+
"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]),
63+
"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]),
64+
"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]),
65+
}
66+
)
67+
68+
# 4. Spawn the rigid object group
69+
obj_group: RigidObjectGroup = sim.add_rigid_object_group(cfg=group_cfg)
70+
71+
# 5. Run or step simulation
72+
sim.update()
73+
```
74+
75+
The example `scripts/tutorials/sim/create_rigid_object_group.py` demonstrates creating and running a scene with a `RigidObjectGroup`.
76+
77+
## Rigid Object Group — Common Methods & Attributes
78+
79+
80+
A group provides batch operations on multiple rigid objects. Key APIs include:
81+
82+
| Method / Property | Return / Args | Description |
83+
| :--- | :--- | :--- |
84+
| `num_objects` | `int` | Number of objects in each group instance. |
85+
| `body_data` | `RigidBodyGroupData` | Data manager providing `pose`, `lin_vel`, `ang_vel` properties. |
86+
| `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]. |
87+
| `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. |
88+
| `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. |
89+
| `get_user_ids()` | `(N, M)` | Get user IDs tensor for all members in the group. |
90+
| `clear_dynamics(env_ids=None)` | - | Reset velocities and clear all forces/torques for the group. |
91+
| `set_visual_material(mat, env_ids=None)` | `mat: VisualMaterial` | Change visual appearance for all members. |
92+
| `set_visible(visible=True)` | `visible: bool` | Set visibility for all members in the group. |
93+
| `set_physical_visible(visible=True, rgba=None)` | - | Set collision body visibility for debugging. |
94+
| `reset(env_ids=None)` | - | Reset all members to their initial configured transforms. |
95+
96+
### Observation Shapes
97+
98+
- Group member poses (`body_data.pose`): `(N, M, 7)` where N is number of environments and M is number of objects in the group.
99+
- Member linear velocities (`body_data.lin_vel`): `(N, M, 3)`.
100+
- Member angular velocities (`body_data.ang_vel`): `(N, M, 3)`.
101+
- Full body state (`body_state`): `(N, M, 13)` containing [position (3), orientation (4), linear velocity (3), angular velocity (3)].
102+
103+
Use these shapes when collecting vectorized observations for multi-environment training.
104+
105+
## Best Practices
106+
107+
- Groups are convenient for batch operations: resetting, setting visibility, and applying transforms to multiple objects together.
108+
- Use `obj_ids` parameter in `set_local_pose()` to control specific objects within the group rather than all members.
109+
- Prefer providing simplified collision meshes or enabling convex decomposition (`max_convex_hull_num` > 1) for complex visual meshes to improve physics stability.
110+
- `RigidObjectGroup` only supports `dynamic` and `kinematic` body types (not `static`).
111+
- When teleporting many members, batch pose updates and call `sim.update()` once to avoid synchronization overhead.
112+
- For GPU physics, set `SimulationManagerCfg.sim_device` to `cuda` and call `sim.init_gpu_physics()` before running simulations.
113+
- Use `clear_dynamics()` to reset velocities without changing poses.
114+
115+
## Example: Working with Group Poses
116+
117+
```python
118+
import torch
119+
120+
# Get current poses of all members
121+
poses = obj_group.get_local_pose() # (N, M, 7) where N=num_envs, M=num_objects
122+
123+
# Move specific objects in the group
124+
# Example: Move only the first object (cube_1) in all environments
125+
new_pose = torch.tensor([[[0.0, 1.0, 0.5, 1, 0, 0, 0]]], device=sim.device) # (1, 1, 7)
126+
obj_group.set_local_pose(new_pose, env_ids=[0], obj_ids=[0])
127+
sim.update()
128+
129+
# Access velocity data for all members
130+
linear_vels = obj_group.body_data.lin_vel # (N, M, 3)
131+
angular_vels = obj_group.body_data.ang_vel # (N, M, 3)
132+
133+
# Reset all objects to initial configuration
134+
obj_group.reset()
135+
sim.update()
136+
```
137+
138+
## Integration with Sensors
139+
140+
Members in a group behave like normal `RigidObject`s: 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.
141+
142+
## Related Topics
143+
144+
- Rigid objects: See the Rigid Object overview for single-body.
145+
- Soft bodies: Deformable objects have different observation semantics (vertex-level data). ([Soft Body Simulation Tutorial](https://dexforce.github.io/EmbodiChain/tutorial/create_softbody.html))
146+
- Examples: `scripts/tutorials/sim/create_rigid_object_group.py`
147+
148+
149+
<!-- End of rigid object group overview -->

0 commit comments

Comments
 (0)