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);
}
}
}
高级功能
自定义消息类型
- 在msg目录下创建消息定义文件,例如
MyMessage.msg
:
int32 id
string name
float32[] data
- 在Cargo.toml中配置消息生成:
[package.metadata.r2r]
messages = ["msg/MyMessage.msg"]
- 在代码中使用自定义消息:
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)?;
性能优化建议
- 对于高频消息,使用
Arc
共享消息数据避免复制 - 考虑使用零拷贝发布模式
- 合理配置QoS策略以匹配应用需求
- 对大消息使用分片传输
注意事项
- 确保ROS2环境已正确配置
- 节点名称在系统中必须唯一
- 注意消息类型的命名空间与ROS2中的定义一致
- 在多线程环境中使用时注意线程安全
r2r_common为Rust开发者提供了强大的ROS2集成能力,使得用Rust构建机器人系统变得更加简单高效。