Wrapper GenServer for estimator callback modules.
Responsibilities:
- Resolves parameter references in opts at startup and on parameter
changes (mirroring
BB.Sensor.Server/BB.Controller.Server). - Subscribes to the estimator's declared input paths.
- Dispatches incoming input messages to the callback module via
BB.Estimator.handle_input/2. Single-input estimators receive the bare%BB.Message{}; multi-input estimators receive a%{input_name => %BB.Message{}}map gathered when the driver input arrives. - For multi-input estimators, enforces
sync_tolerance: if any non-driver input is stale relative to the driver by more than the configured tolerance, the dispatch is dropped (with[:bb, :estimator, :dropped]telemetry) instead of fired with a stale snapshot. - Publishes each
{output_name, message}returned from a callback's{:reply, outputs, state}reply to that output's configured path. - Emits
:input,:output,:latency, and:droppedtelemetry.
Health transitions, lost-detection, and on_degraded / on_lost /
on_recovered command dispatch are Phase 2 and not handled here yet.
Init args
The framework supplies the following keys in the start-link init arg.
Internal keys (double-underscored) are stripped by the server before
calling BB.Estimator.init/1; public keys (:bb,
:estimator_context) are passed through unchanged so user code can
read them.
:__callback_module__- the user's estimator module.:__estimator_inputs__- `%{mode: :single:multi, inputs: [...], sync_tolerance_ns: integer() nil}` describing the input wiring. :__estimator_outputs__-%{output_name => [atom()]}mapping output names to their full pubsub paths.:bb-%{robot: module, path: [atom]}, the per-process context.:estimator_context- theBB.Estimator.Context.t()exposed to the callback module'sinit/1.
Plus any user options declared via the estimator's options_schema/0.
Summary
Functions
Returns a specification to start this module under a supervisor.
Types
@type health_state() :: :healthy | :degraded | :lost
@type t() :: %BB.Estimator.Server{ bb: %{robot: module(), path: [atom()]}, callback_module: module(), consecutive_ok: non_neg_integer(), context: BB.Estimator.Context.t(), driver_input: atom() | nil, health_state: health_state(), input_name_by_path: %{required([atom()]) => atom()}, inputs: [input_spec()], last_messages: %{required(atom()) => BB.Message.t()}, latency_budget_ns: integer() | nil, lost_after_ns: integer() | nil, lost_timer_ref: reference() | nil, mode: :single | :multi, on_degraded: atom() | nil, on_lost: atom() | nil, on_recovered: atom() | nil, outputs: %{required(atom()) => [atom()]}, param_subscriptions: %{required([atom()]) => atom()}, raw_opts: keyword(), recover_after: pos_integer(), resolved_opts: keyword(), sync_tolerance_ns: integer() | nil, user_state: term() }
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.