A simplified implementation of Diffusion Policy for the SO101 robotic arm.
This repository is modified from the original Stanford Diffusion Policy and only retains the components required for image-based imitation learning on the SO101 platform.
- RGB image policy
- Depth image policy
- RGB-D image policy
- Future action prediction (Future3 / Future6 / Future9)
- SO101 RGB-D to Zarr dataset conversion
- Timestamp synchronization
- Diffusion UNet Image Policy
- SO101 inference server
| Version | Description |
|---|---|
| v1 | RGB Diffusion Policy |
| v2 | RGB-D Support |
| v3 | Future Action Prediction |
| Component | Specification |
|---|---|
| GPU | NVIDIA GeForce RTX 3090 (24 GB) |
| Driver | 560.35.05 |
| CUDA | 12.6 |
| Component | Version |
|---|---|
| OS | Ubuntu 22.04 LTS |
| Python | 3.9 |
| Framework | PyTorch |
| CUDA | 12.6 |
git clone <repository_url>
cd SO101_diffusion_policyconda env create -f conda_environment_nomujoco.yaml
conda activate diffusion_policypip install -e .Verify installation
python train.py --helpSO101_diffusion_policy/
├── diffusion_policy/
│ ├── codecs/
│ ├── common/
│ ├── config/
│ ├── dataset/
│ ├── env_runner/
│ ├── model/
│ ├── policy/
│ └── workspace/
│
├── convert_so101_rgbd_to_zarr.py
├── dp_inference_server.py
├── train.py
├── setup.py
├── README.md
└── conda_environment_nomujoco.yaml
Each demonstration episode should contain:
episode_xxxx/
├── image_data.csv
├── robot_state.csv
├── rgb/
│ ├── 000000.png
│ └── ...
└── depth_raw/
├── 000000.npy
└── ...
| File | Description |
|---|---|
| image_data.csv | Image timestamps |
| robot_state.csv | Robot states and timestamps |
| rgb/ | RGB images |
| depth_raw/ | Raw depth (.npy) |
Convert the raw dataset into Zarr format:
python convert_so101_rgbd_to_zarr.py --input /path/to/raw_dataset --output /path/to/output.zarr --height 240 --width 320 --min_depth 0.30 --max_depth 0.90 --max_time_diff 0.03 --overwrite| Argument | Description |
|---|---|
| --input | Raw dataset directory |
| --output | Output Zarr path |
| --height | Output image height |
| --width | Output image width |
| --min_depth | Minimum valid depth (m) |
| --max_depth | Maximum valid depth (m) |
| --max_time_diff | Maximum timestamp difference |
| --overwrite | Overwrite existing dataset |
Future action labels are generated during dataset conversion.
| Future Step | Time @30 FPS |
|---|---|
| Future3 | 0.1 s |
| Future6 | 0.2 s |
| Future9 | 0.3 s |
Example:
future_step = 6The generated dataset may be named:
pick_marker2_rgbd_future6.zarr
dataset.zarr/
├── data/
│ ├── rgb
│ ├── depth
│ ├── state
│ └── action
├── meta/
│ └── episode_ends
└── conversion_info.json
| Array | Shape |
|---|---|
| rgb | (N,240,320,3) |
| depth | (N,240,320,1) |
| state | (N,8) |
| action | (N,8) |
| episode_ends | (Episodes,) |
eef_x
eef_y
eef_z
eef_qx
eef_qy
eef_qz
eef_qw
gripper
Both state and action use:
(N,8)
For every image timestamp, the converter searches for the nearest robot state timestamp.
If the difference exceeds the configured threshold (default 0.03 s), a warning is printed.
Check dataset:
ls dataset.zarrInspect Zarr arrays:
python - <<'PY'
import zarr
root=zarr.open("dataset.zarr","r")
print(root["data/rgb"].shape)
print(root["data/depth"].shape)
print(root["data/state"].shape)
print(root["data/action"].shape)
PYBefore training:
conda activate diffusion_policy
cd ~/SO101_diffusion_policyUse this template for all experiments.
WANDB_MODE=disabled python train.py \
--config-name=train_diffusion_unet_image_workspace \
task=so101_image \
task.dataset_path=/path/to/dataset.zarr \
task.obs_mode=rgb \
task.image_shape=[3,240,320] \
task.in_channels=3 \
policy.obs_encoder.crop_shape=null \
policy.obs_encoder.random_crop=False \
policy.down_dims='[512,1024,2048]' \
optimizer.lr=1e-4 \
optimizer.weight_decay=1e-6 \
dataloader.batch_size=16 \
val_dataloader.batch_size=16 \
training.num_epochs=100 \
training.rollout_every=0 \
training.checkpoint_every=5 \
training.val_every=5task.obs_mode=rgb
task.image_shape=[3,240,320]
task.in_channels=3task.obs_mode=depth
task.image_shape=[1,240,320]
task.in_channels=1task.obs_mode=rgbd
task.image_shape=[4,240,320]
task.in_channels=4| Parameter | Description | Default |
|---|---|---|
| task.dataset_path | Dataset path | *.zarr |
| task.obs_mode | rgb/depth/rgbd | rgb |
| task.image_shape | Input image shape | [3,240,320] |
| task.in_channels | Input channels | 3 |
| policy.down_dims | Diffusion UNet channels | [512,1024,2048] |
| optimizer.lr | Learning rate | 1e-4 |
| optimizer.weight_decay | Weight decay | 1e-6 |
| dataloader.batch_size | Training batch size | 16 |
| val_dataloader.batch_size | Validation batch size | 16 |
| training.num_epochs | Number of epochs | 100 |
| training.checkpoint_every | Checkpoint interval | 5 |
| training.val_every | Validation interval | 5 |
task.dataset_path=/path/to/dataset.zarrOriginal
policy.down_dims='[512,1024,2048]'Medium (Recommended)
policy.down_dims='[256,512,1024]'Small
policy.down_dims='[128,256,512]'| down_dims | Description |
|---|---|
| [512,1024,2048] | Original model |
| [256,512,1024] | Reduced model size (recommended) |
| [128,256,512] | Small model |
optimizer.lr=1e-4Examples
1e-4
5e-5
1e-5
optimizer.weight_decay=1e-6Examples
1e-6
1e-4
1e-3
dataloader.batch_size=16
val_dataloader.batch_size=16or
dataloader.batch_size=8
val_dataloader.batch_size=8training.num_epochs=100Examples
50
100
200
Disable crop
policy.obs_encoder.crop_shape=null
policy.obs_encoder.random_crop=FalseEnable random crop
policy.obs_encoder.crop_shape='[216,288]'
policy.obs_encoder.random_crop=Truetraining.checkpoint_every=5
training.val_every=5Reduce model size
policy.down_dims='[256,512,1024]'Increase weight decay
optimizer.weight_decay=1e-4Reduce learning rate
optimizer.lr=5e-5Increase batch size
dataloader.batch_size=32
val_dataloader.batch_size=32data/outputs/
└── YYYY.MM.DD/
└── HH.MM.SS_train_diffusion_unet_image_so101_image/
├── checkpoints/
│ ├── best.ckpt
│ └── latest.ckpt
├── logs.json.txt
└── config.yaml
conda activate diffusion_policy
cd ~/SO101_diffusion_policy
python dp_inference_server.py \
--checkpoint /path/to/checkpoints/best.ckptdata/outputs/
└── YYYY.MM.DD/
└── HH.MM.SS_train_diffusion_unet_image_so101_image/
└── checkpoints/
├── best.ckpt
└── latest.ckpt
Use:
- best.ckpt : Recommended for deployment
- latest.ckpt : Latest training checkpoint
Camera
│
▼
RGB / Depth Image
│
▼
Image Preprocessing
│
▼
Observation Encoder (ResNet18)
│
▼
Diffusion UNet
│
▼
Future Action Prediction
│
▼
Robot Controller
- Collect demonstrations.
- Convert raw data to Zarr.
- Train the model.
- Select the best checkpoint using validation loss.
- Evaluate on the real robot.
- Collect failure cases.
- Retrain with the expanded dataset.
Recommended order when tuning hyperparameters:
| Step | Parameter |
|---|---|
| 1 | policy.down_dims |
| 2 | optimizer.weight_decay |
| 3 | optimizer.lr |
| 4 | training.num_epochs |
| 5 | batch_size |
| 6 | Early Stopping (future work) |
Only change one parameter at a time to make experiments comparable.
Cannot find primary config
Use:
python train.py \
--config-name=train_diffusion_unet_image_workspaceCould not find task/lift_image_abs
Use:
task=so101_imagepython train.py \
--config-name=train_diffusion_unet_image_workspace \
task=so101_image \
--cfg jobExample:
python train.py \
--config-name=train_diffusion_unet_image_workspace \
task=so101_image \
policy.down_dims='[256,512,1024]' \
--cfg job | grep -A4 down_dimsUse best.ckpt.
[256,512,1024]
It provides a good balance between model capacity and computational cost.
1e-6 (default)
Typical experiments:
1e-4
1e-3
Start with
100
and choose the checkpoint with the lowest validation loss.
- Early Stopping
- EMA tuning
- Multi-camera support
- Reactive Diffusion Policy
- Marker-based observation
- Force / tactile sensing
- Automatic dataset validation
- Configurable future prediction
- ONNX / TensorRT deployment
If this repository is useful, please cite the original Diffusion Policy paper.
@inproceedings{chi2023diffusionpolicy,
title={Diffusion Policy: Visuomotor Policy Learning via Action Diffusion},
author={Chi, Cheng and others},
booktitle={Robotics: Science and Systems},
year={2023}
}This project is built upon the original Stanford Diffusion Policy implementation.
Please follow the corresponding open-source licenses when using this repository.