Standard Messages

Standard message types for robotics communication. All messages are designed for zero-copy shared memory transport.

use horus::prelude::*;

Geometry

Spatial primitives for position, orientation, and motion.

Twist

3D velocity command with linear and angular components.

pub struct Twist {
    pub linear: [f64; 3],       // [x, y, z] in m/s
    pub angular: [f64; 3],      // [roll, pitch, yaw] in rad/s
    pub timestamp_ns: u64,      // Timestamp in nanoseconds since epoch
}

Constructors

// Full 3D velocity
let twist = Twist::new([1.0, 0.0, 0.0], [0.0, 0.0, 0.5]);

// 2D velocity (forward + rotation)
let twist = Twist::new_2d(1.0, 0.5);  // 1 m/s forward, 0.5 rad/s rotation

// Stop command
let twist = Twist::stop();

Methods

MethodDescription
is_valid()Returns true if all values are finite

Pose2D

2D pose (position and orientation) for planar robots.

pub struct Pose2D {
    pub x: f64,            // X position in meters
    pub y: f64,            // Y position in meters
    pub theta: f64,        // Orientation in radians
    pub timestamp_ns: u64, // Timestamp in nanoseconds since epoch
}

Constructors

let pose = Pose2D::new(1.0, 2.0, 0.5);  // x=1m, y=2m, theta=0.5rad
let pose = Pose2D::origin();             // (0, 0, 0)

Methods

MethodDescription
distance_to(&other)Euclidean distance to another pose
normalize_angle()Normalize theta to [-π, π]
is_valid()Returns true if all values are finite

TransformStamped

Timestamped 3D transformation (translation + quaternion rotation) for message passing.

pub struct TransformStamped {
    pub translation: [f64; 3],  // [x, y, z] in meters
    pub rotation: [f64; 4],     // Quaternion [x, y, z, w]
    pub timestamp_ns: u64,
}

Constructors

let tf = TransformStamped::identity();
let tf = TransformStamped::new([1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]);
let tf = TransformStamped::from_pose_2d(&pose);

Methods

MethodDescription
is_valid()Check if quaternion is normalized
normalize_rotation()Normalize the quaternion

Note: For coordinate frame management (lookups, chains, interpolation), see TransformFrame which uses its own Transform type.


Point3

3D point in space.

pub struct Point3 {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

Methods

let p1 = Point3::new(1.0, 2.0, 3.0);
let p2 = Point3::origin();
let dist = p1.distance_to(&p2);

Vector3

3D vector for representing directions and velocities.

pub struct Vector3 {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

Methods

MethodDescription
magnitude()Vector length
normalize()Normalize to unit vector
dot(&other)Dot product
cross(&other)Cross product

Quaternion

Quaternion for 3D rotation representation.

pub struct Quaternion {
    pub x: f64,
    pub y: f64,
    pub z: f64,
    pub w: f64,
}

Constructors

let q = Quaternion::identity();
let q = Quaternion::new(0.0, 0.0, 0.0, 1.0);
let q = Quaternion::from_euler(roll, pitch, yaw);

Pose3D

3D pose with position and quaternion orientation.

pub struct Pose3D {
    pub position: Point3,       // Position in 3D space
    pub orientation: Quaternion, // Orientation as quaternion
    pub timestamp_ns: u64,
}

Constructors

let pose = Pose3D::new(Point3::new(1.0, 2.0, 0.5), Quaternion::identity());
let pose = Pose3D::identity();
let pose = Pose3D::from_pose_2d(&pose_2d);  // Lift 2D pose into 3D

Methods

MethodDescription
distance_to(&other)Euclidean distance to another pose
is_valid()Check if position is finite and quaternion is normalized

PoseStamped

Pose with coordinate frame identifier.

pub struct PoseStamped {
    pub pose: Pose3D,
    pub frame_id: [u8; 32],    // Coordinate frame (null-terminated, max 31 chars)
    pub timestamp_ns: u64,
}

Constructors

let stamped = PoseStamped::new();
let stamped = PoseStamped::with_frame_id(pose, "map");

Methods

MethodDescription
frame_id_str()Get frame ID as &str
set_frame_id(id)Set frame ID string

Accel

Linear and angular acceleration.

pub struct Accel {
    pub linear: [f64; 3],      // [x, y, z] in m/s²
    pub angular: [f64; 3],     // [roll, pitch, yaw] in rad/s²
    pub timestamp_ns: u64,
}

Constructors

let accel = Accel::new([0.0, 0.0, 9.81], [0.0, 0.0, 0.0]);

Methods

MethodDescription
is_valid()Check if all values are finite

AccelStamped

Acceleration with coordinate frame.

pub struct AccelStamped {
    pub accel: Accel,
    pub frame_id: [u8; 32],    // Coordinate frame (null-terminated, max 31 chars)
    pub timestamp_ns: u64,
}

Constructors

let stamped = AccelStamped::new();
let stamped = AccelStamped::with_frame_id(accel, "imu_link");

Methods

MethodDescription
frame_id_str()Get frame ID as &str
set_frame_id(id)Set frame ID string

PoseWithCovariance

Pose with 6x6 uncertainty covariance matrix.

pub struct PoseWithCovariance {
    pub pose: Pose3D,
    pub covariance: [f64; 36],  // 6x6 covariance (row-major): x, y, z, roll, pitch, yaw
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Constructors

let pose_cov = PoseWithCovariance::new();
let pose_cov = PoseWithCovariance::with_frame_id(pose, covariance, "map");

Methods

MethodDescription
position_variance()Get [x, y, z] variance from diagonal
orientation_variance()Get [roll, pitch, yaw] variance from diagonal
frame_id_str()Get frame ID as &str
set_frame_id(id)Set frame ID string

Example

// EKF localization output with uncertainty
let mut pose_cov = PoseWithCovariance::new();
pose_cov.pose = estimated_pose;
// Diagonal: position uncertainty 0.1m, orientation 0.05rad
pose_cov.covariance[0] = 0.01;   // x variance
pose_cov.covariance[7] = 0.01;   // y variance
pose_cov.covariance[14] = 0.04;  // z variance
pose_cov.covariance[21] = 0.0025; // roll variance
pose_cov.covariance[28] = 0.0025; // pitch variance
pose_cov.covariance[35] = 0.0025; // yaw variance
topic.send(pose_cov);

TwistWithCovariance

Velocity with 6x6 uncertainty covariance matrix.

pub struct TwistWithCovariance {
    pub twist: Twist,
    pub covariance: [f64; 36],  // 6x6 covariance (row-major): vx, vy, vz, wx, wy, wz
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Constructors

let twist_cov = TwistWithCovariance::new();
let twist_cov = TwistWithCovariance::with_frame_id(twist, covariance, "base_link");

Methods

MethodDescription
linear_variance()Get [vx, vy, vz] variance from diagonal
angular_variance()Get [wx, wy, wz] variance from diagonal
frame_id_str()Get frame ID as &str
set_frame_id(id)Set frame ID string

Sensor

Standard sensor data formats.

LaserScan

2D LiDAR scan data with 360 range measurements.

pub struct LaserScan {
    pub ranges: [f32; 360],      // Range measurements in meters
    pub angle_min: f32,          // Start angle in radians
    pub angle_max: f32,          // End angle in radians
    pub range_min: f32,          // Minimum valid range
    pub range_max: f32,          // Maximum valid range
    pub angle_increment: f32,    // Angular resolution
    pub time_increment: f32,     // Time between measurements
    pub scan_time: f32,          // Full scan time
    pub timestamp_ns: u64,
}

Constructors

let scan = LaserScan::new();
let scan = LaserScan::default();

Methods

MethodDescription
angle_at(index)Get angle for range index
is_range_valid(index)Check if reading is valid
valid_count()Count valid readings
min_range()Get minimum valid range

Example

if let Some(scan) = scan_sub.recv() {
    if let Some(min_dist) = scan.min_range() {
        if min_dist < 0.5 {
            // Obstacle detected!
        }
    }
}

Imu

IMU sensor data (orientation, angular velocity, acceleration).

pub struct Imu {
    pub orientation: [f64; 4],              // Quaternion [x, y, z, w]
    pub orientation_covariance: [f64; 9],   // 3x3 covariance (-1 = no data)
    pub angular_velocity: [f64; 3],         // [x, y, z] in rad/s
    pub angular_velocity_covariance: [f64; 9],
    pub linear_acceleration: [f64; 3],      // [x, y, z] in m/s²
    pub linear_acceleration_covariance: [f64; 9],
    pub timestamp_ns: u64,
}

Constructors

let imu = Imu::new();

Methods

MethodDescription
set_orientation_from_euler(roll, pitch, yaw)Set orientation from Euler angles
has_orientation()Check if orientation data is available
is_valid()Check if all values are finite
angular_velocity_vec()Get angular velocity as Vector3
linear_acceleration_vec()Get linear acceleration as Vector3

Odometry

Combined pose and velocity estimate.

pub struct Odometry {
    pub pose: Pose2D,
    pub twist: Twist,
    pub pose_covariance: [f64; 36],    // 6x6 covariance
    pub twist_covariance: [f64; 36],
    pub frame_id: [u8; 32],            // e.g., "odom"
    pub child_frame_id: [u8; 32],      // e.g., "base_link"
    pub timestamp_ns: u64,
}

Methods

MethodDescription
set_frames(frame, child)Set frame IDs
update(pose, twist)Update pose and velocity
is_valid()Check validity

GPS/GNSS position data.

pub struct NavSatFix {
    pub latitude: f64,           // Degrees (+ North, - South)
    pub longitude: f64,          // Degrees (+ East, - West)
    pub altitude: f64,           // Meters above WGS84
    pub position_covariance: [f64; 9],
    pub position_covariance_type: u8,
    pub status: u8,              // Fix status
    pub satellites_visible: u16,
    pub hdop: f32,
    pub vdop: f32,
    pub speed: f32,              // m/s
    pub heading: f32,            // degrees
    pub timestamp_ns: u64,
}

Constants

NavSatFix::STATUS_NO_FIX    // 0
NavSatFix::STATUS_FIX       // 1
NavSatFix::STATUS_SBAS_FIX  // 2
NavSatFix::STATUS_GBAS_FIX  // 3

Methods

MethodDescription
from_coordinates(lat, lon, alt)Create from coordinates
has_fix()Check if GPS has fix
is_valid()Check coordinate validity
horizontal_accuracy()Estimated accuracy in meters
distance_to(&other)Distance to another position (Haversine)

BatteryState

Battery status information.

pub struct BatteryState {
    pub voltage: f32,            // Volts
    pub current: f32,            // Amperes (negative = discharging)
    pub charge: f32,             // Amp-hours
    pub capacity: f32,           // Amp-hours
    pub percentage: f32,         // 0-100
    pub power_supply_status: u8,
    pub temperature: f32,        // Celsius
    pub cell_voltages: [f32; 16],
    pub cell_count: u8,
    pub timestamp_ns: u64,
}

Constants

BatteryState::STATUS_UNKNOWN     // 0
BatteryState::STATUS_CHARGING    // 1
BatteryState::STATUS_DISCHARGING // 2
BatteryState::STATUS_FULL        // 3

Methods

MethodDescription
new(voltage, percentage)Create new battery state
is_low(threshold)Check if below threshold
is_critical()Check if below 10%
time_remaining()Estimated time in seconds

RangeSensor

Single-point distance measurement (ultrasonic, IR).

pub struct RangeSensor {
    pub sensor_type: u8,     // 0=ultrasonic, 1=infrared
    pub field_of_view: f32,  // radians
    pub min_range: f32,      // meters
    pub max_range: f32,      // meters
    pub range: f32,          // meters
    pub timestamp_ns: u64,
}

JointState

Joint positions, velocities, and efforts for multi-joint robots (up to 16 joints).

pub struct JointState {
    pub names: [[u8; 32]; 16],  // Joint names (null-terminated, max 31 chars each)
    pub joint_count: u8,        // Number of valid joints
    pub positions: [f64; 16],   // Radians (revolute) or meters (prismatic)
    pub velocities: [f64; 16],  // rad/s or m/s
    pub efforts: [f64; 16],     // Torque (Nm) or force (N)
    pub timestamp_ns: u64,
}

Methods

MethodDescription
new()Create empty joint state
add_joint(name, pos, vel, effort)Add a joint entry
joint_name(index)Get joint name as &str
position(index)Get position for joint
velocity(index)Get velocity for joint
effort(index)Get effort for joint

Example

let mut joints = JointState::new();
joints.add_joint("shoulder", 0.5, 0.0, 1.2);
joints.add_joint("elbow", -0.8, 0.1, 0.5);
joints.add_joint("wrist", 0.2, 0.0, 0.1);
joint_topic.send(joints);

Temperature

Temperature reading in Celsius.

pub struct Temperature {
    pub temperature: f64,    // Degrees Celsius
    pub variance: f64,       // Variance (0 if exact)
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Constructors

let temp = Temperature::new();
let temp = Temperature::with_frame_id(22.5, 0.1, "motor_0");

FluidPressure

Pressure reading in Pascals.

pub struct FluidPressure {
    pub fluid_pressure: f64, // Pressure in Pascals
    pub variance: f64,       // Variance (0 if exact)
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Constructors

let pressure = FluidPressure::new();
let pressure = FluidPressure::with_frame_id(101325.0, 10.0, "barometer");

Illuminance

Light level in Lux.

pub struct Illuminance {
    pub illuminance: f64,    // Illuminance in Lux
    pub variance: f64,       // Variance (0 if exact)
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Constructors

let lux = Illuminance::new();
let lux = Illuminance::with_frame_id(500.0, 5.0, "ambient_sensor");

MagneticField

Magnetic field vector in Tesla with 3x3 covariance.

pub struct MagneticField {
    pub magnetic_field: [f64; 3],             // [x, y, z] in Tesla
    pub magnetic_field_covariance: [f64; 9],  // 3x3 covariance (row-major). [0] = -1 means unknown
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Constructors

let mag = MagneticField::new();
let mag = MagneticField::with_frame_id([25e-6, 0.0, -45e-6], "imu_link");

Vision

Image and camera data types.

Image

Pool-backed RAII camera image type with zero-copy shared memory transport. Fields are private — use accessor methods.

// Image is an RAII type, not a plain struct.
// Create with Image::new(width, height, encoding)?
// Access data with .data(), .pixel(), etc.
// See Vision Messages for full API.
let mut img = Image::new(640, 480, ImageEncoding::Rgb8)?;
img.copy_from(&pixel_data);

ImageEncoding

pub enum ImageEncoding {
    Rgb8,
    Bgr8,
    Rgba8,
    Bgra8,
    Mono8,
    Mono16,
    Yuv422,
    Mono32F,
    Rgb32F,
    BayerRggb8,
    Depth16,
}

CameraInfo

Camera calibration information.

pub struct CameraInfo {
    pub width: u32,
    pub height: u32,
    pub distortion_model: [u8; 16],
    pub distortion_coefficients: [f64; 8],  // [k1, k2, p1, p2, k3, k4, k5, k6]
    pub camera_matrix: [f64; 9],            // Intrinsic matrix (3x3)
    pub rectification_matrix: [f64; 9],     // Rectification (3x3)
    pub projection_matrix: [f64; 12],       // Projection (3x4)
}

RegionOfInterest

Region of interest for image cropping and processing.

pub struct RegionOfInterest {
    pub x_offset: u32,
    pub y_offset: u32,
    pub width: u32,
    pub height: u32,
    pub do_rectify: bool,
}

Methods

MethodDescription
new(x, y, w, h)Create a new ROI
contains(x, y)Check if point is inside ROI
area()Get area in pixels

CompressedImage

Compressed image data (JPEG, PNG, WebP).

pub struct CompressedImage {
    pub format: [u8; 8],        // "jpeg", "png", "webp"
    pub data: Vec<u8>,          // Compressed image bytes
    pub width: u32,
    pub height: u32,
    pub frame_id: [u8; 32],
    pub timestamp_ns: u64,
}

Note: CompressedImage uses Vec<u8> for variable-length data, so it is not POD — it uses MessagePack serialization instead of zero-copy.


Detection

Object detection result (2D).

pub struct Detection {
    pub bbox: BoundingBox2D,
    pub confidence: f32,
    pub class_id: u32,
    pub class_name: [u8; 32],
    pub instance_id: u32,
}

BoundingBox2D

2D bounding box in pixel coordinates.

pub struct BoundingBox2D {
    pub x: f32,       // Top-left X (pixels)
    pub y: f32,       // Top-left Y (pixels)
    pub width: f32,   // Width (pixels)
    pub height: f32,  // Height (pixels)
}

Methods

MethodDescription
new(x, y, w, h)Create from top-left corner
from_center(cx, cy, w, h)Create from center point
center_x() / center_y()Get center coordinates
area()Get area in pixels²
iou(&other)Intersection over Union

BoundingBox3D

3D bounding box in world coordinates.

pub struct BoundingBox3D {
    pub cx: f32,      // Center X (meters)
    pub cy: f32,      // Center Y (meters)
    pub cz: f32,      // Center Z (meters)
    pub length: f32,  // Along X axis (meters)
    pub width: f32,   // Along Y axis (meters)
    pub height: f32,  // Along Z axis (meters)
    pub roll: f32,    // Rotation around X (radians)
    pub pitch: f32,   // Rotation around Y (radians)
    pub yaw: f32,     // Rotation around Z (radians)
}

Methods

MethodDescription
new(cx, cy, cz, l, w, h)Create axis-aligned box
with_rotation(cx, cy, cz, l, w, h, roll, pitch, yaw)Create rotated box
volume()Get volume in m³

Detection3D

3D object detection result with optional velocity tracking.

pub struct Detection3D {
    pub bbox: BoundingBox3D,
    pub confidence: f32,
    pub class_id: u32,
    pub class_name: [u8; 32],
    pub velocity_x: f32,      // m/s (for tracking)
    pub velocity_y: f32,
    pub velocity_z: f32,
    pub instance_id: u32,
}

Methods

MethodDescription
new(bbox, confidence, class_id)Create detection
with_velocity(vx, vy, vz)Add velocity estimate
class_name()Get class name as &str
set_class_name(name)Set class name string

Control

Actuator command messages.

MotorCommand

Motor control command.

pub struct MotorCommand {
    pub motor_id: u8,
    pub mode: u8,             // 0=velocity, 1=position, 2=torque, 3=voltage
    pub target: f64,
    pub max_velocity: f64,
    pub max_acceleration: f64,
    pub feed_forward: f64,
    pub enable: u8,
    pub timestamp_ns: u64,
}

ServoCommand

Servo position command.

pub struct ServoCommand {
    pub servo_id: u8,
    pub position: f32,       // radians
    pub speed: f32,          // 0-1 (0 = max speed)
    pub enable: u8,
    pub timestamp_ns: u64,
}

PidConfig

PID controller configuration.

pub struct PidConfig {
    pub controller_id: u8,
    pub kp: f64,
    pub ki: f64,
    pub kd: f64,
    pub integral_limit: f64,
    pub output_limit: f64,
    pub anti_windup: u8,
    pub timestamp_ns: u64,
}

CmdVel

Simple 2D velocity command — the preferred type for ground robots.

pub struct CmdVel {
    pub timestamp_ns: u64,
    pub linear: f32,   // Forward velocity in m/s
    pub angular: f32,  // Turning velocity in rad/s
}

Constructors

let cmd = CmdVel::new(0.5, 0.2);  // 0.5 m/s forward, 0.2 rad/s left turn
let cmd = CmdVel::zero();          // Stop

Converts to/from Twist:

let twist: Twist = cmd.into();
let cmd = CmdVel::from(twist);

DifferentialDriveCommand

Left/right wheel velocity command for 2-wheel robots.

pub struct DifferentialDriveCommand {
    pub left_velocity: f64,      // Left wheel in rad/s
    pub right_velocity: f64,     // Right wheel in rad/s
    pub max_acceleration: f64,   // Maximum acceleration in rad/s²
    pub enable: u8,              // Enable motors
    pub timestamp_ns: u64,
}

Constructors

let cmd = DifferentialDriveCommand::new(5.0, 5.0);  // Both wheels forward
let cmd = DifferentialDriveCommand::stop();           // Emergency stop
let cmd = DifferentialDriveCommand::from_twist(&twist, wheel_separation);

Methods

MethodDescription
is_valid()Check if velocities are finite

TrajectoryPoint

Waypoint in a trajectory with position, velocity, acceleration, and timing.

pub struct TrajectoryPoint {
    pub position: [f64; 3],          // [x, y, z]
    pub velocity: [f64; 3],          // [vx, vy, vz]
    pub acceleration: [f64; 3],      // [ax, ay, az]
    pub orientation: [f64; 4],       // Quaternion [x, y, z, w]
    pub angular_velocity: [f64; 3],  // [wx, wy, wz]
    pub time_from_start: f64,        // Seconds from trajectory start
}

Constructors

let point = TrajectoryPoint::new_2d(1.0, 2.0, 0.5);  // x, y, theta
let point = TrajectoryPoint::stationary([1.0, 2.0, 0.0]);

GenericMessage

Dynamic message type for cross-language communication. Uses a fixed-size buffer (4KB max payload) with MessagePack serialization, making it safe for shared memory transport.

pub struct GenericMessage {
    pub inline_data: [u8; 256],    // First 256 bytes (inline)
    pub overflow_data: [u8; 3840], // Overflow up to 3840 more bytes
    pub metadata: [u8; 256],       // Optional metadata
    // ... internal length tracking fields
}

Total maximum payload: 4,096 bytes (inline_data + overflow_data).

Constructors

// From raw bytes (returns Err if > 4KB)
let msg = GenericMessage::new(data_vec)?;

// From any serializable type (uses MessagePack)
let msg = GenericMessage::from_value(&my_struct)?;

// With metadata string (max 255 chars)
let msg = GenericMessage::with_metadata(data, "my_type".to_string())?;

Methods

MethodReturn TypeDescription
data()Vec<u8>Get payload bytes
metadata()Option<String>Get metadata string if present
to_value::<T>()Result<T, String>Deserialize from MessagePack to typed value

Example

use std::collections::HashMap;

// Send any serializable data
let mut data = HashMap::new();
data.insert("x", 1.0);
data.insert("y", 2.0);
let msg = GenericMessage::from_value(&data)?;
topic.send(msg);

// Receive and deserialize
if let Some(msg) = topic.recv() {
    let data: HashMap<String, f64> = msg.to_value()?;
    println!("x: {}", data["x"]);
}

Use typed messages (e.g., Twist, Pose2D) instead of GenericMessage whenever possible — they are faster (POD zero-copy) and type-safe.


Perception

Types for computer vision, landmark detection, and semantic understanding.

Landmark

2D landmark point (keypoint, fiducial marker).

pub struct Landmark {
    pub x: f32,           // X coordinate (pixels or normalized 0-1)
    pub y: f32,           // Y coordinate (pixels or normalized 0-1)
    pub visibility: f32,  // Confidence (0.0 - 1.0)
    pub index: u32,       // Landmark ID (e.g., 0=nose, 1=left_eye)
}

Methods

MethodDescription
new(x, y, visibility, index)Create landmark
visible(x, y, index)Create with visibility = 1.0
is_visible()Check if visibility > 0
distance_to(&other)Euclidean distance

Landmark3D

3D landmark point with depth.

pub struct Landmark3D {
    pub x: f32,           // X (meters or normalized)
    pub y: f32,           // Y (meters or normalized)
    pub z: f32,           // Z (depth)
    pub visibility: f32,  // Confidence (0.0 - 1.0)
    pub index: u32,       // Landmark ID
}

Methods

MethodDescription
new(x, y, z, visibility, index)Create 3D landmark
to_2d()Project to 2D Landmark (drops z)
distance_to(&other)3D Euclidean distance

LandmarkArray

Collection of landmarks for a single detection (pose, face, hand).

pub struct LandmarkArray {
    pub num_landmarks: u32,
    pub dimension: u32,      // 2 for 2D, 3 for 3D
    pub instance_id: u32,    // Person/detection ID
    pub confidence: f32,     // Overall pose confidence (0.0 - 1.0)
    pub timestamp_ns: u64,
    pub bbox_x: f32,         // Bounding box X (pixels)
    pub bbox_y: f32,         // Bounding box Y (pixels)
    pub bbox_width: f32,
    pub bbox_height: f32,
}

Constructors

let pose = LandmarkArray::coco_pose();       // 17 keypoints (COCO format)
let pose = LandmarkArray::mediapipe_pose();   // 33 keypoints
let hand = LandmarkArray::mediapipe_hand();   // 21 keypoints
let face = LandmarkArray::mediapipe_face();   // 468 keypoints

PlaneDetection

Detected plane surface (floor, wall, table).

pub struct PlaneDetection {
    pub coefficients: [f64; 4],  // [a, b, c, d] where ax + by + cz + d = 0
    pub center: Point3,          // Center of the plane
    pub normal: Vector3,         // Normal vector
    pub size: [f64; 2],          // [width, height] if bounded
    pub inlier_count: u32,       // Number of inlier points
    pub confidence: f32,         // Detection confidence (0.0 - 1.0)
    pub plane_type: [u8; 16],    // "floor", "wall", "table", etc.
    pub timestamp_ns: u64,
}

Methods

MethodDescription
new()Create empty plane
distance_to_point(&point)Signed distance from point to plane
contains_point(&point)Check if point is within plane bounds
with_type(label)Set plane type label
plane_type_str()Get plane type as &str

SegmentationMask

Pixel-level semantic/instance segmentation.

pub struct SegmentationMask {
    pub width: u32,
    pub height: u32,
    pub num_classes: u32,  // Number of semantic classes
    pub mask_type: u32,    // 0=semantic, 1=instance, 2=panoptic
    pub timestamp_ns: u64,
    pub seq: u64,
    pub frame_id: [u8; 32],
}

Constructors

let mask = SegmentationMask::semantic(640, 480, 21);   // 21 classes
let mask = SegmentationMask::instance(640, 480, 80);   // 80 instance classes
let mask = SegmentationMask::panoptic(640, 480, 133);  // Panoptic segmentation

Methods

MethodDescription
is_semantic()Check if semantic segmentation
is_instance()Check if instance segmentation
is_panoptic()Check if panoptic segmentation
data_size()Required buffer size for u8 labels
data_size_u16()Required buffer size for u16 labels

Path planning and goal management.

Navigation goal with target pose and tolerances.

pub struct NavGoal {
    pub target_pose: Pose2D,
    pub tolerance_position: f64,  // Position tolerance in meters
    pub tolerance_angle: f64,     // Orientation tolerance in radians
    pub timeout_seconds: f64,     // Max time to reach goal (0 = no limit)
    pub priority: u8,             // Goal priority (0 = highest)
    pub goal_id: u32,             // Unique goal identifier
    pub timestamp_ns: u64,
}

Constructors

let goal = NavGoal::new(Pose2D::new(5.0, 3.0, 0.0));
let goal = NavGoal::new(target).with_timeout(30.0).with_priority(1);

Methods

MethodDescription
is_position_reached(&current)Check if position is within tolerance
is_orientation_reached(&current)Check if angle is within tolerance
is_reached(&current)Check if both position and angle are reached

Example

let goal = NavGoal::new(Pose2D::new(5.0, 3.0, 1.57));
goal_topic.send(goal);

// In planner node
if let Some(goal) = goal_topic.recv() {
    if goal.is_reached(&current_pose) {
        hlog!(info, "Goal {} reached!", goal.goal_id);
    }
}

Ordered sequence of waypoints (up to 256).

pub struct NavPath {
    pub waypoints: [Waypoint; 256],  // Waypoint = {pose, velocity, time_from_start, curvature, stop_required}
    pub waypoint_count: u16,
    pub total_length: f64,           // Total path length in meters
    pub duration_seconds: f64,       // Estimated completion time
    pub frame_id: [u8; 32],
    pub algorithm: [u8; 32],         // e.g., "a_star", "rrt"
    pub timestamp_ns: u64,
}

Methods

MethodDescription
new()Create empty path
add_waypoint(waypoint)Append a waypoint
waypoints()Get slice of valid waypoints
closest_waypoint_index(&pose)Find nearest waypoint to pose
calculate_progress(&pose)Get progress along path (0.0 - 1.0)
frame_id_str()Get frame ID as &str

Diagnostics

System health, monitoring, and diagnostic data.

DiagnosticValue

Typed key-value pair for diagnostic data.

pub struct DiagnosticValue {
    pub key: [u8; 32],       // Key name (null-terminated)
    pub value: [u8; 64],     // Value as string (null-terminated)
    pub value_type: u8,      // 0=string, 1=int, 2=float, 3=bool
}

Constructors

let val = DiagnosticValue::string("firmware", "v2.1.0");
let val = DiagnosticValue::int("error_count", 3);
let val = DiagnosticValue::float("temperature", 45.2);
let val = DiagnosticValue::bool("calibrated", true);

DiagnosticReport

Component health report with up to 16 key-value entries.

pub struct DiagnosticReport {
    pub component: [u8; 32],
    pub values: [DiagnosticValue; 16],
    pub value_count: u8,
    pub level: u8,            // Overall status level
    pub timestamp_ns: u64,
}

Methods

MethodDescription
new(component)Create empty report
add_value(value)Add a diagnostic value
add_string(key, val)Add string entry
add_int(key, val)Add integer entry
add_float(key, val)Add float entry
add_bool(key, val)Add boolean entry
set_level(level)Set status level

Example

let mut report = DiagnosticReport::new("left_motor");
report.add_float("temperature", 42.5);
report.add_int("error_count", 0);
report.add_bool("calibrated", true);
report.add_string("firmware", "v2.1.0");
report.set_level(0); // OK
diag_topic.send(report);

NodeHeartbeat

Periodic node health signal (written via filesystem, not Topic).

pub struct NodeHeartbeat {
    pub state: u8,                 // Node execution state
    pub health: u8,                // Health status
    pub tick_count: u64,
    pub target_rate_hz: u32,
    pub actual_rate_hz: u32,
    pub error_count: u32,
    pub last_tick_timestamp: u64,  // Unix epoch seconds
    pub heartbeat_timestamp: u64,  // Unix epoch seconds
}

Methods

MethodDescription
new()Create default heartbeat
update_timestamp()Set heartbeat_timestamp to now
is_fresh(max_age_secs)Check if heartbeat is recent
to_bytes() / from_bytes()Serialize for filesystem storage

POD Types and Zero-Copy

Most HORUS message types are POD (Plain Old Data) — they use #[repr(C)] layout and implement the PodMessage trait, enabling zero-copy shared memory transport at ~50ns latency.

POD types (94% of all messages): Fixed-size, no heap allocation, zero-copy capable. Non-POD types: Use Vec for variable-size data — serialized via MessagePack.

CategoryPOD / TotalNon-POD Types
Geometry12/12
Sensor11/11
Control9/9
Vision5/7Image (pool-backed RAII), CompressedImage
Detection4/4
Perception4/6PointCloud (pool-backed RAII), DepthImage (pool-backed RAII)
Navigation9/11OccupancyGrid, CostMap
Diagnostics11/11
Force/Haptics5/5

POD detection is automatic — you don't need to configure anything. HORUS checks at topic creation time whether your type is POD and selects the optimal backend.

Size Reference

MessageSizePOD
CmdVel16 bytesYes
Twist56 bytesYes
Pose2D32 bytesYes
Pose3D72 bytesYes
Imu~200 bytesYes
JointState~1.5 KBYes
LaserScan~1.5 KBYes
NavPath~32 KBYes
ImagePool-backed RAIIDescriptor is Pod
GenericMessage~4.5 KBYes

Detailed Message Documentation

For comprehensive documentation of specialized message types, see:

CategoryDescription
Vision MessagesImage, CameraInfo, Detection, CompressedImage
Perception MessagesPointCloud, DepthImage, BoundingBox3D, PlaneDetection
Control MessagesMotorCommand, ServoCommand, PidConfig, JointCommand
Force & Haptic MessagesWrenchStamped, ImpedanceParameters, ForceCommand
Navigation MessagesGoal, Path, OccupancyGrid, CostMap, VelocityObstacle
Diagnostics MessagesHeartbeat, DiagnosticStatus, EmergencyStop, ResourceUsage, SafetyStatus
Input MessagesKeyboardInput, JoystickInput for teleoperation and HID control
Clock & Time MessagesClock, TimeReference for simulation time and synchronization
TensorPool APIZero-copy tensor memory management

Python Equivalents

All message types above are available in Python with identical fields. See: