### Setup for ROS 2 Lyrical Luth and Rolling Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Installs required message packages, clones the examples repository, and sets up the workspace for ROS 2 Lyrical Luth and Rolling. ```shell 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 ``` -------------------------------- ### Run Minimal Publisher Example Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Sources the workspace and runs the minimal publisher node. Ensure you have built the examples. ```shell . ./install/setup.sh ros2 run examples_rclrs_minimal_pub_sub minimal_publisher ``` -------------------------------- ### Run Minimal Subscriber Example Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Sources the workspace and runs the minimal subscriber node. Ensure you have built the examples. ```shell . ./install/setup.sh ros2 run examples_rclrs_minimal_pub_sub minimal_subscriber ``` -------------------------------- ### Setup for ROS 2 Humble Hawksbill Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Clones ROS 2 message packages, rosidl_rust, and examples repositories for ROS 2 Humble Hawksbill. ```shell mkdir -p workspace/src && cd workspace git clone -b humble https://github.com/ros2/common_interfaces.git src/common_interfaces git clone -b humble https://github.com/ros2/example_interfaces.git src/example_interfaces git clone -b humble https://github.com/ros2/rcl_interfaces.git src/rcl_interfaces git clone -b humble https://github.com/ros2/rosidl_core.git src/rosidl_core git clone -b humble https://github.com/ros2/rosidl_defaults.git src/rosidl_defaults git clone -b humble 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 ``` -------------------------------- ### Setup for ROS 2 Jazzy Jalisco Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Clones ROS 2 message packages, rosidl_rust, and examples repositories for ROS 2 Jazzy Jalisco. ```shell 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 ``` -------------------------------- ### Install Rust and System Dependencies Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Installs Rust via rustup and essential system packages for ROS 2 development. Also installs colcon plugins for Rust. ```shell curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh sudo apt install -y git clang python3-pip python3-vcstool pip install --break-system-packages colcon-cargo colcon-ros-cargo ``` -------------------------------- ### Run Minimal Pub/Sub Launch File Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Sources the workspace and launches the minimal publisher and subscriber nodes using a launch file. Ensure you have built the examples. ```shell . ./install/setup.sh ros2 launch examples_rclrs_minimal_pub_sub minimal_pub_sub.launch.xml ``` -------------------------------- ### Example Subscriber Output Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md This is an example of the output you should see in the subscriber's terminal if the publisher and subscriber nodes are running correctly. ```text Hello World 230 Hello World 231 Hello World 232 Hello World 233 Hello World 234 Hello World 235 Hello World 236 Hello World 237 Hello World 238 Hello World 239 Hello World 240 Hello World 241 Hello World 242 Hello World 243 Hello World 244 Hello World 245 Hello World 246 ``` -------------------------------- ### Rust ROS 2 Publisher Node Example Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md This code constructs a ROS 2 node and a publisher for string messages. It initializes the node and publisher, and sets up a loop to publish 'Hello World' messages in a separate thread. ```rust /// Creates a SimplePublisherNode, initializes a node and publisher, and provides /// methods to publish a simple "Hello World" message on a loop in separate threads. use rclrs::{create_node, Context, Node, Publisher, RclrsError, QOS_PROFILE_DEFAULT}; use std::{env, sync::Arc, thread, time::Duration}; use rclrs::std_msgs::msg::String as StringMsg; /// SimplePublisherNode struct contains node and publisher members. /// Used to initialize a ROS 2 node and publisher, and publish messages. struct SimplePublisherNode { node: Arc, publisher: Arc>, } impl SimplePublisherNode { fn new(context: &Context) -> Result { let node = create_node(context, "simple_publisher").unwrap(); let publisher = node .create_publisher("publish_hello", QOS_PROFILE_DEFAULT) .unwrap(); Ok(Self { node, publisher }) } fn publish_data(&self, increment: i32) -> Result { let msg: StringMsg = StringMsg { data: format!("Hello World {}", increment), }; self.publisher.publish(msg).unwrap(); Ok(increment + 1_i32) } } fn main() -> Result<(), RclrsError> { let context = Context::new(env::args()).unwrap(); let publisher = Arc::new(SimplePublisherNode::new(&context).unwrap()); let publisher_other_thread = Arc::clone(&publisher); let mut count: i32 = 0; thread::spawn(move || loop { thread::sleep(Duration::from_millis(1000)); count = publisher_other_thread.publish_data(count).unwrap(); }); rclrs::spin(publisher.node.clone()) } ``` -------------------------------- ### Source ROS 2 Installation in Bash Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Sources the ROS 2 installation script to set up necessary environment variables. This is typically done in the shell before building. ```shell # You can also do `source /opt/ros/humble/setup.bash` in bash . /opt/ros/humble/setup.sh ``` -------------------------------- ### Building and Running the ROS 2 Rust Package Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Build your ROS 2 Rust package using colcon and source the setup script. Then, run your node using the 'ros2 run' command, specifying the package name and the executable name defined in Cargo.toml. ```sh cd WORKSPACE colcon build source install/setup.bash ros2 run rust_pubsub simple_publisher ``` -------------------------------- ### Setup for ROS 2 Kilted Kaiju Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Clones ROS 2 message packages and the rosidl_rust repository for ROS 2 Kilted Kaiju. ```shell 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 ``` -------------------------------- ### Install ROS 2 Rust Dependencies on Ubuntu Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Installs Rust, ROS 2, and essential colcon/cargo plugins and libraries required for building ros2_rust on Ubuntu. Ensure Rust and ROS 2 are installed prior to running these commands. ```shell # Install Rust, e.g. as described in https://rustup.rs/ # Install ROS 2 as described in https://docs.ros.org/en/humble/Installation.html # Assuming you installed the minimal version of ROS 2, you need these additional packages: sudo apt install -y git libclang-dev python3-pip python3-vcstool # libclang-dev is required by bindgen # Install these plugins for cargo and colcon: pip install git+https://github.com/colcon/colcon-cargo.git pip install git+https://github.com/colcon/colcon-ros-cargo.git ``` -------------------------------- ### Install Workaround Packages for rclrs Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Installs necessary ROS 2 packages as a workaround for an issue in the rclrs crate. ```shell sudo apt install -y ros-$ROS_DISTRO-example-interfaces sudo apt install -y ros-$ROS_DISTRO-test-msgs ``` -------------------------------- ### Main function to initialize and spin the node Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Implement the main function to initialize the rclrs context, create an instance of your node struct, and start the ROS 2 event loop using rclrs::spin. ```rust fn main() -> Result<(), rclrs::RclrsError> { let context = rclrs::Context::new(std::env::args())?; let republisher = RepublisherNode::new(&context)?; rclrs::spin(republisher.node) } ``` -------------------------------- ### List Colcon Packages Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Verifies the ROS 2 build environment setup by listing all packages known to colcon. A successful output should include `rclrs` with the `ament_cargo` build type. ```shell colcon list ``` -------------------------------- ### Run ROS 2 Rust Development Docker Container Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Runs the previously built Docker container, mounting the current directory as a workspace. This command starts an interactive bash session inside the container. ```shell # Make sure to run this in the workspace directory docker run --rm -it --volume $(pwd):/workspace ros2_rust_dev /bin/bash ``` -------------------------------- ### Main Function Entry Point Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md The main function initializes the ROS 2 context and node, sets up a publisher, spawns a new thread for publishing, and spins the main thread to process events. ```rust fn main() -> Result<(), RclrsError> { let context = Context::new(std::env::args()).unwrap(); let publisher = Arc::new(SimplePublisherNode::new(&context).unwrap()); let publisher_other_thread = Arc::clone(&publisher); let mut iterator: i32 = 0; thread::spawn(move || -> () { loop { thread::sleep(Duration::from_millis(1000)); iterator = publisher_other_thread.publish_data(iterator).unwrap(); } }); rclrs::spin(publisher.node.clone()); Ok(()) } ``` -------------------------------- ### Create a Cargo Package Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Initializes a new Rust project using Cargo and navigates into the project directory. ```sh cargo new rust_pubsub && cd rust_pubsub ``` -------------------------------- ### Main Function for ROS 2 Publisher in Rust Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Sets up a ROS 2 context, creates a SimplePublisherNode, and spawns a thread to publish messages at 1 Hz. The main thread then spins the ROS 2 node. ```rust fn main() -> Result<(), RclrsError> { let context = Context::new(env::args()).unwrap(); let publisher = Arc::new(SimplePublisherNode::new(&context).unwrap()); let publisher_other_thread = Arc::clone(&publisher); let mut count: i32 = 0; thread::spawn(move || loop { thread::sleep(Duration::from_millis(1000)); count = publisher_other_thread.publish_data(count).unwrap(); }); rclrs::spin(publisher.node.clone()) } ``` -------------------------------- ### Create ROS 2 Node and Subscriber Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Initializes a ROS 2 node and sets up a subscription to the 'publish_hello' topic. It uses Arc and Mutex to safely share received messages. ```rust fn new(context: &Context) -> Result { let node = create_node(context, "simple_subscription").unwrap(); let data: Arc>> = Arc::new(Mutex::new(None)); let data_mut: Arc>> = Arc::clone(&data); let _subscriber = node .create_subscription::( "publish_hello", QOS_PROFILE_DEFAULT, move |msg: StringMsg| { *data_mut.lock().unwrap() = Some(msg); }, ) .unwrap(); Ok(Self { node, _subscriber, data, }) } ``` -------------------------------- ### Build ROS 2 Humble Hawksbill Workspace Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Builds the ROS 2 workspace for Humble Hawksbill. Ensure your ROS 2 environment is sourced. ```shell . /opt/ros/humble/setup.sh colcon build ``` -------------------------------- ### Import ROS 2 Rust Repositories Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Imports necessary auxiliary repositories into the workspace using the `vcs` tool. This command should be run from the workspace directory. ```shell # Make sure to run this in the workspace directory vcs import src < src/ros2_rust/ros2_rust_humble.repos ``` -------------------------------- ### Build ROS 2 Jazzy Jalisco Workspace Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Builds the ROS 2 workspace for Jazzy Jalisco. Ensure your ROS 2 environment is sourced. ```shell . /opt/ros/jazzy/setup.sh colcon build ``` -------------------------------- ### Build Docker Image for ROS 2 Rust Development Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Builds a Docker image for ros2_rust development. Ensure you are in the workspace directory before running. Replace `humble` with your desired ROS 2 distribution if necessary. ```shell # Make sure to run this in the workspace directory # ROS_DISTRO can be humble|rolling docker build -f src/ros2_rust/Dockerfile --build-arg "ROS_DISTRO=humble" -t ros2_rust_dev . ``` -------------------------------- ### Initialize Publisher in Node Constructor Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Create a new ROS 2 publisher within the RepublisherNode's constructor. This publisher will send messages on the 'out_topic'. ```rust // Change the end of RepublisherNode::new() to this: let publisher = node.create_publisher("out_topic", rclrs::QOS_PROFILE_DEFAULT)?; Ok(Self { node, _subscription, publisher, data, }) ``` -------------------------------- ### Build ROS 2 Kilted Kaiju Workspace Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Builds the ROS 2 workspace for Kilted Kaiju. Ensure your ROS 2 environment is sourced. ```shell . /opt/ros/kilted/setup.sh colcon build ``` -------------------------------- ### Define package.xml for colcon build Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Create a package.xml file to make your Rust ROS 2 node buildable with colcon. Ensure the build type is set to ament_cargo and dependencies are listed. ```xml republisher_node 0.0.0 TODO: Package description user TODO: License declaration rclrs std_msgs ament_cargo ``` -------------------------------- ### SimplePublisherNode Implementation in Rust Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Defines methods for creating a ROS 2 node and publisher, and for publishing string messages. The `new` method initializes the node and publisher, while `publish_data` sends messages with an incrementing counter. ```rust impl SimplePublisherNode { fn new(context: &context) -> result { let node = create_node(context, "simple_publisher").unwrap(); let publisher = node .create_publisher("publish_hello", qos_profile_default) .unwrap(); ok(self { node, publisher }) } fn publish_data(&self, increment: i32) -> Result { let msg: StringMsg = StringMsg { data: format!("Hello World {}", increment), }; self.publisher.publish(msg).unwrap(); Ok(increment + 1_i32) } } ``` -------------------------------- ### Build ROS 2 Package with Colcon Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Use this command to build a specific ROS 2 package and its dependencies using colcon. Ensure you are in the workspace directory when executing. ```shell # Make sure to run this in the workspace directory colcon build --packages-up-to $YOUR_PACKAGE ``` -------------------------------- ### SimpleSubscriptionNode Implementation Block Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Contains methods for the SimpleSubscriptionNode struct, including a constructor for creating the node and subscription, and a callback for processing received messages. ```rust impl SimpleSubscriptionNode { fn new(context: &Context) -> Result { let node = create_node(context, "simple_subscription").unwrap(); let data: Arc>> = Arc::new(Mutex::new(None)); let data_mut: Arc>> = Arc::clone(&data); let _subscriber = node .create_subscription::( "publish_hello", QOS_PROFILE_DEFAULT, move |msg: StringMsg| { *data_mut.lock().unwrap() = Some(msg); }, ) .unwrap(); Ok(Self { node, _subscriber, data, }) } fn data_callback(&self) -> Result<(), RclrsError> { if let Some(data) = self.data.lock().unwrap().as_ref() { println!("{}", data.data); } else { println!("No message available yet."); } Ok(()) } } ``` -------------------------------- ### Create a new Rust package Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Use cargo to create a new Rust project for your ROS 2 node. This sets up the basic project structure. ```bash cargo new republisher_node && cd republisher_node ``` -------------------------------- ### Build and Run ROS 2 Rust Nodes Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Commands to build your ROS 2 Rust package using colcon and run the publisher and subscriber nodes in separate terminals. ```bash cd WORKSPACE colcon build ``` ```bash cd WORKSPACE source install/setup.bash ros2 run rust_pubsub your_node_name ``` -------------------------------- ### Build ROS 2 Lyrical Luth and Rolling Workspace Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Builds the ROS 2 workspace after cloning necessary repositories. Ensure your ROS 2 environment is sourced. ```shell . /opt/ros/rolling/setup.sh # Or source your ROS 2 installation colcon build ``` -------------------------------- ### Create package.xml for Colcon Build Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Defines the ROS 2 package metadata, specifying `ament_cargo` as the build type and listing `rclrs` and `std_msgs` as dependencies. ```xml rust_pubsub 0.0.0 TODO: Package description. user TODO: License declaration. rclrs std_msgs ament_cargo ``` -------------------------------- ### Spawn Thread for Periodic Republishing (Initial Attempt) Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Attempt to spawn a new thread to call the republish function every second. This version may encounter lifetime issues. ```rust fn main() -> Result<(), rclrs::RclrsError> { let context = rclrs::Context::new(std::env::args())?; let republisher = RepublisherNode::new(&context)?; std::thread::spawn(|| -> Result<(), rclrs::RclrsError> { loop { use std::time::Duration; std::thread::sleep(Duration::from_millis(1000)); republisher.republish()?; } }); rclrs::spin(republisher.node) } ``` -------------------------------- ### Implement Simple Subscriber Node in Rust Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md This Rust code defines a ROS 2 subscriber node. It includes a struct to hold the node, subscription, and data, along with methods for initialization and data handling. The main function sets up the context, creates the subscriber, and spins the node. ```rust use rclrs::{create_node, Context, Node, RclrsError, Subscription, QOS_PROFILE_DEFAULT}; use std:: env, sync::{Arc, Mutex}, thread, time::Duration, }; use rclrs::std_msgs::msg::String as StringMsg; pub struct SimpleSubscriptionNode { node: Arc, _subscriber: Arc>, data: Arc>>, } impl SimpleSubscriptionNode { fn new(context: &Context) -> Result { let node = create_node(context, "simple_subscription").unwrap(); let data: Arc>> = Arc::new(Mutex::new(None)); let data_mut: Arc>> = Arc::clone(&data); let _subscriber = node .create_subscription::( "publish_hello", QOS_PROFILE_DEFAULT, move |msg: StringMsg| { *data_mut.lock().unwrap() = Some(msg); }, ) .unwrap(); Ok(Self { node, _subscriber, data, }) } fn data_callback(&self) -> Result<(), RclrsError> { if let Some(data) = self.data.lock().unwrap().as_ref() { println!("{}", data.data); } else { println!("No message available yet."); } Ok(()) } } fn main() -> Result<(), RclrsError> { let context = Context::new(env::args()).unwrap(); let subscription = Arc::new(SimpleSubscriptionNode::new(&context).unwrap()); let subscription_other_thread = Arc::clone(&subscription); thread::spawn(move || loop { thread::sleep(Duration::from_millis(1000)); subscription_other_thread.data_callback().unwrap() }); rclrs::spin(subscription.node.clone()) } ``` -------------------------------- ### Clone ros2_rust Repository Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/building.md Clone the ros2_rust repository into the 'src' subdirectory of your workspace. Ensure you are in your chosen workspace directory before running these commands. ```shell # Make sure to run this in the workspace directory mkdir src git clone https://github.com/ros2-rust/ros2_rust.git src/ros2_rust ``` -------------------------------- ### Cargo.toml Configuration for Multiple Binaries Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Configure your Cargo.toml file to define multiple executable targets for your ROS 2 Rust package. This allows you to have separate entry points for different nodes. ```toml [package] name = "rust_pubsub" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] name="simple_publisher" path="src/simple_publisher.rs" [dependencies] rclrs = "*" std_msgs = "*" ``` -------------------------------- ### Publishing Another String Message Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Publishes a different string message to the '/in_topic' topic. This demonstrates how subsequent messages are handled. ```bash ros2 topic pub /in_topic std_msgs/msg/String '{data: "Servus"}' -1 ``` -------------------------------- ### Write the Publisher Node in Rust Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Implements a ROS 2 publisher node in Rust that sends string messages on the 'topic' topic. Requires `rclrs` and `std_msgs`. ```rust use rclrs::{Node, Publisher, QosProfile, Topic}; // Use Topic for explicit topic definition use std_msgs::msg::String as StringMsg; fn main() -> Result<(), Box> { // Initialize ROS 2 client library let mut context = rclrs::Context::new(std::env::args().collect())?; // Create a new node let mut node = Node::new(&context, "rust_publisher", None, None)?; // Define the topic with a specific QoS profile let topic = Topic::::new(&context, "topic")?; let publisher = node.create_publisher(topic, QosProfile::default())?; // Create a timer to publish messages periodically let mut timer = node.create_wall_timer(std::time::Duration::from_millis(500), move || { let mut msg = StringMsg::new(); let count = msg.data.chars().count(); // Get current message count msg.data = format!("Hello from Rust! ({count})"); if let Err(e) = publisher.publish(msg) { eprintln!("Error publishing: {e}"); } })?; println!("Publisher started. Publishing messages..."); // Spin the node to process callbacks rclrs::spin(node)?; Ok(()) } ``` -------------------------------- ### Publishing a String Message Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Publishes a single string message to the '/in_topic' topic. Use this to send data to a ROS 2 node. ```bash ros2 topic pub /in_topic std_msgs/msg/String '{data: "Bonjour"}' -1 ``` -------------------------------- ### Rust Imports for ROS 2 Publisher Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Imports necessary modules for thread synchronization, time handling, ROS 2 communication, and string message publishing. ```rust use rclrs::{create_node, Context, Node, Publisher, RclrsError, QOS_PROFILE_DEFAULT}; use std::{env, sync::Arc, thread, time::Duration}; use rclrs::std_msgs::msg::String as StringMsg; ``` -------------------------------- ### Configure Cargo.toml for rclrs Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Add rclrs and std_msgs as dependencies in your Cargo.toml file to enable their use in your Rust ROS 2 node. ```toml rclrs = "*" std_msgs = "*" ``` -------------------------------- ### Rust ROS 2 Node with Shared Data Handling Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Demonstrates a Rust struct for a ROS 2 node that subscribes to a topic and stores received messages using Arc and Mutex for shared ownership. ```rust use std::sync::{Arc, Mutex}; use rclrs::std_msgs::msg::String as StringMsg; struct RepublisherNode { node: Arc, _subscription: Arc>, data: Arc>>, // (2) } impl RepublisherNode { fn new(context: &rclrs::Context) -> Result { let node = rclrs::Node::new(context, "republisher")?; let data = Arc::new(Mutex::new(None)); // (3) let data_cb = Arc::clone(&data); let _subscription = { // Create a new shared pointer instance that will be owned by the closure node.create_subscription( "in_topic", rclrs::QOS_PROFILE_DEFAULT, move |msg: StringMsg| { // This subscription now owns the data_cb variable *data_cb.lock().unwrap() = Some(msg); // (4) }, )? }; Ok(Self { node, _subscription, data, }) } } ``` -------------------------------- ### Add Binary Target to Cargo.toml Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Define a new binary target for your ROS 2 Rust package in the Cargo.toml file. This specifies the name and path of the executable. ```toml [[bin]] name="simple_subscriber" path="src/simple_subscriber.rs" ``` -------------------------------- ### Spawn Thread for Periodic Republishing with Arc Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Correctly spawn a thread for periodic republishing using Arc for shared ownership, resolving `'static` lifetime errors. This ensures the thread can safely access the node's data. ```rust 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)) } ``` -------------------------------- ### Write the Subscriber Node in Rust Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Implements a ROS 2 subscriber node in Rust that listens for string messages on the 'topic' topic and prints them. ```rust use rclrs::{Node, Subscriber, Topic}; use std_msgs::msg::String as StringMsg; fn main() -> Result<(), Box> { // Initialize ROS 2 client library let mut context = rclrs::Context::new(std::env::args().collect())?; // Create a new node let mut node = Node::new(&context, "rust_subscriber", None, None)?; // Define the topic to subscribe to let topic = Topic::::new(&context, "topic")?; // Create a subscriber and define the callback function let _subscriber = node.create_subscription(topic, move |msg: StringMsg| { println!("I heard: '{}'", msg.data); })?; println!("Subscriber started. Waiting for messages..."); // Spin the node to process callbacks rclrs::spin(node)?; Ok(()) } ``` -------------------------------- ### Add rclrs to Project Dependencies Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Specifies the rclrs crate as a dependency in your Cargo.toml file. ```toml [dependencies] rclrs = "0.7" ``` -------------------------------- ### Rust Structure for SimplePublisherNode Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Defines the SimplePublisherNode structure, holding references to a ROS 2 node and a publisher for string messages, ensuring thread-safe access via Arc. ```rust struct SimplePublisherNode { node: Arc, publisher: Arc>, } ``` -------------------------------- ### Clone rosidl_rust for Lyrical Luth and Rolling Source: https://github.com/ros2-rust/ros2_rust/blob/main/README.md Temporarily clones the rosidl_rust repository for code generator support. This can be removed once updated. ```shell mkdir -p workspace/src && cd workspace git clone https://github.com/ros2-rust/rosidl_rust.git src/rosidl_rust ``` -------------------------------- ### ROS 2 Rust Node Subscription Callback Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md This closure is used as a callback for a ROS 2 subscription. It captures a message and stores it. ```rust |msg: StringMsg| { data = Some(msg); }, ``` -------------------------------- ### SimpleSubscriptionNode Struct Definition Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md Defines the structure for a ROS 2 subscriber node in Rust. It holds the ROS 2 node, the subscription object, and a mutex-protected optional message for thread-safe data access. ```rust pub struct SimpleSubscriptionNode { node: Arc, _subscriber: Arc>, data: Arc>>, } ``` -------------------------------- ### Rust Subscriber Data Callback Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing_a_simple_publisher_and_subscriber.md This function accesses received message data in a ROS 2 Rust subscriber. It checks for a message, prints its content, or indicates if no message is available. ```rust fn data_callback(&self) -> Result<(), RclrsError> { if let Some(data) = self.data.lock().unwrap().as_ref() { println!("{}", data.data); } else { println!("No message available yet."); } Ok(()) } ``` -------------------------------- ### Republish Latest Received Message Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Implement a function to publish the most recently received message. This function checks if a message exists before publishing. ```rust fn republish(&self) -> Result<(), rclrs::RclrsError> { if let Some(s) = &*self.data.lock().unwrap() { self.publisher.publish(s)?; } Ok(()) } ``` -------------------------------- ### Define the RepublisherNode struct Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Structure your ROS 2 node in Rust by defining a struct to hold the rclrs node, subscription, and message data. This approach is used due to Rust's lack of inheritance. ```rust use std::sync::Arc; use rclrs::std_msgs::msg::String as StringMsg; struct RepublisherNode { node: Arc, _subscription: Arc>, data: Option, } impl RepublisherNode { fn new(context: &rclrs::Context) -> Result { let node = rclrs::Node::new(context, "republisher")?; let data = None; let _subscription = node.create_subscription( "in_topic", rclrs::QOS_PROFILE_DEFAULT, |msg: StringMsg| { todo!("Assign msg to self.data") }, )?; Ok(Self { node, _subscription, data, }) } } ``` -------------------------------- ### Add Publisher Field to Node Struct Source: https://github.com/ros2-rust/ros2_rust/blob/main/docs/writing-your-first-rclrs-node.md Define the publisher field within the RepublisherNode struct. This field will be used to send messages. ```rust // Add this new field to the RepublisherNode struct, after the subscription: publisher: Arc>, ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.