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
30 changes: 30 additions & 0 deletions airbot_ie/lerobot_plugin/configs/act_infer_aao.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ACT inference on AAO MuJoCo simulator via lerobot-rollout + aao_sim robot plugin.
#
# This uses the absolute_random_wrist checkpoint trained with observation_rotation=rot6d
# (10-dim state = pos[3] + rot6d[6] + gripper[1]). The env must match by setting
# observation_rotation: rot6d below.
#
# Run:
# pixi run -e infer-aao mcap-lerobot-infer -c airbot_ie/lerobot_plugin/configs/act_infer_aao.yaml

preserve_keys: [sim_cameras]

robot:
type: aao_sim
task_config: open_door
operator: arm
kinematic: false
substeps: 1
has_gripper: true
observation_rotation: rot6d # → 10-dim state = pos(3) + rot6d(6) + grip(1)
sim_cameras:
wrist_cam: wrist_cam
camera_shape: [352, 640, 3]
mujoco_gl: egl

policy:
path: models_open_door/absolute_random_wrist/pretrained_model

task: "open the door"
fps: 30
duration: 10
36 changes: 36 additions & 0 deletions airbot_ie/lerobot_plugin/configs/act_infer_mock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# ACT inference on MOCK AIRBOT Play arm (no hardware needed).
#
# Uses pose control mode with arm + eef components:
# observation.state = eef pos(3) + quat(4) + gripper(1) = (8,)
# action = target eef pos(3) + quat(4) + gripper(1) = (8,)
#
# Run:
# pixi run -e act-infer mcap-lerobot-infer -c airbot_ie/lerobot_plugin/configs/act_infer_mock.yaml

preserve_keys: [cameras]

robot:
type: airbot_play
mock: true
control_mode: pose
components: [arm, eef] # observation.state (8,): eef pos+quat+gripper
cameras:
eef_wrist_cam:
target: airdc.common.devices.cameras.mock.MockCamera
width: 640
height: 352
fps: 30
extra: { random: true }
env1_cam:
target: airdc.common.devices.cameras.mock.MockCamera
width: 640
height: 352
fps: 30
extra: { random: true }

policy:
path: outputs/train/my_act/checkpoints/last/pretrained_model

task: "open the door"
fps: 30
duration: 3
39 changes: 39 additions & 0 deletions airbot_ie/lerobot_plugin/configs/act_infer_real.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ACT inference on REAL AIRBOT Play arm.
#
# Before running: update `url` and camera `camera_index` values for your setup.
# Uses pose control mode with arm + eef components:
# observation.state = eef pos(3) + quat(4) + gripper(1) = (8,)
# action = target eef pos(3) + quat(4) + gripper(1) = (8,)
#
# Run:
# pixi run -e act-infer mcap-lerobot-infer -c airbot_ie/lerobot_plugin/configs/act_infer_real.yaml

preserve_keys: [cameras]

robot:
type: airbot_play
control_mode: pose
components: [arm, eef] # observation.state (8,): eef pos+quat+gripper
url: localhost # ← change to arm's IP if remote
port: 50051
return_to_initial_position: true
cameras:
eef_wrist_cam:
target: airdc.common.devices.cameras.v4l2.V4L2Camera
camera_index: 0 # ← change to your wrist camera index
width: 640
height: 352
fps: 30
env1_cam:
target: airdc.common.devices.cameras.v4l2.V4L2Camera
camera_index: 1 # ← change to your env camera index
width: 640
height: 352
fps: 30

policy:
path: outputs/train/my_act/checkpoints/last/pretrained_model

task: "open the door"
fps: 30
duration: 0 # 0 = run until Ctrl-C
57 changes: 57 additions & 0 deletions airbot_ie/lerobot_plugin/configs/act_train.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# ACT (Action Chunking with Transformers) training config on MCAP dataset.
#
# ACT is a lightweight policy (no pretrained backbone), trained from scratch on
# your own demonstrations. Much smaller than pi0.5/SmolVLA and faster to train.
#
# Run:
# pixi run -e act mcap-lerobot-train -c airbot_ie/lerobot_plugin/configs/act_train.yaml

env:
HF_HUB_OFFLINE: "1"
TRANSFORMERS_OFFLINE: "1"

# ============================================================================
# Common training knobs
# ============================================================================
steps: 20000
save_freq: 5000
log_freq: 100
batch_size: 8
num_workers: 1
output_dir: outputs/train/my_act
seed: 1000

wandb:
enable: true
project: airbot-act
mode: offline

policy:
type: act
push_to_hub: false
chunk_size: 100 # ACT action horizon
n_action_steps: 100 # steps to execute per chunk

dataset:
root: data
repo_id: mcap
streaming: true

mcap:
# observation.state = arm eef pose (position[3] + orientation[4]) + gripper (1) -> (8,)
states:
- arm/pose/position
- arm/pose/orientation
- eef/joint_state/position
# Wrist cam + env cam -> each (3, H, W)
images:
- eef_wrist_cam/color/image_raw
- env1_cam/color/image_raw
# action = target eef pose (position[3] + orientation[4]) + gripper (1) -> (8,)
actions:
- action/arm/pose/position
- action/arm/pose/orientation
- action/eef/joint_state/position
# ACT does not use language conditioning
task_source: none
task: "do the task"
65 changes: 65 additions & 0 deletions airbot_ie/lerobot_plugin/lerobot_env_aao_sim/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# lerobot_env_aao_sim

LeRobot **Env** plugin: a `gymnasium.Env` over the auto-atomic-operation (aao)
MuJoCo simulator, for **native success-rate evaluation** with `lerobot-eval`.

## Why this exists

`lerobot-rollout` (the Robot path used by `lerobot_robot_aao_sim`) is written for
real hardware — it has no success detection and just runs to `duration`.
`lerobot-eval` drives a gymnasium `VectorEnv` and computes `pc_success` natively
from each env's `step()` returning `info["is_success"]`. This plugin supplies
that env, so you get success rate + mp4 videos out of the box.

LeRobot auto-discovers this by the distribution name prefix `lerobot_env_`, and
`@EnvConfig.register_subclass("aao_sim")` registers `--env.type=aao_sim`.

## Success signal

`step()` reports success via `backend.is_object_displaced(success_object,
initial_pose, threshold)` — the same displacement check the aao task graph uses.
For `open_door` the target is `handle_body_phys` (threshold 0.01 m). Both are
config fields (`success_object`, `displacement_threshold`).

## Usage

```bash
pixi run -e infer-aao lerobot-eval \
--policy.path=models_open_door/absolute_random_wrist/pretrained_model \
--env.type=aao_sim \
--env.task_config=open_door \
--env.observation_rotation=rot6d \
--eval.n_episodes=10 \
--eval.batch_size=1 \
--policy.device=cuda
```

Outputs: `outputs/eval/<run>/videos/*.mp4` + `metrics.json` with `pc_success`.

## observation_rotation

| Value | observation.state dim | Use when |
|---|---|---|
| `rot6d` (default) | 10 (pos3 + rot6d6 + grip1) | checkpoint trained with 6-D obs (e.g. absolute_random_wrist) |
| `quat` | 8 (pos3 + quat4 + grip1) | checkpoint trained with quaternion obs |

`action_rotation` controls the policy action representation:

| Value | action dim | Execution path |
|---|---|---|
| `quat` (default) | 8 (pos3 + quat4 + grip1) | passed directly to `apply_pose_action` |
| `rot6d` | 10 (pos3 + rot6d6 + grip1) | converted to quaternion before `apply_pose_action` |

## rot6d convention

AAO simulation, MCAP `Rotation6D.quat_to_rot6d()` conversion, and real-robot
data all use the same column-vector convention:

```text
[r00, r10, r20, r01, r11, r21]
```

It is the first two columns of the 3×3 rotation matrix. No observation or action
convention wrapper is required. Checkpoints trained with the old row-major
simulation representation are not compatible with this unified path and must
be converted or retrained.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""LeRobot Env plugin: a gymnasium env over the auto-atomic-operation MuJoCo
simulator, for native success-rate evaluation via ``lerobot-eval``.

Unlike ``lerobot_robot_aao_sim`` (which drives ``lerobot-rollout`` and has no
success signal), this exposes a ``gym.Env`` whose ``step()`` returns
``info["is_success"]`` so ``lerobot-eval`` computes ``pc_success`` natively.

LeRobot auto-discovers this by the distribution name prefix ``lerobot_env_``,
and ``@EnvConfig.register_subclass("aao_sim")`` registers ``--env.type=aao_sim``.
"""

from .config_aao_sim_env import AAOSimEnvConfig

__all__ = ["AAOSimEnvConfig"]
Loading