Message Types
HORUS provides 60+ typed messages covering every common robotics domain. All types are available in both Rust (use horus::prelude::*;) and Python (from horus import TypeName).
Coming from ROS2?
| ROS2 Package | ROS2 Message | HORUS Equivalent |
|---|---|---|
geometry_msgs | Twist, Pose, Pose2D, TransformStamped, Vector3, Quaternion | Twist, Pose3D, Pose2D, TransformStamped, Vector3, Quaternion |
sensor_msgs | Imu, LaserScan, Image, PointCloud2, JointState, BatteryState, CameraInfo | Imu, LaserScan, Image, PointCloud, JointState, BatteryState, CameraInfo |
nav_msgs | Odometry, OccupancyGrid, Path | Odometry, OccupancyGrid, NavPath + Waypoint |
vision_msgs | Detection2D, Detection3D | Detection, Detection3D |
audio_common_msgs | AudioData | AudioFrame |
std_msgs | Header | (embedded — timestamp_ns and frame_id are fields on each message) |
Key difference from ROS2: No separate Header message. Every HORUS message has timestamp_ns and frame_id as direct fields.
Message Categories
| Category | Types | Use Case |
|---|---|---|
| Geometry | Pose2D, Pose3D, Twist, Vector3, Point3, Quaternion, TransformStamped, Accel | Position, orientation, motion |
| Sensors | Imu, LaserScan, Odometry, JointState, BatteryState, Range, Temperature, MagneticField | Sensor data from hardware |
| Control | CmdVel, MotorCommand, ServoCommand, JointCommand, PidState | Motor and actuator commands |
| Navigation | NavGoal, GoalResult, Waypoint, NavPath, OccupancyGrid, CostMap, VelocityObstacle | Path planning and mapping |
| Perception | Detection, Detection3D, TrackedObject, SegmentationMask, LandmarkArray, PlaneDetection | Computer vision and ML output |
| Vision | CompressedImage, CameraInfo, RegionOfInterest, StereoInfo | Camera configuration and compressed data |
| Force/Haptics | WrenchStamped, ForceCommand, ContactInfo, ImpedanceParameters, HapticFeedback | Force sensing and control |
| Diagnostics | Heartbeat, DiagnosticStatus, NodeHeartbeat, SafetyStatus, EmergencyStop | System health monitoring |
| Audio | AudioFrame | Microphone data, speech, anomaly detection |
| Input | JoystickInput, KeyboardInput | Human input devices |
Custom Messages
Need a type that doesn't exist? Create your own:
// simplified
use horus::prelude::*;
message! {
MotorStatus {
rpm: f32,
current_amps: f32,
temperature_c: f32,
fault_code: u32,
}
}
// Now use it like any standard message
let topic: Topic<MotorStatus> = Topic::new("motor.status")?;
Design Decisions
Why fixed-size Pod types for most messages? Fixed-size types (#[repr(C)], Copy, Pod) can be placed directly in shared memory ring buffers with no serialization, allocation, or copying. This gives deterministic sub-microsecond latency. Variable-length types (Image, PointCloud) use a descriptor + pool pattern -- the descriptor is fixed-size and travels through the ring buffer, while bulk data lives in a separate memory pool.
Why no Header message like ROS2? ROS2's std_msgs/Header adds an indirection layer and allocation for every message. HORUS embeds timestamp_ns and frame_id directly as fields on each message type, eliminating the extra allocation and keeping messages flat and Pod-compatible.
Why categories instead of a flat namespace? Grouping by domain (geometry, sensor, control, navigation, perception, etc.) helps users discover the right type. The Rust use horus::prelude::* and Python from horus import X still provide flat access -- the categories are organizational, not API barriers.
See Also
- Message Types Concept — How messages work in HORUS
- Custom Messages Tutorial — Step-by-step guide
- Python Message Library — Python equivalents