guides/commands.md

# Command Reference

This guide provides a comprehensive reference for all RoArm robot commands and their parameters.

## Command Architecture

RoArm Elixir uses a 3-layer architecture for command handling:

1. **High-level functions** (`move_joints/2`, `led_on/2`, etc.)
2. **Validation layer** (`send_valid_command/2`)
3. **Raw communication** (`send_custom_command/2`)

```mermaid
graph TD
    A[High-level Functions] --> B[send_valid_command/2]
    B --> C[CommandValidator.validate_command/1]
    C --> D[send_custom_command/2]
    D --> E[UART Communication]
```

## Symbolic Values

Many parameters support symbolic values that automatically resolve to appropriate ranges:

- `:min` - Minimum value for the parameter
- `:mid` - Middle value for the parameter
- `:max` - Maximum value for the parameter

```elixir
# These are equivalent:
Roarm.Robot.send_valid_command(%{t: 121, joint: 1, angle: :max, spd: :mid})
Roarm.Robot.send_valid_command(%{t: 121, joint: 1, angle: 180.0, spd: 2049})
```

## Movement Commands

### Home Position (`T: 100`)

Returns the robot to its home/initialization position.

```elixir
{:ok, response} = Roarm.Robot.home()
```

**High-level function:**
- `Roarm.Robot.home/1`

**Parameters:** None

---

### Single Joint Control - Radians (`T: 101`)

Control individual joints using radian values.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 101,
  joint: 1,           # Joint number (1-6)
  radian: 1.57,       # Angle in radians (-π to π)
  spd: 1000           # Speed (1-4096, optional)
})
```

**Parameters:**
- `joint`: Integer, 1-6, required
- `radian`: Float, -3.14159 to 3.14159, required
- `spd`: Integer, 1-4096, default: 1000

---

### All Joints Control - Radians (`T: 102`)

Control all joints simultaneously using radian values.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 102,
  b: 0.0,             # Base joint
  s: 0.5,             # Shoulder joint
  e: -0.5,            # Elbow joint
  h: 0.0,             # Hand/wrist joint
  w: 0.0,             # Wrist rotation (M3 only)
  g: 0.0,             # Gripper rotation (M3 only)
  spd: 1500
})
```

**Parameters:**
- `b`, `s`, `e`, `h`, `w`, `g`: Float, -3.14159 to 3.14159, defaults: 0.0
- `spd`: Integer, 1-4096, default: 1000

---

### Single Joint Control - Degrees (`T: 121`)

Control individual joints using degree values.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 121,
  joint: 1,           # Joint number (1-6)
  angle: 90.0,        # Angle in degrees (-180 to 180)
  spd: :max           # Symbolic value for maximum speed
})
```

**High-level function:**
- Not directly exposed (use `move_joints/2` instead)

**Parameters:**
- `joint`: Integer, 1-6, required
- `angle`: Float, -180.0 to 180.0, required
- `spd`: Integer/Symbol, 1-4096, default: 1000

---

### All Joints Control - Degrees (`T: 122`)

Control all joints simultaneously using degree values.

```elixir
# Using high-level function
{:ok, response} = Roarm.Robot.move_joints(%{
  j1: 45.0,           # Maps to 'b' (base)
  j2: 30.0,           # Maps to 's' (shoulder)
  j3: -45.0,          # Maps to 'e' (elbow)
  j4: 15.0            # Maps to 'h' (hand/wrist)
}, speed: 2000)

# Using raw command
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 122,
  b: 45.0,            # Base joint
  s: 30.0,            # Shoulder joint
  e: -45.0,           # Elbow joint
  h: 15.0,            # Hand/wrist joint
  w: 0.0,             # Wrist rotation (M3 only)
  g: 0.0,             # Gripper rotation (M3 only)
  spd: 2000
})
```

**High-level function:**
- `Roarm.Robot.move_joints/2`

**Parameters:**
- `b`, `s`, `e`, `h`, `w`, `g`: Float, -180.0 to 180.0, defaults: 0.0
- `spd`: Integer/Symbol, 1-4096, default: 1000

---

### Position Control (`T: 1041`)

Move the robot to a specific XYZ position.

```elixir
# Using high-level function
{:ok, response} = Roarm.Robot.move_to_position(%{
  x: 200.0,           # X coordinate in mm
  y: 0.0,             # Y coordinate in mm
  z: 150.0,           # Z coordinate in mm
  t: 0.0              # Tool angle in degrees
}, speed: 1500, acceleration: 100)
```

**High-level function:**
- `Roarm.Robot.move_to_position/2`

**Parameters:**
- `x`: Float, -500.0 to 500.0 mm, required
- `y`: Float, -500.0 to 500.0 mm, required
- `z`: Float, 0.0 to 500.0 mm, required
- `t`: Float, -180.0 to 180.0 degrees, default: 0.0
- `spd`: Integer, 1-4096, default: 1000
- `acc`: Integer, 1-254, default: 100

## System Commands

### Get Feedback (`T: 105`)

Request current position and joint information from the robot.

```elixir
{:ok, position} = Roarm.Robot.get_position()
{:ok, joints} = Roarm.Robot.get_joints()
```

**High-level functions:**
- `Roarm.Robot.get_position/1`
- `Roarm.Robot.get_joints/1`

---

### Torque Control (`T: 210`)

Enable or disable joint torque (motor power).

```elixir
# Enable torque (lock joints)
{:ok, response} = Roarm.Robot.set_torque_enabled(true)

# Disable torque (allow manual movement)
{:ok, response} = Roarm.Robot.set_torque_enabled(false)
```

**High-level function:**
- `Roarm.Robot.set_torque_enabled/2`

**Parameters:**
- `cmd`: Integer, 0 (disable) or 1 (enable), required

---

### Set Middle Position (`T: 502`)

Set the current position as the middle/reference position.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{t: 502})
```

## LED Commands

### LED Control (`T: 114`)

Control the gripper-mounted LED.

```elixir
# Using high-level functions
{:ok, response} = Roarm.Robot.led_on(200)      # Brightness 0-255
{:ok, response} = Roarm.Robot.led_off()

# Using raw command with RGB values
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 114,
  led: 255,           # LED brightness (0-255)
  r: 255,             # Red component (0-255)
  g: 0,               # Green component (0-255)
  b: 0                # Blue component (0-255)
})
```

**High-level functions:**
- `Roarm.Robot.led_on/2`
- `Roarm.Robot.led_off/1`
- `Roarm.Robot.set_led/2`

**Parameters:**
- `led`: Integer/Symbol, 0-255, default: 255
- `r`, `g`, `b`: Integer, 0-255, defaults: 0

## Mission Commands

### Create Mission (`T: 220`)

Create a new mission for recording a sequence of movements.

```elixir
{:ok, response} = Roarm.Robot.create_mission("pickup_sequence", "Pick up object from table")
```

**High-level function:**
- `Roarm.Robot.create_mission/3`

**Parameters:**
- `name`: String, required
- `intro`: String, default: ""

---

### Add Mission Step (`T: 223`)

Add the current robot position as a step in the mission.

```elixir
{:ok, response} = Roarm.Robot.add_mission_step("pickup_sequence", 0.5)
```

**High-level function:**
- `Roarm.Robot.add_mission_step/3`

**Parameters:**
- `mission`: String, mission name, required
- `spd`: Float, 0.1-1.0, movement speed, default: 0.25

---

### Add Mission Delay (`T: 224`)

Add a delay step to the mission.

```elixir
{:ok, response} = Roarm.Robot.add_mission_delay("pickup_sequence", 2000)
```

**High-level function:**
- `Roarm.Robot.add_mission_delay/3`

**Parameters:**
- `mission`: String, mission name, required
- `delay`: Integer, 0-60000 ms, required

---

### Play Mission (`T: 242`)

Execute a recorded mission.

```elixir
{:ok, response} = Roarm.Robot.play_mission("pickup_sequence", 3)  # Repeat 3 times
```

**High-level function:**
- `Roarm.Robot.play_mission/3`

**Parameters:**
- `name`: String, mission name, required
- `times`: Integer, 1-1000, repetitions, default: 1

## Advanced Commands

### PID Parameters (`T: 108`)

Set PID control parameters for a joint.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 108,
  joint: 1,           # Joint number (1-6)
  p: 16,              # Proportional gain (0-100)
  i: 0,               # Integral gain (0-100)
  d: 1                # Derivative gain (0-100)
})
```

**Parameters:**
- `joint`: Integer, 1-6, required
- `p`, `i`, `d`: Integer, 0-100, required

---

### Dynamic Force Adaptation (`T: 112`)

Configure force adaptation for compliant control.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 112,
  mode: 1,            # Enable (1) or disable (0)
  b: 600,             # Base joint force (0-1000)
  s: 700,             # Shoulder joint force (0-1000)
  e: 500,             # Elbow joint force (0-1000)
  h: 400              # Hand joint force (0-1000)
  # w and g default to 500
})
```

**Parameters:**
- `mode`: Integer, 0-1, required
- `b`, `s`, `e`, `h`, `w`, `g`: Integer, 0-1000, defaults: 500

---

### Gripper Control (`T: 222`) - M3 Only

Control the gripper on M3 models.

```elixir
{:ok, response} = Roarm.Robot.send_valid_command(%{
  t: 222,
  mode: 1,            # Gripper mode
  angle: 75           # Gripper angle (0-100)
})
```

**Parameters:**
- `mode`: Integer, 0-1, required
- `angle`: Integer, 0-100, required

## Teaching Mode

### Drag Teaching

Record movements by manually moving the robot arm.

```elixir
# Start teaching mode (disables torque)
{:ok, response} = Roarm.Robot.drag_teach_start("my_sequence.json")

# ... manually move the robot arm ...

# Stop teaching and save
{:ok, num_samples} = Roarm.Robot.drag_teach_stop()

# Replay the recorded sequence
{:ok, response} = Roarm.Robot.drag_teach_replay("my_sequence.json")
```

**High-level functions:**
- `Roarm.Robot.drag_teach_start/2`
- `Roarm.Robot.drag_teach_stop/1`
- `Roarm.Robot.drag_teach_replay/2`

## Error Handling

All commands return either `{:ok, response}` or `{:error, reason}`:

```elixir
case Roarm.Robot.move_joints(%{j1: 45.0}) do
  {:ok, response} ->
    Logger.info("Success: #{response}")

  {:error, :not_connected} ->
    Logger.info("Robot not connected")

  {:error, {:validation_error, message}} ->
    Logger.info("Invalid command: #{message}")

  {:error, {:unknown_command, t_code}} ->
    Logger.info("Unknown T-code: #{t_code}")

  {:error, reason} ->
    Logger.info("Error: #{inspect(reason)}")
end
```

## Range Limits Summary

| Parameter | Type | Range | Default |
|-----------|------|-------|---------|
| Joint angles (degrees) | Float | -180.0 to 180.0 | 0.0 |
| Joint angles (radians) | Float | -π to π | 0.0 |
| Speed (`spd`) | Integer | 1 to 4096 | 1000 |
| Position X,Y | Float | -500.0 to 500.0 mm | - |
| Position Z | Float | 0.0 to 500.0 mm | - |
| LED brightness | Integer | 0 to 255 | 255 |
| RGB values | Integer | 0 to 255 | 0 |
| Mission delay | Integer | 0 to 60000 ms | - |
| Force values | Integer | 0 to 1000 | 500 |

All values are automatically clamped to valid ranges during validation.