ROS2入门教程
原理、架构与设计思想
info ROS2简介
ROS2(Robot Operating System 2)是一个用于编写机器人软件的灵活框架,是ROS1的下一代版本。ROS2解决了ROS1的许多局限性,提供了更好的实时性、安全性和多平台支持。
ROS2与ROS1的主要区别
特性 | ROS1 | ROS2 |
---|---|---|
通信机制 | 基于TCPROS/UDPROS | 基于DDS(Data Distribution Service) |
系统架构 | 中心化架构(依赖roscore) | 去中心化架构 |
实时性 | 弱实时性,适合实验室环境 | 强实时性,支持硬实时系统 |
多平台支持 | 主要支持Linux | 支持Linux、Windows、macOS和RTOS |
安全性 | 无原生安全支持 | 内建安全功能(身份验证、加密等) |
architecture ROS2架构
ROS2采用分层架构设计,分为三层:应用层、中间件层和操作系统层。
应用层(Application Layer)
中间件层(Middleware Layer)
操作系统层(OS Layer)
应用层:包含用户编写的机器人应用程序,基于ROS2提供的API实现各种功能。
中间件层:包括DDS实现层、RMW(抽象的DDS层)和RCL(ROS2 Client层),负责通信和功能实现。
操作系统层:提供底层支持,ROS2可以运行在Linux、Windows、macOS甚至嵌入式实时操作系统上。
widgets ROS2核心概念
节点(Node)
ROS2中的基本计算单元,每个节点都是一个独立的进程,负责执行特定功能。
话题(Topic)
节点间异步通信的机制,基于发布者-订阅者模型,适合连续数据流传输。
服务(Service)
节点间同步通信的机制,基于请求-响应模型,适合需要即时反馈的场景。
动作(Action)
用于长时间运行的任务,提供目标、反馈和结果的完整通信机制。
参数(Parameter)
用于配置和存储节点的运行时参数,支持动态修改。
sync_alt ROS2通信机制
ROS2采用DDS(Data Distribution Service)作为底层通信中间件,这是一个用于实时分布式系统的数据分发标准。
DDS的主要特点:
- 去中心化的发布/订阅模型
- 支持多种QoS(Quality of Service)策略
- 提供实时、可靠的数据传输
- 支持跨平台、跨语言通信
- 支持多机器人系统和网络通信
ROS2通过RMW(ROS Middleware Interface)层抽象了不同的DDS实现,使得用户可以在不同的DDS实现之间无缝切换。
download ROS2安装教程
设置UTF-8编码环境
添加ROS2软件源和GPG密钥
更新软件包列表
安装ROS2桌面版(推荐)
设置环境变量
详细安装步骤请参考ROS2官方文档或使用鱼香ROS的一键安装工具。
code ROS2代码示例
Python示例 – 简单发布者节点
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class Talker(Node):
def __init__(self):
super().__init__('talker')
self.publisher_ = self.create_publisher(String, 'chatter', 10)
timer_period = 0.5 # 秒
self.timer = self.create_timer(timer_period, self.timer_callback)
self.count = 0
def timer_callback(self):
msg = String()
msg.data = 'Hello World: %d' % self.count
self.publisher_.publish(msg)
self.get_logger().info('Publishing: "%s"' % msg.data)
self.count += 1
def main(args=None):
rclpy.init(args=args)
talker = Talker()
rclpy.spin(talker)
talker.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
C++示例 – 简单订阅者节点
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
class Listener : public rclcpp::Node {
public:
Listener() : Node("listener") {
subscription_ = this->create_subscription(
"chatter", 10, std::bind(&Listener::topic_callback, this, std::placeholders::_1));
}
private:
void topic_callback(const std_msgs::msg::String::SharedPtr msg) const {
RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
}
rclcpp::Subscription::SharedPtr subscription_;
};
int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared());
rclcpp::shutdown();
return 0;
}
Go示例 – 简单发布者节点
package main
import (
"context"
"fmt"
"time"
"github.com/ros2-go/ros2"
"github.com/ros2-go/ros2/msg/std_msgs"
)
func main() {
ctx := context.Background()
node, err := ros2.NewNode(ctx, "go_talker")
if err != nil {
panic(err)
}
defer node.Close()
pub, err := node.CreatePublisher(std_msgs.StringType, "chatter")
if err != nil {
panic(err)
}
count := 0
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ticker.C. msg := std_msgs.String{Data: fmt.Sprintf("Hello World: %d", count)}✅
pub.Publish(msg)
fmt.Printf("Publishing: '%s'\n", msg.Data)
count++
case <-ctx.Done():
return
}
}
}
Go示例 - 简单订阅者节点
package main
import (
"context"
"fmt"
"github.com/ros2-go/ros2"
"github.com/ros2-go/ros2/msg/std_msgs"
)
func main() {
ctx := context.Background()
node, err := ros2.NewNode(ctx, "go_listener")
if err != nil {
panic(err)
}
defer node.Close()
sub, err := node.CreateSubscription(std_msgs.StringType, "chatter", func(msg std_msgs.String) {
fmt.Printf("I heard: '%s'\n", msg.Data)
})
if err != nil {
panic(err)
}
// 保持节点运行
<-ctx.Done()
}
Go语言在ROS2中的支持:
- Go语言通过第三方库(如 https://github.com/tiiuae/rclgo )支持ROS2
- 支持节点、话题、服务等核心ROS2概念
- 适合需要高性能和并发处理的机器人应用
- 提供简洁的API和良好的类型安全