ODE Policy (Euler solver) β€” R1 Lite "open drawer, multimodal" (two arms)

Checkpoints of the ODE policy trained on real-robot demonstrations of the Galaxea R1 Lite opening a drawer with either arm: in each demonstration one arm grasps the handle and pulls (left in 25, right in 25 of the 50 episodes). The policy learns a velocity field Θ§ = f(c, s, a) over the 12 joint targets of both arms and produces each 8-step action chunk by integrating that field with the explicit Euler solver (one field evaluation per control step, training and inference alike) from the current target.

Files

Path Content
checkpoints/{50,100,150,200,250,300}.ckpt Full training checkpoints: 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 at a version with two-arm support (branch r1lite_exp, commit e9cc9c0 or later: ODEImagePolicy with n_grippers / state_pose_index) and torch.load(..., pickle_module=dill, weights_only=False) β€” only load checkpoints you trust.

Data

at237299966/r1lite_open_drawer_multimodal: LeRobot v2.1, 50 episodes / 15,896 frames at 15 Hz (268–393 frames each), task "open drawer multimodal".

Input / output Definition
Cameras head_rgb (720Γ—1280), right_wrist_rgb and left_wrist_rgb (360Γ—640), padded to square then resized to 256Γ—256 (same geometry as the robot client)
agent_pos 14-D, the robot client's order: [L1..L6 (rad), L_grip (mm), R1..R6 (rad), R_grip (mm)]
ODE state a the 12 absolute joint targets [L1..L6, R1..R6] (rad). Row convention: a[t] = commanded target at tβˆ’1 (episode start: measured joints)
Gripper head binary per gripper (left, right), +1 close / βˆ’1 open. The grippers close onto the handle and stop part-way (held at 25–55 mm, median 43 mm) and snap open, so the labels use plateau detection (--gripper-ramp-mask moving, threshold 75 mm): the label flips where the operator starts closing and where the release starts
Window 8 observation frames, 8-step action chunk

Training

Model ResNet18 (GroupNorm, random crop) per camera (3 cameras), 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 (2 logits per step)
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 rad except L2 0.0184, L3 0.0111, R2 0.023, R3 0.0131 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), 40 per GPU = 80 global (the three-camera setting of the two-arm runs)
Wall clock 9 h 19 min (112 s/epoch), 300 epochs, 194 steps/epoch, 58,200 steps in total
epoch 0 10 50 100 150 200 250 300
train loss 1.11 0.252 0.0614 0.0334 0.0201 0.0132 0.00926 0.00816
val loss 0.696 0.672 0.662 0.664 0.75 0.755 0.794 0.798 (ep 295)

Lowest validation loss: 0.557 at epoch 5 (validation every 5 epochs). Columns 50, 100, ... are the saved checkpoints (checkpoints/<epoch>.ckpt).

The validation loss is a weak signal: one held-out episode, raw (non-EMA) weights, with the training start perturbation still active. 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; it must send all three cameras). The server reads the two-arm layout and the Euler solver from the checkpoint, re-integrates a chunk every 8 ticks from the last target it sent and walks the client through it; both arms are commanded:

python -m roboverse_learn.il.deploy.serve_policy \
    --checkpoint checkpoints/100.ckpt --host 0.0.0.0 --port 8000 --device cuda:0 \
    --gripper_close 43 --gripper_open 100 --gripper_ramp_ticks 31
python -m roboverse_learn.il.deploy.test_client --host 127.0.0.1 --port 8000 -n 40 --bimanual --gripper_range 43 100   # pre-flight

--gripper_close 43 is the median width the demonstrations held on the handle (commanding 0 would squeeze harder than the operator did); --gripper_ramp_ticks 31 is the demonstrations' closing ramp (the server uses the same rate for opening, which in the demos was a 1–2 frame step). Set the robot to the demonstrations' start pose before a run (torso [-0.6826, 1.4936, 0.8012] rad, both arms at ~0, grippers 100; the torso is not part of the policy's state). Code: ODE_Policy repository, neural_ode/real/ (data + training) and roboverse_learn/il/deploy/ (server).

Downloads last month

-

Downloads are not tracked for this model. How to track
Video Preview
loading

Dataset used to train at237299966/ODE_policy_euler_open_drawer_multimodal