rclrs ROS 2 Client Library for Rust

repository·main·Indexed 23 days ago

https://github.com/ros2-rust/ros2_rust

A ROS 2 client library (version 0.7.0) for developing robotics applications in Rust. It enables native integration with the ROS 2 ecosystem, providing support for message generation, publishers, subscribers, services, and actions while leveraging Rust's safety and performance guarantees.

Tokens
22.6K
Snippets
45
Records
100
Agent score
80%

What's inside rclrs

  1. Overview of rclrs

    main
    rclrs is the ROS 2 client library for Rust. It allows developers to write robotics applications in Rust that integrate natively with the ROS 2 ecosystem, enabling the use of Rust's safety and performance guarantees within ROS 2-based systems.
  2. How to structure an rclrs Node

    main

    Unlike rclcpp or rclpy, rclrs does not use inheritance for nodes. Instead, you should define a custom struct that holds the rclrs::Node as a member.

    Because the node and its components (like subscriptions) often need to be shared between the main execution loop and callbacks/threads, it is common to wrap the node and its data in Arc (Atomic Reference Counted) pointers.

    use std::sync::Arc;
    use rclrs::std_msgs::msg::String as StringMsg;
    
    struct RepublisherNode {
        node: Arc<rclrs::Node>,
        _subscription: Arc<rclrs::Subscription<StringMsg>>,
        data: Option<StringMsg>,
    }
    
    impl RepublisherNode {
        fn new(context: &rclrs::Context) -> Result<Self, rclrs::RclrsError> {
            let node = rclrs::Node::new(context, "republisher")?;
            // ... initialization logic ...
        }
    }
  3. Build and run examples for ROS 2 Rolling or Lyrical Luth

    main

    To run the rclrs examples on ROS 2 Rolling or Lyrical Luth, you need to install specific interface packages, clone the examples, and clone the rosidl_rust code generator.

    Note: The requirement to clone rosidl_rust is a temporary measure as of 2025-01-21.

    Setup Steps

    # Install interface packages
    sudo apt install -y ros-rolling-example-interfaces ros-rolling-test-msgs
    
    # Create workspace and clone examples
    mkdir -p workspace/src && cd workspace
    git clone https://github.com/ros2-rust/examples.git src/examples
    
    # Clone the code generator (Temporary requirement)
    git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust

    Build

    . /opt/ros/rolling/setup.sh  # Or source your ROS 2 installation
    colcon build
    # Install interface packages
    sudo apt install -y ros-rolling-example-interfaces ros-rolling-test-msgs
    mkdir -p workspace/src && cd workspace
    git clone https://github.com/ros2-rust/examples.git src/examples
    
    # Clone the code generator (Temporary requirement)
    git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust
    
    # Build the workspace
    . /opt/ros/rolling/setup.sh
    colcon build
  4. Build ROS 2 Rust packages with colcon

    main

    Use colcon build to build a package and its dependencies.

    Note: You may see warnings about packages being already built in an underlay workspace; this is expected as ROS 2 message definitions are regenerated for Rust bindings.

    Warning: Do not run multiple Rust builds in parallel, as they may conflict when writing to .cargo/config.toml.

    # Make sure to run this in the workspace directory
    colcon build --packages-up-to $YOUR_PACKAGE
  5. Integrate Rust binaries with ROS 2 tools using cargo-ament-build

    main

    To make Rust binaries available to ros2 run and ros2 launch without using colcon, use the cargo-ament-build plugin. This plugin handles the necessary file placement in the install directory (per REP 122).

    1. Use cargo ament-build --install-base <path> instead of cargo build.
    2. Source the resulting install directory using . install/setup.sh.
    3. Use ros2 run to execute your binary.
  6. Create a ROS 2 Rust package with colcon support

    main

    To build a ROS 2 Rust package using colcon, you must create a standard Cargo package and add a package.xml file. The package.xml must specify the build type as ament_cargo and include your ROS 2 dependencies.

    1. Create the Cargo package:
    cargo new rust_pubsub && cd rust_pubsub
    1. Configure Cargo.toml with dependencies:
    [package]
    name = "rust_pubsub"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    rclrs = "*"
    std_msgs = "*"
    1. Create package.xml for colcon integration:
    <package format="3">
      <name>rust_pubsub</name>
      <version>0.0.0</version>
      <description>TODO: Package description.</description>
      <maintainer email="user@todo.todo">user</maintainer>
      <license>TODO: License declaration.</license>
    
      <depend>rclrs</depend>
      <depend>std_msgs</depend>
    
      <export>
        <build_type>ament_cargo</build_type>
      </export>
    </package>
    cargo new rust_pubsub && cd rust_pubsub
  7. Run periodic tasks in rclrs

    main

    As of the current version, rclrs does not have built-in ROS timers. To run a function periodically (e.g., for republishing), you can spawn a separate thread that runs a loop with a sleep interval.

    Because the thread closure must be 'static, you cannot borrow the node directly. You must wrap your node struct in an Arc and clone it for the thread.

    fn main() -> Result<(), rclrs::RclrsError> {
        let context = rclrs::Context::new(std::env::args())?;
        let republisher = Arc::new(RepublisherNode::new(&context)?);
        let republisher_other_thread = Arc::clone(&republisher);
    
        std::thread::spawn(move || -> Result<(), rclrs::RclrsError> {
            loop {
                use std::time::Duration;
                std::thread::sleep(Duration::from_millis(1000));
                republisher_other_thread.republish()?;
            }
        });
    
        rclrs::spin(Arc::clone(&republisher.node))
    }
  8. Add multiple binary targets to a single Rust package

    main

    Instead of creating a new package for every node, you can define multiple executable targets in a single Cargo.toml using the [[bin]] section. This allows you to run different nodes from the same package.

    In Cargo.toml:

    [[bin]]
    name="simple_publisher"
    path="src/simple_publisher.rs"
    
    [[bin]]
    name="simple_subscriber"
    path="src/simple_subscriber.rs"

    Note: Use snake_case for the name field to avoid compiler issues. You can then run these nodes using:

    ros2 run rust_pubsub simple_publisher
    [[bin]]
    name="simple_publisher"
    path="src/simple_publisher.rs"
  9. Build and run examples for ROS 2 Jazzy Jalisco

    main

    For ROS 2 Jazzy, you need to clone the Jazzy branches of the ROS 2 message packages, the rosidl_rust code generator, and the rclrs examples into your workspace.

    Setup Steps

    mkdir -p workspace/src && cd workspace
    git clone -b jazzy https://github.com/ros2/common_interfaces.git src/common_interfaces
    git clone -b jazzy https://github.com/ros2/example_interfaces.git src/example_interfaces
    git clone -b jazzy https://github.com/ros2/rcl_interfaces.git src/rcl_interfaces
    git clone -b jazzy https://github.com/ros2/rosidl_core.git src/rosidl_core
    git clone -b jazzy https://github.com/ros2/rosidl_defaults.git src/rosidl_defaults
    git clone -b jazzy https://github.com/ros2/unique_identifier_msgs.git src/unique_identifier_msgs
    git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust
    git clone https://github.com/ros2-rust/examples.git src/examples

    Build

    . /opt/ros/jazzy/setup.sh
    colcon build
    mkdir -p workspace/src && cd workspace
    git clone -b jazzy https://github.com/ros2/common_interfaces.git src/common_interfaces
    git clone -b jazzy https://github.com/ros2/example_interfaces.git src/example_interfaces
    git clone -b jazzy https://github.com/ros2/rcl_interfaces.git src/rcl_interfaces
    git clone -b jazzy https://github.com/ros2/rosidl_core.git src/rosidl_core
    git clone -b jazzy https://github.com/ros2/rosidl_defaults.git src/rosidl_defaults
    git clone -b jazzy https://github.com/ros2/unique_identifier_msgs.git src/unique_identifier_msgs
    git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust
    git clone https://github.com/ros2-rust/examples.git src/examples
    
    . /opt/ros/jazzy/setup.sh
    colcon build
  10. Build and run examples for ROS 2 Kilted Kaiju

    main

    For ROS 2 Kilted, you must clone the specific Kilted branches of the ROS 2 message packages and the rosidl_rust code generator into your workspace.

    Setup Steps

    mkdir -p workspace/src && cd workspace
    git clone -b kilted https://github.com/ros2/common_interfaces.git src/common_interfaces
    git clone -b kilted https://github.com/ros2/example_interfaces.git src/example_interfaces
    git clone -b kilted https://github.com/ros2/rcl_interfaces.git src/rcl_interfaces
    git clone -b kilted https://github.com/ros2/rosidl_core.git src/rosidl_core
    git clone -b kilted https://github.com/ros2/rosidl_defaults.git src/rosidl_defaults
    git clone -b kilted https://github.com/ros2/unique_identifier_msgs.git src/unique_identifier_msgs
    
    # Clone the code generator (Temporary requirement)
    git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust

    Build

    . /opt/ros/kilted/setup.sh
    colcon build
    mkdir -p workspace/src && cd workspace
    git clone -b kilted https://github.com/ros2/common_interfaces.git src/common_interfaces
    git clone -b kilted https://github.com/ros2/example_interfaces.git src/example_interfaces
    git clone -b kilted https://github.com/ros2/rcl_interfaces.git src/rcl_interfaces
    git clone -b kilted https://github.com/ros2/rosidl_core.git src/rosidl_core
    git clone -b kilted https://github.com/ros2/rosidl_defaults.git src/rosidl_defaults
    git clone -b kilted https://github.com/ros2/unique_identifier_msgs.git src/unique_identifier_msgs
    git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust
    
    . /opt/ros/kilted/setup.sh
    colcon build
  11. Import auxiliary ROS 2 repositories

    main

    ros2_rust requires additional repositories to be present in the workspace. You can import them using the vcs tool and the .repos files provided in the ros2_rust repository. This typically places the new repositories in src/ros2.

    # Make sure to run this in the workspace directory
    vcs import src < src/ros2_rust/ros2_rust_humble.repos
  12. Install ROS 2 for Rust (rclrs)

    main

    To use rclrs in your Rust projects, you must first install the Rust toolchain and necessary system dependencies. You also need to install colcon plugins for Cargo to enable seamless integration with the ROS 2 build system.

    1. Install Rust

    Use rustup to install the Rust toolchain:

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

    2. Install System Dependencies

    Install git, libclang-dev, python3-pip, and python3-vcstool via apt:

    sudo apt install -y git libclang-dev python3-pip python3-vcstool

    3. Install colcon plugins for Rust

    Install the required colcon plugins using pip:

    pip install --break-system-packages colcon-cargo colcon-ros-cargo

    4. Install Workaround Packages

    Due to a known issue in rclrs, you must install the following ROS 2 packages as a workaround:

    sudo apt install -y ros-$ROS_DISTRO-example-interfaces
    sudo apt install -y ros-$ROS_DISTRO-test-msgs
    # Install Rust (see https://rustup.rs/)
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    
    # Install required system packages
    sudo apt install -y git libclang-dev python3-pip python3-vcstool
    
    # Install colcon plugins for Rust
    pip install --break-system-packages colcon-cargo colcon-ros-cargo
    
    # Install workaround packages
    sudo apt install -y ros-$ROS_DISTRO-example-interfaces
    sudo apt install -y ros-$ROS_DISTRO-test-msgs