BB.Robot.Runtime (bb v0.4.0)

View Source

Runtime process for a BB robot.

Manages the robot's runtime state including:

  • The BB.Robot struct (static topology)
  • The BB.Robot.State ETS table (dynamic joint state)
  • Robot state machine (disarmed/idle/executing)
  • Command execution lifecycle
  • Sensor telemetry collection (subscribes to JointState messages)

Robot States

The robot progresses through these states:

  • :disarmed - Robot is not armed, commands restricted
  • :idle - Robot is armed and ready for commands
  • :executing - A command is currently executing

State Transitions

:disarmed arm :idle
:idle execute :executing
:executing complete :idle
:executing disarm :disarmed
:idle disarm :disarmed

Command Execution

Commands execute in supervised tasks. The caller receives a Task.t() and can use Task.await/2 or Task.yield/2 to get the result. The Runtime monitors the task and transitions back to :idle when it completes.

Summary

Functions

Cancel the currently executing command.

Check if the robot is in one of the allowed states.

Returns a specification to start this module under a supervisor.

Execute a command with the given goal.

Get the static robot struct (topology).

Get the robot state (ETS-backed joint positions/velocities).

Get all joint positions as a map.

Starts the runtime for a robot module.

Get the current robot state machine state.

Transition the robot to a new state.

Get all joint velocities as a map.

Returns the via tuple for process registration.

Types

robot_state()

@type robot_state() :: :disarmed | :disarming | :idle | :executing | :error

t()

@type t() :: %BB.Robot.Runtime{
  commands: %{required(atom()) => BB.Dsl.Command.t()},
  current_command_name: atom() | nil,
  current_execution_id: reference() | nil,
  current_task: Task.t() | nil,
  current_task_ref: reference() | nil,
  parameter_store: module() | nil,
  parameter_store_state: term() | nil,
  robot: BB.Robot.t(),
  robot_module: module(),
  robot_state: BB.Robot.State.t(),
  state: robot_state()
}

Functions

cancel(robot_module)

@spec cancel(module()) :: :ok | {:error, :no_execution}

Cancel the currently executing command.

Terminates the command task immediately. The caller will receive an exit when awaiting the task.

check_allowed(robot_module, allowed_states)

@spec check_allowed(module(), [robot_state()]) ::
  :ok | {:error, BB.Robot.Runtime.StateError.t()}

Check if the robot is in one of the allowed states.

Reads directly from ETS for fast concurrent access.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

execute(robot_module, command_name, goal)

@spec execute(module(), atom(), map()) :: {:ok, Task.t()}

Execute a command with the given goal.

Returns {:ok, task} where task can be awaited for the result. The task handles subscription to command events internally.

Examples

{:ok, task} = Runtime.execute(MyRobot, :navigate, %{target: pose})
{:ok, result} = Task.await(task)

# Or with timeout
case Task.yield(task, 5000) || Task.shutdown(task) do
  {:ok, result} -> handle_result(result)
  nil -> handle_timeout()
end

Errors

Errors are returned through the awaited task result:

  • {:error, %StateError{}} - Robot not in allowed state
  • {:error, {:unknown_command, name}} - Command not found
  • {:error, reason} - Command handler returned an error

get_robot(robot_module)

@spec get_robot(module()) :: BB.Robot.t()

Get the static robot struct (topology).

get_robot_state(robot_module)

@spec get_robot_state(module()) :: BB.Robot.State.t()

Get the robot state (ETS-backed joint positions/velocities).

positions(robot_module)

@spec positions(module()) :: %{required(atom()) => float()}

Get all joint positions as a map.

Reads directly from ETS for fast concurrent access. Returns a map of joint names to their current positions (in radians for revolute joints, metres for prismatic joints).

Positions are updated automatically by the Runtime when sensors publish JointState messages.

Examples

iex> BB.Robot.Runtime.positions(MyRobot)
%{pan_joint: 0.0, tilt_joint: 0.0}

start_link(arg)

Starts the runtime for a robot module.

state(robot_module)

@spec state(module()) :: robot_state()

Get the current robot state machine state.

Returns :disarmed if the robot is not armed (via BB.Safety), otherwise returns the internal state (:idle or :executing).

Reads directly from ETS for fast concurrent access.

transition(robot_module, new_state)

@spec transition(module(), robot_state()) :: {:ok, robot_state()} | {:error, term()}

Transition the robot to a new state.

velocities(robot_module)

@spec velocities(module()) :: %{required(atom()) => float()}

Get all joint velocities as a map.

Reads directly from ETS for fast concurrent access. Returns a map of joint names to their current velocities (in rad/s for revolute joints, m/s for prismatic joints).

Velocities are updated automatically by the Runtime when sensors publish JointState messages.

Examples

iex> BB.Robot.Runtime.velocities(MyRobot)
%{pan_joint: 0.0, tilt_joint: 0.0}

via(robot_module)

Returns the via tuple for process registration.