BB.Servo.Robotis.Controller (bb_servo_robotis v0.6.1)

Copy Markdown View Source

A controller that manages a Robotis/Dynamixel servo bus.

This controller wraps the Robotis GenServer and provides a shared ETS table for actuators to write commands to. The controller runs a fixed-rate control loop that batches all pending commands into writes and reads positions via bulk reads (fast_sync_read).

On each loop tick, the controller:

  1. Reads all pending commands from the ETS table
  2. Writes them to the serial bus
  3. Clears the command fields
  4. Reads all servo positions via fast_sync_read
  5. Updates the ETS table with current positions
  6. Publishes JointState messages for positions that exceed deadband

Configuration

The controller is typically defined in the robot DSL:

controllers do
  controller :dynamixel, {BB.Servo.Robotis.Controller,
    port: "/dev/ttyUSB0",
    baud_rate: 1_000_000,
    control_table: Robotis.ControlTable.XM430,
    loop_interval_ms: 10
  }
end

Options

  • :port - (required) The serial port path, e.g., "/dev/ttyUSB0"
  • :baud_rate - Baud rate in bps (default: 1_000_000)
  • :control_table - The servo control table to use (default: Robotis.ControlTable.XM430). Robotis.ControlTable.XL320 is rejected: the XL320 is an earlier servo generation whose control table has none of the registers this driver drives, and whose 1024-step travel doesn't match the 12-bit position conversion used throughout.
  • :loop_interval_ms - Control loop interval in ms (default: 10, i.e. 100Hz)
  • :status_poll_interval_ms - Status polling interval in ms (default: 1000, set to 0 to disable)
  • :disarm_action - Action to take when robot is disarmed (default: :disable_torque)
    • :disable_torque - Disable torque on all servos (safe default)
    • :hold - Keep torque enabled (servos hold position)

ETS Table Structure

Each registered servo has a row in the ETS table:

{servo_id, actuator_path, position_deadband, last_position_raw, present_position,
 present_temperature, present_voltage, present_current, hardware_error,
 pending_write, torque_enabled}

Actuators write pending_write — a {param, raw_value} pair, naming whichever goal register their operating mode acts on — via :ets.update_element/3. The controller writes and clears them each tick.

Torque state

torque_enabled caches what this controller last told each servo, so an actuator can tell whether its goal will actually be acted on without spending a bus round trip per command. Every write to torque_enable passes through this controller — the actuators, the parameter bridge and arming all go through handle_call/3 or enable_all_torque/1 — which is what makes the cache trustworthy.

It is only meaningful while the robot is armed. Disarming turns torque off without updating the cache, because commands can't reach an actuator in that state anyway, and arming re-establishes it for every registered servo.

Safety

This controller implements the BB.Controller behaviour's disarm/1 safety callback. When the robot is disarmed or crashes, torque is disabled on all known servo IDs using acknowledged per-servo writes, so disarm/1 only reports :ok once the bus has confirmed every servo is safe; any failed or undeliverable write returns {:error, reason} and drives the robot into the :error state.

Summary

Functions

Handle disarm based on the configured disarm_action.

Functions

disarm(opts)

Handle disarm based on the configured disarm_action.

Called by BB.Safety.Controller when the robot is disarmed or crashes. By default, disables torque on all registered servo IDs.