Getting Started with HORUS

Welcome to HORUS - a high-performance framework for building distributed systems with sub-microsecond inter-process communication.

What is HORUS?

HORUS is a framework for building applications with multiple independent components that need to communicate efficiently. Each component handles one responsibility, and they communicate through ultra-low-latency shared memory.

Built in Rust

HORUS is written in Rust, which gives you:

  • Speed - Sub-microsecond communication latency (296ns-2.8µs)
  • Safety - Compile-time checks prevent common bugs
  • Clean APIs - Well-designed interfaces that leverage Rust's type system
  • Reliability - Production-ready from day one

Multi-Language Support

Don't know Rust? No problem! HORUS works with:

  • Python - Simple functional API, perfect for prototyping
  • C - Integrate existing hardware drivers
  • Rust - Full framework power for performance-critical code

Why Use HORUS?

1. Extremely Fast Communication

HORUS: Messages arrive in 366-1,580 nanoseconds Other frameworks: Messages take 40,000-100,000 nanoseconds

What this means: Your components can talk to each other 100-270x faster. This matters for:

  • Real-time control systems
  • High-frequency data processing
  • Responsive user interfaces
  • Multi-sensor fusion

2. Ergonomic APIs

HORUS provides clean, Rust-native APIs:

Manual Implementation:

use horus::prelude::*;

struct SensorNode {
    publisher: Hub<f32>,
}

impl SensorNode {
    fn new() -> HorusResult<Self> {
        Ok(Self {
            publisher: Hub::new("temperature")?,
        })
    }
}

impl Node for SensorNode {
    fn name(&self) -> &'static str { "SensorNode" }

    fn tick(&mut self, ctx: Option<&mut NodeInfo>) {
        let temp = 25.0; // Read from sensor
        self.publisher.send(temp, ctx).ok();
    }
}

Macro-Based Implementation (covered in node! Macro Guide):

node! {
    SensorNode {
        pub { temperature: f32 -> "temperature" }
        tick(ctx) {
            self.temperature.send(25.0, ctx).ok();
        }
    }
}

3. Built-in Developer Tools

HORUS includes everything you need:

# Create a new project
$ horus new my_project

# Run your application
$ horus run

# Monitor in real-time (separate terminal)
$ horus dashboard

The dashboard shows:

  • All running nodes
  • Message flow between components
  • Performance metrics
  • Real-time debugging

4. Works on Your Hardware

HORUS uses shared memory for communication, which means:

  • No network overhead - Everything runs on the same machine efficiently
  • Zero serialization cost - Data is shared directly, not copied
  • Predictable performance - No network jitter or packet loss

Perfect for:

  • Embedded systems
  • Robot controllers
  • Edge computing devices
  • Multi-core applications

Core Concepts

Nodes

A Node is just a component that does one thing. Examples:

  • Read data from a sensor
  • Process some information
  • Control a motor
  • Display data on screen

Nodes have a simple lifecycle:

  1. Init - Start up (optional)
  2. Tick - Do work repeatedly
  3. Shutdown - Clean up (optional)

Topics

A Topic is a named channel for sending messages. Think of it like a radio frequency - anyone can broadcast on it, anyone can listen.

// Node A sends on "temperature"
publisher.send(25.0, ctx);

// Node B receives from "temperature"
if let Some(temp) = subscriber.recv(ctx) {
    println!("Got temperature: {}", temp);
}

Hub

A Hub is how you create publishers and subscribers:

// Create a publisher
let publisher: Hub<f32> = Hub::new("temperature")?;

// Create a subscriber (same topic name)
let subscriber: Hub<f32> = Hub::new("temperature")?;

It's that simple! The Hub handles all the complexity of shared memory for you.

Scheduler

The Scheduler runs your nodes in order:

let mut scheduler = Scheduler::new();
scheduler.register(Box::new(SensorNode::new()?), 0, Some(true));
scheduler.register(Box::new(DisplayNode::new()?), 1, Some(true));
scheduler.tick_all()?; // Run forever

Numbers are priorities (0 = highest). Nodes with priority 0 run first, then priority 1, etc.

Using Pre-Built Nodes

HORUS includes a library of ready-to-use nodes. Just import and connect with topic names:

use horus::prelude::*;
use horus_library::{KeyboardInputNode, DifferentialDriveNode};

fn main() -> HorusResult<()> {
    let mut scheduler = Scheduler::new();

    // Create nodes - they auto-connect via topics
    let keyboard = KeyboardInputNode::new();
    let drive = DifferentialDriveNode::new();

    scheduler.register(Box::new(keyboard), 0, Some(true));
    scheduler.register(Box::new(drive), 1, Some(true));

    scheduler.tick_all()?;
    Ok(())
}

That's it! 7 lines for a keyboard-controlled robot. No configuration needed - nodes know their topics.

Available nodes: KeyboardInputNode, JoystickInputNode, CameraNode, LidarNode, ImuNode, DifferentialDriveNode, PidControllerNode, EmergencyStopNode, SafetyMonitorNode, and more!

Quick Example: Temperature Monitor

Or build custom nodes when needed:

use horus::prelude::*;
use std::time::Duration;

// Node that generates temperature readings
struct TemperatureSensor {
    publisher: Hub<f32>,
    reading: f32,
}

impl TemperatureSensor {
    fn new() -> HorusResult<Self> {
        Ok(Self {
            publisher: Hub::new("temperature")?,
            reading: 20.0,
        })
    }
}

impl Node for TemperatureSensor {
    fn name(&self) -> &'static str { "TemperatureSensor" }

    fn tick(&mut self, ctx: Option<&mut NodeInfo>) {
        // Simulate temperature changes
        self.reading += 0.1;
        self.publisher.send(self.reading, ctx).ok();
        std::thread::sleep(Duration::from_secs(1));
    }
}

// Node that displays temperature
struct TemperatureDisplay {
    subscriber: Hub<f32>,
}

impl TemperatureDisplay {
    fn new() -> HorusResult<Self> {
        Ok(Self {
            subscriber: Hub::new("temperature")?,
        })
    }
}

impl Node for TemperatureDisplay {
    fn name(&self) -> &'static str { "TemperatureDisplay" }

    fn tick(&mut self, ctx: Option<&mut NodeInfo>) {
        if let Some(temp) = self.subscriber.recv(ctx) {
            println!("Current temperature: {:.1}°C", temp);
        }
    }
}

// Main program
fn main() -> HorusResult<()> {
    let mut scheduler = Scheduler::new();

    // Register nodes (sensor has higher priority)
    scheduler.register(Box::new(TemperatureSensor::new()?), 0, Some(true));
    scheduler.register(Box::new(TemperatureDisplay::new()?), 1, Some(true));

    // Run forever (Ctrl+C to stop)
    scheduler.tick_all()?;
    Ok(())
}

Run it:

$ horus run temperature_monitor.rs
Current temperature: 20.1°C
Current temperature: 20.2°C
Current temperature: 20.3°C

What Makes HORUS Different?

vs Traditional Approaches

Traditional: Everything in one big program

  • Hard to test individual components
  • Changes break everything
  • Difficult to reuse code

HORUS: Independent nodes

  • Test each component separately
  • Change one node without affecting others
  • Reuse nodes in different projects

vs Message Queues (RabbitMQ, Kafka)

Message Queues: Network-based

  • 10-100ms latency
  • Complex setup and configuration
  • Designed for distributed systems over networks

HORUS: Shared memory-based

  • 296ns-2.8µs latency (sub-microsecond)
  • Minimal configuration required
  • Optimized for single-machine, multi-process communication

Learning Path

** Quick Start** (30 minutes)

  1. Installation - Install HORUS
  2. Quick Start - Build your first app
  3. CLI Reference - Learn the commands

Core Concepts (2 hours) 4. Nodes - Build components 5. Hub - Send and receive messages 6. Scheduler - Run your application

Practical Features (3 hours) 7. node! Macro - Eliminate boilerplate 8. Message Types - Work with data safely 9. Dashboard - Monitor and debug

Advanced (When you need it) 10. Multi-Language - Python and C 11. Performance - Optimize for speed 12. Examples - Real projects

When to Use HORUS

Great for:

  • Multi-component applications
  • Real-time data processing
  • Sensor data fusion
  • Control systems
  • Parallel processing pipelines
  • Distributed applications on one machine

Not ideal for:

  • Single-script programs (use plain Rust/Python instead)
  • Over-the-internet communication (use gRPC/HTTP instead)
  • Simple CRUD apps (use web frameworks instead)

Architecture Overview

─────────────────────────────────────────
         Your Application                 
─────────────────────────────────────────
  Node 1    Node 2    Node 3              
  [Sensor] [Process] [Display]            
                                       
     ────────────────                
                                        
     ────▼─────────▼────                
       Shared Memory                    
       (Topics)                         
     ───────────────────                
─────────────────────────────────────────
         HORUS Framework                  
  • Hub (Communication)                   
  • Scheduler (Execution)                 
  • Logging (Debugging)                   
─────────────────────────────────────────

Next Steps

Ready to build with HORUS?

  1. Install HORUS Get up and running in 5 minutes

  2. Quick Start Tutorial Build a working application

  3. See Examples Learn from real projects

Questions? Check out the CLI Reference or Architecture pages.

Let's build something amazing!