Jul 11, 2026 · ros2 · python · getting-started
I rewrote my ROS 2 node in 8 lines of Python
A ROS 2 publisher/subscriber is a class, an __init__, a spin loop, and a launch file. The same robot in HORUS is eight lines — and the messages never serialize.
If you have written a ROS 2 node in Python, you know the shape of it: subclass Node,
call super().__init__('name'), create a publisher, create a subscriber with a callback,
then hand yourself to rclpy.spin. Then a second file — the launch file — to actually run it.
Here is the same sensor→controller robot in HORUS, in Python, in full:
import horus
def sensor_tick(node):
node.send("sensor.data", {"position": sensor_tick.pos, "velocity": 0.5})
sensor_tick.pos += 0.01
sensor_tick.pos = 0.0
def controller_tick(node):
s = node.recv("sensor.data")
if s is not None:
node.send("motor.cmd", {"voltage": (1.0 - s["position"]) * 0.5})
horus.run(
horus.Node(name="sensor", pubs=["sensor.data"], tick=sensor_tick, rate=1000),
horus.Node(name="ctrl", subs=["sensor.data"], pubs=["motor.cmd"], tick=controller_tick, rate=1000),
)No class boilerplate. No separate launch file. No colcon build. horus.run(...) is the
launch file. And both nodes tick at 1 kHz — set by rate=1000, not by a wall-clock sleep
you tuned by hand.
The part that isn't just less typing
The interesting difference is underneath. In ROS 2, sensor.data crosses the process
boundary through DDS — it gets serialized, shipped, and deserialized every message. The nearest
published figure for the default DDS stack is REP 2014's ~5 µs for a small message, and larger
payloads and stricter QoS only go up from there. In HORUS, that Python detector and the
controller share the same shared-memory ring buffer, enabling zero-copy messaging across languages and processes. The message is the type's memory layout; there is no serialization step at all. The same topic that costs microseconds in ROS 2
moves in nanoseconds here.
That is also why the Python node and a C++ controller can subscribe to the same topic with zero glue: all three languages agree on the wire format because the wire format is just the bytes. This brevity isn’t just syntax sugar — it reflects a fundamentally simpler runtime model built around deterministic scheduling and shared memory. Learn more about what zero-copy messaging means for robotics.
When this matters (and when it doesn't)
If you are prototyping and your loop runs at 10 Hz, ROS 2's overhead is invisible and its ecosystem is enormous — use it. HORUS earns its keep when the timing is real: a 1 kHz motor loop, a camera→inference→actuation pipeline you want in one process, or a controller that must not miss its deadline. There, a messaging layer measured in nanoseconds rather than microseconds — and, more to the point, one whose worst case you can bound — stops being a benchmark curiosity and starts being the difference between a robot that holds its control loop and one that doesn't.
HORUS achieves 171 ns end-to-end cross-process latency, as measured on an i9-14900K using cargo run --release -p horus_benchmarks --bin all_paths_latency. In direct comparison with iceoryx2 under the same conditions, HORUS is 2.1× faster in cross-process scenarios — a result you can reproduce with cargo run --release --bin iceoryx2_comparison --features iceoryx2. These numbers aren't extrapolated or estimated — they're measured, reproducible, and rooted in real IPC performance.
For teams building AI-driven robots, HORUS enables seamless integration of machine learning models directly into real-time control loops, eliminating serialization bottlenecks between inference and actuation. Explore how in our guide to the best robotics frameworks for AI and LLM developers in 2026. If your robot runs an onboard AI model, see why shared-memory messaging is critical in the best middleware for robots that run an AI model on-board.
The benchmarks are open so you can validate them yourself — no hidden setup, no synthetic filters. If you're building systems where determinism and speed are non-negotiable, that transparency matters.
If you're coming from ROS 2, the migration guide maps every concept — Node, Topic, Service, Action, tf2, QoS — to its HORUS equivalent.
For teams transitioning from web development, HORUS offers a familiar, function-first programming model with minimal runtime configuration, making it easier to move into robotics without learning complex build systems or distributed messaging layers. See how it compares in our guide to the best robotics middleware for teams coming from web development.
The whole thing is open-source and Apache-2.0. If the 8-line version made you curious, the code above is a real example in the repo.