Message Types Reference

View Source

All message payloads in BB PubSub. Messages are wrapped in BB.Message:

%BB.Message{
  timestamp: integer(),   # System.monotonic_time(:nanosecond)
  frame_id: atom(),       # Coordinate frame (typically joint/link name)
  payload: struct()       # One of the message types below
}

Note on timestamps: The timestamp is monotonic time in nanoseconds (System.monotonic_time(:nanosecond)), not wall-clock time. This means:

  • Timestamps are suitable for ordering events and measuring durations
  • They cannot be converted to wall-clock/UTC time
  • They are only meaningful within a single BEAM VM instance

Sensor Messages

JointState

State of one or more joints.

Module: BB.Message.Sensor.JointState

Fields:

FieldTypeRequiredDescription
names[atom]YesJoint names
positions[float]NoPositions in radians (revolute) or metres (prismatic)
velocities[float]NoVelocities in rad/s or m/s
efforts[float]NoEfforts in Nm or N

Published to: [:sensor, joint_name]

Example:

JointState.new!(
  names: [:shoulder, :elbow],
  positions: [0.5, 1.2],
  velocities: [0.1, 0.0]
)

BatteryState

Battery status information.

Module: BB.Message.Sensor.BatteryState

Fields:

FieldTypeRequiredDescription
voltagefloatYesBattery voltage in volts
currentfloatNoCurrent draw in amps
percentagefloatNoCharge percentage (0.0-1.0)
presentbooleanNoWhether battery is present

Published to: [:sensor, :battery] or custom path

IMU

Inertial measurement unit data.

Module: BB.Message.Sensor.IMU

Fields:

FieldTypeRequiredDescription
orientationQuaternionNoOrientation quaternion
angular_velocityVec3NoAngular velocity in rad/s
linear_accelerationVec3NoLinear acceleration in m/s²

Published to: [:sensor, :imu] or custom path

LaserScan

2D laser range finder data.

Module: BB.Message.Sensor.LaserScan

Fields:

FieldTypeRequiredDescription
angle_minfloatYesStart angle in radians
angle_maxfloatYesEnd angle in radians
angle_incrementfloatYesAngle between measurements
ranges[float]YesRange measurements in metres
intensities[float]NoIntensity values

Published to: [:sensor, :lidar] or custom path

Range

Single distance measurement.

Module: BB.Message.Sensor.Range

Fields:

FieldTypeRequiredDescription
rangefloatYesMeasured distance in metres
min_rangefloatNoMinimum valid range
max_rangefloatNoMaximum valid range
radiation_typeatomNo:ultrasound or :infrared

Published to: [:sensor, sensor_name]

Image

Camera image data.

Module: BB.Message.Sensor.Image

Fields:

FieldTypeRequiredDescription
heightintegerYesImage height in pixels
widthintegerYesImage width in pixels
encodingstringYesPixel encoding (e.g., "rgb8", "mono8")
databinaryYesRaw image data

Published to: [:sensor, :camera] or custom path

Actuator Messages

BeginMotion

Published when an actuator starts moving.

Module: BB.Message.Actuator.BeginMotion

Fields:

FieldTypeRequiredDescription
initial_positionfloatYesStarting position
target_positionfloatYesTarget position
expected_arrivalintegerYesExpected completion time (monotonic ms)
command_idreferenceNoCorrelation ID
command_typeatomNo:position, :velocity, :effort, :trajectory

Published to: [:actuator, actuator_name]

Used by: OpenLoopPositionEstimator for position feedback without encoders.

EndMotion

Published when an actuator completes a motion.

Module: BB.Message.Actuator.EndMotion

Fields:

FieldTypeRequiredDescription
final_positionfloatYesAchieved position
command_idreferenceNoCorrelation ID

Published to: [:actuator, actuator_name]

Actuator Command Messages

Commands sent to actuators.

Command.Position

Position target command.

Module: BB.Message.Actuator.Command.Position

Fields:

FieldTypeRequiredDescription
targetfloatYesTarget position

Published to: [:actuator, actuator_name]

Command.Velocity

Velocity command.

Module: BB.Message.Actuator.Command.Velocity

Fields:

FieldTypeRequiredDescription
velocityfloatYesTarget velocity

Command.Effort

Effort (torque/force) command.

Module: BB.Message.Actuator.Command.Effort

Fields:

FieldTypeRequiredDescription
effortfloatYesTarget effort

Command.Trajectory

Multi-point trajectory command.

Module: BB.Message.Actuator.Command.Trajectory

Fields:

FieldTypeRequiredDescription
points[TrajectoryPoint]YesTrajectory waypoints

Command.Hold

Hold current position.

Module: BB.Message.Actuator.Command.Hold

No additional fields.

Command.Stop

Stop motion immediately.

Module: BB.Message.Actuator.Command.Stop

No additional fields.

Geometry Messages

Geometric primitives used as components in other messages.

Point3D

3D point.

Module: BB.Message.Geometry.Point3D

Fields:

FieldTypeRequiredDescription
xfloatYesX coordinate
yfloatYesY coordinate
zfloatYesZ coordinate

Pose

Position and orientation.

Module: BB.Message.Geometry.Pose

Fields:

FieldTypeRequiredDescription
positionPoint3DYesPosition
orientationQuaternionYesOrientation

Twist

Linear and angular velocity.

Module: BB.Message.Geometry.Twist

Fields:

FieldTypeRequiredDescription
linearVec3YesLinear velocity (m/s)
angularVec3YesAngular velocity (rad/s)

Accel

Linear and angular acceleration.

Module: BB.Message.Geometry.Accel

Fields:

FieldTypeRequiredDescription
linearVec3YesLinear acceleration (m/s²)
angularVec3YesAngular acceleration (rad/s²)

Wrench

Force and torque.

Module: BB.Message.Geometry.Wrench

Fields:

FieldTypeRequiredDescription
forceVec3YesForce (N)
torqueVec3YesTorque (Nm)

System Messages

StateMachine.Transition

Robot state machine transition.

Published to: [:state_machine]

Fields:

FieldTypeDescription
fromatomPrevious state
toatomNew state

Safety.HardwareError

Hardware error report.

Published to: [:safety, :error]

Fields:

FieldTypeDescription
path[atom]Path to component
errortermError details

Creating Messages

All message types support new/1 and new!/1:

# Returns {:ok, message} or {:error, reason}
{:ok, msg} = JointState.new(names: [:shoulder], positions: [0.5])

# Raises on validation error
msg = JointState.new!(names: [:shoulder], positions: [0.5])

Message Wrapper

Messages are wrapped in BB.Message:

%BB.Message{
  payload: %JointState{...},
  timestamp: ~U[2025-01-18 12:00:00Z],
  frame_id: "shoulder"
}

Create wrapped messages:

BB.Message.new(JointState, :shoulder, names: [:shoulder], positions: [0.5])