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

Copy Markdown View Source

An actuator that uses a Robotis controller to drive a Dynamixel servo.

Configuration is derived from the joint's motor_profile injected by BB.Actuator.Server:

  • Position limits from motor_profile.motor_lower / motor_upper
  • Velocity limit from motor_profile.motor_velocity_limit
  • Position range maps to the servo's goal_position register

When initialised, the actuator:

  1. Disables torque on the servo
  2. Asks the servo what model it is, and sets its operating mode if it isn't already in the configured one
  3. Registers with the controller, receiving the shared ETS table reference
  4. Writes profile_velocity from the joint's velocity limit
  5. Subscribes to the commands its mode admits

Position feedback

A Dynamixel knows where it is, so this driver declares :position_feedback and the joint needs no sensor of its own. The reading is published by BB.Servo.Robotis.Controller, which does a fast_sync_read of present_position across the bus on every tick and emits a BB.Message.Sensor.JointState per servo that has moved further than its :position_deadband. That read isn't optional and isn't the status poll, so it happens whatever :status_poll_interval_ms is set to.

Velocity and effort aren't claimed. The servos report both, but the controller doesn't read them and nothing puts them in a JointState.

Operating modes

A Dynamixel does one thing at a time, and :mode picks which. It's set once at startup and never changed while running: switching modes resets the servo's PID gains, its profile velocity and acceleration to 0, and its goal current to the current limit — including tuning applied through BB.Servo.Robotis.Bridge, which this driver has no way to put back.

:modecommands it accepts
:position (default)Position, Hold, Stop
:velocityVelocity, Hold, Stop
:currentEffort, Stop
:current_positionPosition, Effort, Hold, Stop

Anything outside that list is refused by the framework with BB.Error.State.UnsupportedCommand before it reaches the driver. Hold is absent from :current because a servo in current control is a torque source with no position to hold.

Not every servo implements every mode — an XL430 has no current control at all — so the mode is checked against the model the servo reports, and the actuator refuses to start rather than run in a mode nobody asked for. See BB.Servo.Robotis.Model.

Commands

  • Command.Position — travel to a position. Clamped to the joint's limits.
  • Command.Velocity — turn at a rate, clamped to the joint's velocity limit.
  • Command.Effort — in :current mode, the torque to aim for; in :current_position mode, a ceiling on the current a position move may draw. Newton metres are converted using the model's published torque constant, which is quoted at the recommended supply voltage and drifts with it — treat effort as approximate rather than calibrated.
  • Command.Stop — cut torque, leaving the joint passive and free to be backdriven. Both :immediate and :decelerate do the same thing, because becoming passive is a single register write with no ramp available.
  • Command.Hold — stay under power without driving. A servo already doing that needs nothing; after a Stop it re-applies torque where the joint has come to rest.

A Position, Velocity or Effort command sent to a joint left passive by Stop re-applies torque on the way past, so callers don't have to pair the two.

Velocity and Effort carry a duration. When it runs out, :expiry_action decides whether the joint goes passive (:stop, the default) or stays under power without driving (:hold) — the same choice the controller's :disarm_action makes for the whole bus.

Beware that a passive joint under load will move, and Stop does not wait for it to settle. Hold and Position both re-apply torque from the servo's own present position, so neither snaps back to a pre-Stop goal, but a joint that has sagged will still be somewhere the caller may not expect.

None of this is the safety path: making the hardware safe is disarm/1, which is robot-wide and leaves the robot unable to move until it is armed again.

Example DSL Usage

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

joint :shoulder, type: :revolute do
  limit lower: ~u(-90 degree), upper: ~u(90 degree), velocity: ~u(60 degree_per_second)

  actuator :servo, {BB.Servo.Robotis.Actuator, servo_id: 1, controller: :dynamixel}
end

Summary

Functions

Safety disarm callback.

Functions

disarm(opts)

Safety disarm callback.

Returns :ok because torque management is handled by the controller.