121 lines
6.3 KiB
Markdown
121 lines
6.3 KiB
Markdown
# dora-teleop
|
|
|
|
dora-rs teleoperation node: normalises two control sources — a gamepad read from
|
|
`dora-joy`, and a web console served by this node itself — into one owner's lease, and
|
|
emits velocity set-points and robot-agnostic commands. It carries no hardware driver: pad
|
|
I/O lives in `dora-joy`, arm I/O in a robot node.
|
|
|
|
**Requirements:** dora 1.0+ (verified with `dora-cli 1.0.1`), Python 3.12+, `uv`.
|
|
|
|
## System
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
pad([gamepad]) --> joy
|
|
browser([browser]) -- "ws: held directions, verbs" --> web
|
|
web -- "ui_state snapshot" --> browser
|
|
joy["dora-joy — sibling repo"]
|
|
subgraph teleop["dora-teleop"]
|
|
web["web console — built in, HTTP + ws on one port"]
|
|
core["command arbitration"]
|
|
end
|
|
joy -- "joy: axes, buttons, present" --> core
|
|
web -- "held directions, ±1" --> core
|
|
core -- "twist SI · command verbs (standard)" --> arm
|
|
core -- "jog · request (deprecated)" --> arm
|
|
arm -. "state · poses · response" .-> core
|
|
arm["robot node"]
|
|
```
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
uv sync
|
|
dora run dataflow.yml --uv # teleop + bench stand-in: no pad, no arm
|
|
```
|
|
|
|
Open `http://localhost:7000` and drive the robot from the console. The bench answers
|
|
services and publishes telemetry so the loop closes.
|
|
|
|
### Watching the wire
|
|
|
|
Every dataflow sets `debug: enable_debug_inspection: true`, so dora can inspect the wire
|
|
without any node printing. This needs a coordinator, so it works for the arm-free dataflow:
|
|
|
|
```bash
|
|
dora up
|
|
dora start dataflow.yml --uv --name teleop-bench
|
|
dora topic list -d teleop-bench # every edge in the graph
|
|
dora topic echo -d teleop-bench teleop/jog # every velocity, live
|
|
dora topic hz -d teleop-bench teleop/jog --duration 10 # the re-send cadence
|
|
dora stop --name teleop-bench && dora down
|
|
```
|
|
|
|
## Running with hardware
|
|
|
|
| Dataflow | Nodes | Needs |
|
|
|------------------------|--------------------------------------|--------------------|
|
|
| `dataflow.yml` | teleop + bench stand-in | nothing |
|
|
| `dataflow-robot.yml` | joy + teleop + ulite6 | a pad and an arm |
|
|
| `dataflow-gamepad.yml` | the same, plus the probe, no console | a pad and an arm |
|
|
|
|
## Gamepad
|
|
|
|
| Control | Does (base frame) | Index | Units |
|
|
|----------------------|----------------------------------------------------------------|--------------|-------|
|
|
| Left stick X / Y | Translate in the horizontal plane: `+X` stick up, `+Y` stick right | axes 0, 1 | mm/s |
|
|
| Left / right trigger | Translate along Z: right trigger lifts (`+Z`), left lowers | axes 4, 5 | mm/s |
|
|
| Right stick X / Y | Rotate: `+roll` stick right, `+pitch` stick up | axes 2, 3 | deg/s |
|
|
| LB / RB | Yaw: RB is `+yaw` | buttons 6, 7 | deg/s |
|
|
| A | Close the tool | button 0 | — |
|
|
| B | Open the tool | button 1 | — |
|
|
| X | Release the E-STOP and clear the arm's error | button 3 | — |
|
|
| Y | Toggle freedrive | button 4 | — |
|
|
| Back | **E-STOP** — latches until X | button 11 | — |
|
|
|
|
The sticks move the arm in its horizontal X/Y plane only; the triggers are the one path
|
|
to Z. Up on the stick sends the arm away from the operator, the same `+X` convention the
|
|
console draws.
|
|
|
|
## Inputs and outputs
|
|
|
|
| Direction | Name | Description |
|
|
|-----------|----------------|--------------------------------------------------------|
|
|
| in | `tick` | 50 ms — change detection, deadman, telemetry |
|
|
| in | `joy` | One pad reading from `dora-joy` |
|
|
| in | `response` | An answer from the arm |
|
|
| in | `motion_state` | How a motion ended |
|
|
| in | `robot_state` | The arm's own state |
|
|
| in | `tcp_pose` | Tool-tip pose, six float32, mm and degrees |
|
|
| in | `joint_pose` | Joint angles, six float32, degrees |
|
|
| out | `twist` | **Standard.** `{linear, angular, frame}`, SI |
|
|
| out | `command` | **Standard.** `{action, value}`, robot-agnostic verbs |
|
|
| out | `jog` | *Deprecated.* mm/s + deg/s, for `dora-ulite6` |
|
|
| out | `request` | *Deprecated.* A service call, `request_id` in metadata |
|
|
| out | `ui_state` | The console's telemetry snapshot, as JSON |
|
|
|
|
## Environment variables
|
|
|
|
| Variable | Default | Description |
|
|
|--------------------------|-----------|--------------------------------------------------------|
|
|
| `SPEED_MM_S` | `60.0` | Translation speed at full deflection |
|
|
| `SPEED_DEG_S` | `30.0` | Rotation speed at full deflection |
|
|
| `DEADZONE` | `0.12` | Stick travel near centre to ignore |
|
|
| `EXPO` | `0.4` | How much of the curve is cubic; 0 is linear |
|
|
| `JOG_TTL_S` | `0.4` | Owner silence before the arm is stopped |
|
|
| `JOG_KEEPALIVE_S` | `0.2` | How often an unchanged velocity is repeated |
|
|
| `JOY_TTL_S` | `0.2` | `joy` silence before the pad reads as gone |
|
|
| `GAMEPAD_IDLE_RELEASE_S` | `2.0` | Untouched pad before it hands the arm back |
|
|
| `STATE_POLL_S` | `0.5` | How often to ask the arm what telemetry does not carry |
|
|
| `WEB_HOST` | `0.0.0.0` | Address the console binds to |
|
|
| `WEB_PORT` | `7000` | Console port; `0` opens no port at all |
|
|
|
|
## Development
|
|
|
|
```bash
|
|
uv sync --group dev
|
|
uv run pytest # 149 tests, no gamepad, arm, browser or daemon needed
|
|
uv run ruff check .
|
|
uv run ruff format --check .
|
|
```
|