Choosing a Language
HORUS supports both Rust and Python. This guide helps you choose the right one for your project.
Quick Decision
Use Python if:
- You're prototyping or experimenting
- You're new to robotics programming
- You want to integrate with ML/AI libraries (TensorFlow, PyTorch)
- Development speed matters more than runtime performance
Use Rust if:
- You need maximum performance
- You're building production systems
- You want compile-time safety guarantees
- You're comfortable with Rust (or want to learn)
Side-by-Side Comparison
Hello World: Temperature Sensor
Python:
from horus import Node, Topic, Scheduler
class TempSensor(Node):
def __init__(self):
super().__init__("TempSensor")
def init(self):
self.pub_topic = Topic("temperature")
def tick(self):
temp = 25.0 # Read sensor
self.pub_topic.send(temp)
scheduler = Scheduler()
scheduler.node(TempSensor()).order(5).build()
scheduler.run()
Rust:
use horus::prelude::*;
struct TempSensor {
pub_topic: Topic<f32>,
}
impl TempSensor {
fn new() -> Result<Self> {
Ok(Self { pub_topic: Topic::new("temperature")? })
}
}
impl Node for TempSensor {
fn name(&self) -> &str { "TempSensor" }
fn tick(&mut self) {
let temp = 25.0; // Read sensor
self.pub_topic.send(temp);
}
}
fn main() -> Result<()> {
let mut scheduler = Scheduler::new();
scheduler.add(TempSensor::new()?).order(5).build()?;
scheduler.run()
}
Or with the Rust node! macro:
use horus::prelude::*;
node! {
TempSensor {
pub { temperature: f32 -> "temperature" }
tick {
let temp = 25.0;
self.temperature.send(temp);
}
}
}
fn main() -> Result<()> {
let mut scheduler = Scheduler::new();
scheduler.add(TempSensor::new()).order(5).build()?;
scheduler.run()
}
Detailed Comparison
| Aspect | Python | Rust |
|---|---|---|
| Learning curve | Easy | Steeper |
| Setup time | 5 minutes | 10 minutes |
| Compile time | None | A few seconds |
| Runtime performance | Good | Excellent |
| Memory safety | Runtime checks | Compile-time guarantees |
| ML/AI integration | Excellent (numpy, torch, etc.) | Limited |
| Debugging | Simple print debugging | More tooling needed |
| Production readiness | Good for prototypes | Production-grade |
Performance Comparison
| Operation | Python | Rust | Difference |
|---|---|---|---|
| Node tick latency | ~10μs | ~1μs | 10x faster |
| Message send | ~2μs | ~400ns | 5x faster |
| Control loop (1kHz) | Achievable | Easy | - |
| Control loop (10kHz) | Difficult | Achievable | - |
Bottom line: For most robotics applications, both are fast enough. Rust matters when you need:
- Very high-frequency control (>1kHz)
- Hard real-time guarantees
- Minimal memory footprint
When to Choose Python
Rapid Prototyping
# Quick experiment - try different approaches fast
from horus import Node, Topic, Scheduler
class ExperimentalController(Node):
def __init__(self):
super().__init__("ExperimentalController")
def init(self):
self.sensor_sub = Topic("sensor")
self.output_pub = Topic("output")
def tick(self):
input_val = self.sensor_sub.recv() or 0.0
strategy = "aggressive"
if strategy == "aggressive":
output = input_val * 2.0
else:
output = input_val * 0.5
self.output_pub.send(output)
Machine Learning Integration
import torch
from horus import Node, Topic, Scheduler
class MLController(Node):
def __init__(self):
super().__init__("MLController")
self.model = torch.load("my_model.pt")
def init(self):
self.sensor_sub = Topic("sensor_data")
self.output_pub = Topic("control_output")
def tick(self):
sensor_data = self.sensor_sub.recv()
if sensor_data is not None:
with torch.no_grad():
output = self.model(torch.tensor(sensor_data))
self.output_pub.send(output.item())
Education and Learning
Python's readable syntax makes it easier to understand robotics concepts without fighting the language.
When to Choose Rust
Production Deployments
// Rust catches bugs at compile time
impl Node for SafetyMonitor {
fn tick(&mut self) {
// Compiler ensures we handle all cases
match self.check_safety() {
SafetyStatus::OK => self.continue_operation(),
SafetyStatus::Warning(msg) => self.log_warning(&msg),
SafetyStatus::Critical(msg) => self.emergency_stop(&msg),
}
}
}
High-Frequency Control
// Rust can sustain 10kHz+ control loops
impl Node for MotorController {
fn tick(&mut self) {
// Microsecond-level timing is reliable
let error = self.target - self.position;
let output = self.pid.compute(error);
self.motor.send(output);
}
}
Resource-Constrained Environments
// Rust has minimal runtime overhead
// Perfect for embedded systems and single-board computers
Mixed Language Projects
You can use both languages in the same project! HORUS nodes communicate via shared memory, which works across languages.
Example: Python for AI, Rust for control
Python ML node:
from horus import Node, Topic, Scheduler
class ObjectDetector(Node):
def __init__(self):
super().__init__("ObjectDetector")
def init(self):
self.camera_sub = Topic("camera")
self.detection_pub = Topic("detections")
def tick(self):
camera_image = self.camera_sub.recv()
if camera_image is not None:
detections = model.detect(camera_image)
self.detection_pub.send(detections)
Rust control node:
impl Node for NavigationController {
fn tick(&mut self) {
if let Some(detections) = self.detection_sub.recv() {
// React to Python node's output
self.plan_path(&detections);
}
}
}
Recommendation by Use Case
| Use Case | Recommended Language |
|---|---|
| Learning HORUS | Python |
| University project | Python |
| Hobby robot | Either |
| Machine learning robot | Python + Rust |
| Industrial automation | Rust |
| Drone/UAV | Rust |
| Research prototype | Python |
| Competition robot | Rust |
| Product development | Rust |
Getting Started
Ready to start with Python?
- Python API Reference (uses Python)
- Python API Reference
Ready to start with Rust?
- Quick Start (uses Rust)
- node! Macro Guide
- Rust API Reference
Still Unsure?
Start with Python. It's faster to get something working, and you can always port critical parts to Rust later. HORUS makes it easy to mix languages.