BB.Parameter behaviour (bb v0.2.1)
View SourceRuntime-adjustable parameters for robot components.
Parameters provide a way to configure robot behaviour at runtime without recompilation. They support validation, change notifications via PubSub, and optional persistence.
Behaviour
Components that expose parameters implement the BB.Parameter behaviour:
defmodule MyController do
use GenServer
@behaviour BB.Parameter
@impl BB.Parameter
def param_schema do
Spark.Options.new!(
kp: [type: :float, required: true, doc: "Proportional gain"],
ki: [type: :float, default: 0.0, doc: "Integral gain"],
kd: [type: :float, default: 0.0, doc: "Derivative gain"]
)
end
endPath-Based Identification
Parameters are identified by hierarchical paths that match the PubSub convention:
[:robot, :max_velocity]- Robot-level parameter[:controller, :pid, :kp]- Component parameter[:sensor, :imu, :sample_rate]- Sensor configuration
Usage
# Read a parameter (fast, direct ETS access)
{:ok, value} = BB.Parameter.get(MyRobot, [:motion, :max_speed])
# Write a parameter (validated, publishes change)
:ok = BB.Parameter.set(MyRobot, [:motion, :max_speed], 2.0)
# Atomic batch update
:ok = BB.Parameter.set_many(MyRobot, [
{[:controller, :pid, :kp], 2.0},
{[:controller, :pid, :ki], 0.2}
])
# List parameters
params = BB.Parameter.list(MyRobot, prefix: [:controller])Change Notifications
Parameter changes are published via BB.PubSub with the :param prefix:
BB.PubSub.subscribe(MyRobot, [:param, :controller, :pid])
# Receives: {:bb, [:param, :controller, :pid, :kp], %BB.Message{}}
Summary
Callbacks
Returns a compiled Spark.Options schema for this component's parameters.
Functions
Get a parameter value.
Get a parameter value, raising if not found.
Get a parameter value from a remote system via a bridge.
Check if a module implements the BB.Parameter behaviour.
List all parameters, optionally filtered by path prefix.
List parameters available on a remote system via a bridge.
Register a component's parameters with the robot.
Set a parameter value.
Set multiple parameters atomically.
Set a parameter value on a remote system via a bridge.
Subscribe to changes for a remote parameter via a bridge.
Callbacks
@callback param_schema() :: Spark.Options.t()
Returns a compiled Spark.Options schema for this component's parameters.
The schema defines parameter names, types, defaults, and constraints.
Functions
Get a parameter value.
Returns {:ok, value} if the parameter exists, {:error, :not_found} otherwise.
This is a fast operation - it reads directly from ETS.
Examples
{:ok, 1.5} = BB.Parameter.get(MyRobot, [:motion, :max_speed])
{:error, :not_found} = BB.Parameter.get(MyRobot, [:nonexistent])
Get a parameter value, raising if not found.
Examples
1.5 = BB.Parameter.get!(MyRobot, [:motion, :max_speed])
@spec get_remote(module(), atom(), BB.Parameter.Protocol.param_id()) :: {:ok, term()} | {:error, term()}
Get a parameter value from a remote system via a bridge.
The bridge must implement get_remote/2.
Examples
{:ok, 0.15} = BB.Parameter.get_remote(MyRobot, :mavlink, "PITCH_RATE_P")
Check if a module implements the BB.Parameter behaviour.
List all parameters, optionally filtered by path prefix.
Returns a list of {path, metadata} tuples where metadata includes
the current value, type, and other schema information.
Options
:prefix- Only return parameters under this path prefix (default:[])
Examples
# All parameters
params = BB.Parameter.list(MyRobot)
# Parameters under [:controller]
params = BB.Parameter.list(MyRobot, prefix: [:controller])
List parameters available on a remote system via a bridge.
Returns a list of parameter info from the remote (e.g., flight controller).
The bridge must implement list_remote/1.
Examples
{:ok, params} = BB.Parameter.list_remote(MyRobot, :mavlink)
# => [{id: "PITCH_RATE_P", value: 0.1, type: :float, doc: "..."}, ...]
Register a component's parameters with the robot.
Called by components during init to register their parameter schema. Parameters are initialised with default values from the schema.
Examples
def init(opts) do
bb = Keyword.fetch!(opts, :bb)
BB.Parameter.register(bb.robot, bb.path, __MODULE__)
{:ok, %{bb: bb}}
end
Set a parameter value.
The value is validated against the registered schema (if any) before being stored. On success, a change notification is published via PubSub.
Returns :ok on success, {:error, reason} on validation failure.
Examples
:ok = BB.Parameter.set(MyRobot, [:motion, :max_speed], 2.0)
{:error, reason} = BB.Parameter.set(MyRobot, [:motion, :max_speed], -1.0)
Set multiple parameters atomically.
All parameters are validated before any are written. If any validation fails, no parameters are changed.
Examples
:ok = BB.Parameter.set_many(MyRobot, [
{[:controller, :pid, :kp], 2.0},
{[:controller, :pid, :ki], 0.2}
])
@spec set_remote(module(), atom(), BB.Parameter.Protocol.param_id(), term()) :: :ok | {:error, term()}
Set a parameter value on a remote system via a bridge.
The bridge must implement set_remote/3.
Examples
:ok = BB.Parameter.set_remote(MyRobot, :mavlink, "PITCH_RATE_P", 0.15)
@spec subscribe_remote(module(), atom(), BB.Parameter.Protocol.param_id()) :: :ok | {:error, term()}
Subscribe to changes for a remote parameter via a bridge.
When the remote parameter changes, the bridge publishes via BB.PubSub.
The path structure is determined by the bridge implementation.
The bridge must implement subscribe_remote/2.
Examples
:ok = BB.Parameter.subscribe_remote(MyRobot, :mavlink, "PITCH_RATE_P")