Introduction

The iteration loop

An embodied policy is produced by a closed loop, not a single training run: collect demonstration data on the real robot, train a policy from it, deploy the checkpoint back to the robot, then run on-robot evaluation; whatever the eval exposes feeds the next round of collection, and the model gets stronger loop by loop.

Inside that loop, training runs in your own stack; everything else is real-robot work — and EVA is exactly the real-robot infrastructure that handles it: data collection, model deployment, and on-robot evaluation, in one piece of software.

Embodied-AI iteration loop
01 Collect data Teleoperate the robot, record clean LeRobot demonstration episodes. EVA 02 Train External step: train a VLA from the dataset in your own stack. 03 Deploy Connect the policy server, deploy the checkpoint to the robot. EVA 04 Evaluate Multi-checkpoint trials on the real robot: score, replay, compare. EVA eval logs → next round of collection
Four-step loop: collect → train → deploy → evaluate → feed back. Training is in the loop but runs in an external stack; collection, deployment, and on-robot evaluation are handled by EVA.

Terms: chunk is a short action sequence the policy emits per inference call; episode is used in the LeRobot v2.1 sense.

Software architecture

The action signal for a run originates at a policy server (the trained VLA) or from human teleoperation, passes through EVA-Client — which buffers, smooths, and converts it — then is dispatched to the real robot hardware to execute; the camera and joint observations the robot publishes travel back through EVA to the signal source.

Software architecture
Signal source Policy server (trained VLA) or human teleoperation. openpi starvla gr00t teleop EVA-Client Console, config, strategy, recorder, visualization. MANUAL COLLECT DEBUG EVAL Real robot hardware Runs action commands, publishes cameras + joints. ros1 ros2 zmq dataset action action
EVA is the client, not the robot driver: the motor-level driver runs as a separate program on the robot side, publishing observations and executing the actions EVA sends. EVA sits between the signal source and the robot, owning the console, messaging, recording, and visualization.

Connecting the policy, stepping inference, recording, and evaluation all run from a single web console served on a local port. A run is fully determined by the config file passed on the command line — a .py file naming the robot, transport, policy server, and strategy. Changing behavior means pointing --config at a different file, not editing flags. See Configuration.

Consoles and workflow

The console tabs aren't isolated features — they fall onto three flows: collection, deployment, and evaluation. Establish that logical path first, then look at what each tab does:

Collection

TabWhat it does
MANUALSlider-driven joint control for hardware adaptation and link checks — verify control and observation links before connecting a policy. See MANUAL.
COLLECTTeleop capture and QC; each attempt is recorded as an episode in LeRobot v2.1 format. See Data collection.
REPLAYOpen-loop playback of a recorded episode for offline QC; reuses the same visualization pipeline, no robot or policy server required.

Deployment

TabWhat it does
DEBUGConnect the policy and run inference — continuous, simulation-preview-only, or step-by-chunk in 3D before dispatching to hardware. See DEBUG.

Evaluation

TabWhat it does
EVALMulti-checkpoint sweep; each checkpoint is shown as a slot letter (Model A / B / …) plus its real name, and scored per instruction. See EVAL.
RESULTSynchronized camera video, 3D replay, joint charts, and scores over recorded attempts. See RESULT.

The landing tab is determined by the config: evaluation configs (configs/03_evaluation/) open into EVAL/RESULT; deploy configs open into DEBUG.

Launching EVA

Prerequisites: eva on PATH (see Installation) and a reachable policy server (address comes from the config; see Policy backends). Offline replay needs neither.

eva requires --config pointing at a .py file; --web-port defaults to 8080.

bash
# Deploy config — opens in DEBUG.
eva --config configs/01_deploy/dual_agilex_AGILEX/openpi_qpos.py

# Offline replay — no policy server, no robot.
eva --config configs/00_openloop/dual_agilex_AGILEX_openloop.py

# Checkpoint-sweep evaluation — opens EVAL/RESULT.
eva --config configs/03_evaluation/arx_r5_eval.py

Bundled config folders are named after the target robot (dual_agilex_AGILEX, arx_r5, …). See Configuration for adapting one.

Startup signal. The log prints the console URL followed by a started-on-port line. If the port is taken, rerun with a different --web-port.
log
eva --config configs/01_deploy/arx_r5/openpi_qpos.py
12:14:24.426 INFO  Creating transport: type=zmq robot=arx_r5
12:14:24.430 INFO  ZMQ transport ready: sub=tcp://127.0.0.1:5555 pub=tcp://127.0.0.1:5556 robot=arx_r5
12:14:24.430 INFO  Transport ready: type=zmq obs_mode=JointState
12:14:24.481 INFO  UrdfScene ready for 'arx_r5': 2 parts, 1 URDFs, 9 meshes
12:14:24.483 INFO  Console web server: http://127.0.0.1:8080
12:14:24.483 INFO  Console web server started on port 8080

For a remote robot, forward the port: ssh -L 8080:localhost:8080 you@robot-host. Full options: CLI reference.

Building blocks

Every config wires four pluggable pieces, each selected by a short name:

One config wires four choices
config.py Transport How obs and actions travel to the robot. ros1 ros2 zmq dataset Policy backend Which model server EVA talks to. openpi starvla gr00t mock Inference strategy How chunks are buffered, smoothed, and sent. sync async naive act rtc Action space Joint states or end-effector poses. JointState EEFPose
Swapping the config swaps the robot, connection, model backend, inference behavior, and action representation without touching the console.

Bundled robots: agilex_AGILEX, arx_r5, dual_franka, agibot_g2, r1_lite, ur5e. Add your own.

Where to go next