Running a workflow on real hardware
Switch the Workflow Editor to Real Hardware and run, with the preflight checks and stop behaviour explained.
Running on real hardware happens in the Workflow Editor, the same screen you use for a simulated run. There is no separate execution screen. The one control that decides whether physical arms move is the execution world dropdown in the editor's top bar, next to the Run button.
Robots move. Clear the workspace of people and obstacles before you run, and keep a physical emergency stop within reach. The Pause and Stop buttons in the UI are software commands sent over the network. They are not a substitute for an e-stop.
Simulation and real hardware are two live worlds
The backend does not boot into one mode or the other. It brings up two worlds at once and keeps both alive: a simulated one and a real one. Each gets its own Viser 3D server. The viewport panel in the editor is connected to both at all times and swaps between the two clients when you change the dropdown, which is why switching is instant instead of reloading the viewer.
The dropdown offers exactly two options, Simulation and Real Hardware. Your choice is sent with the run as simulation_mode. It is a per-run parameter, not an install setting. You can run the same workflow in sim, change one dropdown, and run it again on the arms without editing anything or restarting a service. The same dropdown appears in the Skills Editor for single-skill runs.
Whether the "real" world actually drives motors depends on the machine you are connected to, and is fixed when that machine starts. A lab machine wired to a robot drives the arms. A machine with no hardware attached backs its "real" world with a stand-in, so choosing Real Hardware there moves nothing physical. If you are unsure which you are on, assume the arms are live and treat the workspace accordingly.
In the cloud there is no hardware at all. The frontend detects the online run mode and forces the dropdown to Simulation, hiding the Real Hardware option entirely; hovering the control shows the tooltip "Cloud runs simulation only".
Workflows themselves are portable. The workflow JSON never records which world it ran in. A skill's Python can ask, using is_sim_mode() from execution.execution_functions:
import math
import numpy as np
from execution.execution_functions import is_sim_mode, load_object_anchor
if is_sim_mode():
rotor_angle = float(np.random.uniform(-math.pi, math.pi))
else:
# Real run: read the rotor angle off the AprilTags.
...That is a common pattern: in sim a skill can fabricate a plausible reading, and on hardware it does the real camera work. Most skills need no such branch.
Checking hardware before a run
The Hardware button in the header shows a coloured dot: green when everything expected is connected, amber when a device is missing, grey when the execution service cannot be reached. Clicking it opens a popover listing Cameras, Robot Arms, and (when the rig has one) Pipette, each as "N of M detected", or "N of M connected" for the pipette. It polls /api/hardware/status every 10 seconds, and toasts once on the transition into a degraded state so a change is not missed.
Be clear about what this does and does not tell you:
| The indicator tells you | It does not tell you |
|---|---|
| How many arms, cameras, and pipettes were detected out of how many are expected | Where the arms currently are (there is no pose readout) |
| Which side is missing, when the backend reports per-device detail | Whether a camera is producing images right now |
| Whether the execution service is reachable | Whether the physical scene matches your world |
For arms and cameras the numbers come from a boot snapshot, the state recorded when the execution service last initialised hardware. They change on a restart or a reconnect, not continuously. A green dot means "these devices connected when the backend started", not "these devices are healthy this second".
Two things you should verify yourself, because nothing in the UI checks them:
- The physical scene matches the world you are about to run. If the workflow expects a plate at an anchor, the plate has to be there. Open the World Builder and compare the saved world against the bench.
- Each arm is fitted with the endpoint the software thinks it is. The header ⋮ menu has Hardware Setup, which lists the active gripper endpoint per arm under a
live:label and lets you change it. Changing it stages the selection and restarts the backend (about 15 seconds), so do it before you run, not during.
Running
- Open
http://localhost:3000and pick your project. - Open the Workflow Editor, the Execute Workflow tile on Home.
- Pick the Workflow and World in the top bar.
- Set the execution world dropdown to Real Hardware.
- Fill in the workflow's inputs in the Inputs tab on the right.
- Click Run. A dialog titled "Name this run" appears; type a label so you can recognise the run later, or leave it blank for an auto-generated id, then click Start.
The dropdown is disabled while a run is in progress. The tooltip reads "Cannot change execution world during active execution". If you change it while a run is live, the run is cancelled first.
Switching from Real Hardware to Simulation on a localized workflow copies the real world's object poses into the sim world. Switching the other way copies nothing. The real world keeps the poses it got from localization, and any changes you made while testing in sim are discarded. Sim work can never move real objects.
What Run does before the arms move
For a real-hardware run, Run does not launch immediately. It runs two preflight gates that sim runs skip entirely. Both are pass/fail: on failure the run never starts, no execution is created, and you get a toast telling you what to fix.
| Gate | What it does | On failure |
|---|---|---|
| Wrist cameras | Grabs one fresh frame from each wrist camera to confirm it is streaming now, rather than only that it enumerated at boot | " |
| Pipette | Homes the pipette, which reconnects a dropped link and initialises it if it was never initialised | "Pipette not connected. Check that the pipette is powered on, power-cycle it, then press Run again." |
The camera check runs first because it is read-only and fast. A rig with no pipette passes the pipette gate automatically.
Once both gates pass, the editor reloads the selected world before signalling execution. This matters: a run mutates object poses in the live in-memory world and never persists them, so re-running the same world without a reload would execute against the previous run's end state. After the load it waits a few seconds for the scene to settle, so the arms do not start moving while the viewport still looks half-loaded.
During a run
The editor is three panels. World View on the left is the Viser viewport for whichever world you selected: the sim scene or the real one, one at a time, never overlaid. Graph Editor in the middle shows the workflow nodes. The right-hand panel switches to the Log tab when the run starts, and the status badge in the top bar reads RUNNING, then COMPLETED, FAILED, or CANCELLED.
If a skill needs an operator decision mid-run, a prompt dialog opens and the run waits for your answer.
Pausing and stopping
Neither button is an emergency stop, but both act on the arms immediately rather than waiting for the current motion to finish.
- Pause stops both arms straight away, mid-move, and sets a flag so the execution loop halts after the current node. The badge reads
PAUSED. Resume with the green Resume button; a skill can register extra labelled resume actions, which appear as additional buttons beside it. - Stop cancels the run. It issues a hard stop to both arm controllers so any in-flight streamed motion is rejected rather than resumed, then clears errors and re-enables the controllers so your next move or gripper command works without manual recovery.
The arms are never automatically homed, not on Pause, not on Stop, not on failure, not on a clean finish. They stay exactly where they stopped. Plan for that: a stop mid-transfer can leave an arm holding a plate over an open instrument.
Stop deliberately keeps your setup on screen. The workflow, world, and input values stay as they were so you can adjust something on the bench and press Run again with the same inputs. Only the pointer to the cancelled execution is forgotten, so a page refresh will not reconnect you to a dead run.
When a skill fails
Execution stops at the failing node and the status badge turns FAILED. The error surfaces in the Log tab. The arms hold position.
Fix the cause (re-place an object, re-seat a camera, correct the world, edit the skill) and run again.
If the workflow got part-way through and you want to continue rather than start over, use the Resume run dropdown in the top bar. It lists incomplete past runs under the heading "Resume an incomplete run" and re-launches into that run's existing execution folder, so liquid-handling skills skip transfers already recorded as done.
The resume wizard moves hardware
Resuming does not go straight back to running. It opens a five-step wizard that walks you through recovering the pipette by hand, because the arms were left wherever they stopped:
- Resume this run? Explains that it will clear the current world, restore the run's inputs, and continue from where execution stopped.
- Hold the pipette. Asks you to take hold of the pipette that is still in the gripper.
- Open the gripper. Gives you a slider per arm.
- Return the pipette. Asks you to place it back in its stand.
- Ready to resume. Resumes the workflow.
The sliders in step 3 drive the physical gripper. They are not a simulation preview. Moving one opens or closes the real gripper immediately, at the point in the wizard where you have been told to be holding the pipette. Have a firm hold on it before you touch a slider, keep your other hand clear of the jaws, and move the slider in small increments.
Where to go next
Updated 2 days ago