MANUAL
Hand-drive a real robot with one slider per joint — no policy in the loop. Stage a target pose, preview it as a ghost arm, CONNECT, then SEND TO REAL; the button becomes STOP mid-dispatch. HOME returns the arm to its rest pose.
Overview
MANUAL is the only tab that drives the arm with no policy in the loop. Use it for hardware bring-up, parking at a known pose, or verifying that the configured transport actually drives the robot. No policy server is required.
Connect, stage a pose, send it, or go home
The control column has four panels, top to bottom: connect, dispatch, tuning, target joints.
| Panel / control | What it does |
|---|---|
| CONNECT | Toggles connect/disconnect to the real robot; the line above shows link status (see Connecting to the robot). Greyed out when the transport is not a live type. |
| SEND TO REAL ▶ | Dispatch the staged target to the real robot. Clickable only when connected and receiving live data. Mid-dispatch the button becomes a red STOP ■ that halts motion immediately. |
| HOME ⌂ | Set the target to the robot's rest pose and send it. The rest pose comes from your config (see Config). Always clickable. |
| publish rate Hz + APPLY ⤓ | Adjust the dispatch rate (frames per second). Change the value and click APPLY (or press Enter); a line below shows applying… / applied / failed. Defaults to the config's publish_rate. |
| sliders (one per joint) | Each slider sets the target angle for one joint (j00, j01…, range ≈ −3.2 to 3.2 rad). Moving them only updates the staged target and ghost arm; they do not move hardware. |
SEND TO REAL is the only action that reaches the robot. The arm interpolates smoothly from the current pose to the staged target rather than teleporting.
On entry the target is seeded from the current measured pose. For dual-arm robots the sliders cover every joint across both arms; one staged pose drives the whole robot.
Connecting to the robot
The CONNECT panel has one toggle button; the line above it shows one of four states:
| Status line | Meaning | Button |
|---|---|---|
| SIM DEBUG · no real robot | Transport is not a live type — preview only. | CONNECT REAL (greyed out) |
| SIM DEBUG · press CONNECT REAL | Live transport available, not yet connected. | CONNECT REAL (clickable) |
| WAITING FOR ROBOT… | Connection requested, no live data yet. | CANCEL |
| REAL ROBOT · LIVE | Connected and receiving live data. | DISCONNECT |
LIVE requires the backend to actually be receiving robot data. With the robot off or silent, the state stays at WAITING FOR ROBOT… and SEND TO REAL remains locked.
The two overlaid arms
MANUAL renders into the shared 3D scene with two arms overlaid:
- Solid arm — current measured pose.
- Ghost arm — staged target, i.e. where
SEND TO REALwill drive it.
The gap between solid and ghost is the move about to be commanded.
Stopping a move that looks wrong
Dispatch is interruptible. Options, fastest to safest:
- STOP ■ — mid-dispatch the
SEND TO REALbutton becomes a red STOP; click halts immediately. - HOME — redirect to the rest pose.
- Physical e-stop for true emergencies — the console does not replace hardware safety.
When SEND TO REAL actually moves the arm
Two conditions: transport type and connection state. CONNECT is available only for zmq, ros1, or ros2; SEND TO REAL enables only after connect plus incoming live data. A dataset transport has no live arm — preview only.
The config MANUAL needs
MANUAL has no config section of its own — any deploy config works. Two things matter: a robot definition (so sliders map to joints and HOME has a target) and a live transport (so SEND TO REAL can reach the arm). Launch:
eva --config configs/01_deploy/my_robot/manual.py --web-port 8080
Minimal deploy config — replace the marked values:
# Deploy config: MANUAL drives the real arm via a live transport. # Path is relative to THIS file. _base_ = ['../../00_base/defaults.py'] robot = dict( type='', # EDIT: robot key, e.g. 'ur5e' (see list below). initial_qpos=None, # Rest pose for HOME. None uses the robot's default. ) transport = dict( type='', # EDIT: 'zmq', 'ros1', or 'ros2'. )
| Field | Why MANUAL cares |
|---|---|
transport.type | Must be zmq, ros1, or ros2 for SEND TO REAL to reach a live arm. dataset has no live arm. |
robot.type | Selects the robot and the joints the sliders expose. Built-in keys: agilex_AGILEX, arx_r5, dual_franka, agibot_g2, r1_lite, ur5e. Custom robots: see Add a robot. |
robot.initial_qpos | HOME's target pose. None uses the robot's built-in default. Set explicitly for a specific HOME target; ensure it is collision-free. |
publish_rate | Default value of the TUNING panel's publish rate Hz input; adjustable at runtime. |
What success and failure look like
| You see… | It means… |
|---|---|
| Ghost arm tracks the sliders | Staging is working. Nothing has reached hardware yet. |
Status reads REAL ROBOT · LIVE | Connected and receiving live data; SEND TO REAL is enabled. |
Status stuck on WAITING FOR ROBOT… | No robot data arriving. Check power, e-stop, and transport details. |
| Solid arm slowly catches up to ghost | Real arm is moving to target. |
| SEND TO REAL greyed out | Transport is dataset, or not connected, or no live data yet. See Connecting to the robot. |