BB.Robot.Runtime (bb v0.15.0)
View SourceRuntime process for a BB robot.
Manages the robot's runtime state including:
- The
BB.Robotstruct (static topology) - The
BB.Robot.StateETS table (dynamic joint state) - Robot state machine (disarmed/idle/executing)
- Command execution lifecycle
- Sensor telemetry collection (subscribes to
JointStatemessages)
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──→ :disarmedCommand Execution
Commands execute as supervised GenServers. The caller receives the command
pid and can use BB.Command.await/2 or BB.Command.yield/2 to get the
result. The Runtime monitors the command server and transitions back to
:idle when it completes.
Summary
Functions
Cancel the currently executing command.
Get the availability of each command category.
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.
Check if any command is currently executing.
Check if a specific category has commands executing.
Get information about all currently executing commands.
Get the static robot struct (topology).
Get the robot state (ETS-backed joint positions/velocities).
Get the actual operational state, without backwards compatibility translation.
Get all joint positions as a map.
Get the simulation mode for a robot.
Starts the runtime for a robot module.
Get the current robot state machine state.
Transition the robot to a new state.
Transition the operational state during command execution.
Get all joint velocities as a map.
Returns the via tuple for process registration.
Types
@type robot_state() :: :disarmed | :disarming | :idle | :executing | :error | atom()
@type simulation_mode() :: nil | :kinematic | :external
@type t() :: %BB.Robot.Runtime{ category_counts: %{required(atom()) => non_neg_integer()}, category_limits: %{required(atom()) => pos_integer()}, commands: %{required(atom()) => BB.Dsl.Command.t()}, current_command_name: atom() | nil, current_command_pid: pid() | nil, current_command_ref: reference() | nil, current_execution_id: reference() | nil, executing_commands: %{required(reference()) => BB.Robot.CommandInfo.t()}, operational_state: atom(), parameter_store: module() | nil, parameter_store_state: term() | nil, robot: BB.Robot.t(), robot_module: module(), robot_state: BB.Robot.State.t(), simulation_mode: simulation_mode(), valid_states: [atom()] }
Functions
@spec cancel(module()) :: :ok | {:error, :no_execution}
Cancel the currently executing command.
Stops the command server with :cancelled reason. Awaiting callers
will receive the result from the command's result/1 callback.
@spec category_availability(module()) :: %{ required(atom()) => {non_neg_integer(), pos_integer()} }
Get the availability of each command category.
Returns a map of category names to {current_count, limit} tuples.
@spec check_allowed(module(), [robot_state()]) :: :ok | {:error, BB.Error.State.NotAllowed.t()}
Check if the robot is in one of the allowed states.
Reads directly from ETS for fast concurrent access.
Returns a specification to start this module under a supervisor.
See Supervisor.
Execute a command with the given goal.
Returns {:ok, pid} where pid is the command server process.
Use BB.Command.await/2 or BB.Command.yield/2 to get the result.
Examples
{:ok, cmd} = Runtime.execute(MyRobot, :navigate, %{target: pose})
{:ok, result} = BB.Command.await(cmd)
# Or with timeout
case BB.Command.yield(cmd, 5000) do
nil -> still_running()
{:ok, result} -> handle_result(result)
{:error, reason} -> handle_error(reason)
endErrors
{:error, %StateError{}}- Robot not in allowed state{:error, {:unknown_command, name}}- Command not found- Other errors are returned through
BB.Command.await/2
Check if any command is currently executing.
Reads directly from ETS for fast concurrent access.
Check if a specific category has commands executing.
Get information about all currently executing commands.
@spec get_robot(module()) :: BB.Robot.t()
Get the static robot struct (topology).
@spec get_robot_state(module()) :: BB.Robot.State.t()
Get the robot state (ETS-backed joint positions/velocities).
Get the actual operational state, without backwards compatibility translation.
Unlike state/1, this returns the actual operational state regardless of
whether commands are executing. Use this when you need to know the true
operational context (e.g., :idle, :recording, :reacting).
Reads directly from ETS for fast concurrent access.
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}
@spec simulation_mode(module()) :: simulation_mode()
Get the simulation mode for a robot.
Returns nil if running in hardware mode, or the simulation mode atom
(e.g., :kinematic, :external) if running in simulation.
Starts the runtime for a 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 operational state.
For backwards compatibility:
- When
operational_stateis:idlebut commands are executing, returns:executing - Custom operational states (e.g.,
:recording) are returned directly
Reads directly from ETS for fast concurrent access.
@spec transition(module(), robot_state()) :: {:ok, robot_state()} | {:error, term()}
Transition the robot to a new state.
Transition the operational state during command execution.
This is called by BB.Command.transition_state/2 to change the robot's
operational state mid-execution. Only the command with the matching
execution_id can trigger a transition.
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}
Returns the via tuple for process registration.