### horus install examples Source: https://docs.horusrobotics.dev/package-management/package-management Examples of installing packages from the HORUS registry and from crates.io (auto-detected). Shows version pinning with @version and default latest. ```bash # From HORUS registry horus install pid-controller horus install motion-planner@2.0.1 # From crates.io (auto-detected) horus install serde horus install tokio@1.35.0 horus install clap ``` -------------------------------- ### Install hardware drivers with horus install Source: https://docs.horusrobotics.dev/development/cli-reference Example commands for installing hardware drivers by package name. ```bash horus install realsense-driver horus install rplidar-driver ``` -------------------------------- ### Quick start: apply RtConfig and create Topic Source: https://docs.horusrobotics.dev/advanced/rt-config Quick start example that builds an RtConfig with the same settings as the previous snippet and applies it with the ? operator. After applying, it creates a Topic for the cmd_vel channel, assuming RT guarantees are active. ```rust use horus::prelude::*; // Apply hard real-time configuration let config = RtConfig::builder() .memory_locked(true) .scheduler(RtScheduler::Fifo) .priority(80) .cpu_affinity(&[2, 3]) // Pin to cores 2, 3 .build(); config.apply()?; // Now all HORUS operations run with RT guarantees let link: Topic = Topic::new("cmd_vel")?; // see Performance Impact below ``` -------------------------------- ### init() Setup: Hardware, Buffers, State Source: https://docs.horusrobotics.dev/concepts/core-concepts-nodes Shows what to include in the init() method, which runs once when the node starts. Use it to set up hardware connections, pre-allocate buffers, initialize hardware state, and set initial values before tick() begins. The example opens a serial port, allocates a command buffer, sends an init sequence, and sets initial state. ```rust fn init(&mut self) -> Result<()> { hlog!(info, "Initializing MyMotorNode"); // 1. Open hardware connections self.serial_port = serialport::new("/dev/ttyUSB0", 115200) .open() .map_err(|e| Error::node("MyMotorNode", format!("Failed to open serial: {}", e)))?; // 2. Pre-allocate buffers (avoid allocation in tick) self.command_buffer = vec![0u8; 256]; // 3. Initialize hardware state self.send_init_sequence()?; // 4. Set initial values self.velocity = 0.0; self.is_armed = false; hlog!(info, "MyMotorNode initialized successfully"); Ok(()) } ``` -------------------------------- ### Install components for autonomous robot Source: https://docs.horusrobotics.dev/package-management/using-prebuilt-nodes Installs the required packages for the autonomous robot example. Run these commands to set up the necessary drivers and components. ```bash horus install lidar-driver horus install obstacle-detector horus install path-planner horus install differential-drive horus install emergency-stop ``` -------------------------------- ### Full scheduler example Source: https://docs.horusrobotics.dev/cpp/api/duration Complete scheduler setup with three nodes at different rates and miss policies. Shows how to configure rate, budget, deadline, miss policy, core pinning, priority, order, and tick callback. ```cpp #include using namespace horus::literals; int main() { horus::Scheduler sched; sched.tick_rate(1000_hz); // Hard RT: motor control at 1 kHz, enters safe state on overrun sched.add("motor_ctrl") .rate(1000_hz) .budget(800_us) .deadline(950_us) .on_miss(horus::Miss::SafeMode) .pin_core(2) .priority(90) .order(0) .tick([&] { /* PID loop */ }) .build(); // Soft RT: state estimation at 200 Hz, skips on overrun sched.add("estimator") .rate(200_hz) .budget(4_ms) .deadline(4500_us) .on_miss(horus::Miss::Skip) .order(10) .tick([&] { /* EKF update */ }) .build(); // Best effort: logging at 10 Hz, warns on overrun sched.add("logger") .rate(10_hz) .budget(50_ms) .on_miss(horus::Miss::Warn) .order(100) .tick([&] { /* write logs */ }) .build(); sched.spin(); } ``` -------------------------------- ### Run application and start monitor Source: https://docs.horusrobotics.dev/troubleshooting Run the application in one terminal and start the monitor in another. If the monitor reports "The monitor plugin is not installed", install it with `horus install horus-monitor`. ```bash horus run ``` ```bash horus monitor ``` -------------------------------- ### Install common packages with horus install Source: https://docs.horusrobotics.dev/development/cli-reference Example commands for installing common packages, including version pinning with `@`. ```bash horus install kalman-filter horus install pid-controller@2.0.0 ``` -------------------------------- ### Install simulator and run with --sim Source: https://docs.horusrobotics.dev/getting-started/installation Installs the simulator plugin and runs with `--sim` to swap hardware entries marked `sim = true` for stub nodes. `--sim` auto-launches the simulator plugin (sim3d by default, or `[robot].simulator`); if the plugin is not installed, `horus run --sim` refuses to start. ```bash horus install horus-sim3d # one-time: the simulator plugin `--sim` launches horus run --sim # swaps every [hardware] entry marked `sim = true` # for a stub node ``` -------------------------------- ### Install and use a CLI plugin Source: https://docs.horusrobotics.dev/plugins Shows the basic workflow for installing a plugin, using it as a native command, and listing installed plugins. The commands are `horus install --plugin horus-sim3d`, `horus sim3d --robot kuka_iiwa`, and `horus list`. ```bash # Install a plugin horus install --plugin horus-sim3d # Use it as a native command horus sim3d --robot kuka_iiwa # List installed plugins horus list ``` -------------------------------- ### Install Horus with curl and check help Source: https://docs.horusrobotics.dev/getting-started/installation Downloads and runs the official install script, then verifies installation by displaying the help command. If help output appears, installation is complete. ```bash curl -fsSL https://github.com/softmata/horus/raw/main/install.sh | bash horus --help ``` -------------------------------- ### horus new Rust with macro example Source: https://docs.horusrobotics.dev/development/cli-reference Example of starting a new Rust project with the `node!` macro, changing into the project directory, and running it with `horus run`. ```bash horus new temperature_monitor --macro cd temperature_monitor horus run ``` -------------------------------- ### Start sim3d visual simulator Source: https://docs.horusrobotics.dev/examples Start the sim3d simulator in visual mode with a robot and world file. Optional for examples that publish and subscribe without it. ```bash sim3d --mode visual --robot robots/.urdf --world worlds/.yaml ``` -------------------------------- ### Full robot setup with transforms, params, and scheduler Source: https://docs.horusrobotics.dev/tutorials/03-full-robot-python Sets up coordinate frames, runtime parameters, and a scheduler with nodes in execution order. The scheduler runs at 200 Hz and nodes are added with implicit order values. The example prints the node count and names before running. ```python # ── Main ──────────────────────────────────────────────────────────────── # Coordinate transforms: lidar sits 20 cm forward and 30 cm up on the base. tf = horus.TransformFrame() tf.register_frame("world") tf.register_frame("base_link", parent="world") tf.register_frame("lidar", parent="base_link") tf.update_transform("lidar", horus.Transform(translation=[0.2, 0.0, 0.3])) # Runtime parameters, tunable while the robot runs. params = horus.Params() params["max_speed"] = 0.3 params["safe_distance"] = 0.5 sched = horus.Scheduler(tick_rate=200, name="full_robot") # Add nodes in execution order. sched.add(ImuDriver()) # 200 Hz, order 0 sched.add(LidarDriver()) # 10 Hz, order 1 sched.add(SafetyMonitor()) # 50 Hz, order 2 — critical sched.add(Controller(params)) # 100 Hz, order 10 sched.add(MotorDriver()) # 100 Hz, order 20 sched.add(Telemetry()) # 1 Hz, order 100 print(f"Robot ready: {sched.get_node_count()} nodes") for n in sched.get_node_names(): print(f" - {n}") sched.run() ``` -------------------------------- ### Search and install a plugin Source: https://docs.horusrobotics.dev/development/cli-reference Searches for a plugin and installs it from the registry. ```bash horus search visualizer horus install horus-visualizer ``` -------------------------------- ### Generic topic import (Python) Source: https://docs.horusrobotics.dev/concepts/multi-language Starts the generic topic example by importing the Topic class. The full example is not shown on the page. ```python from horus import Topic ``` -------------------------------- ### Usage example: node definition and scheduler setup Source: https://docs.horusrobotics.dev/rust/api/macros Shows how to define a node, register it with `Scheduler`, set tick rate via `.rate()`, and run. A `rate` section inside `node!` is a compile error; rate is set on the builder. ```rust use horus::prelude::*; node! { MyNode { pub { output: f32 -> "data" } tick { self.output.send(42.0); } } } fn main() -> Result<()> { let mut scheduler = Scheduler::new(); scheduler.add(MyNode::new()).order(0).rate(100_u64.hz()).done(); scheduler.run() } ``` -------------------------------- ### First time setup: horus auth login Source: https://docs.horusrobotics.dev/development/cli-reference Logs in with GitHub via browser. Use this for first-time setup. ```bash horus auth login # Opens browser for GitHub login ``` -------------------------------- ### horus install target examples Source: https://docs.horusrobotics.dev/package-management/environment-management Shows how the -t/--target flag changes where horus install places packages: global cache by default, or a specific workspace. ```bash # No target: installs into the global cache ~/.cache/horus/ horus install serde # With a target: installs into that workspace's .horus/packages/ horus install serde -t my_robot_project ``` -------------------------------- ### version examples Source: https://docs.horusrobotics.dev/package-management/configuration Examples of semantic version strings for the version key. ```toml version = "0.1.0" # Initial development version = "1.0.0" # First stable release version = "2.3.1" # Mature project ``` -------------------------------- ### Install a plugin with horus install (auto-detection and --plugin) Source: https://docs.horusrobotics.dev/plugins/managing-plugins Shows how horus install auto-detects plugin packages and registers their commands. The first command installs horus-sim3d globally without needing --plugin. The second explicitly uses --plugin, but registration still depends on the package's own plugin metadata; otherwise you get "Package installed but no CLI plugin detected" and no command is registered. ```bash # Auto-detects as a plugin and installs globally horus install horus-sim3d # Take the plugin install path explicitly (registration still depends on the # package's own plugin metadata — without it you get "Package installed but no # CLI plugin detected" and no command is registered) horus install my-tool --plugin ``` -------------------------------- ### Example usage and run command Source: https://docs.horusrobotics.dev/package-management/package-management Example usage of the node in a demo program and the command to run it. ```rust // examples/demo.rs use my_package::MyControllerNode; use horus::prelude::*; fn main() { let mut scheduler = Scheduler::new(); let controller = MyControllerNode::new(2.5); scheduler.add(controller).order(5).done(); scheduler.run().expect("Scheduler failed"); } ``` ```bash horus run examples/demo.rs --release ``` -------------------------------- ### Install PID Controller via Registry Source: https://docs.horusrobotics.dev/package-management/using-prebuilt-nodes Before you can use a pre-built node, install it with the `horus install` command. Note: this requires a registry; if none is configured, use path or git dependencies in horus.toml. ```shell # Install from registry horus install pid-controller ``` -------------------------------- ### Run a Python example Source: https://docs.horusrobotics.dev/examples Run the python_robot example with `horus run main.py`. ```bash cd horus/examples/python_robot horus run main.py ``` -------------------------------- ### Expected output of temperature monitoring program Source: https://docs.horusrobotics.dev/getting-started/quick-start Example output showing the program starting and printing temperature readings. Press Ctrl+C to stop. Scheduler lines before the first reading are normal. ```text Starting temperature monitoring system... Temperature: 20.1°C Temperature: 20.2°C Temperature: 20.3°C Temperature: 20.4°C ... ``` -------------------------------- ### Clone and run a Rust example Source: https://docs.horusrobotics.dev/examples Clone the HORUS repository and run the differential_drive example with `horus run main.rs`. ```bash git clone https://github.com/softmata/horus.git cd horus/examples/differential_drive horus run main.rs ``` -------------------------------- ### Install HORUS from a clone Source: https://docs.horusrobotics.dev/getting-started/installation Clones the HORUS repository, navigates into it, and runs the install script to install a release tag. ```shell git clone https://github.com/softmata/horus.git cd horus ./install.sh ``` -------------------------------- ### Install HORUS from local source tree Source: https://docs.horusrobotics.dev/getting-started/installation Runs the installer with HORUS_LOCAL_SOURCE set to the current directory to install the checkout you're standing in. ```shell HORUS_LOCAL_SOURCE="$PWD" ./install.sh ``` -------------------------------- ### Install HORUS on macOS Source: https://docs.horusrobotics.dev/getting-started/installation Installs Xcode Command Line Tools (if needed), downloads and runs the HORUS install script, and verifies the installation with horus --help. Requires no Rust toolchain as prebuilt binaries are provided. ```bash # 1. Install Xcode Command Line Tools (if not already installed) — this is # where git comes from on a clean macOS xcode-select --install # 2. Install HORUS. Both Apple Silicon and Intel have a prebuilt binary, so # this needs no Rust toolchain. curl -fsSL https://github.com/softmata/horus/raw/main/install.sh | bash # 3. Verify installation horus --help ``` -------------------------------- ### Install a HORUS plugin: copy to global bin or horus install Source: https://docs.horusrobotics.dev/plugins/creating-plugins Two installation options for a HORUS plugin. Option A copies the built binary into the global plugin bin directory, renaming it to horus-mycommand so HORUS can find it. Option B installs from the registry once published; note that horus install has no local-path mode, so Option A is needed for testing unpublished builds. ```bash mkdir -p ~/.config/horus/bin cp target/release/mycommand ~/.config/horus/bin/horus-mycommand ``` ```bash horus install --plugin horus-mycommand ``` -------------------------------- ### name examples Source: https://docs.horusrobotics.dev/package-management/configuration Examples of valid project names for the name key. ```toml name = "temperature-monitor" name = "mobile_robot_controller" name = "warehouse-navigation" ``` -------------------------------- ### Install a package with horus install Source: https://docs.horusrobotics.dev/development/cli-reference Install a package by name. ```bash horus install pid-controller ``` -------------------------------- ### Read or install HORUS man page Source: https://docs.horusrobotics.dev/development/cli-reference Read the HORUS manual page without installing it, or install it for the current user. The first command pipes the generated man page to the man viewer. The second creates the man directory, writes the page, and opens it. The install.sh script already performs this installation; the command is intended for package maintainers and source builds. ```bash horus man | man -l - ``` ```bash mkdir -p ~/.local/share/man/man1 horus man > ~/.local/share/man/man1/horus.1 man horus ``` -------------------------------- ### Install the monitor plugin Source: https://docs.horusrobotics.dev/development/monitor Install the horus-monitor plugin and add its install directory to PATH. The plugin is not part of the core HORUS install; a global plugin install does not put the binary on PATH, so the export is required. ```shell # One-time: install the monitor plugin horus install horus-monitor # The install directory is not one horus monitor searches — add it to PATH export PATH="$HOME/.config/horus/bin:$PATH" ``` -------------------------------- ### README template for HORUS package Source: https://docs.horusrobotics.dev/package-management/package-management A complete README template for a HORUS package, including features, installation, usage, examples, and license. Use it as a starting point when documenting your own packages. ```markdown # PID Controller Production-ready PID controller for HORUS robotics framework. ## Features - Anti-windup protection - Derivative filtering - Output clamping ## Installation ```bash horus install pid-controller ``` ## Usage ```rust use pid_controller::PIDController; let mut pid = PIDController::new(1.0, 0.1, 0.01); let output = pid.update(error); ``` ## Examples See `examples/` directory for complete examples. ## License MIT ``` -------------------------------- ### Install a package, driver, or plugin with horus install Source: https://docs.horusrobotics.dev/development/cli-reference Shows the basic usage of the `horus install` command, including auto-detection of package, driver, or plugin, version pinning with `@`, and the `--plugin` flag. ```bash # Install a package (auto-detected) horus install pid-controller # Install with specific version horus install sensor-fusion@1.2.0 # Install a driver (drivers install by package name) horus install camera-driver # Install as a CLI plugin horus install horus-visualizer --plugin ``` -------------------------------- ### Create a new project from an example Source: https://docs.horusrobotics.dev/examples Use `horus new my_robot --from differential_drive` to copy an example and rename the package, then run it. ```bash horus new my_robot --from differential_drive cd my_robot horus run main.rs ``` -------------------------------- ### Install dependencies and output Source: https://docs.horusrobotics.dev/package-management/package-management Command to install dependencies and its output showing the resolved dependency tree. ```bash horus install robot-controller ``` ```text Resolving dependencies... robot-controller@1.0.0 ── motion-planner@2.0.1 ── pathfinding-utils@1.2.0 ── pid-controller@1.2.0 ── control-utils@1.0.0 Installing 5 packages... All dependencies installed ``` -------------------------------- ### Search and install Horus components Source: https://docs.horusrobotics.dev/package-management/using-prebuilt-nodes Search for available components and install the keyboard-input and differential-drive packages. ```bash horus search keyboard horus search motor # Install what you need horus install keyboard-input horus install differential-drive ``` -------------------------------- ### Manually copy an example directory Source: https://docs.horusrobotics.dev/examples Copy the example directory by hand, edit the manifest name, and run. Note that the manifest is the only file holding the package name. ```bash cp -r horus/examples/differential_drive my_robot cd my_robot # edit horus.toml: change `name = "differential_drive"` to `name = "my_robot"` horus run main.rs ``` -------------------------------- ### Install numpy from PyPI with output Source: https://docs.horusrobotics.dev/package-management/package-management Install a Python package from PyPI. Requires Python 3.x and pip in PATH. Output shows download and installation location. ```bash horus install numpy ``` ```text Installing numpy from PyPI... Downloading numpy-1.24.0... Installing to .horus/packages/numpy/ Package installed: numpy@1.24.0 Location: .horus/packages/numpy/ ``` -------------------------------- ### Install HORUS on Windows with PowerShell Source: https://docs.horusrobotics.dev/getting-started/installation Downloads and runs the Windows installer install.ps1 via PowerShell, then verifies with horus --help. The installer downloads horus-windows-amd64.zip, verifies checksums, clones source, installs horus.exe, and adds it to the user PATH. Requires git. ```powershell irm https://github.com/softmata/horus/raw/main/install.ps1 | iex horus --help ``` -------------------------------- ### Frequency::deadline_default() usage example Source: https://docs.horusrobotics.dev/cpp/api/duration Example of using deadline_default() to get the default deadline. ```cpp auto rate = 100_hz; auto deadline = rate.deadline_default(); // 9,500 us = 9.5 ms (95% of 10 ms) ``` -------------------------------- ### Install from cached HORUS tree Source: https://docs.horusrobotics.dev/python/api Install from the tree cached by the HORUS installer, using the same tag as your CLI. Substitute the version printed by horus --version. ```bash pip install ~/.horus/cache/horus@0.4.0/horus_py ``` -------------------------------- ### Frequency::period() usage example Source: https://docs.horusrobotics.dev/cpp/api/duration Example of using period() to get the period in microseconds. ```cpp auto rate = 100_hz; auto p = rate.period(); // 10,000 us = 10 ms ``` -------------------------------- ### Frequency::value() usage example Source: https://docs.horusrobotics.dev/cpp/api/duration Example of using value() to get the frequency in Hz. ```cpp auto rate = 100_hz; double hz = rate.value(); // 100.0 ``` -------------------------------- ### First-time HORUS project setup Source: https://docs.horusrobotics.dev/development/cli-reference First-time workflow: create a new project with the --macro flag, run it in release mode, and monitor it in a separate terminal. The --macro flag is required for macro support. ```bash # Create a project horus new my_first_app --macro cd my_first_app # Run it horus run --release # Monitor it (new terminal) horus monitor ``` -------------------------------- ### Frequency::budget_default() usage example Source: https://docs.horusrobotics.dev/cpp/api/duration Example of using budget_default() to get the default compute budget. ```cpp auto rate = 100_hz; auto budget = rate.budget_default(); // 8,000 us = 8 ms (80% of 10 ms) ``` -------------------------------- ### repository, categories, package-type examples Source: https://docs.horusrobotics.dev/package-management/configuration Examples of registry metadata keys. These are used as defaults by 'horus publish'. ```toml repository = "https://github.com/acme/warehouse-navigation" categories = ["navigation", "slam"] package-type = "node" ``` -------------------------------- ### Run HORUS and start the monitor Source: https://docs.horusrobotics.dev/development/monitor Start your HORUS application, then in another terminal start the monitor. The browser opens to http://localhost:3000 and asks for a password on first run. ```shell # Start your HORUS application horus run ``` ```shell # In another terminal, start the monitor horus monitor ``` -------------------------------- ### Install HORUS and create a project Source: https://docs.horusrobotics.dev/getting-started/installation Installs HORUS and creates a new project. A new project declares no [hardware], so a bare `horus run` does not touch any device. ```bash # 1. Install HORUS normally (no hardware packages needed) curl -fsSL https://github.com/softmata/horus/raw/main/install.sh | bash # 2. Create and run your project horus new my_robot cd my_robot horus run # Builds and runs your nodes. A new project declares no # [hardware], so nothing here touches a device. ``` -------------------------------- ### Get package info with horus info Source: https://docs.horusrobotics.dev/development/cli-reference Get details about one package: version, description, owner and dependency information, whether or not it is installed. ```bash horus info rplidar horus info rplidar --json ``` -------------------------------- ### Install exact HORUS version with curl and HORUS_VERSION Source: https://docs.horusrobotics.dev/troubleshooting Install the exact version this CLI came from by setting `HORUS_VERSION` to the version printed as **CLI version** in the warning. Use this when you want to match the CLI to the installed libraries. ```bash curl -fsSL https://github.com/softmata/horus/raw/main/install.sh | HORUS_VERSION=v0.4.1 bash ``` -------------------------------- ### Create the full_robot project with horus new Source: https://docs.horusrobotics.dev/tutorials/03-full-robot-rust Initializes a new Horus project and moves into its directory. ```bash horus new full_robot cd full_robot ``` -------------------------------- ### Install Rust with rustup Source: https://docs.horusrobotics.dev/getting-started/installation Downloads and installs Rust using rustup on Linux, WSL, or Docker. ```shell curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### Complete horus publish example Source: https://docs.horusrobotics.dev/package-management/package-management Complete example of publishing a package with `horus publish`, including the interactive prompts for documentation and source repository, and the final output. ```text $ cd my-sensor-package $ horus publish Detected horus.toml manifest Publishing my-sensor-package v1.0.0... Package Metadata (optional) Help users discover and use your package by adding: Documentation Found local /docs folder with markdown files Add documentation? (y/n): y Documentation options: 1. External URL - Link to online documentation 2. Local /docs - Bundle markdown files in a /docs folder [i] Your /docs folder should contain .md files organized as: /docs/README.md (main documentation) /docs/getting-started.md (guides) /docs/api.md (API reference) Choose option (1/2/skip): 2 Will bundle local /docs folder with package Source Repository Auto-detected: https://github.com/robotics-lab/my-sensor-package Add source repository? (y/n): y Use detected URL? (y/n): y Source repository: https://github.com/robotics-lab/my-sensor-package Uploaded to registry Published: my-sensor-package@1.0.0 View at: https://registry.example.com/packages/my-sensor-package ``` -------------------------------- ### Use installed package in Rust code Source: https://docs.horusrobotics.dev/concepts/goals Shows how to use an installed HORUS package in Rust code. The example adds a CartographerNode to the scheduler with order 2. ```rust use slam_cartographer::CartographerNode; scheduler.add(CartographerNode::new()?).order(2).done(); ``` -------------------------------- ### Install sensor fusion components Source: https://docs.horusrobotics.dev/package-management/using-prebuilt-nodes Install the lidar driver, IMU driver, and Kalman filter packages for sensor fusion. ```bash horus install lidar-driver horus install imu-driver horus install kalman-filter ``` -------------------------------- ### horus init existing code example Source: https://docs.horusrobotics.dev/development/cli-reference Example of initializing existing code as a HORUS project. After changing to the project directory, `horus init` creates `horus.toml` with the project configuration. ```bash cd ~/my-robot-code horus init # Creates horus.toml with project configuration ``` -------------------------------- ### Complete example: Nodes, scheduler, and statistics in Python Source: https://docs.horusrobotics.dev/python/api/python-bindings Sets up three nodes for sensor reading, control, and logging at different rates with order ranking. Schedules them on a node for a 5-second run. It creates a node and checks its total ticks. ```python import horus def sensor_tick(node): """High-frequency sensor (100Hz)""" # The publisher stamps the message — nothing stamps it for you imu = {"accel_x": 1.0, "accel_y": 0.0, "accel_z": 9.8, "timestamp_ns": horus.timestamp_ns()} node.send("imu_data", imu) node.log_info("Published IMU") def control_tick(node): """Medium-frequency control (50Hz)""" if node.has_msg("imu_data"): imu = node.recv("imu_data") # Check for stale data age = (horus.timestamp_ns() - imu["timestamp_ns"]) / 1e9 if age > 0.05: node.log_warning("Stale IMU data!") return cmd = {"linear": 1.0, "angular": 0.0, "timestamp_ns": horus.timestamp_ns()} node.send("cmd_vel", cmd) def logger_tick(node): """Low-frequency logging (10Hz)""" if node.has_msg("cmd_vel"): msg = node.recv("cmd_vel") latency = (horus.timestamp_ns() - msg["timestamp_ns"]) / 1e6 node.log_info(f"Command latency: {latency:.1f}ms") # Create nodes — rate and execution order live on the constructor sensor = horus.Node(name="imu", pubs="imu_data", tick=sensor_tick, order=0, rate=100) controller = horus.Node(name="ctrl", subs="imu_data", pubs="cmd_vel", tick=control_tick, order=1, rate=50) logger = horus.Node(name="log", subs="cmd_vel", tick=logger_tick, order=2, rate=10) # add() takes the node and nothing else, and returns the scheduler so calls chain scheduler = horus.Scheduler() scheduler.add(sensor).add(controller).add(logger) scheduler.run(duration=5.0) # Check statistics stats = scheduler.get_node_stats("imu") print(f"Sensor: {stats['total_ticks']} ticks in 5 seconds") ``` -------------------------------- ### Create a Horus library project with horus new --lib Source: https://docs.horusrobotics.dev/package-management/package-management Use to create a new Horus library project, configure it as a lib in horus.toml, implement modules in src/lib.rs, add an example, test it with horus run, and publish with horus auth login and horus publish. ```bash # 1. Create new project as library horus new my-sensor-lib --rust --lib # 2. Update horus.toml # [package] # name = "my-sensor-lib" # version = "0.1.0" # type = "lib" # 3. Implement in src/lib.rs # pub mod drivers; # pub mod calibration; # 4. Add examples mkdir examples # Create examples/demo.rs # 5. Test horus run examples/demo.rs # 6. Publish horus auth login horus publish ``` -------------------------------- ### Using an installed package in Rust Source: https://docs.horusrobotics.dev/package-management/package-management Example of using an installed package (pid-controller) in a Rust application. It imports the PIDNode and horus prelude, creates a scheduler, adds the PID node, and runs it. ```rust // In your main.rs or any file use pid_controller::PIDNode; use horus::prelude::*; fn main() { let mut scheduler = Scheduler::new(); // Use the installed package let pid = PIDNode::new(1.0, 0.1, 0.01); scheduler.add(pid).order(5).done(); scheduler.run().expect("Scheduler failed"); } ``` -------------------------------- ### Lifecycle Management Source: https://docs.horusrobotics.dev/python/api/python-bindings Shows how to use the init and shutdown handlers for resource initialization and cleanup. The example opens a file during init, writes each tick, and closes it during shutdown. ```python import horus class Context: def __init__(self): self.count = 0 self.file = None ctx = Context() def init_handler(node): print("Starting up!") ctx.file = open("data.txt", "w") def tick_handler(node): ctx.count += 1 data = f"Tick {ctx.count}" node.send("data", data) ctx.file.write(data + "\n") def shutdown_handler(node): print(f"Processed {ctx.count} messages") ctx.file.close() node = horus.Node( pubs="data", init=init_handler, tick=tick_handler, shutdown=shutdown_handler, rate=10 ) horus.run(node, duration=5) ``` -------------------------------- ### horus doctor -v: missing tool output Source: https://docs.horusrobotics.dev/development/cli-reference Example line from `horus doctor -v` showing a missing tool and its install command. `-v` lists every tool, its version, and the command that installs missing ones. ```text a C++ compiler: not found (g++, clang++ or MSVC — cmake picks one) - install: sudo apt install build-essential ``` -------------------------------- ### Recording session directory structure Source: https://docs.horusrobotics.dev/development/testing Example directory structure of a recording session. Each node gets its own recording file, and the scheduler execution order is stored separately. ```text ~/.local/share/horus/recordings/my_session/ ├── sensor_node@abc123.horus # Node recording ├── control_node@def456.horus # Node recording └── scheduler@main789.horus # Scheduler execution order ``` -------------------------------- ### Version mismatch error output Source: https://docs.horusrobotics.dev/development/cli-reference Example error message that can occur when the horus CLI version is out of sync with the installed horus_core. Using --clean fixes this mismatch. ```text error: the package `horus` depends on `horus_core 0.1.0`, but `horus_core 0.1.3` is installed ``` -------------------------------- ### Using has() to check for a parameter before reading Source: https://docs.horusrobotics.dev/cpp/api/params Example of using has() to check for a key before reading it with a default value. The get call supplies a fallback of 100.0 if the key is absent. ```cpp if (params.has("safety.max_force")) { double limit = params.get("safety.max_force", 100.0); // apply force limit... } ``` -------------------------------- ### Running multi-process HORUS with horus run and manual start Source: https://docs.horusrobotics.dev/tutorials/08-multi-process-rust Builds and runs the three binaries (lidar, controller, safety) with `horus run`, then shows how to start them manually in any order and monitor topics, nodes, and services. Rust binaries link HORUS statically, so no `LD_LIBRARY_PATH` is needed. ```bash # Build all three binaries in one cargo invocation and spawn one process each horus run nodes/lidar.rs nodes/controller.rs nodes/safety.rs # That run leaves the binaries behind, so you can also start them by hand # afterwards (order does not matter — start them in any order) .horus/target/debug/controller & .horus/target/debug/lidar & .horus/target/debug/safety & # Monitor from any terminal horus topic list # shows lidar.scan, cmd_vel, estop.request horus node list # shows lidar, controller, safety (separate PIDs) horus service list # shows estop ``` -------------------------------- ### Runtime parameters with horus::Params set/get Source: https://docs.horusrobotics.dev/cpp/hardware Shows how to set and get runtime parameters for hardware tuning without recompiling. The example sets lidar_rpm, motor_max_torque, and imu_calibration_offset, then retrieves motor_max_torque with a default of 1.0. ```cpp horus::Params params; params.set("lidar_rpm", int64_t(600)); params.set("motor_max_torque", 2.5); params.set("imu_calibration_offset", 0.02); // In driver tick: double max_torque = params.get("motor_max_torque", 1.0); ``` -------------------------------- ### Motor controller, simulated encoder, and commander nodes with scheduler setup Source: https://docs.horusrobotics.dev/tutorials/02-motor-controller-python Complete example for a motor controller system using the Horus framework. Includes MotorController, SimEncoder, and Commander nodes, plus scheduler setup with deterministic execution. Note that overriding tick() or init() replaces the base-class implementation that stores NodeInfo on self, so self.info must be assigned to use self.log_info() or self.log_error(). ```python # Clamp to the actuator limit and publish. self.motor.send( CmdVel(linear=clamp(lin_output, MAX_PWM), angular=clamp(ang_output, MAX_PWM)) ) # Publish state for monitoring every 10th tick → 10 Hz. self.ticks += 1 if self.ticks % 10 == 0: self.state.send(CmdVel(linear=actual_linear, angular=lin_error)) def enter_safe_state(self): self.send_zero() # Clear the integrators too: resuming with a wound-up integral would # kick the motors the moment the node recovers. self.lin_integral = 0.0 self.ang_integral = 0.0 self.log_error("Safe state - motors zeroed") # ── Simulated Encoder (for testing without hardware) ──────────────────── class SimEncoder(horus.Node): def __init__(self): super().__init__(name="sim_encoder", rate=100, order=0) self.pwm = Topic(CmdVel, endpoint="motor.pwm") self.encoder = Topic(CmdVel, endpoint="encoder.velocity") self.velocity = 0.0 def tick(self, info=None): while True: cmd = self.pwm.recv() if cmd is None: break # Simulate motor dynamics: velocity tracks PWM with lag. self.velocity = 0.9 * self.velocity + 0.1 * cmd.linear self.encoder.send(CmdVel(linear=self.velocity, angular=0.0)) # ── Simulated Command Source ──────────────────────────────────────────── class Commander(horus.Node): def __init__(self): super().__init__(name="commander", rate=100, order=5) self.cmd = Topic(CmdVel, endpoint="cmd_vel") self.ticks = 0 def tick(self, info=None): # Drive at 0.5 m/s for 3 s, then stop. linear = 0.5 if self.ticks < 300 else 0.0 self.ticks += 1 self.cmd.send(CmdVel(linear=linear, angular=0.0)) # ── Main ──────────────────────────────────────────────────────────────── # deterministic=True keeps every node on the main tick loop, sequential # sequence — without it, rate= makes all three RT nodes on separate threads. sched = horus.Scheduler(tick_rate=100, name="motor_ctrl", deterministic=True) sched.add(SimEncoder()) # order 0 — runs first, provides feedback sched.add(Commander()) # order 5 sched.add(MotorController()) # order 10 — reads command + encoder print("Motor controller running at 100 Hz (Ctrl+C to stop)") sched.run() ``` -------------------------------- ### Deploy on robot with system packages and --release Source: https://docs.horusrobotics.dev/getting-started/installation Installs system packages on the robot and runs against real hardware with `--release`. Use this for deployment on the robot. ```bash # 1. Install system packages on the robot sudo apt install libraspberrypi-dev i2c-tools can-utils # 2. Run against the real hardware horus run --release ``` -------------------------------- ### Portable project setup with git clone and horus run Source: https://docs.horusrobotics.dev/package-management/environment-management Shows how a team member clones a project and runs it with horus run, which auto-installs dependencies. This demonstrates the portability of horus.toml across machines. ```bash # Team member clones your project git clone your-repo cd your-repo horus run # Auto-installs dependencies and runs ``` -------------------------------- ### Complete example: custom messages with dict topics Source: https://docs.horusrobotics.dev/python/api/custom-messages Complete example showing custom messages with dict topics. Creates a sensor node that publishes a dict to 'my.sensor' and a processor node that receives it, printing the reading. Runs both nodes for 3 seconds. ```python #!/usr/bin/env python3 """Custom message example with dict topics.""" import horus def sensor_tick(node): """Publish sensor readings.""" node.send("my.sensor", { "distance": 2.5, "angle": 0.785, "confidence": 0.95, "object_id": 42, }) def processor_tick(node): """Process sensor readings.""" if node.has_msg("my.sensor"): reading = node.recv("my.sensor") # -> dict print(f"Object {reading['object_id']}: {reading['distance']}m at {reading['angle']}rad") # Create nodes sensor = horus.Node("sensor", pubs="my.sensor", tick=sensor_tick, rate=10) processor = horus.Node("processor", subs="my.sensor", tick=processor_tick) # Run horus.run(sensor, processor, duration=3) ``` -------------------------------- ### horus new options Source: https://docs.horusrobotics.dev/development/cli-reference Options for `horus new`. Includes flags for language selection, starting from an example, workspace creation, library crate, output path, and accepting defaults. Note that `-r`, `-p`, and `-c` are deprecated and will stop being accepted in HORUS 0.4.0. ```bash horus new [OPTIONS] Options: -m, --macro Rust with node! macro (less boilerplate) --rust Plain Rust project --python Python project --cpp C++ project --from Start from a shipped example instead of the blank template (e.g. --from differential_drive); the language comes from the example, so the language flags do not apply -w, --workspace Create as a workspace with multiple crates -l, --lib Create as a library crate (instead of binary) -o, --output Where to create it (default: current directory) -y, --yes Accept defaults without prompting ``` -------------------------------- ### Documentation coverage example Source: https://docs.horusrobotics.dev/package-management/using-prebuilt-nodes Example output showing documentation coverage percentage. Use this to evaluate the quality of a package's documentation. ```text Documentation: 98% coverage ``` -------------------------------- ### Run obstacle_detector.rs with horus run Source: https://docs.horusrobotics.dev/rust/examples/basic-examples Runs the obstacle detector example. The command executes the Rust file with the Horus runtime, starting the scheduler and both nodes. The output will show the lidar simulation and obstacle detection logs, including warnings when an obstacle is within the safety distance. ```rust use horus::prelude::*; // Lidar -> Scan data struct LidarNode { scan_pub: Topic, angle: f32, } impl LidarNode { fn new() -> Result { Ok(Self { scan_pub: Topic::new("scan")?, angle: 0.0, }) } } impl Node for LidarNode { fn name(&self) -> &str { "LidarNode" } fn init(&mut self) -> Result<()> { hlog!(info, "Lidar initialized"); Ok(()) } fn tick(&mut self) { let mut scan = LaserScan::new(); // Simulate lidar readings (sine wave for demo) for i in 0..360 { scan.ranges[i] = 5.0 + (self.angle + i as f32 * 0.01).sin() * 2.0; } // Add one close obstacle in front scan.ranges[0] = 0.3; // 30cm directly ahead! self.scan_pub.send(scan); self.angle += 0.1; } fn shutdown(&mut self) -> Result<()> { hlog!(info, "Lidar offline"); Ok(()) } } // Scan data -> Obstacle detection -> Stop command struct ObstacleDetector { scan_sub: Topic, cmd_pub: Topic, safety_distance: f32, } impl ObstacleDetector { fn new(safety_distance: f32) -> Result { Ok(Self { scan_sub: Topic::new("scan")?, cmd_pub: Topic::new("cmd_vel")?, safety_distance, }) } } impl Node for ObstacleDetector { fn name(&self) -> &str { "ObstacleDetector" } fn init(&mut self) -> Result<()> { hlog!(info, "Obstacle detector active - safety distance: {:.2}m", self.safety_distance); Ok(()) } fn tick(&mut self) { if let Some(scan) = self.scan_sub.recv() { // Find minimum distance if let Some(min_dist) = scan.min_range() { if min_dist < self.safety_distance { // Emergency stop! let stop = CmdVel::zero(); self.cmd_pub.send(stop); hlog!(warn, "[WARNING] Obstacle detected at {:.2}m - STOPPING!", min_dist); } else { // Safe to move hlog!(debug, "Safe - closest obstacle: {:.2}m", min_dist); } } } } fn shutdown(&mut self) -> Result<()> { hlog!(info, "Obstacle detector offline"); Ok(()) } } fn main() -> Result<()> { let mut scheduler = Scheduler::new(); scheduler.add(LidarNode::new()?).order(0).build()?; // Obstacle detector ticks right after the lidar, in the critical band (order 1) scheduler.add(ObstacleDetector::new(0.5)?).order(1).build()?; scheduler.run()?; Ok(()) } ``` ```bash horus run obstacle_detector.rs ``` -------------------------------- ### Full robot system main.rs (complete) Source: https://docs.horusrobotics.dev/tutorials/03-full-robot-rust Sets up the full six-node pipeline, schedules nodes at their respective rates, and starts the Horus runtime. ```rust fn main() -> Result<()> { let mut app = App::new("full_robot")?; let params = app.runtime_params(); app.add_node("lidar", LidarDriver::new()?)?; app.add_node("imu", ImuDriver::new()?)?; app.add_node("controller", Controller::new(params.clone())?)?; app.add_node("safety", SafetyNode::new(params.clone())?)?; app.add_node("telemetry", TelemetryNode::new()?)?; app.add_schedule( "drivers", [200, 200, 100, 100, 50, 1], ["lidar", "imu", "controller", "safety", "telemetry", "telemetry"], )?; app.start(); Ok(()) } struct SafetyNode { estop: Topic, cmd: Topic, params: RuntimeParams, } impl SafetyNode { fn new(params: RuntimeParams) -> Result { Ok(Self { estop: Topic::new("estop")?, cmd: Topic::new("cmd_vel")?, params, }) } } impl Node for SafetyNode { fn name(&self) -> &str { "safety" } fn tick(&mut self) { if let Ok(estop) = self.estop.try_recv() { ESTOP_ACTIVE.store(estop, Ordering::Relaxed); if estop { self.cmd.send(CmdVel::new(0.0, 0.0)); } } let max_speed = self.params.get_or("max_speed", 0.3_f64); if ESTOP_ACTIVE.load(Ordering::Relaxed) && self.params.get_or("safety_enabled", false) { self.cmd.send(CmdVel::new(0.0, 0.0)); } } } struct TelemetryNode { cmd: Topic, imu: Topic, } impl TelemetryNode { fn new() -> Result { Ok(Self { cmd: Topic::new("cmd_vel")?, imu: Topic::new("imu.data")?, }) } } impl Node for TelemetryNode { fn name(&self) -> &str { "telemetry" } fn tick(&mut self) { // This is where telemetry would be logged or streamed. } } ```