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 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 (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

Fixed-Size Types and Zero-Copy

Most HORUS message types are fixed-size with no heap allocation, enabling zero-copy shared memory transport at ~50ns latency.

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

CategoryFixed-Size / TotalVariable-Size 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

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

Size Reference

MessageSizeZero-Copy
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 fixed-size
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
Tensor APIZero-copy tensor memory management

Python Equivalents

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