RESULT

Read-only viewer over eval recordings: a model → task → trial tree plus a synced camera / 3D / chart replay of any scored attempt.

RESULT: read-only browser over recorded eval attempts with camera, 3D, and chart playback.
RESULT: read-only browser over recorded eval attempts with camera, 3D, and chart playback.

Overview

RESULT appears whenever the launched config contains an eval section. It replays what EVAL recorded; with nothing recorded the tree is empty.

bash
eva --config configs/03_evaluation/ur5e_eval.py

The page splits into two panes:

Where the data comes from

There is no single results file. Each model's attempts are recorded into that model's own dataset folder under the run's output directory; rows load directly from those datasets.

Output directory. Defaults to work_dirs/<config path without leading configs/>/ — launching configs/03_evaluation/ur5e_eval.py writes to work_dirs/03_evaluation/ur5e_eval/. Each model gets its own subfolder.

Each recorded attempt carries the fields RESULT displays:

FieldMeaning
trial identityTask and attempt number this recording belongs to. Bound when RUN is pressed on EVAL. Un-evaluated recordings have none and are skipped.
prompt · trialWhich task, which repeat.
score · max scoreScore given, and the task's milestone count (its maximum).
milestones · notePer-milestone marks and free-text note.
scored at · durationWhen scored, and run duration.

Re-testing the same attempt keeps only the latest recording.

Models in the tree. RESULT lists the models named in the eval config, then picks up any other model folder under the output directory that holds recordings — a model renamed in a prior run still appears.

Model · task · trial tree

Collapsible three-level tree: model, task, attempt. One model and one task expand at a time. Each model and task row shows two ring gauges:

A gauge reads with nothing scored, and turns red on a zero. Expanding a task reveals its attempt grid, one cell per attempt slot.

Attempt grid

One cell per attempt:

If two recordings land on the same cell, the scored one wins, so a later unscored re-run cannot hide a score. Task labels show prompt_zh when set, otherwise prompt_en.

Selection

The right pane starts empty ("Expand a model and task, then select a trial to replay."). Clicking a scored cell loads its replay; the selected cell stays highlighted across tree redraws.

score% and success% roll up identically at every level: a task's gauges sum its scored cells; a model's gauges sum every scored cell across its tasks. A zero-scored cell still counts.

Replay

The replay shows all panels at once — no tabs. The header shows prompt, attempt number, score, and the task's read-only milestone steps. All panels share one timeline:

PanelContent
cameraEvery recorded camera side by side, one video each. Seeking is frame-exact. Only cameras with a recording on disk appear.
urdf3D playback driven by forward kinematics from the recorded joint angles. If the robot has no URDF set in its config, this panel reads "no URDF replay"; camera and chart panels still work.
chartsTwo per-frame line charts — ACTION (commanded) and STATE (measured). Each line is one joint or axis; toggle individually (all on by default).

The scrub bar and play button drive one cursor across all panels, keeping cameras, 3D, and charts in lockstep. Playback paces by the recording's own frame timing.

Browsing other models. Any recorded model can be replayed from the tree, not just the most recently run. Scoring only writes to the model actively running on EVAL.

Configuration

RESULT has no settings of its own — it shows whatever the eval run recorded. The same eval_cfg block that drives EVAL fills RESULT:

An eval preset is a deploy config to inherit from plus a filled eval_cfg. Full field semantics: Configuration → Eval configs. Replace <…> values below.

configs/03_evaluation/ur5e_eval.py
# Eval preset: a deploy config to inherit + a filled `eval_cfg` section.
_base_ = ['<path to your deploy config, e.g. ../01_deploy/ur5e/openpi_qpos.py>']

eval_cfg = dict(
    storage=dict(fps=20, save_queue_max=15),  # recording frame rate; sets replay pacing.
    trials_per_prompt=5,                      # attempts per task = grid width.
    cli_mode='real',                          # real vs sim; see Eval configs.
    inference_strategy='async',               # action timing; see Inference strategies.
    checkpoints=[                              # one model row per entry.
        dict(
            name='<your model name>',       # names the on-disk folder and the tree row.
            config='<path to that model's deploy config>',
            port=9000,                          # policy server port; one per model.
        ),
    ],
    tasks=[                                    # one task row per entry.
        dict(
            prompt_en='<instruction>',
            milestones=(                       # (key, description) pairs; count = max score.
                ('<key>', '<what this step achieves>'),
                ('<key>', '<what this step achieves>'),
            ),
        ),
    ],
)
FieldWhat RESULT does with it
checkpoints[].nameModel folder name under the output directory and label on the model row. Renamed or extra folders from prior runs are still discovered.
tasks[].prompt_enShown as the task row and in the replay header. Overridden by prompt_zh in the tree when set.
tasks[].milestones(key, description) pairs. Count = max score; descriptions render read-only above the replay panels.
trials_per_promptAttempt cells per task.
storage.fpsRecording frame rate; paces replay seeking and the chart cursor.
RESULT reads; it never starts a run. A task with no milestones has max score zero, so its scored cells count toward attempts but not toward score% or success%.

Full eval field reference — cli_mode, inference_strategy, reset_after_each_trial, shuffle_ckpts, the ssh block, optional prompt_zh and init_pose — see Eval configs.