### Build and Run ROS2 Subscriber Example Source: https://github.com/sequenceplanner/r2r/blob/master/r2r/README.md Demonstrates how to build the R2R crate and run a subscriber example. Ensure your ROS2 environment is sourced before execution. ```bash . /opt/ros/humble/setup.sh cargo build cargo run --example subscriber # In other shell ros2 topic pub /topic std_msgs/msg/String "data: 'Hello, world'" ``` -------------------------------- ### Complete Action Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/04-action-clients-and-servers.md A comprehensive example demonstrating the creation and usage of both typed action clients and servers, including goal sending, feedback, cancellation handling, and result retrieval. ```APIDOC ## Complete Action Example ### Description This example illustrates a complete workflow for R2R actions, showcasing how to set up both an action client and an action server for the same action type. It covers sending goals, publishing feedback, handling cancellations, and receiving results. ### Code ```rust use r2r::{Node, Context}; use futures::stream::StreamExt; let ctx = Context::create()?; let mut node = Node::create(ctx, "action_node", "/")?; // Create both client and server for the same action let action_client = node.create_action_client::("/my_action")?; let action_server = node.create_action_server::("/my_action")?; // Server task spawner.spawn_local(async move { let mut stream = action_server; while let Some(goal_request) = stream.next().await { let (mut goal, mut cancel_stream) = goal_request.accept()?; spawner.spawn_local(async move { for i in 0..10 { // Publish feedback goal.publish_feedback(MyAction::Feedback { progress: i * 10 }).ok(); // Check for cancellation if let Ok(Some(cancel)) = cancel_stream.try_next().await { cancel.accept(); goal.cancelled(MyAction::Result { success: false }).ok(); return; } } goal.succeed(MyAction::Result { success: true }).ok(); }); } })?; // Client task spawner.spawn_local(async move { let goal = MyAction::Goal { target: 42 }; let goal_future = action_client.send_goal_request(goal)?; let (goal_handle, result_future, mut feedback) = goal_future.await?; // Listen for feedback while let Some(fb) = feedback.next().await { println!("Feedback: {}", fb.progress); } // Wait for result let (status, result) = result_future.await?; println!("Status: {:?}, Result: {:?}", status, result); })?; ``` ``` -------------------------------- ### Complete Parameter Example in r2r Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Demonstrates initializing a struct with default parameters, creating a parameter handler, listening for changes, and the main node loop. This example requires the `RosParams` derive macro. ```rust use r2r::{Node, Context, RosParams, Parameter, ParameterValue}; use std::sync::{Arc, Mutex}; #[derive(RosParams, Default)] struct RobotConfig { /// Maximum speed in m/s max_speed: f64, /// Enable autonomous navigation autonomous_enabled: bool, } #[tokio::main] async fn main() -> Result<(), Box> { let ctx = Context::create()?; let mut node = Node::create(ctx, "robot_node", "/robot")?; // Initialize config with defaults let config = Arc::new(Mutex::new(RobotConfig { max_speed: 1.0, autonomous_enabled: false, })); // Create parameter handler let (param_handler, mut param_events) = node.make_derived_parameter_handler( config.clone() )?; // Spawn parameter handler tokio::spawn(param_handler); // Listen for parameter changes tokio::spawn(async move { while let Some((name, value)) = param_events.next().await { println!("Parameter {} changed to {:?}", name, value); // Verify the change through the struct let cfg = config.lock().unwrap(); println!("Current config: max_speed={}, autonomous={}", cfg.max_speed, cfg.autonomous_enabled); } }); // Main loop loop { node.spin_once(std::time::Duration::from_millis(100)); tokio::task::yield_now().await; } } ``` -------------------------------- ### Service Type Example (AddTwoInts) Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md An example of a generated service type for `AddTwoInts.srv`, demonstrating the structure of request, response, and the implementation of `WrappedServiceTypeSupport`. ```rust // Generated from example_interfaces/srv/AddTwoInts.srv pub mod add_two_ints { pub struct AddTwoInts; pub struct Request { pub a: i64, pub b: i64, } pub struct Response { pub sum: i64, } impl WrappedServiceTypeSupport for AddTwoInts { type Request = Request; type Response = Response; // ... } } ``` -------------------------------- ### Subscriber Stream Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/TYPES.md Subscribers are returned as `impl Stream`. This example shows how to subscribe to a topic and process incoming messages. ```rust node.subscribe::(...) -> Result + Unpin> ``` -------------------------------- ### Source ROS2 Workspace Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Source the ROS2 environment setup script before running r2r applications. ```bash source /opt/ros/humble/setup.bash ``` -------------------------------- ### NavigateToPose Action Type Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md An example implementation of the WrappedActionTypeSupport trait for the NavigateToPose action, generated from its ROS 2 definition. ```rust // Generated from nav2_msgs/action/NavigateToPose.action pub mod navigate_to_pose { pub struct NavigateToPose; pub struct Goal { pub pose: geometry_msgs::msg::PoseStamped, } pub struct Result { pub error_code: i32, } pub struct Feedback { pub current_pose: geometry_msgs::msg::PoseStamped, pub distance_remaining: f64, } impl WrappedActionTypeSupport for NavigateToPose { type Goal = Goal; type Result = Result; type Feedback = Feedback; // ... } } ``` -------------------------------- ### Typed Publisher and Subscriber Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/02-publishers-and-subscribers.md Demonstrates creating a typed publisher and subscriber, spawning a task to handle incoming messages, and publishing messages. ```rust use r2r::{Node, Context, QosProfile, std_msgs}; use futures::stream::StreamExt; let ctx = Context::create()?; let mut node = Node::create(ctx, "pub_sub_node", "/")?; // Create publisher and subscriber let publisher = node.create_publisher::( "/test_topic", QosProfile::default() )?; let subscriber = node.subscribe::( "/test_topic", QosProfile::default() )?; // Spawn subscriber task spawner.spawn_local(async move { let mut sub = subscriber; while let Some(msg) = sub.next().await { println!("Received: {}", msg.data); } })?; // Publish messages for i in 0..10 { let msg = std_msgs::msg::String { data: format!("Message {}", i), }; publisher.publish(&msg)?; } ``` -------------------------------- ### Logging Example with log Crate Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Demonstrates how to use the standard Rust `log` crate macros for emitting log messages. Ensure the `log` crate is added as a dependency. ```rust use log::{debug, info, warn, error}; let node_name = "my_node"; debug!("Debug message"); info!("Info: {}", node_name); warn!("Warning from {}", node_name); error!("Error in {}", node_name); ``` -------------------------------- ### Rust Parameter Listening Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md This pattern listens for changes in parameters and reacts to them, such as printing the parameter name and its new value. ```rust spawner.spawn_local(async move { while let Some((name, value)) = param_events.next().await { println!("Parameter {} changed to {:?}", name, value); } })?; ``` -------------------------------- ### Complete Action Client-Server Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/04-action-clients-and-servers.md Demonstrates a full cycle of action communication, including creating a node, setting up both a client and a server for the same action, handling goals, publishing feedback, and receiving results. Requires a custom action type `MyAction` with `Goal`, `Feedback`, and `Result` variants. ```rust use r2r::{Node, Context}; use futures::stream::StreamExt; let ctx = Context::create()?; let mut node = Node::create(ctx, "action_node", "/")?; // Create both client and server for the same action let action_client = node.create_action_client::("/my_action")?; let action_server = node.create_action_server::("/my_action")?; // Server task spawner.spawn_local(async move { let mut stream = action_server; while let Some(goal_request) = stream.next().await { let (mut goal, mut cancel_stream) = goal_request.accept()?; spawner.spawn_local(async move { for i in 0..10 { // Publish feedback goal.publish_feedback(MyAction::Feedback { progress: i * 10 }).ok(); // Check for cancellation if let Ok(Some(cancel)) = cancel_stream.try_next().await { cancel.accept(); goal.cancelled(MyAction::Result { success: false }).ok(); return; } } goal.succeed(MyAction::Result { success: true }).ok(); }); } })?; // Client task spawner.spawn_local(async move { let goal = MyAction::Goal { target: 42 }; let goal_future = action_client.send_goal_request(goal)?; let (goal_handle, result_future, mut feedback) = goal_future.await?; // Listen for feedback while let Some(fb) = feedback.next().await { println!("Feedback: {}", fb.progress); } // Wait for result let (status, result) = result_future.await?; println!("Status: {:?}, Result: {:?}", status, result); })?; ``` -------------------------------- ### Rust Action Handler Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md This pattern handles action goals, spawning a new task for each accepted goal to manage its lifecycle, feedback, and final result independently. ```rust spawner.spawn_local(async move { let mut server = action_server; while let Some(goal_req) = server.next().await { let (mut goal, mut cancel_stream) = goal_req.accept()?; spawner.spawn_local(async move { // Handle goal loop { if let Ok(Some(cancel)) = cancel_stream.try_next().await { cancel.accept(); goal.cancelled(result)?; break; } goal.publish_feedback(feedback)?; if done { goal.succeed(result)?; break; } } }); } })?; ``` -------------------------------- ### Implement r2r Service Server and Client Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/03-services-and-clients.md This example demonstrates how to create a service server that handles requests and a client that sends requests to the service. Ensure the service type (e.g., AddTwoInts) and its associated Request and Response types implement WrappedTypesupport. Type support is typically generated by r2r's code generation. ```rust use r2r::{Node, Context, QosProfile}; use futures::stream::StreamExt; // Assuming we have a service type: example_interfaces::srv::AddTwoInts // With Request { a: i64, b: i64 } and Response { sum: i64 } let ctx = Context::create()?; let mut node = Node::create(ctx, "service_node", "/")?; // Create server let server_stream = node.create_service::( "/add_two_ints", QosProfile::services_default() )?; spawner.spawn_local(async move { let mut stream = server_stream; while let Some(request) = stream.next().await { let sum = request.message.a + request.message.b; let response = AddTwoInts::Response { sum }; let _ = request.respond(response); } })?; // Create client (in same or different node/process) let client = node.create_client::("/add_two_ints")?; // Send request let request = AddTwoInts::Request { a: 5, b: 3 }; let response = client.request(&request)?.await?; println!("5 + 3 = {}", response.sum); ``` -------------------------------- ### Rust Service Handler Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Implement this pattern to handle incoming service requests asynchronously. Each request is processed, and a response is sent back via the provided mechanism. ```rust spawner.spawn_local(async move { let mut service = service_stream; while let Some(req) = service.next().await { let response = handle(&req.message); req.respond(response)?; } })?; ``` -------------------------------- ### Get Parameters via Node (Simple Access) Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Access parameters directly and type-safely from a node. Ensure the parameter exists before attempting to get it. ```rust let timeout: f64 = node.get_parameter("timeout")?; let enabled: bool = node.get_parameter("enabled")?; ``` -------------------------------- ### Basic RosParams Struct Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Illustrates how to use the `#[derive(RosParams)]` macro on a struct to automatically handle ROS parameters. Fields with doc comments are documented as parameters. ```rust use r2r::RosParams; #[derive(RosParams, Default)] pub struct MyConfig { /// Maximum speed in m/s max_speed: f64, /// Enable autonomous mode autonomous: bool, /// List of allowed commands commands: Vec, } fn main() -> Result<(), Box> { let config = Arc::new(Mutex::new(MyConfig::default())); // Create handler for this struct let (param_future, param_events) = node.make_derived_parameter_handler(config.clone())?; // Now external clients can set parameters with type checking Ok(()) } ``` -------------------------------- ### Rust Subscriber Loop Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Use this pattern to continuously process messages from a stream. Ensure the subscriber is properly initialized before entering the loop. ```rust spawner.spawn_local(async move { let mut sub = subscriber; while let Some(msg) = sub.next().await { process(msg); } })?; ``` -------------------------------- ### Basic ROS 2 Node with Pub/Sub in Rust Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/README.md This snippet demonstrates how to create a ROS 2 node in Rust using the r2r library, including setting up a publisher and a subscriber. It shows the basic lifecycle of a ROS 2 node: context creation, node initialization, topic communication setup, and a main loop for processing messages. ```rust use r2r::{Context, Node, QosProfile}; use futures::stream::StreamExt; #[tokio::main] async fn main() -> Result<(), Box> { // 1. Create context let ctx = Context::create()?; // 2. Create node let mut node = Node::create(ctx, "my_node", "/")?; // 3. Create publishers/subscribers/services let publisher = node.create_publisher::( "/topic", QosProfile::default() )?; let subscriber = node.subscribe::( "/topic", QosProfile::default() )?; // 4. Spawn async tasks tokio::spawn(async move { let mut sub = subscriber; while let Some(msg) = sub.next().await { println!("Received: {}", msg.data); } }); // 5. Main loop loop { node.spin_once(std::time::Duration::from_millis(10)); tokio::task::yield_now().await; } } ``` -------------------------------- ### Set Parameters via ROS2 Command Line Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Parameters are typically set externally using ROS2 command-line tools. This example shows how to set a parameter value. ```bash # Via ros2 command line ros2 param set /node_name param_name 3.14 # Parameters are then received via the parameter event stream ``` -------------------------------- ### Make Service Requests Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Use the `client.request` method to send a request to a service. This returns a future that resolves to the service response. Ensure you await the future to get the result. ```rust let response_future = client.request(&request)?; let response = response_future.await?; ``` -------------------------------- ### Build r2r Library Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/README.md Build the r2r library with specific ROS2 packages filtered. Ensure ROS2 workspace is sourced and Rust 1.56+ is installed. ```bash source /opt/ros/humble/setup.bash export IDL_PACKAGE_FILTER="std_msgs:geometry_msgs" cargo build --release ``` -------------------------------- ### Get Parameters via Parameter Handler (Structured) Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Create a structured parameter handler to listen for parameter changes. This is useful for reacting to external updates. ```rust let (param_future, mut param_events) = node.make_derived_parameter_handler( Arc::new(Mutex::new(config)) )?; // Listen for changes while let Some((name, value)) = param_events.next().await { println!("Parameter {} changed", name); } ``` -------------------------------- ### Rust Timer Loop Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Use this pattern for tasks that need to be executed periodically. The loop waits for the timer to tick before performing its work. ```rust spawner.spawn_local(async move { loop { let elapsed = timer.tick().await?; // Do periodic work } })?; ``` -------------------------------- ### Get Publisher Information by Topic Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Fetch detailed information about publishers on a specific topic, including node name, namespace, topic type, and QoS profile. This helps in understanding the network topology. ```rust let publishers = node.get_publishers_info_by_topic("/my_topic")?; for pub_info in publishers { println!("Publisher:"); println!(" Node: {}", pub_info.node_name); println!(" Namespace: {}", pub_info.node_namespace); println!(" Type: {}", pub_info.topic_type); println!(" QoS: {:?}", pub_info.qos_profile); } ``` -------------------------------- ### Creating a Custom QoS Profile Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Demonstrates how to create a custom QoS profile by instantiating the QosProfile struct with specific policy settings and then using it to create a publisher. ```rust use r2r::{QosProfile, HistoryPolicy, ReliabilityPolicy, DurabilityPolicy, LivelinessPolicy}; use std::time::Duration; let custom_qos = QosProfile { history: HistoryPolicy::KeepLast, depth: 50, reliability: ReliabilityPolicy::BestEffort, durability: DurabilityPolicy::Volatile, deadline: Duration::from_secs(1), lifespan: Duration::from_secs(10), liveliness: LivelinessPolicy::Automatic, liveliness_lease_duration: Duration::from_secs(5), avoid_ros_namespace_conventions: false, }; let publisher = node.create_publisher::("/topic", custom_qos)?; ``` -------------------------------- ### Get All Topic Names and Types Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Retrieve a list of all available topic names and their associated message types in the ROS 2 network. This is useful for discovering available topics. ```rust let topics = node.get_topic_names_and_types()?; for (topic_name, types) in topics { println!("{}: {:?}", topic_name, types); } ``` -------------------------------- ### Discover ROS2 Topics and Types Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Use this method to get a map of all topic names and their corresponding message types in the ROS2 graph. This is useful for understanding the available communication channels. ```rust let topics = node.get_topic_names_and_types()?; for (topic_name, types) in topics { println!(“{}: {:?}”, topic_name, types); } ``` -------------------------------- ### Configure QoS and Timers with System and ROS Clocks Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Sets up a publisher with a custom QoS profile (reliable, volatile, keep last 20 messages) and demonstrates the creation of both wall timers (system time) and ROS timers (simulated time). It also shows how to access and print ROS time. ```rust use r2r::{Node, Context, QosProfile, HistoryPolicy, ReliabilityPolicy, DurabilityPolicy, LivelinessPolicy, Clock, ClockType}; use std::time::Duration; #[tokio::main] async fn main() -> Result<(), Box> { let ctx = Context::create()?; let mut node = Node::create(ctx, "timing_node", "/")?; // Custom QoS: reliable, low latency, keep last 20 messages let qos = QosProfile { history: HistoryPolicy::KeepLast, depth: 20, reliability: ReliabilityPolicy::Reliable, durability: DurabilityPolicy::Volatile, deadline: Duration::from_millis(100), lifespan: Duration::from_secs(5), liveliness: LivelinessPolicy::Automatic, liveliness_lease_duration: Duration::from_secs(10), avoid_ros_namespace_conventions: false, }; let publisher = node.create_publisher::("/data", qos)?; // Create clocks let system_clock = Clock::create(ClockType::SystemTime)?; let ros_clock = node.get_ros_clock(); // Wall timer (system time) let mut wall_timer = node.create_wall_timer(Duration::from_millis(100))?; // ROS timer (respects simulated time) let mut ros_timer = node.create_timer(Duration::from_secs(1))?; // Check timing { let mut ros = ros_clock.lock().unwrap(); println!("ROS time: {:?}", ros.get_now()?); } // Main loop tokio::spawn(async move { loop { let elapsed = wall_timer.tick().await; if let Ok(dur) = elapsed { let msg = std_msgs::msg::String { data: format!("Wall timer: {:?}", dur), }; publisher.publish(&msg).ok(); } } }); tokio::spawn(async move { loop { let elapsed = ros_timer.tick().await; if let Ok(dur) = elapsed { println!("ROS timer: {:?}", dur); } } }); loop { node.spin_once(Duration::from_millis(10)); tokio::task::yield_now().await; } } ``` -------------------------------- ### node.namespace Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Gets the namespace assigned to the node. ```APIDOC ## node.namespace ### Description Gets the namespace assigned to the node. ### Method Rust method call ### Signature `node.namespace() -> Result` ### Response #### Success Response - **String** - The node's namespace ### Example ```rust let ns = node.namespace()?; ``` ``` -------------------------------- ### node.name Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Gets the local name of the node, excluding its namespace. ```APIDOC ## node.name ### Description Gets the local name of the node, excluding its namespace. ### Method Rust method call ### Signature `node.name() -> Result` ### Response #### Success Response - **String** - The node's local name ### Example ```rust let name = node.name()?; println!("Node name: {}", name); ``` ``` -------------------------------- ### Using Simulated Time in Rust Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Demonstrates setting up a ROS 2 node in Rust and creating a timer that will utilize simulated time when the '/use_sim_time' parameter is enabled. ```rust use r2r::{Node, Context, ClockType}; let ctx = Context::create()?; let mut node = Node::create(ctx, "sim_node", "/")?; // Enable use_sim_time in launch file or via command line // Then create timers - they will use simulation time let mut ros_timer = node.create_timer(Duration::from_secs(1))?; // This timer waits for /clock messages // In simulation, it may complete in seconds or milliseconds // depending on simulation speed ``` -------------------------------- ### logger Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Gets the logger name for this node, which can be used with ROS2 logging functions. ```APIDOC ## logger ### Description Gets the logger name for this node, suitable for use with ROS2 logging. ### Method `node.logger(&self) -> &str` ### Returns `&str` - The logger name ``` -------------------------------- ### Enable Simulated Time via Command Line Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Launches a ROS 2 node with simulated time enabled using command-line arguments. ```bash ros2 run my_package my_node --ros-args -p use_sim_time:=true ``` -------------------------------- ### Get Node Name Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Retrieve the local name of the node, excluding its namespace. ```rust let name = node.name()?; println!("Node name: {}", name); ``` -------------------------------- ### Rust Custom QoS Profile Configuration Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Illustrates how to define a custom Quality of Service (QoS) profile in Rust by manually setting parameters like history, depth, reliability, and durability. ```rust QosProfile { history: HistoryPolicy::KeepLast, depth: 10, reliability: ReliabilityPolicy::Reliable, durability: DurabilityPolicy::Volatile, deadline: Duration::from_secs(1), lifespan: Duration::from_secs(10), liveliness: LivelinessPolicy::Automatic, liveliness_lease_duration: Duration::from_secs(5), avoid_ros_namespace_conventions: false, } ``` -------------------------------- ### ROS 2 Node Parameter Retrieval Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Get the value of a specific parameter by name. ```rust node.get_parameter(name: &str) -> Result ``` -------------------------------- ### Rust Predefined QoS Profiles Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Shows how to select predefined Quality of Service (QoS) profiles for different communication needs in Rust. These profiles offer common configurations for reliability and latency. ```rust QosProfile::default() // General purpose reliable ``` ```rust QosProfile::sensor_data() // Best-effort, low latency ``` ```rust QosProfile::parameters() // Reliable, high depth ``` ```rust QosProfile::services_default() // Service communication ``` -------------------------------- ### Get Non-existent Parameter Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/06-errors.md Accessing a parameter that has not been declared or set on a node will raise an InvalidParameterName error. ```rust let value: f64 = node.get_parameter("nonexistent")?; // Error: InvalidParameterName { name: "nonexistent" } ``` -------------------------------- ### Geometry Pose Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of a Pose message structure from the geometry_msgs library, representing position and orientation. ```rust // Pose Pose { position: Point, orientation: Quaternion, } ``` -------------------------------- ### Geometry Transform Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of a Transform message structure from the geometry_msgs library, combining translation and rotation. ```rust // Transform Transform { translation: Vector3, rotation: Quaternion, } ``` -------------------------------- ### Create Action Client Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/04-action-clients-and-servers.md Instantiates a typed action client for a specific action name. Ensure the action type and name are correctly specified. ```rust use r2r::ActionClient; // Assuming NavigateToPose is an action type let action_client = node.create_action_client::( "/navigate_to_pose" )?; ``` -------------------------------- ### Geometry Quaternion Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of a Quaternion message structure from the geometry_msgs library, used for representing rotations. ```rust // Quaternion Quaternion { x: f64, y: f64, z: f64, w: f64 } ``` -------------------------------- ### Geometry Twist Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of a Twist message structure from the geometry_msgs library, representing linear and angular velocities. ```rust // Twist (velocity) Twist { linear: Vector3, angular: Vector3, } ``` -------------------------------- ### Geometry Point Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of a 3D Point message structure from the geometry_msgs library, used for representing coordinates. ```rust // Point (3D) Point { x: f64, y: f64, z: f64 } ``` -------------------------------- ### Deriving RosParams for RobotConfig Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Example of deriving the RosParams trait for a RobotConfig struct, enabling automatic parameter management. ```rust use r2r::RosParams; #[derive(RosParams)] pub struct RobotConfig { /// Maximum speed in m/s max_speed: f64, /// Enable safety features safety_enabled: bool, /// Allowed commands allowed_commands: Vec, } ``` -------------------------------- ### get_publishers_info_by_topic Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Gets detailed information about all publishers on a specific topic, including node names, namespaces, and QoS settings. ```APIDOC ## get_publishers_info_by_topic ### Description Gets detailed information about all publishers on a specific topic. ### Method `node.get_publishers_info_by_topic(&self, topic_name: &str) -> Result>` ### Parameters #### Path Parameters - **topic_name** (str) - Required - Name of the topic ### Returns `Result>` - Information about publishers including node names, namespaces, and QoS settings ``` -------------------------------- ### Send Action Goals Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Initiate an action by sending a goal request using `client.send_goal_request`. This returns futures for the goal status, result, and a stream for feedback. You can also manage the goal's status and cancellation separately. ```rust client.send_goal_request(goal: T::Goal) -> Result, impl Future>, impl Stream)>>> goal_handle.get_status(&self) -> Result goal_handle.cancel(&self) -> Result>> ``` -------------------------------- ### Get Clock Type Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Returns the type of the clock instance. Use this to check if the clock is SystemTime, RosTime, or SteadyTime. ```rust let clock_type = clock.get_clock_type(); ``` -------------------------------- ### Get Current Time Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Retrieves the current time from a clock instance. The time is returned as a Duration since the epoch. ```rust let now = clock.get_now()?; println!("Current time: {:?}", now); ``` -------------------------------- ### Creating an Action Server Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/04-action-clients-and-servers.md Creates a typed action server for a specific action type. This returns a stream of incoming goal requests that the server will process. ```rust let action_server = node.create_action_server( "/navigate_to_pose" )?; spawner.spawn_local(async move { let mut stream = action_server; while let Some(goal_request) = stream.next().await { // Accept the goal let (mut goal, mut cancel_stream) = goal_request.accept()?; // Handle the goal in a separate task spawner.spawn_local(async move { let mut progress = 0.0; loop { // Simulate work progress += 0.1; // Check for cancellation if let Ok(Some(cancel_req)) = cancel_stream.try_next().await { cancel_req.accept(); goal.cancelled(/* result */).ok(); break; } // Publish feedback let feedback = NavigateToPose::Feedback { distance_remaining: (1.0 - progress) * 100.0, }; goal.publish_feedback(feedback).ok(); if progress >= 1.0 { goal.succeed(/* result */)?; break; } } }); } })?; ``` -------------------------------- ### RosParams Trait Definition Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Defines the interface for types that manage ROS2 parameters, including registration, getting, setting, and checking. ```rust pub trait RosParams { fn register_parameters( &mut self, prefix: &str, desc: Option, params: &mut IndexMap, ) -> Result<()>; fn get_parameter(&mut self, param_name: &str) -> Result; fn set_parameter(&mut self, param_name: &str, param_val: &ParameterValue) -> Result<()>; fn check_parameter(&self, param_name: &str, param_val: &ParameterValue) -> Result<()>; } ``` -------------------------------- ### Create a ROS2 Node Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Use Node::create to initialize a new ROS2 node with a given context, name, and namespace. ```rust use r2r::Context; let ctx = Context::create()?; let mut node = Node::create(ctx, "my_node", "/namespace")?; ``` -------------------------------- ### ROS 2 Node Action Server Creation Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Create an action server that streams incoming goal requests. ```rust node.create_action_server(action_name: &str) -> Result>> ``` -------------------------------- ### Standard ROS Boolean Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of creating a ROS Boolean message using the r2r library's std_msgs module. ```rust // Boolean msg::Bool { data: bool } ``` -------------------------------- ### Node::create Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Creates a new ROS2 node within the given context. This is the entry point for initializing a ROS2 node. ```APIDOC ## Node::create ### Description Creates a new ROS2 node within the given context. This is the entry point for initializing a ROS2 node. ### Method Rust function call ### Signature `Node::create(ctx: Context, name: &str, namespace: &str) -> Result` ### Parameters #### Path Parameters - **ctx** (Context) - Required - The context created via `Context::create()` - **name** (String) - Required - Name of the node (must be valid ROS2 identifier) - **namespace** (String) - Required - Namespace for the node (e.g., "/" or "/my_namespace") ### Response #### Success Response - **Node** - A new node instance #### Error Conditions - `RCL_RET_ERROR` if the node cannot be initialized ### Example ```rust use r2r::Context; let ctx = Context::create()?; let mut node = Node::create(ctx, "my_node", "/namespace")?; ``` ``` -------------------------------- ### Standard ROS String Message Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Example of creating a ROS String message using the r2r library's std_msgs module. ```rust use r2r::std_msgs::msg; // String message msg::String { data: String } ``` -------------------------------- ### Enable Simulated Time via Parameter Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Sets the '/use_sim_time' parameter to true to enable simulated time for ROS 2 nodes. ```bash ros2 param set /node_name use_sim_time true ``` -------------------------------- ### Get Goal Status Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/04-action-clients-and-servers.md Retrieves the current status of an action goal. Ensure the goal handle is valid and the action client is active. ```rust let status = goal_handle.get_status()?; println!("Goal status: {:?}", status); ``` -------------------------------- ### Create and Use a Wall Timer Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Creates a timer based on the system's wall clock. Use for periodic tasks where absolute timing is not critical. ```rust let mut timer = node.create_wall_timer(Duration::from_millis(100))?; loop { let elapsed = timer.tick().await?; println!("Fired after: {:?}", elapsed); } ``` -------------------------------- ### ROS 2 Node Service Creation Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Create a service server that streams incoming requests. ```rust node.create_service(service_name: &str, qos: QosProfile) -> Result>> ``` -------------------------------- ### Standard ROS Float Messages Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Examples of creating float type messages (Float32, Float64) using the r2r library's std_msgs module. ```rust // Float messages msg::Float32 { data: f32 } msg::Float64 { data: f64 } ``` -------------------------------- ### Create a Typed Publisher Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/02-publishers-and-subscribers.md Use `node.create_publisher` to create a typed publisher for a specific message type. Ensure the topic name and QosProfile are correctly provided. This method returns a `Result` which may contain an error if publisher creation fails. ```rust use r2r::{QosProfile, std_msgs}; let publisher = node.create_publisher::( "/my_topic", QosProfile::default() )?; ``` -------------------------------- ### Get Node's ROS Clock Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/07-qos-and-clocks.md Retrieves the shared ROS time clock associated with a node. This clock is used internally for timer creation. ```rust let ros_clock = node.get_ros_clock(); let mut clock = ros_clock.lock().unwrap(); let now = clock.get_now()?; ``` -------------------------------- ### Action Server API Methods Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Methods for managing action goals and cancel requests. Use these to accept, publish feedback, succeed, abort, or cancel goals, and to accept or reject cancel requests. ```rust goal_request.accept(self) -> Result<(ActionServerGoal, impl Stream)> ``` ```rust goal.publish_feedback(&mut self, feedback: T::Feedback) -> Result<()> ``` ```rust goal.succeed(self, result: T::Result) -> Result<()> ``` ```rust goal.abort(self, result: T::Result) -> Result<()> ``` ```rust goal.cancelled(self, result: T::Result) -> Result<()> ``` ```rust cancel_request.accept(self) ``` ```rust cancel_request.reject(self) ``` -------------------------------- ### Get Parameter Value Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Retrieve a ROS2 parameter by name, with automatic type conversion to the specified type T. Ensure T implements TryInto from ParameterValue. ```rust let param_val: i64 = node.get_parameter("my_param")?; let timeout_secs: f64 = node.get_parameter("timeout")?; ``` -------------------------------- ### Type Conversions Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/05-parameters.md Demonstrates how to convert ParameterValue types into standard Rust types using `TryInto`. This includes conversions for scalar types, arrays, and optional values. ```APIDOC ## Type Conversions `ParameterValue` implements `TryInto` for all scalar types and arrays: ```rust // Scalar conversions let bool_val: bool = param_value.clone().try_into()?; let int_val: i64 = param_value.clone().try_into()?; let float_val: f64 = param_value.clone().try_into()?; let string_val: String = param_value.clone().try_into()?; // Array conversions let int_array: Vec = param_value.clone().try_into()?; let string_array: Vec = param_value.clone().try_into()?; // Optional conversions (NotSet becomes None) let optional_int: Option = param_value.clone().try_into()?; ``` If the type doesn't match, `WrongParameterType` is returned. ``` -------------------------------- ### Clock API Methods Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Utilities for creating and interacting with clocks. Use `Clock::create` to instantiate a clock and `clock.get_now` to retrieve the current time. ```rust Clock::create(ct: ClockType) -> Result ``` ```rust clock.get_now(&mut self) -> Result ``` ```rust clock.get_clock_type(&self) -> ClockType ``` ```rust Clock::to_builtin_time(d: &Duration) -> builtin_interfaces::msg::Time ``` -------------------------------- ### Respond to Service Requests Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Use the `respond` method on the request object to send a response back to the service caller. This is typically done after processing a received request. ```rust let (status, goal) = server.next().await; let response = compute_response(&goal); goal.respond(response)?; ``` -------------------------------- ### ROS 2 Node Action Client Creation Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Create typed and untyped clients for interacting with ROS 2 actions. ```rust node.create_action_client(action_name: &str) -> Result> node.create_action_client_untyped(action_name: &str, action_type: &str) -> Result ``` -------------------------------- ### Creating an Untyped Client Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/03-services-and-clients.md This method allows you to create a client for a service where the type is not known at compile time. It takes the service name and its full type name as arguments. ```APIDOC ## node.create_client_untyped ### Description Creates an untyped service client. ### Method `node.create_client_untyped(&mut self, service_name: &str, service_type: &str) -> Result` ### Parameters #### Path Parameters - **service_name** (str) - Required - Service name - **service_type** (str) - Required - Full service type name (e.g., "std_srvs/srv/Empty") ### Returns - `Result` ``` -------------------------------- ### Parameter API - Type Conversion Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Demonstrates converting parameter values to specific types. Use `try_into()` for conversions, which may return an `Option` for types like `i64` that can be absent. ```rust let value: bool = param_value.clone().try_into()?; ``` ```rust let value: Option = param_value.clone().try_into()?; ``` -------------------------------- ### Source ROS2 and Build with Cargo Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Source your ROS2 workspace before building the project with Cargo. This ensures the build environment is correctly configured. ```bash source /opt/ros/humble/setup.bash cargo build ``` -------------------------------- ### Node Action Methods Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Methods for creating and managing ROS2 action clients and servers. ```APIDOC ## Node Action Methods ### `node.create_action_client()` * **Description**: Creates a typed action client for a ROS2 action. * **Parameters**: * `node` (the Node instance) * `action_name`: `&str` - The name of the action. * **Returns**: A `Result` containing an `ActionClient` object. ### `node.create_action_client_untyped()` * **Description**: Creates an untyped action client for a ROS2 action. * **Parameters**: * `node` (the Node instance) * `action_name`: `&str` - The name of the action. * `action_type`: `&str` - The fully qualified action type name. * **Returns**: A `Result` containing an `ActionClientUntyped` object. ### `node.create_action_server()` * **Description**: Creates a ROS2 action server that handles goals of type `T`. * **Parameters**: * `node` (the Node instance) * `action_name`: `&str` - The name of the action. * **Returns**: A `Result` containing a stream of `ActionServerGoalRequest`. ``` -------------------------------- ### WrappedActionTypeSupport Trait Definition Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Defines the trait for action types, specifying the types for Goal, Result, and Feedback, and providing a method to get the action type support structure. ```rust pub trait WrappedActionTypeSupport { type Goal: WrappedTypesupport; type Result: WrappedTypesupport; type Feedback: WrappedTypesupport; fn get_ts() -> &'static rosidl_action_type_support_t; } ``` -------------------------------- ### ROS 2 Node Service Client Creation Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/10-complete-api-reference.md Create typed and untyped clients for making service requests. ```rust node.create_client(service_name: &str) -> Result> node.create_client_untyped(service_name: &str, service_type: &str) -> Result ``` -------------------------------- ### Generated RosParams Trait Methods Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Shows the methods automatically implemented for a struct when `#[derive(RosParams)]` is used. These methods handle registration, getting, setting, and checking parameters. ```rust impl RosParams for MyConfig { fn register_parameters( &mut self, prefix: &str, desc: Option, params: &mut IndexMap, ) -> Result<()>; fn get_parameter(&mut self, param_name: &str) -> Result; fn set_parameter(&mut self, param_name: &str, param_val: &ParameterValue) -> Result<()>; fn check_parameter(&self, param_name: &str, param_val: &ParameterValue) -> Result<()>; } ``` -------------------------------- ### node.create_wall_timer() Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/01-context-and-node.md Creates a wall-clock timer that fires at regular intervals. This timer is best-effort and subject to system scheduling. ```APIDOC ## node.create_wall_timer() ### Description Creates a wall-clock timer that fires at regular intervals. This timer is best-effort and subject to system scheduling. ### Method `create_wall_timer` ### Parameters #### Path Parameters - **period** (Duration) - Required - Time between timer fires ### Returns `Result` - A timer instance ``` -------------------------------- ### Standard ROS Integer Messages Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/08-types-and-messages.md Examples of creating various integer type messages (Int8, Int16, Int32, Int64) using the r2r library's std_msgs module. ```rust // Integer messages msg::Int8 { data: i8 } msg::Int16 { data: i16 } msg::Int32 { data: i32 } msg::Int64 { data: i64 } ``` -------------------------------- ### Node::create_action_server Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/04-action-clients-and-servers.md Creates a typed action server on the given node, allowing it to accept goal requests for a specific action type. ```APIDOC ## Node::create_action_server ### Description Creates a typed action server. ### Method `create_action_server(&mut self, action_name: &str) -> Result> + Unpin>` ### Parameters #### Path Parameters - **action_name** (str) - Required - Action name ### Returns - `Result> + Unpin>`: A stream of incoming goal requests ### Example ```rust let action_server = node.create_action_server::( "/navigate_to_pose" )?; spawner.spawn_local(async move { let mut stream = action_server; while let Some(goal_request) = stream.next().await { // Accept the goal let (mut goal, mut cancel_stream) = goal_request.accept()?; // Handle the goal in a separate task spawner.spawn_local(async move { let mut progress = 0.0; loop { // Simulate work progress += 0.1; // Check for cancellation if let Ok(Some(cancel_req)) = cancel_stream.try_next().await { cancel_req.accept(); goal.cancelled(/* result */).ok(); break; } // Publish feedback let feedback = NavigateToPose::Feedback { distance_remaining: (1.0 - progress) * 100.0, }; goal.publish_feedback(feedback).ok(); if progress >= 1.0 { goal.succeed(/* result */)?; break; } } }); } })?; ``` ``` -------------------------------- ### Nested RosParams Struct Example Source: https://github.com/sequenceplanner/r2r/blob/master/_autodocs/09-utilities-and-macros.md Demonstrates how nested structs with `#[derive(RosParams)]` create hierarchical parameter names on the ROS parameter server. Each nested field is prefixed accordingly. ```rust #[derive(RosParams, Default)] pub struct MotorControl { #[derive(RosParams, Default)] pub left_motor: MotorParams, #[derive(RosParams, Default)] pub right_motor: MotorParams, } #[derive(RosParams, Default)] pub struct MotorParams { /// PWM value pwm: i32, /// Enable motor enabled: bool, } // Creates parameters: // left_motor.pwm // left_motor.enabled // right_motor.pwm // right_motor.enabled ```