a2bf59065d1325ca81081ae36e31f4537841e3bd
The manifest is the only contract a consumer has, since no source package is shared between node repositories, and dora validate checks a dataflow against it without running the node — so CI needs no robot. request and response are deliberately untyped. They carry request_id, and dora defines that as the marker for a pattern-correlated port where several Arrow schemas legitimately flow, one per service; the runtime skips type checks on those messages, so annotating them would claim a contract neither side keeps. examples/ carries its own manifest because dora resolves a node's manifest by walking up from its path, and a manifest applies only when <manifest dir>/<entrypoint> names the same file as the dataflow's path. Without it the example caller would be matched against the arm node's manifest and strict validation would fail on the entrypoint mismatch.
Dora ULite6 Node
Dora node for controlling a UFactory Lite6 robot via REST API, web UI, and publishing joint/TCP state.
Installation
uv pip install -e .
Dataflow
nodes:
- id: ulite6
git: ssh://git@gitea.liria.cl:5001/liria/dora-ulite6.git
git_checkout: v0.1.0
build: uv pip install -e .
path: dora_ulite6/main.py
inputs:
tick: dora/timer/millis/10
outputs: [status, joint_pose, tcp_pose]
inputs: [command]
env:
ROBOT_IP: "192.168.1.192"
DEFAULT_SPEED: "30"
DEFAULT_UNITS: "mm"
API_HOST: "0.0.0.0"
API_PORT: "8080"
VACUUM_ENABLED: "false"
Configuration
| Env Variable | Default | Description |
|---|---|---|
ROBOT_IP |
192.168.1.192 |
Robot IP address |
DEFAULT_SPEED |
30 |
Movement speed (mm/s) |
DEFAULT_UNITS |
mm |
Position units (mm or m) |
API_HOST |
0.0.0.0 |
API server host |
API_PORT |
8080 |
API server port |
VACUUM_ENABLED |
false |
Enable vacuum gripper controls |
TOOL_TYPE |
none |
Mounted tool: none, vacuum, gripper |
TOOL_OFFSET_MM |
0.0 |
Additional Z-offset in mm added on top of the tool preset |
INIT_MODE |
none |
Startup positioning: home, pose, or none |
INIT_X/Y/Z |
300/0/250 |
Initial pose coordinates (mm) |
INIT_ROLL/PITCH/YAW |
180/0/0 |
Initial pose orientation (deg) |
INIT_SPEED |
50 |
Startup movement speed (mm/s) |
Web UI
Access at http://localhost:8080/
- Live status, TCP pose, and joint angles
- Home and Reset buttons
- Move to position form
- Vacuum gripper controls (when enabled)
REST API
Interactive docs at http://localhost:8080/docs
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Web control interface |
| GET | /api/status |
Robot status (connected, errors) |
| GET | /api/pose |
Current TCP pose |
| GET | /api/joints |
Current joint angles |
| GET | /api/config |
API configuration |
| POST | /api/home |
Go to home position |
| POST | /api/reset |
Clear errors and reset state |
| POST | /api/move_to |
Move to position |
| POST | /api/move_to_pose |
Move to full pose |
| POST | /api/disconnect |
Disconnect from robot |
Vacuum Gripper (when VACUUM_ENABLED=true)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/vacuum |
Get vacuum status |
| POST | /api/vacuum/on |
Turn vacuum on |
| POST | /api/vacuum/off |
Turn vacuum off |
CLI Examples
# Get pose
curl http://localhost:8080/api/pose
# Go home
curl -X POST http://localhost:8080/api/home
# Move to position
curl -X POST http://localhost:8080/api/move_to \
-H "Content-Type: application/json" \
-d '{"x": 200, "y": 0, "z": 300}'
# Move with orientation
curl -X POST http://localhost:8080/api/move_to_pose \
-H "Content-Type: application/json" \
-d '{"x": 200, "y": 0, "z": 300, "roll": 180, "pitch": 0, "yaw": 0}'
Dora Outputs
status- JSON:{ok, action, message, timestamp_ns}joint_pose- 6 joint angles in degreestcp_pose-[x, y, z, roll, pitch, yaw]in mm/deg — reflects tool tip whenTOOL_TYPEis set
Dora Inputs
command- JSON string:{id, action, payload}id: unique command id (required)action:home,move_to, ormove_to_posepayload: fields for move (x,y,z,roll,pitch,yaw,speed)
status will include command_id for command responses.