sour5blue's picture
Initial upload: probe + demo-supervised NN-OSC adapters
38ab031 verified
---
license: mit
tags:
- robotics
- diffusion-policy
- robomimic
- osc
- inverse-controller
---
# diffusion-policy-osc-adapters
NN inverse-controller adapters for running a joint-space (Δq) Diffusion Policy on top of the standard Robomimic `OSC_POSE` controller. Companion checkpoints to a fork of [columbia-ai-robotics/diffusion_policy](https://github.com/columbia-ai-robotics/diffusion_policy) on the Robomimic PH lowdim benchmark.
The adapter maps `(state, desired Δq) → a_OSC` so a policy trained to predict joint deltas can be rolled out through a Cartesian-space controller.
## Layout
```
probe_nn_osc/ Probe-based adapters (Brian-style env-probing sampler)
nn_adapter_lift.pt
nn_adapter_can.pt
nn_adapter_square.pt
nn_adapter_tool_hang.pt
nn_adapter_transport.pt (dual-arm)
demosup_nn_osc/ Demo-supervised adapters (one training pair per demo timestep)
lift/ { best.pt, config.json, collect_metadata.json }
can/ ...
square/ ...
```
`config.json` is the trainer-emitted hyperparameter dump; `collect_metadata.json` records dataset, obs_keys, and demo IDs the adapter was trained on.
## Architecture (`demosup_nn_osc/*`)
Brian Zhang's `InverseControllerMLP`: 3×512 SiLU + LayerNorm. Input is `(state, desired_Δq)` concatenated (33+7 = 40-D), output is the 7-D OSC normalized command. Per-channel input/output normalizers stored alongside in `best.pt`.
State features (single-arm): `object, robot0_eef_pos, robot0_eef_quat, robot0_gripper_qpos, robot0_joint_pos`.
## Results — full-pipeline rollout (DP + adapter)
Robomimic PH lowdim, `test_start_seed=100000`, n_test=50, OSC default kp. DP is the 5k-epoch joint-delta UNet checkpoint.
| Task | Probe NN-OSC | **Demo-supervised NN-OSC** | FK→OSC reference |
|--------|--------------|----------------------------|------------------|
| lift | 0.00 | **0.90** | 0.94 |
| can | 0.02 | **0.64** | 0.88 |
| square | 0.00 | **0.48** | 0.50 (kp=3000) |
Demo-supervised closes most of the gap to the analytic FK→OSC adapter, and trains in ~5 min/task on a single H100/H200. The probe-based adapter fails because OSC's Cartesian command is a many-to-one inverse of Δq; the demo-supervised dataset restricts training to the demo manifold where teleop already picked a consistent branch.
## Usage
```python
import torch
ckpt = torch.load("demosup_nn_osc/lift/best.pt", map_location="cpu")
# ckpt contains: state_dict, input_mean/std, command_mean/std, hidden_dims, ...
# See reverse_controller/train_inverse_model.py in the source repo for the full
# build_model + normalize pipeline.
```
## Source
- Code branch: https://github.com/sour5blue/diffusion_policy/tree/sour/obs-noise-param (`writeup.md`, sections D–F).
- Upstream: https://github.com/WubbLord/diffusion_policy
- Demo-supervised collector: `collect_demo_only_osc.py`.
- Trainer: `reverse_controller/train_inverse_model.py`.
- Eval entrypoint: `eval_nn_osc.py`.