Sensor Messages (C++)
All sensor types live in horus::msg:: namespace. Include via <horus/msg/sensor.hpp>.
Quick Reference
| Type | Size | Key Fields | Use Case |
|---|---|---|---|
LaserScan | 1472 B | ranges[360], angle_min/max | 2D LiDAR |
Imu | 304 B | orientation[4], angular_velocity[3], linear_acceleration[3] | IMU |
Odometry | ~700 B | pose (Pose2D), twist (Twist), covariance matrices | Wheel encoders |
JointState | ~900 B | names[16][32], positions[16], velocities[16], efforts[16] | Robot arms |
RangeSensor | 32 B | range, min/max_range, field_of_view | Ultrasonic/IR |
BatteryState | 40 B | voltage, current, percentage, health, status | Battery monitor |
NavSatFix | 112 B | latitude, longitude, altitude, satellites | GPS |
MagneticField | 136 B | magnetic_field[3], covariance | Magnetometer |
Temperature | 56 B | temperature (Celsius), variance | Thermometer |
FluidPressure | 56 B | fluid_pressure (Pascals) | Barometer |
Illuminance | 56 B | illuminance (Lux) | Light sensor |
LaserScan
The most common sensor message. 360 range readings for a full-circle 2D LiDAR.
#include <horus/horus.hpp>
class LidarNode : public horus::Node {
public:
LidarNode() : Node("lidar") {
pub_ = advertise<horus::msg::LaserScan>("lidar.scan");
}
void tick() override {
auto scan = pub_->loan();
// Fill range data (meters, 0 = invalid)
for (int i = 0; i < 360; i++) {
scan->ranges[i] = read_range(i);
}
scan->angle_min = 0.0f; // start angle (radians)
scan->angle_max = 6.28318f; // end angle (2*pi)
scan->min_range = 0.12f; // sensor minimum (meters)
scan->max_range = 12.0f; // sensor maximum
scan->time_increment = 0.0f; // time between measurements
scan->scan_time = 0.1f; // full scan duration (seconds)
scan->timestamp_ns = 0;
pub_->publish(std::move(scan));
}
private:
horus::Publisher<horus::msg::LaserScan>* pub_;
float read_range(int angle) { return 2.0f; } // placeholder
};
Finding Minimum Range
auto scan = sub_->recv();
if (!scan) return;
float min_range = 999.0f;
int min_angle = 0;
for (int i = 0; i < 360; i++) {
float r = scan->get()->ranges[i];
if (r > 0.01f && r < min_range) {
min_range = r;
min_angle = i;
}
}
// min_angle is in degrees (0-359)
Imu
9-axis IMU: orientation quaternion + angular velocity + linear acceleration, each with 3x3 covariance.
horus::msg::Imu imu{};
imu.orientation[0] = 0.0; // qx
imu.orientation[1] = 0.0; // qy
imu.orientation[2] = 0.0; // qz
imu.orientation[3] = 1.0; // qw (identity)
imu.angular_velocity[2] = 0.01; // yaw rate (rad/s)
imu.linear_acceleration[2] = 9.81; // gravity (m/s^2)
imu.timestamp_ns = 0;
// Covariance: -1 in first element = "no data"
imu.orientation_covariance[0] = -1.0;
JointState
Up to 16 joints with names, positions, velocities, and efforts:
horus::msg::JointState js{};
js.joint_count = 6; // 6-DOF arm
// Set joint names (null-terminated, max 31 chars)
std::strncpy(reinterpret_cast<char*>(js.names[0]), "shoulder_pan", 31);
std::strncpy(reinterpret_cast<char*>(js.names[1]), "shoulder_lift", 31);
std::strncpy(reinterpret_cast<char*>(js.names[2]), "elbow", 31);
std::strncpy(reinterpret_cast<char*>(js.names[3]), "wrist_1", 31);
std::strncpy(reinterpret_cast<char*>(js.names[4]), "wrist_2", 31);
std::strncpy(reinterpret_cast<char*>(js.names[5]), "wrist_3", 31);
// Set positions (radians for revolute joints)
js.positions[0] = 0.0;
js.positions[1] = -1.57; // shoulder down
js.positions[2] = 1.57; // elbow bent
// velocities and efforts default to 0
See Also
- Control Messages — MotorCommand, ServoCommand, PidConfig
- Geometry Messages — Twist, Pose2D, Point3, Quaternion
- Publisher & Subscriber API — how to send/receive these types