Instructions to use Bigenlight/act_banana_in_pot with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use Bigenlight/act_banana_in_pot with LeRobot:
- Notebooks
- Google Colab
- Kaggle
license: apache-2.0
library_name: lerobot
tags:
- act
- robotics
- lerobot
- ur7e
- imitation-learning
pipeline_tag: robotics
datasets:
- Bigenlight/banana_in_pot_lerobot_v3
ACT β Put the right banana in the pot (UR7e)
An Action Chunking Transformer (ACT) policy trained by imitation learning to perform the manipulation task "put the right banana in the pot" on a Universal Robots UR7e arm with two RGB cameras.
- Policy: ACT (Transformer encoderβdecoder with a CVAE), ResNet18 vision backbone
(ImageNet-pretrained),
chunk_size = 100,n_action_steps = 100. - Trained on:
Bigenlight/banana_in_pot_lerobot_v3(51 teleoperated episodes / 21,524 frames, UR7e follower + GELLO leader, 2 cameras). - Training length: 50,000 steps, batch size 8, AdamW
lr = 1e-5(constant). - Framework: LeRobot v0.6.1.
What the policy does
| I/O | Spec |
|---|---|
observation.state |
(7,) β UR joints q1..q6 (radians) + gripper position |
observation.images.cam1 / cam2 |
RGB, trained at 360Γ640 |
action |
(7,) β [cmd1..cmd6, grip_cmd], absolute joint targets (radians) + ~binary gripper |
Images were captured at 720p and resized on-the-fly to 360Γ640 during training (aspect-preserving half-resolution; no dataset re-encode). You must resize every live camera frame to 360Γ640 at inference β a different aspect ratio or interpolation degrades the policy.
Data & hardware setup
| Component | Detail |
|---|---|
| Robot | Universal Robots UR7e β 6-DOF collaborative arm, joints in radians. Inference uses the UR7e follower only. |
| Teleoperation (data collection) | GELLO low-cost 3D-printed leader arm. Leader signals are recorded but are not policy inputs at inference. |
| Camera 1 | Intel RealSense D435 β RGB only |
| Camera 2 | Intel RealSense D435if β RGB only |
| Camera streams | 1280Γ720 (720p) @ 30 fps, color only (no depth / IR recorded). ACT is trained on the two RGB views resized to 360Γ640. |
| Task | "put the right banana in the pot" β table with distractor objects (2 bananas, apple, carrots/peppers, watermelon slice) and a silver pot; success = the correct banana placed in the pot. |
| Dataset scale | 51 episodes / 21,524 frames / ~12 min @ 30 fps. |
Training configuration
| Item | Value |
|---|---|
| Policy | ACT (ResNet18 backbone, CVAE, chunk_size=100, n_action_steps=100) |
dim_model / heads |
512 / 8 |
| Encoder / decoder layers | 4 / 1 |
| Normalization | MEAN_STD for state, action, and visual |
| Batch / steps | 8 / 50,000 |
| Optimizer | AdamW, lr = 1e-5 (constant), backbone lr = 1e-5 |
| Backbone | ResNet18_Weights.IMAGENET1K_V1 (ImageNet-pretrained) |
| GPU | RTX 3060 12GB (~4.7 GB used, ~3.9 step/s) |
Training loss
Final training loss β 0.065.
Offline evaluation (open-loop: predicted actions vs. ground truth)
Evaluated on held-out episodes (train vs. held-out gap is negligible β generalizes, no overfitting). The step 50,000 checkpoint (this model) is the best by held-out L1.
| step | joints MAE (rad) | overall L1 | gripper acc | train L1 | held-out L1 |
|---|---|---|---|---|---|
| 10000 | 0.0392 | 0.0395 | 98.0% | 0.0392 | 0.0406 |
| 20000 | 0.0354 | 0.0345 | 98.8% | 0.0324 | 0.0356 |
| 30000 | 0.0267 | 0.0265 | 98.8% | 0.0258 | 0.0269 |
| 40000 | 0.0256 | 0.0245 | 99.2% | 0.0222 | 0.0256 |
| 50000 β | 0.0237 | 0.0225 | 99.2% | 0.0205 | 0.0235 |
Best checkpoint (step 50,000):
- Held-out overall L1 = 0.0235 rad (β 1.34Β°); train L1 = 0.0205 β near-zero gap.
- Joints MAE = 0.0237 rad (β 1.36Β°).
- Gripper accuracy 99.2%.
The wrist joint (cmd6) carries the largest error β it is the axis with the most natural
variation. The gripper channel is close to binary.
How to use
Load the policy (LeRobot)
from lerobot.policies.act import ACTPolicy
from lerobot.policies import make_pre_post_processors
policy = ACTPolicy.from_pretrained("Bigenlight/act_banana_in_pot")
policy.eval()
# Normalization is NOT baked into forward() in lerobot 0.6.1 β it lives in the
# processor pipeline saved alongside the checkpoint. select_action returns a
# NORMALIZED action; the post-processor converts it back to radians.
preprocessor, postprocessor = make_pre_post_processors(
policy_cfg=policy.config,
pretrained_path="Bigenlight/act_banana_in_pot",
)
Per control tick:
policy.reset() # once at the start of each rollout
obs = preprocessor(obs) # normalize + batch + move to device
action = policy.select_action(obs) # normalized
action = postprocessor(action) # radians, numpy (7,)
select_action returns one action per call from an internal queue; on an empty queue it
predicts a full 100-step chunk and replans after 100 executed actions (temporal ensembling
is off by default in this config).
Deploy on a real UR7e
LeRobot ships no UR robot class β you build the observation dict yourself and stream
joint targets with ur_rtde at 30 Hz
(33.3 ms control period). Loop: read getActualQ() + gripper β grab both cameras, BGRβRGB,
resize to 360Γ640 β build observation.state / observation.images.cam1 / cam2 β
preprocess β select_action β postprocess β servoJ(q_target[:6]) + drive gripper from
grip_cmd.
β οΈ Safety β actions are ABSOLUTE joint positions (the single biggest safety driver):
- Start near the dataset initial pose
q1..q6 β [2.84, -1.41, 1.78, -2.01, -1.66, -3.42]rad before enabling the policy, or the first absolute command is a large jump. - First-command jump guard: if
max(|q_target β getActualQ()|) > ~0.15 rad, abort. - Clamp per-tick joint change (e.g. β€ 0.05β0.1 rad / 33 ms early on) and clamp to UR software joint limits.
- Reduced speed for first trials; keep a hand on the E-stop dead-man switch.
- Camera mapping matters: the policy learned a fixed
cam1/cam2β physical-viewpoint mapping. Swap them and it fails silently. Verify wiring every session. - Gripper
grip_cmdis ~binary β threshold (e.g.>0.5 β close) and map to your driver.
A full deployment guide (with a reference ur_rtde skeleton and all the citations to the
lerobot inference/normalization code paths) is in the project's DEPLOY_UR.md.
Related repositories
- Dataset:
Bigenlight/banana_in_pot_lerobot_v3 - HIL-SERL prep bundle (reward classifier, SAC config, runbook) for taking this task
online with reinforcement learning:
Bigenlight/banana_in_pot_hilserl
Limitations
- Small dataset (51 demos). Metrics reflect an easy, temporally-correlated task; expect reduced robustness to novel object positions, lighting, or camera placement.
- Offline metrics only. All numbers above are open-loop (predicted vs. ground-truth actions). Real closed-loop task success on the arm has not been measured here β a physical UR7e deployment is required for the final verdict.
- Absolute-joint action space demands the safety guards above; the policy was only ever conditioned on states near the data-collection start pose.
- The ResNet18 backbone is ImageNet-pretrained (not robotics-pretrained); the CVAE and transformer are trained from scratch on this task.


