ODE Policy (Euler solver) — R1 Lite "insert two flowers"
Checkpoints of the ODE policy trained on real-robot demonstrations of the Galaxea R1 Lite right arm
inserting flowers (task r1lite_insert_two_flowers). The policy learns a velocity field ȧ = f(c, s, a)
over the arm's joint targets and produces each 8-step action chunk by integrating that field from the current
target. This run integrates with the explicit Euler solver (one field evaluation per control step) instead
of the RK4 default (four), training and inference alike; everything else is the standard real-robot ODE
configuration.
Files
| Path | Content |
|---|---|
checkpoints/{50,100,150,200,250,300}.ckpt |
Full training checkpoints (485 MB each): model, ema_model, optimizer state dicts + the pickled Hydra config. Serve the EMA weights (the loader does this by default). |
config/config.yaml, config/overrides.yaml |
Resolved training config and the command-line overrides of this run |
logs/logs.json.txt |
Per-step / per-epoch training log (loss, lr, epoch time, val_loss every 5 epochs) |
SHA256SUMS |
Checksums of every uploaded file |
Checkpoints are torch.save(..., pickle_module=dill) payloads written by the ODE_Policy training runner.
Loading them needs that codebase (branch r1lite_exp; roboverse_learn.il.policies.ode.ode_image_policy.ODEImagePolicy)
and torch.load(..., pickle_module=dill, weights_only=False) — only load checkpoints you trust.
Data
at237299966/r1lite_insert_flower:
LeRobot v2.1, 98 episodes / 45,684 frames at 15 Hz, task "insert flower".
| Input / output | Definition |
|---|---|
| Cameras | head_rgb (720×1280) and right_wrist_rgb (360×640), padded to square then resized to 256×256 (same geometry as the robot client) |
agent_pos |
right-arm joint positions (6, rad) + right gripper opening (1, mm) |
ODE state a |
right-arm absolute joint targets (6, rad). Row convention: a[t] = commanded target at t−1 (episode start: measured joints) |
| Gripper head | binary, +1 close / −1 open; the label flips where the operator's gripper ramp starts |
| Window | 8 observation frames, 8-step action chunk |
Training
| Model | ResNet18 (GroupNorm, random crop) per camera, 8 frames → condition c (512); vector field = 4-layer FiLM-MLP, width 512; proprioception enters the field only (cond_use_s=false); separate gripper head |
| Integration | Euler, 1 substep, 8 control steps per chunk, vel_scale=0.05; observation fixed over the chunk (obs_update=fixed) |
| Start perturbation | 50% of samples, per-joint std [0.005, 0.0259, 0.0092, 0.005, 0.005, 0.005] rad, decay 0.7 per step |
| Optimisation | AdamW, lr 1.5e-4, cosine schedule over 300 epochs, warm-up 500 steps, EMA |
| Batch | 2 × A100-40GB (DDP), 48 per GPU = 96 global; 470 steps/epoch, 141,000 steps in total |
| Wall clock | 18 h 12 min (218 s/epoch) |
| epoch | 0 | 10 | 50 | 100 | 150 | 200 | 250 | 300 |
|---|---|---|---|---|---|---|---|---|
| train loss | 0.74 | 0.19 | 0.043 | 0.024 | 0.015 | 0.0098 | 0.0076 | 0.0069 |
| val loss | 0.82 | 0.81 | 0.74 | 0.68 | 0.70 | 0.72 | 0.72 | 0.72 (ep 295) |
The validation loss is a weak signal: one held-out episode, raw (non-EMA) weights, with the training start perturbation still active. Its minimum is at epoch 30 (0.66) and it stays within 0.66–0.74 afterwards, so compare early and late checkpoints on the robot before picking one.
Deployment
The robot side is the unmodified openpi-r1lite closed-loop client (main_r1lite_closedloop.py, 15 Hz,
executes row 0 of every (8, 14) reply). The server reads the solver from the checkpoint, re-integrates a
chunk every 8 ticks from the last target it sent and walks the client through it; the left arm is echoed
(held where it is):
python -m roboverse_learn.il.deploy.serve_policy \
--checkpoint checkpoints/100.ckpt --host 0.0.0.0 --port 8000 --device cuda:0 \
--gripper_close 0 --gripper_open 100 --gripper_ramp_ticks 25
python -m roboverse_learn.il.deploy.test_client --host 127.0.0.1 --port 8000 -n 40 --gripper_range 0 100 # pre-flight
Set the torso to the demonstrations' pose [-0.7745, 1.4887, 0.6998] rad before a run (it is not part of
the policy's state). Code: ODE_Policy repository, neural_ode/real/ (data + training) and roboverse_learn/il/deploy/
(server).