One sensor module, one process.
The process holds the module's state and nothing else: every decision is a
callback on the pure module (Monty.Frameworks.Models.AbstractMontyClasses.SensorModule).
That split is what lets a sensor module be tested with a plain function call
and still be supervised, restarted and inspected at runtime.
The client API below is the only way in. It is deliberately separate from
the callbacks, so call sites read as SensorModuleServer.step(server, ...)
rather than as raw GenServer messages, and every entry point carries a
typespec. The server registers itself in Monty.Runtime.Registry under
{:sensor_module, model_id, id}: after a restart the name points at the new
process and no stored pid goes stale.
Summary
Functions
Returns a specification to start this module under a supervisor.
Drops the observations this sensor kept, keeping what it has learnt.
The module's own state, for tests and the run inspector.
Records the sensor's pose and turns one observation into a percept.
Types
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec clear_buffers(server()) :: :ok
Drops the observations this sensor kept, keeping what it has learnt.
What a run without episode boundaries asks when the object under the sensor
changes: Monty's _reset_modules_buffers.
@spec propose_goals(server()) :: [Monty.Cmp.Goal.t()]
@spec propose_region(server()) :: Monty.Cmp.AttentionRegion.t()
@spec reset(server()) :: :ok
@spec start_link(spec()) :: GenServer.on_start()
The module's own state, for tests and the run inspector.
@spec step(server(), map(), map(), Monty.Context.t(), boolean()) :: Monty.Cmp.Message.t() | nil
Records the sensor's pose and turns one observation into a percept.
One round trip rather than two: update_state exists for the module's sake,
not for the caller's.