# Dora ULite6 Node

Dora node for controlling a UFactory Lite6 robot via REST API, web UI, and publishing joint/TCP state.

## Dataflow

```yaml
- id: ulite6
  build: uv pip install -e dora_ulite6
  path: dora_ulite6/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 |

## 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

```bash
# 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 degrees
- `tcp_pose` - `[x, y, z, roll, pitch, yaw]` in mm/deg

## Dora Inputs

- `command` - JSON string: `{id, action, payload}`
  - `id`: unique command id (required)
  - `action`: `home`, `move_to`, or `move_to_pose`
  - `payload`: fields for move (`x`, `y`, `z`, `roll`, `pitch`, `yaw`, `speed`)

`status` will include `command_id` for command responses.
