一、ROS2核心概念与生态:理解DDS、节点、话题、服务、动作的核心机制

各位同学,欢迎来到这门课的第一章。说实话,每次带新人入门ROS2,我都会先问一个问题:你为什么要从ROS1迁移过来?或者,你为什么要直接学ROS2?

答案其实很简单——因为ROS2解决了ROS1里那些让人头疼的“硬伤”。比如节点一多就掉线、实时性没法保证、跨机器通信配置繁琐……这些坑,我当年在项目里都踩过。今天我们就从最核心的概念讲起,把ROS2的“骨架”搭清楚。

1.1 DDS:ROS2的通信基石

ROS2和ROS1最大的区别,就是底层通信换成了DDS(Data Distribution Service)。说白了,DDS是一个“去中心化”的实时数据分发标准。它不像ROS1那样需要一个Master节点来管着所有人,而是每个节点自己就能发现对方、建立连接。

核心优势:

  • 去中心化:没有单点故障,一个节点挂了不影响全局
  • QoS策略:你可以控制消息的可靠性、历史记录、生命周期
  • 跨平台:Windows、Linux、嵌入式系统都能跑

我个人习惯把DDS理解成一个“智能邮局”。你寄信时,可以选“挂号信”(可靠传输)或者“平信”(尽力传输),可以选“保留最近10封”(KEEP_LAST历史策略),甚至可以选“信过了3秒就作废”(LIFESPAN)。这些在ROS1里根本做不到。

避坑指南:我曾经在一个项目中,因为没设置QoS的reliability策略,导致控制指令偶尔丢失,车子在测试时突然急停。后来改成RELIABLE模式,问题就解决了。记住:默认的QoS不一定适合你的场景。

1.2 节点:ROS2的最小执行单元

节点就是ROS2里的“工人”。每个节点负责一个具体的任务,比如读取激光雷达数据、处理图像、控制电机。节点之间通过话题、服务、动作来通信。

在ROS2里,创建一个节点非常简单:

import rclpy
from rclpy.node import Node

class MyNode(Node):
    def __init__(self):
        super().__init__('my_node')
        self.get_logger().info('节点已启动!')

def main(args=None):
    rclpy.init(args=args)
    node = MyNode()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

你想想看,这段代码里最核心的就是rclpy.spin()——它让节点一直“活着”,等待处理消息。如果忘了这行,节点跑完就退出了,啥也干不了。

1.3 话题:发布-订阅模式

话题是ROS2里最常用的通信方式。一个节点发布消息到某个话题,其他节点订阅这个话题就能收到消息。这是“一对多”的异步通信。

举个例子,激光雷达节点发布/scan话题,定位节点订阅它来获取环境数据。这种模式的好处是解耦——发布者和订阅者互不知道对方的存在。

代码示例:发布者

class PublisherNode(Node):
    def __init__(self):
        super().__init__('publisher')
        self.pub = self.create_publisher(String, 'chatter', 10)
        self.timer = self.create_timer(1.0, self.timer_callback)

    def timer_callback(self):
        msg = String()
        msg.data = 'Hello, ROS2!'
        self.pub.publish(msg)

这里有个细节:create_publisher的第三个参数是QoS深度(10),表示缓存10条消息。如果订阅者处理不过来,旧消息会被丢弃。嗯,这里要注意,如果你的系统对实时性要求高,建议用rclpy.qos.QoSProfile来精细控制。

1.4 服务:请求-响应模式

话题是“发了就不管”,服务则是“你问我答”。客户端发送请求,服务端处理并返回响应。适合那些需要确认结果的场景,比如“请帮我规划一条路径”或者“请设置目标速度”。

服务定义使用.srv文件:

# AddTwoInts.srv
int64 a
int64 b
---
int64 sum

服务端实现:

class ServiceNode(Node):
    def __init__(self):
        super().__init__('service_server')
        self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_callback)

    def add_callback(self, request, response):
        response.sum = request.a + request.b
        return response

我在项目中遇到过一个问题:服务调用如果超时,客户端会一直阻塞。所以建议给服务调用加上超时时间,比如client.call_async()配合asyncio.wait_for。

1.5 动作:带反馈的长时间任务

动作是服务的“升级版”。它适合那些需要长时间执行、并且需要中途反馈的任务,比如“导航到目标点”——你可以实时收到当前位置、剩余距离等反馈。

动作定义使用.action文件:

# NavigateToPose.action
# 目标
geometry_msgs/PoseStamped target_pose
---
# 结果
bool success
---
# 反馈
geometry_msgs/PoseStamped current_pose
float32 distance_remaining

动作客户端可以取消任务、接收反馈,这是服务做不到的。我记得有一次做自动泊车,用服务来执行泊车动作,结果车子卡在半路没法取消,只能重启系统。后来改成动作,加了个“紧急停止”的取消逻辑,问题就解决了。

1.6 ROS2与ROS1的核心差异

特性 ROS1 ROS2
通信中间件 自定义TCPROS/UDPROS DDS(如Fast DDS、Cyclone DDS)
节点发现 依赖Master节点 去中心化,自动发现
QoS支持 无 丰富的QoS策略
实时性 不支持 支持(需配置)
跨平台 主要Linux Windows、macOS、嵌入式
Python版本 Python 2 Python 3

说白了,ROS2就是ROS1的“现代化重构”。它保留了ROS1的编程模型(节点、话题、服务、动作),但底层换成了DDS,解决了ROS1在实时性、可靠性、跨平台上的短板。

1.7 搭建完整的开发环境

我个人推荐使用Ubuntu 22.04 + ROS2 Humble。安装步骤很简单:

# 设置locale
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8

# 添加ROS2源
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update && sudo apt install curl
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg

# 安装ROS2 Humble
sudo apt update
sudo apt install ros-humble-desktop

# 设置环境变量
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc

注意:如果你用的是Windows或macOS,建议用Docker或者虚拟机。我试过在Windows上直接编译ROS2,折腾了两天才搞定,后来老老实实用WSL2了。

安装完成后,运行一个简单的测试:

# 终端1:启动talker
ros2 run demo_nodes_cpp talker

# 终端2:启动listener
ros2 run demo_nodes_py listener

如果能看到“Hello World”在终端里来回打印,恭喜你,环境搭建成功了!

知识体系总览

下面这张图总结了本章的核心内容,你可以把它当作ROS2的“地图”:

ROS2核心知识体系 DDS通信中间件 节点 (Node) 话题 (Topic) 服务 (Service) 动作 (Action) 发布-订阅 一对多异步 请求-响应 带反馈长任务 QoS策略控制:可靠性、历史记录、生命周期

这张图里,DDS在最底层,支撑着节点、话题、服务、动作这四大核心。节点是执行单元,话题用于异步通信,服务用于同步请求,动作用于长时间任务。而QoS策略贯穿其中,让你能精细控制通信行为。

我的建议:刚开始学ROS2,不要急着看源码。先动手跑几个demo,感受一下节点怎么启动、话题怎么收发。等你有感觉了,再深入DDS和QoS的细节。我当年就是先跑通了talker-listener,才真正理解了“发布-订阅”是怎么回事。

好了,这一章的内容就到这里。记住:ROS2的核心不是代码,而是通信模型。理解了DDS、节点、话题、服务、动作,你就掌握了ROS2的“魂”。

可可精品资料库