Rust机器人中间件库r2r_common的使用,r2r_common为ROS2机器人系统提供高效通信与消息处理功能

Rust机器人中间件库r2r_common的使用

r2r_common是r2r项目的内部依赖库,为ROS2机器人系统提供高效通信与消息处理功能。

安装

在项目目录中运行以下Cargo命令:

cargo add r2r_common

或者在Cargo.toml中添加:

r2r_common = "0.9.5"

示例代码

以下是使用r2r_common创建ROS2节点并发布消息的完整示例:

use r2r::{Context, Node, QosProfile};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建上下文和节点
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "rust_publisher", "")?;
    
    // 创建发布者
    let publisher = node.create_publisher::<std_msgs::msg::String>("topic", QosProfile::default())?;
    
    // 发送消息
    let mut count = 0;
    loop {
        let msg = std_msgs::msg::String {
            data: format!("Hello ROS2 from Rust! {}", count),
        };
        publisher.publish(&msg)?;
        count += 1;
        
        tokio::time::sleep(Duration::from_millis(1000)).await;
    }
}

以下是订阅消息的示例:

use r2r::{Context, Node, QosProfile};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建上下文和节点
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "rust_subscriber", "")?;
    
    // 创建订阅者
    let subscriber = node.subscribe::<std_msgs::msg::String>("topic", QosProfile::default())?;
    
    // 处理接收到的消息
    while let Some(msg) = subscriber.recv().await {
        println!("Received: {}", msg.data);
    }
    
    Ok(())
}

完整示例

以下是一个完整的发布者-订阅者示例,包含在两个独立节点中的实现:

发布者节点 (publisher.rs):

use r2r::{Context, Node, QosProfile};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化上下文和节点
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "rust_publisher", "")?;
    
    // 创建String类型消息的发布者
    let publisher = node.create_publisher::<std_msgs::msg::String>(
        "rust_chatter",  // 话题名称
        QosProfile::default()  // 使用默认QoS配置
    )?;
    
    println!("Publisher started. Sending messages...");
    
    let mut count = 0;
    loop {
        // 创建消息
        let msg = std_msgs::msg::String {
            data: format!("Hello ROS2 from Rust! ({})", count),
        };
        
        // 发布消息
        publisher.publish(&msg)?;
        println!("Sent: {}", msg.data);
        count += 1;
        
        // 每秒发送一次
        tokio::time::sleep(Duration::from_millis(1000)).await;
    }
}

订阅者节点 (subscriber.rs):

use r2r::{Context, Node, QosProfile};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化上下文和节点
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "rust_subscriber", "")?;
    
    // 创建String类型消息的订阅者
    let subscriber = node.subscribe::<std_msgs::msg::String>(
        "rust_chatter",  // 话题名称(与发布者一致)
        QosProfile::default()  // 使用默认QoS配置
    )?;
    
    println!("Subscriber started. Waiting for messages...");
    
    // 持续接收消息
    while let Some(msg) = subscriber.recv().await {
        println!("Received: {}", msg.data);
    }
    
    Ok(())
}

特性

  • 提供ROS2消息的发布/订阅功能
  • 支持服务质量(QoS)配置
  • 异步消息处理
  • 与Rust生态系统无缝集成

许可证

该项目使用MIT许可证。


1 回复

Rust机器人中间件库r2r_common使用指南

概述

r2r_common是一个为Rust语言设计的ROS2机器人中间件库,专门用于在机器人系统中实现高效通信和消息处理。它为ROS2系统提供了Rust原生支持,使开发者能够用Rust构建高性能、安全的机器人应用。

主要特性

  • 提供ROS2消息、服务和动作的Rust实现
  • 支持DDS通信协议
  • 线程安全的API设计
  • 与C++ ROS2节点无缝互操作
  • 支持QoS配置

安装方法

在Cargo.toml中添加依赖:

[dependencies]
r2r = "0.7"

基本使用方法

1. 创建节点和发布者

use r2r::{Context, Node, QosProfile};
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "rust_node", "")?;
    
    let publisher = node.create_publisher::<r2r::std_msgs::msg::String>("/topic", QosProfile::default())?;
    
    let mut count = 0;
    loop {
        let msg = r2r::std_msgs::msg::String {
            data: format!("Hello, ROS2 from Rust! {}", count),
        };
        publisher.publish(&msg)?;
        count += 1;
        
        std::thread::sleep(Duration::from_millis(1000));
    }
}

2. 创建订阅者

use r2r::{Context, Node, QosProfile};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "rust_subscriber", "")?;
    
    let subscription = node.subscribe::<r2r::std_msgs::msg::String>("/topic", QosProfile::default())?;
    
    loop {
        if let Ok(msg) = subscription.recv() {
            println!("Received: {}", msg.data);
        }
    }
}

3. 使用服务

服务端实现:

use r2r::{Context, Node, QosProfile};
use r2r::example_interfaces::srv::AddTwoInts;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "add_two_ints_server", "")?;
    
    let service = node.create_service::<AddTwoInts::Service>("/add_two_ints", QosProfile::default())?;
    
    loop {
        if let Ok((request, response)) = service.rcv_request() {
            let sum = request.a + request.b;
            println!("Got request: {} + {} = {}", request.a, request.b, sum);
            response.send(&AddTwoInts::Response { sum })?;
        }
    }
}

客户端实现:

use r2r::{Context, Node, QosProfile};
use r2r::example_interfaces::srv::AddTwoInts;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "add_two_ints_client", "")?;
    
    let client = node.create_client::<AddTwoInts::Service>("/add_two_ints", QosProfile::default())?;
    
    // 等待服务可用
    while !client.service_ready() {
        std::thread::sleep(std::time::Duration::from_millis(100));
    }
    
    let request = AddTwoInts::Request { a: 5, b: 7 };
    let response = client.request(&request)?.await?;
    
    println!("Response: {}", response.sum);
    Ok(())
}

完整示例代码:自定义消息类型的发布订阅系统

// 1. 首先在项目目录下创建msg/Vector3.msg文件,内容如下:
/*
float32 x
float32 y
float32 z
*/

// 2. 配置Cargo.toml
/*
[dependencies]
r2r = "0.7"

[package.metadata.r2r]
messages = ["msg/Vector3.msg"]
*/

use r2r::{Context, Node, QosProfile};
use std::time::Duration;

mod msg {
    // 自动生成的消息模块
    r2r::include!(messages());
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建上下文和节点
    let ctx = Context::create()?;
    let mut node = Node::create(ctx, "custom_msg_demo", "")?;

    // 创建发布者
    let publisher = node.create_publisher::<msg::Vector3>("/position", QosProfile::default())?;
    
    // 创建订阅者
    let subscription = node.subscribe::<msg::Vector3>("/position", QosProfile::default())?;

    // 启动发布线程
    std::thread::spawn(move || {
        let mut count = 0.0;
        loop {
            let msg = msg::Vector3 {
                x: count,
                y: count * 2.0,
                z: count * 3.0,
            };
            publisher.publish(&msg).unwrap();
            count += 0.1;
            std::thread::sleep(Duration::from_millis(500));
        }
    });

    // 主线程处理订阅消息
    loop {
        if let Ok(msg) = subscription.recv() {
            println!("Received position: x={:.2}, y={:.2}, z={:.2}", 
                msg.x, msg.y, msg.z);
        }
    }
}

高级功能

自定义消息类型

  1. 在msg目录下创建消息定义文件,例如MyMessage.msg
int32 id
string name
float32[] data
  1. 在Cargo.toml中配置消息生成:
[package.metadata.r2r]
messages = ["msg/MyMessage.msg"]
  1. 在代码中使用自定义消息:
use my_package::msg::MyMessage;

let msg = MyMessage {
    id: 42,
    name: "test".into(),
    data: vec![1.0, 2.0, 3.0],
};

QoS配置

use r2r::QosProfile;

let custom_qos = QosProfile {
    reliability: r2r::QosReliabilityPolicy::Reliable,
    history: r2r::QosHistoryPolicy::KeepLast(10),
    durability: r2r::QosDurabilityPolicy::Volatile,
    ..Default::default()
};

let publisher = node.create_publisher::<r2r::std_msgs::msg::String>("/topic", custom_qos)?;

性能优化建议

  1. 对于高频消息,使用Arc共享消息数据避免复制
  2. 考虑使用零拷贝发布模式
  3. 合理配置QoS策略以匹配应用需求
  4. 对大消息使用分片传输

注意事项

  • 确保ROS2环境已正确配置
  • 节点名称在系统中必须唯一
  • 注意消息类型的命名空间与ROS2中的定义一致
  • 在多线程环境中使用时注意线程安全

r2r_common为Rust开发者提供了强大的ROS2集成能力,使得用Rust构建机器人系统变得更加简单高效。

回到顶部