A message in Monty's cortical messaging protocol (CMP).
Mirrors tbp/monty/cmp.py::Message. The same payload represents an observed
state (from a sensor module), a hypothesized state (from a learning module)
or a goal (from a goal generator) — the receiver decides how to read it.
Differences from the Python class, on purpose:
sender_typeis an atom (:sm | :lm) here and the strings"SM"/"LM"on the wire (Monty.Cmp.encode/1), so a typo is a compile-time warning rather than a runtime assertion.Construction returns
{:ok, message} | {:error, reason}instead of raising, because messages are built inside supervised processes whose job is to keep the run alive.- Vectors are plain lists (
[x, y, z],[[x, y, z], ...]), the shape Nx and JSON both read without conversion. semantic_idis a field here and a private attribute in Python (percept._semantic_id). Monty sets it "just for logging" — its own words, on the line that sets it — and nothing in matching reads it; here a private field does not exist, so the annotation is a field and the promise is the same one Monty makes in a comment.
Summary
Types
Where a message came from. :gsg only appears on Monty.Cmp.Goal.
Functions
The two principal curvature directions, for SurfacePoseVectors.
Looks a feature up among the morphological and then the non-morphological features.
True when the message was produced by a sensor module.
Builds a message, validating the fields the Python class asserts on.
Whether the sender believes the sensor is on an object.
Records how the sensor moved since the previous message, and optionally the point-pair feature that goes with it.
The surface normal, for messages carrying SurfacePoseVectors.
Applies a translation and/or rotation to the message's pose.
Types
@type pose_vectors() :: Monty.Geometry.SurfacePoseVectors.t() | Monty.Geometry.OrientationMatrix.t() | Monty.Geometry.GazeDirection.t()
@type sender_type() :: :sm | :lm | :gsg
Where a message came from. :gsg only appears on Monty.Cmp.Goal.
@type t() :: %Monty.Cmp.Message{ confidence: float(), displacement: %{optional(String.t()) => term()} | nil, location: vector() | nil, morphological_features: %{optional(String.t()) => term()}, non_morphological_features: %{optional(String.t()) => term()}, pass_message: boolean(), process_features_in_lm: boolean(), semantic_id: integer() | nil, sender_id: String.t(), sender_type: sender_type() }
@type vector() :: [float()]
Functions
The two principal curvature directions, for SurfacePoseVectors.
Looks a feature up among the morphological and then the non-morphological features.
True when the message was produced by a sensor module.
Builds a message, validating the fields the Python class asserts on.
A location-only message (process_features_in_lm: false) may omit the pose
features; it only synchronises the receiver's sense of where the sensor is.
Whether the sender believes the sensor is on an object.
Monty's default is true when the feature is absent, because a message that
says nothing about it came from a sensor that could not tell. The feature
itself is a number — a sensor module writes 1.0 or 0.0, a goal generator
1 — which Monty's get_on_object hands on and every caller only ever asks
as a question, so the answer here is the question's answer.
Records how the sensor moved since the previous message, and optionally the point-pair feature that goes with it.
The surface normal, for messages carrying SurfacePoseVectors.
@spec transform_morphological_features(t(), vector() | nil, [[float()]] | nil) :: {:ok, t()} | {:error, :gaze_direction_not_transformable}
Applies a translation and/or rotation to the message's pose.
Mirrors Message.transform_morphological_features: the location moves by the
translation, and the pose vectors are rotated by rotation * pose_vectors.
A GazeDirection cannot be rotated — it is a goal direction, not a frame.