Quick Start: C++
If you prefer Rust, see the Rust Quick Start. For Python, see the Python Quick Start.
Prerequisites
- HORUS CLI installed (Installation Guide)
- CMake 3.20+ and GCC 12+ (or Clang 15+)
What You'll Build
A temperature monitoring system with two nodes communicating over shared memory:
- Sensor node — publishes temperature readings at 10 Hz
- Monitor node — subscribes, detects overheating, publishes alerts
Both nodes run in the same scheduler with deterministic ordering.
Step 1: Create the Project
horus new temp_monitor --lang cpp
cd temp_monitor
This creates:
temp_monitor/
├── horus.toml # Project config (single source of truth)
├── src/
│ └── main.cpp # Your code goes here
└── include/
Step 2: Write the Sensor Node
Replace src/main.cpp:
#include <horus/horus.hpp>
#include <cstdio>
#include <cmath>
using namespace horus::literals;
// Simulated temperature sensor
static float read_temperature() {
static int tick = 0;
return 22.0f + 5.0f * std::sin(tick++ * 0.1f); // oscillates 17-27°C
}
int main() {
// Create scheduler at 10 Hz
horus::Scheduler sched;
sched.tick_rate(10_hz);
sched.name("temp_monitor");
// Create pub/sub — both share the same SHM topic
horus::Publisher<horus::msg::CmdVel> sensor_pub("temp.reading");
horus::Subscriber<horus::msg::CmdVel> monitor_sub("temp.reading");
// Sensor node: reads temperature, publishes it
sched.add("sensor")
.order(0) // runs first
.tick([&] {
auto sample = sensor_pub.loan(); // zero-copy from SHM
sample->linear = read_temperature(); // store temp in linear field
sample->timestamp_ns = 0;
sensor_pub.publish(std::move(sample));
})
.build();
// Monitor node: reads temperature, checks threshold
sched.add("monitor")
.order(10) // runs after sensor
.tick([&] {
auto msg = monitor_sub.recv();
if (!msg) return;
float temp = msg->get()->linear;
if (temp > 25.0f) {
std::printf("[ALERT] Temperature %.1f°C exceeds threshold!\n", temp);
} else {
std::printf("[OK] Temperature %.1f°C\n", temp);
}
})
.build();
std::printf("Starting temperature monitor (Ctrl+C to stop)...\n");
sched.spin(); // blocks until stopped
}
Step 3: Build and Run
horus build
horus run
Output:
Starting temperature monitor (Ctrl+C to stop)...
[OK] Temperature 22.0°C
[OK] Temperature 22.5°C
[OK] Temperature 23.5°C
[OK] Temperature 24.8°C
[ALERT] Temperature 25.9°C exceeds threshold!
[ALERT] Temperature 26.7°C exceeds threshold!
[ALERT] Temperature 26.9°C exceeds threshold!
...
Step 4: Monitor with CLI
In a second terminal:
horus topic list # see active topics
horus topic echo temp.reading # watch raw messages
horus node list # see running nodes
What Just Happened?
- Zero-copy IPC —
sensor_pub.loan()returns a pointer directly into shared memory. The monitor reads from the same memory. No serialization, no copying. - Deterministic ordering —
order(0)guarantees sensor runs beforeorder(10)monitor, every tick. - Single scheduler — both nodes share one tick loop. No threads, no race conditions.
Next Steps
- Getting Started with C++ — full API overview with all message types
- C++ API Reference — complete class/method reference
- Migrating from ROS2 C++ — side-by-side comparison
- Multi-Language Guide — mix C++, Rust, and Python in one system
- Tutorials — LiDAR robot, motor controllers, sensor fusion