← All skills

Skill

Robot learning

Robots that learn their behavior from data: vision-language-action models and reinforcement learning. I built and ran the VLA benchmark for the ARCHITECT paper, and a reset for online RL.

4 log entries2 projects

Benchmarking VLAs for ARCHITECTBest example

Designing the benchmark: what makes a VLA test fair

Task configs

Also shows: Experiment design

A VLA can look great near its training setup and fall apart a few centimeters away, so the hard part is deciding what a fair test is. We picked eight tasks across six kinds of challenge and changed the objects' placement and the wording on each of ten rollouts. We randomized the placements within a set workspace before running any evaluation, and every method ran the same ones. If I ran it again, the biggest thing I'd change is the lighting: we didn't control it well, and the models performed noticeably differently early in the morning than late at night.

Grid of success rates for eight tasks and six methods. The four VLAs score well only on simple pick and place, led by π0.5 at 0.9 and 1.0, and near zero on the drawer, the cloth fold and the banana under a cloth. Code as Policies peaks at 0.6. ARCHITECT scores 0.7 to 1.0 on every task
Success rate over 10 rollouts per task, from the paper's Tables 1 and 2.
Filmstrips of the eight evaluation tasks on the Franka, each labeled with its challenge and instruction: three pick and place tasks, a two-object pick and place, picking bread from a cluttered box, closing a drawer, folding a cloth and uncovering a banana
The eight tasks, from the paper's Figure 3.

Success alone also hides a lot, so in the main benchmark each rollout was scored three ways: did it succeed, what fraction of the goals were met, and how far along a written rubric it got. Separately from that benchmark, we ran an ablation on wording alone: one task with the apple held still and only the instruction changed, fifteen phrasings run once each. π0.5 succeeded on "Grab the apple and set it on the pan" and failed on "Take the apple and place it onto the pan." It was sensitive to how specific the prompt was: given an underspecified one like "Put the apple away," the arm wandered without targeting the apple before eventually turning to the task, and an overly specified prompt degraded it the same way. It struggles when the task's intent is missing or buried.

MolmoAct2 was strong on the banana but struggled with the other pick-and-place tasks, which suggests it's fragile to object type, and on the harder tasks it often misread the prompt entirely, pressing the top of the cabinet instead of closing the drawer. It also disengaged early: in the two-object task it moved one object and withdrew, and in the cluttered box it picked the wrong object and never came back for the right one. Across all of it, the VLAs failed in the same few ways: sensitivity to how the prompt was worded, dependence on the object (π0 never got the baseball into the bucket), and poor spatial reasoning. They ignored vertical clearance, like the height of a barrier or how high to lift a cloth before setting it aside, and when a task called for a specific procedure they defaulted to another one that couldn't finish it, grabbing the drawer's lip instead of pushing it closed.

For π0 and π0.5 on each task, success rate beside task progression. On the hard tasks success is 0 to 0.1 while progression is often higher, such as π0 reaching 0.40 of the cloth fold
Why one number isn't enough: success against how far the policy got.
Fifteen phrasings of the same apple-to-pan instruction, with π0.5 and ARCHITECT marked for each. π0.5 succeeds on 6, failing on synonyms, reordered and ambiguous wording, typos and under- or over-specified instructions. ARCHITECT succeeds on 13
The language ablation: one task, fifteen phrasings, each run once.

Benchmarking VLAs for ARCHITECT

An evaluation harness for any VLA

Code

Also shows: Python

Every VLA ships its own server, and they don't agree on how to talk: openpi's π0 and π0.5 use WebSockets, GR00T uses ZMQ and MolmoAct2 uses HTTP. I wrote one harness that hides all of that behind a single interface: a new model, task or whole benchmark is a short YAML file, not new code.

On the robot, the harness asks the policy for a chunk of actions, runs eight of them open loop, then asks again, recording the scene and wrist cameras throughout. The operator scores each rollout, everything is saved as it goes so an interrupted run resumes, and one script turns the results into success rates per task and per prompt.

Diagram of the harness: YAML configs feed run_eval.py, which drives the DROID robot and asks one policy client for chunks of actions; the client reaches π0 and π0.5 over WebSocket, GR00T N1.7 over ZMQ and MolmoAct2 over HTTP; every rollout's scores and videos go to a results folder that compute_results.py turns into CSVs
How a run fits together.
π0.5 putting the banana on the plate.

Benchmarking VLAs for ARCHITECT

The paper: A Few Words Go a Long Way

PaperWebsite

ARCHITECT is the lab's system, not mine: I'm a co-author for the VLA benchmark behind its comparison. The paper asks whether robot programs written by a coding agent, and fixed with a few words from a person, can beat end-to-end VLAs. ARCHITECT has an LLM write a program from perception and control tools, runs it, and reads back an execution trace. When it fails, a person says what went wrong ("grasp the cup from the top"), and the fix is saved to a skill library the agent reuses on later tasks.

On eight real tasks on a Franka Panda, ARCHITECT succeeded 70 to 100% of the time on every one, while Code as Policies, which writes the program once, topped out at 60%. The VLAs held their own only on simple pick and place, where π0.5 succeeded 90% of the time on the banana and every time on the block, against ARCHITECT's 80% and 70%; they scored 0 to 10% on the drawer, the cloth and the hidden banana. A six-person study tested the skill library: with skills learned on the cup task, people needed 0.83 corrections per trial on the box task instead of 4.67, and with no corrections at all, success on the box task went from 0 of 6 to 4 of 6.

Banana under a cloth: ARCHITECT, Code as Policies, π0 and π0.5.
Bar chart of human queries per trial with and without a skill library: about 4.7 without, under 1 with, one line per participant
Corrections needed, without and with skills from an earlier task (N = 6).

Fleet RL

Resetting the peg without a person

Code

Also shows: Motion planningPython

In online RL an arm practises a task over and over, so after every try something has to put the peg back where the task starts. I built that reset for the peg-insertion task. A teammate and I designed the tagging together, and they wrote the code that reads it: ten AprilTags on the peg's faces, from which the scene camera solves the peg's full pose. I calibrated each camera with a ChArUco board, first its lens (the intrinsics), then its pose relative to the arm (the extrinsics). For the second, a calibration script has the arm set the tagged peg down at a grid of spots on the board and fits the arm's joint zeros and the camera's pose to where the arm thought the peg was against where the camera saw it. With that, the reset finds the peg anywhere in the workspace, works out how it is lying, and plans every waypoint of the pick and the place before the arm moves, choosing the grasp the arm can reach with the least travel within its joint limits. It then checks where the peg landed. This lets the teammate's automatic success detection score each try, so the arms can run online RL on their own. The reset has run on a real arm; the clip shows the same planner in simulation.

Four resets from four scrambled spots, planned by the reset code and shown in simulation at 2× speed.
Four views of the square peg with a tag on the top, the bottom and two on each side face, numbered 0 to 9, with a red arrow marking each tag's top edge
Where the ten tags go on the peg.