Running Inference#
The recommended way to run inference is to use the eval_server.py script. This script connects as a websocket client to a separately started policy server and runs rollouts on the evaluation set, outputting videos and statistics. With this approach, you can interface with your policy after writing a minimal policy server wrapper, avoiding the necessity to merge MESA’s dependencies into your own.
Running the evaluation server#
To start the evaluation server, run the following command:
uv run scripts/eval_server.py \
--exp-name <exp_name> \
--variant-name <variant_name> \
--eval-set-name <eval_set_name> \
--num-rollouts-per-task <num_rollouts_per_task> \
--controller-type <controller_type> \
--port <port>
Some notable arguments:
--exp-nameand--variant-name: These optional arguments are used to determine the output directory for the evaluation results. If provided, the results will be saved inexperiments/<eval_set_name>/<exp_name>/<variant_name>/. If not provided, the results will be saved inexperiments/<eval_set_name>/<date>/<time>/.--eval-set-name: The name of the evaluation set to run.--num-rollouts-per-task: The number of rollouts to run per task. This will iterate through all the task variant BDDL files before repeating any.--controller-type: The type of controller to use. Valid options areosc_poseandjoint_pos. If using delta actions, you’ll need to add--control-delta.--port: The policy-server port to connect to.--task-filter: Optional task names to evaluate; other tasks are excluded.--eval-split: Task-definition split to use (evalby default).--max-stepsand--per-subtask-extra-steps: Initial action budget and additional actions allowed per completed subtask.
The sequential eval_server.py script is useful for debugging, when speed is not a concern. For large evaluation jobs, you should use the parallel eval_server_parallel.py script which has the same interface and outputs but runs rollouts in parallel.
Start a policy server#
Next, implement a policy server that ingests observations and returns actions. MESA provides mesa.serving.websocket_policy_server.WebsocketPolicyServer, based on openpi. Its websocket client comes from openpi-client (included in third_party/openpi-client). A sample policy server which outputs random actions is provided in scripts/demo_policy_server.py, which you can run with
uv run scripts/demo_policy_server.py --port <port>
For example, to run a policy server that outputs random delta end effector pose actions, you would run
uv run scripts/demo_policy_server.py \
--port 8001 \
--controller-type osc_pose \
--control-delta
in one terminal and
uv run scripts/eval_server.py \
--port 8001 \
--eval-set-name mesa-70 \
--num-rollouts-per-task 10 \
--controller-type osc_pose \
--control-delta \
--render
in another.
For real models, run your model-specific websocket server and point MESA to it. For example, our policy server for pi models is provided in our fork of the openpi repo, and our GR00T-N1.6 server in pairlab/mesa-GR00T.
Bimanual (BiMESA) evaluation#
The BiMESA suites run through the same evaluation server with the dual-arm I/O contract. As in the single-arm setting, each rollout restores a fixed initial state from mesa/task_suites/init_states/bimesa, downloaded by ./scripts/setup.sh (or uv run python scripts/setup/download_init_states.py), so results are comparable across methods. Add the dual-arm robots, controller, cameras, and state keys:
uv run scripts/eval_server_parallel.py \
--port 8001 \
--eval-set-name bimesa-id \
--num-rollouts-per-task 50 \
--controller-type joint_pos \
--robots ReverseMountedYam ReverseMountedYam \
--camera-names egocentric robot0_eye_in_hand robot1_eye_in_hand \
--state-keys robot0_joint_pos robot0_gripper_jaw_width robot1_joint_pos robot1_gripper_jaw_width
Set --eval-set-name to one of bimesa-id, bimesa-spatial, bimesa-instance, bimesa-object, or bimesa-composite. The 14-D observation state concatenates each arm’s joint positions and gripper width, matching the 14-D action. On the policy side, the openpi-mesa serve_policy.py uses the BiMESA observation format automatically for *_bimesa configs (or explicitly with --policy-format bimesa); this is a policy-server option, not an evaluation-server option.
For more information on running inference with our trained models, please refer to the evaluating trained policies page.