The AY-Robots training matrix on /train with five policy models as rows and four robot arms as columns, every cell linking to that exact training guide
evaluationvlapolicy-trainingbenchmarksgr00tlerobot

Open-Loop vs Closed-Loop Evaluation of Robot Policies

AY-Robots ResearchAugust 23, 202623 min read

Open-loop evaluation scores predicted actions against recorded ones. Closed-loop evaluation runs the policy on the robot. Which to run when, with real commands, defaults and rollout-count statistics.

A fine-tuning run just finished. There are eight checkpoints in the bucket and one arm on the desk. Two different tests are now available, and they answer two different questions. Open-loop evaluation replays a recorded episode and asks how close the model's predicted action is to the action a human actually sent. Closed-loop evaluation hands the model the robot and asks whether the task got done. Teams routinely run the first, report the number, and are then surprised that the arm never closes the gripper.

This page is about which test to run when, what each number really means, and the specific ways both of them mislead you. Every command below was read out of the upstream repository on 24 August 2026; flag names and defaults change, so the version is named wherever it matters.

What you need to know

  • Open-loop evaluation compares predicted actions against recorded actions. No robot, no simulator, no reset. It runs in seconds on one GPU.
  • Closed-loop evaluation lets the policy drive, so its own action decides the next observation. It is the only test that answers whether the task gets done.
  • The two disagree often enough that picking a checkpoint by lowest error is a documented failure mode, not a rare accident.
  • Isaac-GR00T ships both paths: gr00t/eval/open_loop_eval.py prints unnormalized action MSE and MAE, gr00t/eval/rollout_policy.py runs rollouts and reports a success rate.
  • GR00T's open-loop eval is not fully open loop. It re-reads the recorded observation every --execution-horizon steps (default 16), so error cannot compound past one chunk.
  • Rollout count is the hidden cost of closed loop. Twenty rollouts at 70 percent give a 95 percent Wilson interval of roughly 48 to 86 percent.
  • Rule of thumb: open loop to catch broken plumbing, closed loop before making any claim about the task.

The two questions, side by side

Both tests take the same artifact, a trained policy checkpoint, and both produce a single number. That is where the similarity ends. Open loop is a supervised-learning measurement: the model sees a real observation from your LeRobot dataset and its output is scored against the recorded label. Closed loop is a control measurement: the model sees whatever its own previous action produced, which after a few seconds is a state no human demonstrator ever visited.

Open-loop evaluationClosed-loop evaluation
Question answeredDoes the model predict the recorded action?Does the arm finish the task?
Who supplies the next observationThe recorded datasetThe policy's own consequences
OutputA regression error (MSE, MAE) per trajectoryA success rate over N rollouts
What you needOne GPU and the datasetA robot or a simulator, plus a reset between episodes
Wall clock for one checkpointSeconds to minutesTens of minutes to hours
Do errors compoundNo (or only within one chunk)Yes, that is the whole point
Needs a human in the loopNoOn real hardware, yes, to judge success
Good at catchingWrong normalisation, wrong camera keys, dead checkpointsDrift, timing, grasp failures, task-level behaviour

The compounding-error asymmetry is the entire reason the two disagree. Imitation learning trains on a distribution of states a human produced. At rollout time the policy leaves that distribution the moment it makes a small mistake, and the errors it makes off-distribution are not the errors the training loss ever penalised. A model can be very good at the first question and useless at the second. See imitation learning for the background, and loss falls, policy does nothing for the version of this that shows up in a support ticket.

What open-loop evaluation actually measures

NVIDIA's GR00T N1.7 repository has a section literally called Open-Loop Evaluation, and one called Closed-Loop Evaluation right underneath it. The open-loop entry point is a tyro CLI at gr00t/eval/open_loop_eval.py. Point it at a dataset and a checkpoint and it walks a trajectory, asks the model for actions, and compares them against the recorded ones.

bash
uv run python gr00t/eval/open_loop_eval.py \
    --dataset-path <DATASET_PATH> \
    --embodiment-tag NEW_EMBODIMENT \
    --model-path <CHECKPOINT_PATH> \
    --traj-ids 0 \
    --execution-horizon 16
The open-loop command from the Isaac-GR00T README, read 24 August 2026. It writes a plot to /tmp/open_loop_eval/traj_0.jpeg and logs unnormalized action MSE and MAE.

Leave out --model-path and the script does not load a checkpoint at all: it falls back to a PolicyClient talking to a running policy server on 127.0.0.1:5555. That is the same server the closed-loop path uses, which is convenient, and it is also the first thing that silently changes the meaning of your run. Here are the real defaults from the ArgsConfig dataclass.

FlagDefaultWhat it does to the number
--traj-ids[0]Evaluates exactly one episode, index 0. If episode 0 is in the training set, the result is a fit number, not a held-out number.
--steps200Upper bound on steps evaluated, capped by trajectory length. A shorter window hides late-episode drift.
--execution-horizon16How many predicted actions are consumed before the recorded observation is read again. Lower means more re-anchoring and lower error.
--denoising-steps4Diffusion sampling steps for the action head. Changes the actions, and therefore the MSE. Ignored when talking to a remote server.
--embodiment-tagnew_embodimentWhich embodiment head is used. Wrong tag, meaningless number.
--host / --port127.0.0.1 / 5555Used only when --model-path is omitted.
--save-plot-pathNoneFalls back to /tmp/open_loop_eval/traj_{id}.jpeg.
GR00T's open-loop eval is not fully open loop

The loop is for step_count in range(0, actual_steps, execution_horizon). At every one of those boundaries the observation is pulled from the recorded trajectory again, not from wherever the policy would have driven the arm. The model is teacher-forced back onto the human's path every 16 steps by default. Compounding error is truncated at the chunk boundary, which is exactly the error mode that kills a real rollout. This also means MSE numbers are only comparable at the same --execution-horizon: shorten it and the error drops without the model getting better.

The MSE number and what it hides

The script computes mean squared error and mean absolute error over the unnormalized action vector, averaged across every action dimension and every time step, then averages those per-trajectory values. Four consequences follow, and all four bite in practice.

  • Units are whatever your dataset stores. Unnormalized means degrees, or radians, or raw servo ticks. An MSE of 0.8 is meaningless without the unit. It is a within-project number, never a cross-project one.
  • All joints are averaged together. On an SO-100 that is five arm joints plus a gripper, so the gripper is one sixth of the score. A policy that tracks the arm perfectly and never closes the gripper still posts a respectable MSE.
  • One trajectory by default. --traj-ids defaults to [0]. One episode of one task is a sample size of one.
  • It is scored against a human, not against success. Two different valid grasp approaches score as a large error against each other. A slower but correct trajectory scores worse than a fast wrong one.
Documented, not hypothetical

Montagut Bofi et al. fine-tuned SmolVLA and Pi0.5 for an 11-DoF mobile manipulator and found the checkpoint with the lowest aggregate MSE was not the one that performed best on the real robot. Their expert-only variant had the best total MSE and lost the real-robot comparison across 60 trials. Their conclusion is that per-group error is a more reliable checkpoint-selection signal than total MSE on robots with heterogeneous action spaces (arXiv:2606.00253, May 2026). The older robomimic study reached the same place from the other direction: the best-validation-loss policy is 50 to 100 percent worse than the best-performing policy, so every checkpoint has to be tried on the robot.

What closed-loop evaluation actually measures

Closed loop means the environment steps. GR00T runs it as a server plus a client: the checkpoint is served over ZMQ, and a separate process owns the simulator or the robot and calls get_action in the control loop. The split exists because the simulator and the model usually want incompatible Python environments, and it is the same split the platform's inference pods use.

  1. 1
    Serve the checkpoint

    One process holds the weights. --use-sim-policy-wrapper adapts the observation format for the simulator client.

    bash
    uv run python gr00t/eval/run_gr00t_server.py \
        --model-path checkpoints/GR00T-N1.7-LIBERO/libero_10 \
        --embodiment-tag LIBERO_PANDA \
        --use-sim-policy-wrapper
  2. 2
    Run rollouts against it

    The client owns the environment. Note that it runs from the benchmark's own virtualenv, not the project root's.

    bash
    gr00t/eval/sim/LIBERO/libero_uv/.venv/bin/python gr00t/eval/rollout_policy.py \
        --n-episodes 10 \
        --policy-client-host 127.0.0.1 \
        --policy-client-port 5555 \
        --max-episode-steps 720 \
        --env-name libero_sim/KITCHEN_SCENE3_turn_on_the_stove_and_put_the_moka_pot_on_it \
        --n-action-steps 8 \
        --n-envs 5
  3. 3
    Sanity-check the harness before you trust it

    Start the server with --dataset-path and no --model-path and it replays recorded actions instead of predicting them. --execution-horizon is required on this path even though the README example omits it; without it the server raises before it binds. If ReplayPolicy does not solve the task, your environment is wrong and no checkpoint will save you.

    bash
    uv run python gr00t/eval/run_gr00t_server.py \
        --embodiment-tag NEW_EMBODIMENT \
        --dataset-path <DATASET_PATH> \
        --execution-horizon 16
rollout_policy.py fieldDefaultWhy it matters
n_episodes50Rollouts per environment name. The LIBERO example overrides it to 10.
n_envs8Parallel environments. Throughput only, but it changes seeding.
n_action_steps8Actions consumed per inference call, the closed-loop twin of --execution-horizon.
max_episode_steps720Hard timeout. A slow-but-correct policy is scored as a failure.
terminate_on_successnot a CLI flagRolloutConfig has no such field. run_gr00t_sim_policy pins terminate_on_success=True when it builds MultiStepConfig, so the episode stops at the first success. The MultiStepConfig dataclass default is False, which is what you get if you drive the rollout helpers yourself.
seedNoneUnset by default, so initial states vary run to run. When None it falls back to the GR00T_EVAL_SEED environment variable; if that is unset too, the run stays non-deterministic.
Success means ever reached, not still true at the end

Both harnesses accumulate success with an any reduction rather than reading the final state: GR00T does current_successes[env_idx] |= bool(env_success), LeRobot reduces its per-step success tensor with "b n -> b", "any". The shipped GR00T sim entry point then pins terminate_on_success=True, so the episode is cut at the first success; the MultiStepConfig default is False, so a harness you write yourself on top of those helpers silently scores "ever succeeded" instead. LeRobot sidesteps it differently: its rollout docstring says success "can only be True upon environment termination/truncation". Neither reports whether the block was still on the plate when the episode ended. If your task cares about the final state, you need your own criterion, not the benchmark's.

On a real arm there is no is_success

In simulation the environment hands you info["is_success"]. On an SO-100 on a desk, nothing does. Somebody watches the rollout and writes a tick or a cross on paper. That is not a gap in the tooling, it is the actual state of the field, and it is why RoboArena went to double-blind pairwise comparisons across seven institutions rather than trying to standardise an absolute success number.

LeRobot's real-hardware path is lerobot-rollout. In the current docs it is the documented way to deploy a trained policy on the arm, and depending on the strategy it also records what happened. It gives you the rollout; it does not give you a verdict.

bash
lerobot-rollout \
  --strategy.type=episodic \
  --policy.path=${HF_USER}/my_policy \
  --policy.pretrained_revision=010000 \
  --robot.type=so100_follower \
  --robot.port=/dev/ttyACM1 \
  --robot.cameras="{ up: {type: opencv, index_or_path: /dev/video10, width: 640, height: 480, fps: 30}}" \
  --task="Put lego brick into the transparent box" \
  --duration=600
LeRobot real-robot rollout, docs read 24 August 2026. --strategy.type selects base, sentry, highlight, dagger or episodic; episodic adds reset phases between episodes, which is what you want for counting trials.

Two details in that command carry more weight than they look. --policy.pretrained_revision lets you pin a specific pushed checkpoint by its step tag, so you can evaluate step 10000 and step 40000 without renaming directories. And all strategies accept --inference.type=rtc, real-time chunking, which exists because a 485 ms model cannot be run naively at 30 Hz. See action chunking and inference latency for what that is compensating for.

Numbered step list on the AY-Robots GR00T N1.7 on SO-100 training guide, showing the ordered run procedure
The step list on /train/groot-n1-7-on-so-100. The guide ends at a checkpoint; the evaluation decisions on this page are what you do next with it.

How many rollouts is enough

This is the question that decides whether a closed-loop number means anything, and it is almost never stated. A success rate over N rollouts is a binomial proportion. The confidence interval at small N is much wider than people's intuition, which is why two checkpoints that look 15 points apart are frequently indistinguishable.

The table below is the 95 percent Wilson score interval for an observed 70 percent success rate at different rollout counts, plus the smallest gap between two checkpoints that reaches significance in a two-proportion test around 60 percent. Because successes are whole numbers, the achievable gaps are coarse at small N: at 10 rollouts per arm the counts move in 10-point steps, and 4/10 against 8/10 still does not reach significance. These are standard statistics you can recompute in a few lines of Python, not measurements from any particular robot.

RolloutsObserved95% Wilson intervalInterval widthSmallest achievable gap that is significant vs another arm of the same size
107 / 10 = 70%39.7% to 89.2%49.5 pointsabout 50 points
2014 / 20 = 70%48.1% to 85.5%37.4 pointsabout 30 points
5035 / 50 = 70%56.2% to 80.9%24.6 pointsabout 20 points
10070 / 100 = 70%60.4% to 78.1%17.7 pointsabout 14 points
500350 / 500 = 70%65.8% to 73.9%8.0 pointsabout 6 points
The trap that eats a day

You evaluate checkpoint A over 10 rollouts and get 8/10. You evaluate checkpoint B and get 6/10. You delete B, retrain around A, and spend the next day chasing a difference whose two-sided Fisher exact p is 0.63. At 10 rollouts per arm you cannot resolve anything smaller than 50 points. Either budget 50 rollouts per checkpoint, or stop comparing checkpoints and only ask the binary question: does this one do the task at all. See policy only works in one setup for the related failure where the rollouts were all run from the same starting pose.

The vendors are not consistent about this either, which is worth knowing before you compare published numbers. NVIDIA's LIBERO results for GR00T N1.7 are reported over 200 rollouts per suite, ranging from 189/200 on the long-horizon suite to 197/200 on the object suite. The openpi LIBERO client defaults to num_trials_per_task = 50, which over ten tasks is 500 rollouts per suite. Same benchmark, two and a half times the sample size, and a confidence interval about 1.6 times wider at 200 rollouts than at 500.

Simulation benchmarks sit in between

There is a middle option that is genuinely closed loop but does not require your robot: run the rollouts in a simulator. It removes the reset labour and the human judgement, and it introduces a new question, namely whether the simulator ranks policies the way reality does.

LIBEROSimplerEnvYour own arm
What it is130 tasks in four suites: Spatial, Object, Goal, and LIBERO-100 (split into 90 for pretraining, 10 for testing)Simulated replicas of Google Robot and WidowX plus Bridge setupsOne task, your cameras, your lighting
Closed loopYesYesYes
Success signalAutomaticAutomaticA human with a tally sheet
Transfers to your taskNo, different embodiment and scenesNo, different embodimentBy definition
Good forComparing methods against published numbersChecking whether a sim eval pipeline ranks policies like the real worldThe only claim that matters for your project
Cited protocolGR00T: 200 rollouts per suite. openpi: 50 trials per task, so 500 per suiteVisual matching and variant aggregation, scored with MMRV and Pearson correlationWhatever you write down

SIMPLER is the interesting one methodologically, because it is a benchmark about benchmarks. Li et al. (2024) build simulated environments by green-screening simulated assets onto real backgrounds and matching object textures, then score the evaluation pipeline itself with two metrics: Mean Maximum Rank Violation and the Pearson correlation coefficient, both computed between simulated and real policy performance. The repository ships mean_maximum_rank_violation and pearson_correlation plus a table of real-world performance so you can score your own offline eval approach the same way. If you are building any kind of proxy evaluation, that is the honest way to justify it: show that it ranks policies the way the robot does.

Neither benchmark tells you about your SO-100

LIBERO runs a simulated Franka Panda. SimplerEnv runs a simulated Google Robot or WidowX. A 97 percent LIBERO score for a checkpoint fine-tuned on LIBERO says the architecture works; it says nothing about your five-joint arm, your task, or your 50 episodes. Cross-embodiment numbers are useful for picking a starting model, which is what the arena and the head-to-head comparisons are for. They are not a substitute for rollouts on your own hardware.

Which test to run when

The decision is not open loop versus closed loop as a philosophy. It is: what am I trying to rule out right now, and what is the cheapest test that rules it out. Open loop is a smoke test with a numeric output. Closed loop is the acceptance test.

SituationRunWhy
The run just finished and you do not know if the checkpoint loadsOpen loop, one trajectorySeconds, and it catches a corrupt or empty checkpoint immediately
Normalisation statistics may be wrongOpen loopA normalisation mismatch shows as predictions in the wrong numeric range, obvious in the plot
Camera keys or modality config may be mismatchedOpen loopWrong image feed produces a large, flat error on every joint
Choosing between 8 checkpoints from one runOpen loop to shortlist 2 or 3, then closed loopOpen loop is too cheap to skip and too unreliable to decide
Deciding whether to record more episodesClosed loopOnly rollouts tell you whether failures are data coverage or model capacity
Comparing two policy architecturesClosed loop, 50 rollouts eachAnything smaller cannot resolve the difference
Reporting a result to anyone elseClosed loop, with N statedA success rate without a rollout count is not a result
The policy freezes mid-motionClosed loop, watch the videoOpen loop cannot represent the failure at all
Leading with open-loop evaluation
Advantages
  • Runs on the same GPU that just trained the model, in seconds, with no robot and no reset labour.
  • Catches the whole class of plumbing bugs: wrong embodiment tag, wrong normalisation statistics, wrong camera keys, dead checkpoint.
  • Produces a plot per joint, so you can see which dimension is wrong instead of only that something is.
  • Cheap enough to run on every saved checkpoint, which gives you a shape over training steps.
  • Requires no success criterion, so it works on tasks where success is hard to define.
Trade-offs
  • The number does not predict task success, and the failure is documented in both robomimic and recent VLA fine-tuning work.
  • Averaging across joints lets a broken gripper hide behind five well-tracked arm joints.
  • Unnormalized MSE has no absolute scale, so it cannot be compared across datasets or projects.
  • GR00T's implementation re-anchors to the recorded trajectory every --execution-horizon steps, so it never sees compounding drift.
  • Defaults to one trajectory, which is a sample size of one unless you pass a list.
AY-Robots policy comparison table listing GR00T N1.7, GR00T N1.5, Pi0.5, SmolVLA and ACT with parameters, GPU tier, inference latency and minimum episodes
The five trainable policies on /policies. The latency column is what sets your closed-loop control rate: 20 ms for ACT against 485 ms for Pi0.5.

That latency column changes how closed-loop evaluation feels in practice. ACT at 20 ms per action step runs comfortably above 30 Hz, so a rollout looks like a normal robot motion. Pi0.5 at 485 ms per action step only works because the model emits a chunk and the controller plays it out. That is why real-time chunking exists, and why an evaluation that ignores the control rate is measuring the wrong thing. GR00T N1.7 sits at 152 ms, SmolVLA at 245 ms.

Running both, two ways

Everything above runs on your own machine, provided you have the card for it. GR00T N1.7 fine-tuning and serving want an 80 GB class GPU; ACT and SmolVLA fit on 24 GB. The friction is not the commands, it is the three environments (trainer, simulator, robot client) and the dataset version dance.

  1. 1
    Get the dataset into the version the loader wants

    GR00T needs LeRobot v2.0 or v2.1. A v3.0 dataset crashes the loader, so convert down first.

    bash
    cd scripts/lerobot_conversion
    uv venv && source .venv/bin/activate
    uv pip install -e . --verbose
    python convert_v3_to_v2.py --repo-id <DATASET_REPO_ID>
  2. 2
    Open loop on a held-out episode

    Pass trajectory ids you did not train on. Run it on more than one.

    bash
    uv run python gr00t/eval/open_loop_eval.py \
        --dataset-path ./my_so100_data \
        --embodiment-tag NEW_EMBODIMENT \
        --model-path /tmp/run/checkpoint-20000 \
        --traj-ids 47 48 49 \
        --execution-horizon 16
  3. 3
    Serve the shortlisted checkpoint

    One process holds weights, one owns the hardware.

    bash
    uv run python gr00t/eval/run_gr00t_server.py \
        --embodiment-tag NEW_EMBODIMENT \
        --model-path /tmp/run/checkpoint-20000 \
        --device cuda:0 \
        --host 0.0.0.0 --port 5555
  4. 4
    Rollout and count

    On simulation, use rollout_policy.py. On a real arm, use LeRobot and a tally sheet. Fix N before you start, and do not stop early because the numbers look good.

    bash
    lerobot-rollout \
      --strategy.type=episodic \
      --policy.path=outputs/train/act_so100/checkpoints/040000/pretrained_model \
      --robot.type=so100_follower \
      --robot.port=/dev/ttyACM1 \
      --task="Put the cube in the bowl" \
      --duration=600
Port 5555 and the silent flag

If the server says ZMQError: Address already in use, something else holds 5555; pass --port. And note that --denoising-steps passed to the open-loop client is ignored when you are talking to a remote server. It is only applied when the client loads the checkpoint itself. Set it on run_gr00t_server.py instead, or you will compare two runs that used different sampling without knowing it.

A loop that survives contact with a real week

Here is the sequence that wastes the least time, assuming one task, one arm, and a fine-tuning run that saved checkpoints along the way. It is built around the fact that open-loop evaluation is nearly free and closed-loop evaluation is not.

  1. 1
    Replay one recorded episode on the arm first

    Before evaluating any model, replay a recorded episode. If the recorded actions do not reproduce the task, your calibration or your dataset is wrong and every evaluation after this is noise.

    bash
    lerobot-replay \
        --robot.type=so100_follower \
        --robot.port=/dev/ttyACM1 \
        --robot.id=my_follower \
        --dataset.repo_id=${HF_USER}/my-task \
        --dataset.episode=0
  2. 2
    Open loop on three held-out episodes, every checkpoint

    Same --execution-horizon and same --denoising-steps for all of them, or the comparison is meaningless. Look at the per-joint plots, not only the scalar.

    bash
    for CKPT in 5000 10000 15000 20000; do
      uv run python gr00t/eval/open_loop_eval.py \
        --dataset-path ./my_so100_data \
        --embodiment-tag NEW_EMBODIMENT \
        --model-path /tmp/run/checkpoint-$CKPT \
        --traj-ids 47 48 49 \
        --execution-horizon 16 \
        --save-plot-path ./plots/ckpt-$CKPT.jpeg
    done
  3. 3
    Throw away only the obviously broken ones

    Use open loop to eliminate, not to rank. A checkpoint whose predictions are in the wrong numeric range or flat on the gripper dimension is dead. Two checkpoints within a few percent of each other are tied, whatever the decimal places say.

  4. 4
    Closed loop on the survivors, fixed N, fixed start states

    Pick N before you start. Twenty rollouts is enough to answer does this work at all. Fifty is the smallest number that lets you rank two candidates. Vary the object start pose deliberately across the rollouts, otherwise you are measuring one initial condition.

  5. 5
    Write down N, the successes, and the failure mode

    Not just 14/20. Note what the eight failures looked like: overshoot, early gripper close, freeze, wrong object. That distribution is what tells you whether to record more episodes or change the model, and it is the thing open-loop MSE can never give you.

Cost, honestly

On the A100 or H100 tier that GR00T N1.7, GR00T N1.5 and Pi0.5 need, a run is 3 to 6 hours at 1.20 to 2.00 USD per hour, roughly 4 to 12 USD. On the 24 GB tier that SmolVLA and ACT need, it is 2 to 5 hours at 0.30 to 0.60 USD per hour, roughly 1 to 3 USD. Open-loop evaluation of every checkpoint from one run costs a few minutes of that same GPU. Fifty closed-loop rollouts costs an hour of your own attention and cannot be parallelised on a single arm. Budget the human time, not the GPU time, and see pricing for the run side.

AY-Robots cost table showing which GPU each policy requires, typical run time and price, and how many episodes are needed before a policy is useful
The cost table on /try. The episodes column matters for evaluation too: below the minimum, a low open-loop error usually just means the model memorised a small set.

Where neither test helps, and what to do instead

Both tests share a blind spot: they assume the thing you are measuring is the policy. Often it is not. If inference runs across the public internet, a closed-loop rollout measures your network. The control loop on these models is 20 ms for ACT up to 485 ms for Pi0.5 per action step, and adding round trips on top of that turns a working policy into a hesitant one. Remote inference is viable for slow pick-and-place and not for fast reactive motion. For an evaluation you intend to trust, put the inference next to the servos.

The second blind spot is the dataset. If the recorded episodes contain a systematic defect, a wrist camera that shows a frozen frame, or an action stream sampled on a different raster than the images, then the open-loop error is measuring the defect and the closed-loop failures have a data cause that no checkpoint choice will fix. That check belongs before evaluation, not after it: see collecting high-quality VLA training data and, for the underlying dataset mechanics, episodes and the dataset docs.

Seeds, and why GR00T runs are not bit-for-bit reproducible

GR00T's fine-tuning entry point, launch_finetune.py, exposes no seed. LeRobot's default seed is 1000. That means two GR00T runs with identical hyperparameters produce different weights, and therefore different evaluation numbers. If you are comparing a hyperparameter change, the difference you measure includes run-to-run variance you cannot remove. Treat small gaps between two GR00T runs the way you treat small gaps between two 10-rollout evaluations: as nothing. More on this in the training docs.

Finally, if you want context on how the field reports these numbers at all, the arena collects 85 VLA models and 332 benchmark results with every value linked to its paper or model card. Reading two or three of those source pages is the fastest way to see how differently people define success, and how rarely the rollout count is printed next to the percentage. Related reading on this blog: vision-language-action models for the model class, and the SO-100 complete guide for the hardware end of the loop.

Train it, then actually test it

Pick a model and an arm and get the exact guide for that combination, with the defaults the trainer really sends. The GPU is rented per run and the pod destroys itself when idle.

Open the training guides
Can I use open-loop MSE to pick the best checkpoint?

Only to eliminate, not to rank. The robomimic study found the best-validation-loss policy is 50 to 100 percent worse than the best-performing policy, and a 2026 VLA fine-tuning study found the checkpoint with the lowest total MSE lost the real-robot comparison. Use open-loop error to throw out checkpoints that are clearly broken, then run rollouts on the two or three that survive.

Why is GR00T's open-loop eval called open loop if it re-reads the recorded observation?

Because the environment never steps: the policy's action has no effect on what it sees next. It is open loop in the control sense. But it re-anchors to the recorded trajectory every --execution-horizon steps, default 16, so it is teacher-forced at chunk boundaries and cannot show error compounding across a whole episode. That is worth knowing before you read too much into a low MSE.

How many rollouts do I need before a success rate means anything?

For the binary question does this work at all, 20 rollouts is usually enough: an observed 14/20 has a 95 percent Wilson interval of about 48 to 86 percent, which is comfortably above chance for most tasks. For ranking two checkpoints, 50 per arm is the practical minimum, and even then you can only resolve gaps of roughly 20 points. Published LIBERO numbers use 200 to 500 rollouts per suite for this reason.

Do LIBERO or SimplerEnv scores tell me anything about my SO-100?

They tell you the architecture works and roughly how it ranks against alternatives. They do not transfer to your arm: LIBERO runs a simulated Franka Panda, SimplerEnv runs a simulated Google Robot or WidowX. Use them to choose a starting model, then evaluate on your own hardware. The comparison pages and the arena exist for exactly that first step.

What is the fastest check that a fresh checkpoint is not broken?

Run open-loop evaluation on one held-out trajectory and open the plot. Predictions in a completely wrong numeric range point at normalisation statistics. A flat line on the gripper dimension points at the gripper never being learned. A large error on every joint at once usually means the wrong embodiment tag or a camera key mismatch. All three are visible in under a minute, and none of them need a robot.

Does AY-Robots score my rollouts automatically?

No. The platform provisions the GPU, runs the trainer, serves the checkpoint from an inference pod and connects your robot client to it. Deciding whether a rollout succeeded is still a human watching the arm. There is no automatic success detector for an arbitrary real-world task on this platform, or on any of the open-source tooling for real hardware.

Ready for high-quality robotics data?

AY-Robots connects your robots to skilled operators worldwide.

Get Started