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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
set_frames(frame, child) | Set frame IDs |
update(pose, twist) | Update pose and velocity |
is_valid() | Check validity |
NavSatFix
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Return Type | Description |
|---|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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 |
Navigation
Path planning and goal management.
NavGoal
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
| Method | Description |
|---|---|
is_position_reached(¤t) | Check if position is within tolerance |
is_orientation_reached(¤t) | Check if angle is within tolerance |
is_reached(¤t) | 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(¤t_pose) {
hlog!(info, "Goal {} reached!", goal.goal_id);
}
}
NavPath
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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.
| Category | POD / Total | Non-POD Types |
|---|---|---|
| Geometry | 12/12 | — |
| Sensor | 11/11 | — |
| Control | 9/9 | — |
| Vision | 5/7 | Image (pool-backed RAII), CompressedImage |
| Detection | 4/4 | — |
| Perception | 4/6 | PointCloud (pool-backed RAII), DepthImage (pool-backed RAII) |
| Navigation | 9/11 | OccupancyGrid, CostMap |
| Diagnostics | 11/11 | — |
| Force/Haptics | 5/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
| Message | Size | POD |
|---|---|---|
CmdVel | 16 bytes | Yes |
Twist | 56 bytes | Yes |
Pose2D | 32 bytes | Yes |
Pose3D | 72 bytes | Yes |
Imu | ~200 bytes | Yes |
JointState | ~1.5 KB | Yes |
LaserScan | ~1.5 KB | Yes |
NavPath | ~32 KB | Yes |
Image | Pool-backed RAII | Descriptor is Pod |
GenericMessage | ~4.5 KB | Yes |
Detailed Message Documentation
For comprehensive documentation of specialized message types, see:
| Category | Description |
|---|---|
| Vision Messages | Image, CameraInfo, Detection, CompressedImage |
| Perception Messages | PointCloud, DepthImage, BoundingBox3D, PlaneDetection |
| Control Messages | MotorCommand, ServoCommand, PidConfig, JointCommand |
| Force & Haptic Messages | WrenchStamped, ImpedanceParameters, ForceCommand |
| Navigation Messages | Goal, Path, OccupancyGrid, CostMap, VelocityObstacle |
| Diagnostics Messages | Heartbeat, DiagnosticStatus, EmergencyStop, ResourceUsage, SafetyStatus |
| Input Messages | KeyboardInput, JoystickInput for teleoperation and HID control |
| Clock & Time Messages | Clock, TimeReference for simulation time and synchronization |
| TensorPool API | Zero-copy tensor memory management |
Python Equivalents
All message types above are available in Python with identical fields. See:
- Python Message Library — 55+ message types with Python examples
- Python Memory Types — Image, PointCloud, DepthImage (pool-backed)
- Python Perception — DetectionList, TrackedObject, COCOPose