Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HORUS Integration

Using kinetic with the HORUS robotics framework.

Overview

The horus-kinetic crate bridges kinetic’s motion planning stack with HORUS’s zero-copy shared-memory IPC. It provides three node types that can run as HORUS nodes or standalone with channel-based communication.

Node Architecture

                        HORUS IPC (shared memory topics)
                        ================================
                              |           |          |
plan_request -->  [PlannerNode]  --> trajectory
twist_cmd    -->  [ServoNode]    --> joint_cmd
pointcloud   -->  [SceneNode]    --> scene_update

PlannerNode

Receives planning requests, computes collision-free paths, publishes timed trajectories.

#![allow(unused)]
fn main() {
use horus_kinetic::PlannerNode;

let mut planner = PlannerNode::new("ur5e")?;
// With HORUS IPC: subscribes to "plan_request", publishes to "trajectory"
// Without HORUS: use channel API
}

Topics:

TopicDirectionMessageRate
plan_requestSubscribePlanRequestOn demand
trajectoryPublishTimedTrajectoryOn demand

ServoNode

Real-time reactive control. Receives twist or joint jog commands, outputs joint commands at 500 Hz.

#![allow(unused)]
fn main() {
use horus_kinetic::ServoNode;

let mut servo = ServoNode::new("ur5e")?;
// Subscribes to "twist_cmd" or "joint_jog"
// Publishes "joint_cmd" at 500 Hz
}

Topics:

TopicDirectionMessageRate
twist_cmdSubscribeTwistUp to 500 Hz
joint_jogSubscribeJointJogUp to 500 Hz
joint_cmdPublishJointCommand500 Hz

SceneNode

Manages the collision environment. Ingests point clouds, depth images, and explicit obstacle descriptions.

#![allow(unused)]
fn main() {
use horus_kinetic::SceneNode;

let mut scene = SceneNode::new("ur5e")?;
// Subscribes to "pointcloud", "depth_image"
// Publishes "scene_update" on change
}

Topics:

TopicDirectionMessageRate
pointcloudSubscribePointCloud2Sensor rate
depth_imageSubscribeDepthImageSensor rate
scene_updatePublishSceneUpdateOn change

With vs Without HORUS

The horus-kinetic crate works in two modes:

With HORUS IPC (feature horus-ipc enabled): Full HORUS Node trait implementations with zero-copy shared-memory topics. Nodes are discovered and connected by the HORUS runtime.

Without HORUS (default): Channel-based API for standalone use or integration with other transports.

#![allow(unused)]
fn main() {
use horus_kinetic::PlannerNode;

// Standalone mode (no HORUS dependency)
let mut planner = PlannerNode::new("ur5e")?;

// Send a request through the channel API
let request = PlanRequest {
    start: vec![0.0; 6],
    goal: Goal::Named("home".into()),
    ..Default::default()
};
let trajectory = planner.plan(request)?;
}

This design means kinetic works identically in simulation, on standalone robots, and in full HORUS-networked systems.

Point Cloud Perception Pipeline

The SceneNode processes raw sensor data into a collision world:

Camera/LiDAR --> PointCloud
                    |
              [Downsampling]     -- VoxelGrid or Random
                    |
              [Outlier Removal]  -- Statistical or Radius
                    |
              [Octree Build]     -- Spatial indexing
                    |
              [Sphere Approx]    -- Collision spheres
                    |
              CollisionEnvironment

Configure the pipeline:

#![allow(unused)]
fn main() {
use kinetic::scene::{PointCloudConfig, OutlierConfig};

let config = PointCloudConfig {
    voxel_size: 0.01,       // 1cm voxels
    max_points: 50_000,
    outlier: OutlierConfig::Statistical {
        neighbors: 20,
        std_ratio: 2.0,
    },
    ..Default::default()
};

scene.add_pointcloud("camera_0", &points, config);
}

Building

# Without HORUS (standalone, channel API)
cargo build -p horus-kinetic

# With HORUS IPC (requires horus to be installed)
cargo build -p horus-kinetic --features horus-ipc

The horus-ipc feature adds a compile-time dependency on HORUS. Without it, the crate is fully self-contained and has no HORUS dependency at all.