Grasping in the Dark

A robot arm learns to pick up and lift a cube from a reward it almost never receives — reinforcement learning, in simulation, on a single GPU, in about forty minutes.

Rajat Dandekar

Vizuara AI Labs · RL in Production — Session 3 (Robotics)

The trained RL policy grasping the cube

The trained policy executing a clean reach → grasp → lift (front | wrist cameras) — learned entirely from a sparse reward, in ~40 minutes on a single GPU.

0 → ~100%
grasp success
over one training run
~40 min
wall-clock
to a reliable grasp
1× L4
a single GPU
(~$0.55 of compute)
0
human interventions
(autonomous in sim)
The whole idea

Learn from a reward
you almost never see

The arm gets +1 only when it lifts the cube above 10 cm, and 0 otherwise. For thousands of steps it succeeds by accident, if at all. Yet from that whisper of a signal — plus a handful of prior demonstrations — SAC + RLPD shape a reliable grasp.

why it's surprising

No hand-designed reward, and no human at runtime: in simulation the environment supplies the reward, so training is fully autonomous. The human is a concept we teach, not a dependency.

Why RL is hard on a real robot
On a real robot, data is the scarcest resource — no parallelism, no free resets, no free failure. Every design choice in HIL-SERL answers that constraint.
Learning from a sparse reward
The whole problem in one picture: the reward is 0 almost everywhere and +1 only on a successful lift — so for thousands of steps the agent succeeds by accident, if at all. Prior data does the heavy lifting.
Abstract

Abstract

Reinforcement learning is often dismissed as impractical for real robots — too sample-hungry, too fragile, too expensive outside a simulator. HIL-SERL (Luo et al., 2024) is the counter-argument: it trains vision-based manipulation policies to near-perfect success in one to two hours on a single real robot. We reproduce its learning core — Soft Actor-Critic combined with RLPD (Reinforcement Learning with Prior Data) — entirely in simulation, fully autonomously, on a single L4 GPU. On LeRobot's gym-hil / PandaPickCube task a Franka Panda goes from 0% to ~100% grasp success in ≈5,000 gradient steps (≈40 minutes), learning almost entirely from a sparse reward it initially never receives. We give the full recipe, the learning dynamics, an honest account of the engineering it takes to run distributed RL on ephemeral cloud GPUs, and a concrete sim-to-real bridge to the $200 SO-101 arm — everything one command from reproduction.

Method

HIL-SERL = SAC + RLPD + reward-from-pixels + a human option

Four ideas stack into a system that learns manipulation on raw camera images, sample-efficiently. In simulation we run the first two autonomously; the last two are what carry the method to real hardware.

The autonomous simulation pipeline
The autonomous pipeline: two cameras + an 18-D state → a frozen ResNet-10 encoder → the SAC Gaussian-actor policy → an end-effector action → the gym-hil MuJoCo env, which returns the sparse reward and next observation into a replay buffer that RLPD samples 50/50. In simulation the environment supplies the reward — no human, no reward classifier at runtime.
The HIL-SERL human-in-the-loop correction loop
The full HIL-SERL loop: the policy acts; when it is about to fail a human takes over; corrective transitions flow into a mixed offline buffer; RLPD updates the policy and critics from a 50/50 blend of online and prior data; and human guidance — heavy early — fades as reliability rises.
Soft Actor-Critic
SAC. A maximum-entropy, off-policy actor-critic — it learns from a replay buffer, which is what makes it sample-efficient enough for real hardware.
RLPD — prior data
RLPD. Every batch is 50% fresh experience, 50% prior data, with LayerNorm critics — so successful transitions stay in view long before the policy can succeed alone.
States and actions on a Panda
The interface. The policy sees two 128×128 cameras + an 18-D proprioceptive state, and acts with a 3-D end-effector move plus a gripper command.
Asynchronous actor-learner architecture
The async actor–learner: the actor steps the sim and streams transitions; the learner holds the replay buffers, runs gradient updates on the GPU, and pushes fresh weights back — over localhost gRPC, in one container.
Why prior data is decisive

Anchoring a sparse-reward search

Sparse-reward manipulation is a needle-in-a-haystack exploration problem: the agent gets no gradient until it accidentally succeeds. RLPD's symmetric sampling keeps successful demonstrations in every training batch, so the value function has something to latch onto — and the policy learns to reproduce, then surpass, the demos.

the accelerant

This is why a grasp is learnable in thousands, not millions, of steps.

where the demonstrations come from

The offline half is seeded with ~30 teleoperated demonstrations from the public lilkm/pick_cube_franka_panda_30 dataset — the standard gym-hil seed set, not collected by us. On a real SO-101 you'd record your own ~15–25 teleop demos instead.

RLPD symmetric 50/50 sampling
50/50 symmetric sampling from online and offline buffers, with LayerNorm critics and a high update-to-data ratio.
Results

From 0% to a reliable grasp, in ~40 minutes

The policy begins by failing every episode. Its first successful lift appears around step 2,900; from there RLPD's prior-data blend compounds fast, and within ≈5,000 gradient steps it grasps essentially every time.

Learning curve: grasp success rate rising from 0% to 100% over training
The real learning curve (single autonomous run, one L4 GPU): flat at 0% until the first successful grasp near step 2,900, then RLPD's prior-data blend compounds the climb to ~100% by step ~6,800.

Before & after

Nothing about the task or the reward changed — only the weights did. That is reinforcement learning doing the one thing imitation cannot: getting better than any single demonstration by optimizing the reward directly.

untrained policy flailing, cube untouched
Before — the untrained policy flails; the cube is rarely touched.
trained policy reaching, grasping and lifting the cube
After — the learned policy: a clean reach → grasp → lift.
PolicyGrasp successNote
Random / untrained~0%no reward signal exploited yet
First 20 training episodes0 / 20sparse reward, still exploring
Last 20 training episodes20 / 20converged, ≈opt-step 5,000
Trained policy — converged checkpoint~95%19/20 in the last training window; rolling success plateaus near 100%
Analysis · how the method actually works

Reading the learning dynamics

Three views of the same run — what changes as RLPD's 50/50 prior-data blend compounds a near-absent reward signal into a reliable skill.

Grasp success rate by training stage
Grasp success climbs from ~0% (random) through mid-training to a converged policy — the sparse reward is enough, once prior data anchors the search.
Episode outcomes by training phase
Episode by episode, outcomes shift from failure to grasp — you can watch the value function learn to find the reward.
Sample efficiency milestones
Sample efficiency: the first successful grasp near step ~2,900, and reliable grasping by ~5,000 — about forty minutes on one L4 GPU.
The engineering, honestly

What it takes to run distributed RL on cloud GPUs

A claim that "RL is production-ready" is only credible with its failure modes attached. Every one of these was found by running the system — and every one is mundane and fixable.

  • Pristine output dir — learner & actor both validate it; the actor gets its own throwaway dir.
  • Checkpoint image crash — the buffer dumps float[0,255] images the writer rejects; patch to uint8.
  • Preemption-proofing — checkpoint every 1,000 steps and push each to the Hub from inside the job.

How people tackle robot RL
The landscape of approaches to robot RL — HIL-SERL's sample efficiency is what makes the single-GPU run above possible.
Sim-to-real · the $200 payoff

The same brain drives a real SO-101

The point of learning on a Franka Panda in simulation is a $200 SO-101 arm on a real desk. The encouraging fact is how little changes.

Sim-to-real bridge from Panda to SO-101
What crosses the sim→real gap: the learning brain (actor–learner, SAC, RLPD, the policy) carries over unchanged; only the robot/camera config changes; and the demos + reward-classifier data must be re-collected on the real arm.
Reused unchangedChanges (config)Re-collect on the real arm
async actor–learner · SAC learner · RLPD · policy network · SAC hyperparameters robot = so101_follower · leader arm for teleop · cameras · EE-space IK & workspace bounds ~15–25 teleop demos · a reward-classifier dataset of real labeled frames (sim gives reward for free)

People have trained a real SO-101 grasp from scratch this way in roughly 1–3 hours. And the best part of the sim-to-real story is that we didn't just describe it — we ran it on a real arm.

Real hardware · we actually did it

HIL-SERL on a real SO-101 — teaching an arm to wipe a whiteboard

We took the exact same method to a physical $200 SO-101 on a desk, on an Apple-Silicon Mac (no CUDA), using the leader arm for human interventions. The task: pick up a duster and wipe a marker off a whiteboard. This is the honest, unpolished counterpart to the clean simulation above — and it's where you actually learn what RL on hardware takes.

The real SO-101 rig: leader + follower arms, two cameras, a Mac
The rig: one SO-101 follower does the task, an SO-101 leader is how a human demonstrates and intervenes, two 128×128 cameras (front + wrist), all driven from an Apple-Silicon Mac (MPS, no CUDA).
The task, teleoperated. A leader-arm demonstration of the wipe (front camera) — the kind of successful episode that seeds the offline replay buffer.
Human-in-the-loop, live. During training the policy drives the follower; when it drifts, a human takes over the leader arm to correct it — and those corrections become training data.
The mechanic

The human is the lever, SAC is the engine

The policy explores; the moment it's about to do something unsafe or unproductive, you press SPACE and guide the follower by physically moving the leader arm. The correction flows straight into the replay buffer, and your intervention rate falling over time is the single clearest signal that learning is working.

what stock LeRobot doesn't support

The leader arm as an intervention controller, joint-space actions, and an Apple-Silicon (MPS) backend — none of it works out of the box. Every fix lives in launcher shims + one teleop subclass; LeRobot's source stays untouched.

The leader-arm human-in-the-loop correction cycle
The subtlest bug

One action convention, unnormalize only at the robot

The SAC actor never normalizes its actions. In end-effector space that's invisible; in joint space the raw [-1,1] output goes straight to the motors and the arm drifts to zero and freezes — it looks like the policy gave up, but the action space was simply never mapped to real joints. The fix: keep every source (demos, policy, leader, buffer) in [-1,1] and convert to joint degrees only at the robot boundary. (The same normalization trap bit the simulation eval, too — see the paper.)

The unified [-1,1] action convention
The four walls hit making HIL-SERL run on a real SO-101
Four walls between the tutorial and a working loop — and the minimal fix for each. The biggest time sink was a documented feature (leader-arm control) that isn't actually implemented in the code.
honest results

The full HIL-SERL loop ran live on real hardware with leader interventions — none of which stock LeRobot supports. A fully autonomous wipe did not converge in a single session: MPS-speed training, only 10 seed demos, and joint-space (vs. the paper's end-effector space) all work against it. The value is the loop, not (yet) the trophy — watching a real arm explore, stall, get corrected by a human, and fold that correction into its own learning, live, is a far more honest picture of RL in robotics than a polished highlight reel.

Sim proves the method; real hardware shows what it takes
The two halves of the story: simulation proves the method converges cleanly; real hardware shows what it actually takes to get there — and why the human, end-effector space, and more compute matter.

Full code, every wall, and the fixes are in the so101-hilserl-whiteboard repo — with the demo dataset and policy checkpoint on the Hub.

Reproduce it

Everything is one notebook and one checkpoint away

# train (detached, single L4) modal run --detach modal/train_hilserl.py::main \ --config configs/train_gym_hil.json --save-freq 1000 --gpu L4 \ --hf-repo RajatDandekar/hilserl-panda-pickcube-sac # evaluate a checkpoint (success rate + video) modal run modal/train_hilserl.py::evaluate --n-episodes 50

The trained policy loads from the Hugging Face Hub in one line; the Colab notebook walks setup → env facts → demo → eval + reward curve → the SO-101 bridge.

Citation

Citation

@misc{dandekar2026grasp,
  title  = {Grasping in the Dark: Sample-Efficient Reinforcement Learning for Robotic
          Manipulation, from Reward, on a Single GPU},
  author = {Dandekar, Rajat},
  year   = {2026},
  note   = {Vizuara AI Labs — RL in Production, Session 3. A reproducible study of
          HIL-SERL (SAC + RLPD) in simulation.}
}

Built on HIL-SERL (Luo et al., arXiv:2410.21845), RLPD (Ball et al., arXiv:2302.02948), SERL (arXiv:2401.16013), and SAC (arXiv:1801.01290), via LeRobot.