Custom Messages & Performance

Need a message type that doesn't exist in the standard library? Use the message! macro. HORUS handles all the optimization automatically — you never need to think about serialization or memory layout.

For performance-sensitive applications: standard fixed-size types transfer at ~50ns (zero-copy), variable-size types at ~167ns (serialized). No configuration needed.

Automatic Optimization

When you create a Topic<T>, HORUS inspects the message type at compile time and selects the fastest transfer strategy:

  • Fixed-size types (no heap allocations) use raw memory copy — no serialization overhead
  • Variable-size types (containing String, Vec, etc.) use fast bincode serialization

You always use the same API. The optimization is invisible:

use horus::prelude::*;

// Fixed-size type — automatically uses zero-copy (~50ns cross-process)
let cmd_topic: Topic<CmdVel> = Topic::new("cmd_vel")?;
cmd_topic.send(CmdVel::new(1.0, 0.5));

// Variable-size type — automatically uses serialization (~167ns cross-process)
let log_topic: Topic<String> = Topic::new("log")?;
log_topic.send("Motor started".to_string());

Performance Comparison

Type CategoryCross-Process LatencyExamples
Fixed-size (zero-copy)~50-85nsCmdVel, Imu, Pose2D, Heartbeat
Variable-size (serialized)~167nsString, Vec<f32>, HashMap<K,V>

Same-process communication is fast for both categories since no shared memory serialization is needed.

For most applications, the ~167ns serialized path is more than fast enough. Only high-frequency control loops running at 1kHz+ benefit noticeably from the zero-copy path.

Custom Messages

Use the message! macro to define your own message types. Add #[fixed] for zero-copy shared memory transport (~50ns) when all fields are primitives:

use horus::prelude::*;

message! {
    #[fixed]
    /// Motor feedback — zero-copy via shared memory (~50ns)
    MotorFeedback {
        timestamp_ns: u64,
        motor_id: u32,
        velocity: f32,
        current_amps: f32,
        temperature_c: f32,
    }
}

let feedback: Topic<MotorFeedback> = Topic::new("motor.feedback")?;
feedback.send(MotorFeedback {
    timestamp_ns: 0,
    motor_id: 1,
    velocity: 3.14,
    current_amps: 0.5,
    temperature_c: 45.0,
});

For messages with String, Vec, or other dynamic data, omit #[fixed] — HORUS uses serialization transport automatically (~167ns):

message! {
    /// Diagnostic log — flexible, serialized
    DiagLog {
        node_name: String,
        message: String,
        level: u8,
    }
}

Built-in Message Types

All standard HORUS message types are pre-optimized. Fixed-size types automatically use the zero-copy fast path.

Geometry

MessageDescription
CmdVel2D velocity command (linear + angular)
Pose2D2D position and orientation
Twist3D linear and angular velocity
TransformStamped3D transformation with timestamp
Point33D point
Vector33D vector
QuaternionRotation quaternion

Sensors

MessageDescription
ImuInertial measurement unit data
LaserScan2D laser range data
OdometryPosition/velocity estimate
RangeSensorSingle distance measurement
BatteryStateBattery level and status
NavSatFixGPS position

Control

MessageDescription
MotorCommandIndividual motor control
DifferentialDriveCommandDifferential drive control
ServoCommandServo position/velocity
JointCommandJoint-level control
TrajectoryPointTrajectory waypoint
PidConfigPID controller parameters

Diagnostics

MessageDescription
HeartbeatLiveness signal
NodeHeartbeatPer-node health status
DiagnosticStatusGeneral status report
EmergencyStopEmergency stop signal
SafetyStatusSafety system state
ResourceUsageCPU/memory usage
DiagnosticValueSingle diagnostic measurement
DiagnosticReportFull diagnostic report
MessageDescription
NavGoalNavigation goal
GoalResultGoal completion result
WaypointNavigation waypoint
NavPathSequence of waypoints
PathPlanPlanned path
VelocityObstacleVelocity obstacle for avoidance
VelocityObstaclesSet of velocity obstacles

Force/Haptics

MessageDescription
WrenchStampedForce/torque measurement
ForceCommandForce control command
ImpedanceParametersImpedance control config
ContactInfoContact detection data
HapticFeedbackHaptic output command

Input

MessageDescription
JoystickInputGamepad/joystick state
KeyboardInputKeyboard key events

Tensor

MessageDescription
TensorFixed-size tensor descriptor
use horus::prelude::*;

// All built-in messages use the fastest available path automatically
let cmd: Topic<CmdVel> = Topic::new("cmd_vel")?;
let pose: Topic<Pose2D> = Topic::new("robot_pose")?;
let imu: Topic<Imu> = Topic::new("imu_data")?;
let estop: Topic<EmergencyStop> = Topic::new("emergency_stop")?;

See Also

  • Topic — The unified communication API
  • Message Types — Full message type reference
  • Architecture — How communication fits into the HORUS architecture