Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions 软件(Software)/ROS/ROS2/(ZhaoCake-2026-02)关于ROS2的DDS通信.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# 关于ROS2的DDS通信

如果你以后要从事 ROS 2 相关的工作,那么 DDS 就是一个必然会遇到的核心话题。什么是 DDS?它有什么作用?为何它如此重要?

## 1. 引言:ROS 1 的阿喀琉斯之踵

在正式介绍 DDS 之前,我们不妨先回顾一下 ROS 1 时代的那些“陈年旧账”。

### 痛点回顾

如果你做过 ROS 1 的多机通信项目,你一定有过这样的痛苦回忆:

- **唯一的“大脑” (Roscore)**:ROS 1 强依赖于一个中心主节点 `roscore`。如果它挂了,整个系统就瘫痪了。这种单点故障(Single Point of Failure)让它很难应用于对可靠性要求极高的工业场景。
- **IP 配置噩梦**:在多机通信时,你需要小心翼翼地配置 `ROS_MASTER_URI` 和 `ROS_IP`。一旦 WiFi 信号不好导致 IP 变动,或者网络配置稍有差错,连接就会瞬间断开,且很难自动恢复。
- **“一刀切”的通信模式**:ROS 1 底层基于 TCP/UDP。虽然 TCP 提供了可靠传输,UDP 提供了低延迟,但它们缺乏针对机器人应用场景的精细化控制。比如:“我希望这个雷达数据尽可能快,丢包也无所谓”和“我希望这个控制指令绝对可靠,慢一点没关系”在 ROS 1 中很难灵活切换和共存。

### 引入主角:DDS

ROS 2 的变革不仅是 API 的换皮,更是一次底层的换血。其中最大的改变,就是引入了 **DDS (Data Distribution Service)** 标准作为其通信中间件。

**核心论点:** DDS 不是简单的“换个协议”,而是将 ROS 从“科研玩具”推向“工业级应用”的关键一步。它赋予了 ROS 2 真正的分布式能力、实时性保障以及工业级的可靠性。

---

## 2. 什么是 DDS?(概念扫盲)

### 定义

DDS(Data Distribution Service)是由 **OMG (Object Management Group)** 组织制定的一套工业级数据分发标准。
在此之前,它早已在美军舰艇作战系统、金融高频交易、航空航天等对数据实时性和可靠性要求极高的领域证明了自己的价值。简单来说,它是通信界的“特种部队”。

### 核心架构:DCPS

DDS 的核心理念是 **DCPS (Data-Centric Publish-Subscribe)**,即“以数据为中心的发布-订阅”。

- **传统网络编程**:关注的是“连接”。建立 Socket -> 维护连接 -> 发送数据。如果连接断了,你需要处理重连逻辑。
- **DDS**:关注的是“数据”。我只关心“我要发什么数据”或者“我要收什么数据”。至于数据怎么切片、怎么路由、丢包了怎么重发、网络断了怎么缓存,统统交给 DDS 中间件处理。**“不管你怎么传,我只要数据到了就行。”**

### ROS 2 的架构

为了兼容不同的 DDS 实现,ROS 2 设计了一个巧妙的抽象层。

顶层:User Code (你的 C++/Python 代码)
第二层:ROS Client Library (rclcpp / rclpy)
第三层:RMW (ROS Middleware Interface, 中间件抽象层)
底层:DDS Implementation (FastDDS, CycloneDDS, RTI Connext, etc.)

### 亮点:RMW (ROS Middleware)

ROS 2 并不绑定某一个特定的 DDS 库。通过 RMW 层,你可以像给汽车换轮胎一样,根据你的需求切换底层的 DDS 厂商:

- **Fast DDS (eProsima)**:默认实现,功能全面,开源社区活跃。
- **Cyclone DDS (Eclipse)**:小巧精悍,资源占用低,也是很多项目的首选。
- **RTI Connext**:商业化方案,功能最强,但要花钱。

这种设计的好处是,你不需要修改一行应用层代码,只需要改一个环境变量,就能瞬间切换通信内核。

> 笔者最早接触到DDS相关概念就是在学习Navigation2库的时候涉及到了更换前两个DDS库。

---

## 3. 核心机制一:去中心化的“自动发现” (Discovery)

### 问题解决

还记得 ROS 1 那个必须要先启动的 `roscore` 吗?在 ROS 2 中,**Master 节点消失了**。

### 工作原理

ROS 2 的节点是如何在茫茫网络中找到彼此的呢?这归功于 DDS 的 **RTPS (Real-Time Publish Subscribe)** 协议自带的自动发现机制。

1. **大喇叭广播 (Multicast)**:当一个节点启动时,它会向局域网内的一个预定多播地址(Multicast Address)发送“公告”:
> “我是节点 A,我发布 Topic X,我订阅 Topic Y,我的 QoS 是 Z。”
2. **建立连接**:局域网内的其他节点听到这个广播后,会检查自己的发布/订阅列表。如果发现匹配(Topic 名相同且 QoS 兼容),它们就会与新节点建立点对点的单播(Unicast)连接。

### 优势

- **零配置**:只要在同一个局域网(且支持多播),节点开机即连,无需指定 Master IP。
- **高容错**:真正的分布式系统。任何一个节点(哪怕是原来的核心节点)崩溃,都不会影响其他节点之间的通信。
- **动态扩展**:随时加入新机器,系统自动感知。

---

## 4. 核心机制二:QoS(服务质量)—— 博客的重头戏

### 为什么需要 QoS?

现实世界中的网络环境是复杂的,不仅 WiFi 会丢包,带宽也有限。更重要的是,在机器人系统中,不同的数据有着完全不同的“身价”和“时效性”。
DDS 允许我们为每个 Topic 甚至每个发布者/订阅者定制 **QoS (Quality of Service)** 策略,这是 ROS 1 完全不具备的能力。

### 四大核心 QoS 策略详解

#### 1. Reliability(可靠性):丢包了怎么办?

- **Best Effort (尽力而为)**:只管发,不管你收没收到。适合高频传感器数据。
- *场景*:激光雷达点云(10Hz)。如果丢了一帧,没关系,下一帧马上就来了。重传旧数据反而会阻塞新数据。
- *图解*:投手疯狂扔球,不管捕手接没接住。
- **Reliable (可靠传输)**:保证数据必达,如果丢包会重传。适合关键控制指令。
- *场景*:机械臂关节目标位置。如果指令丢了,机械臂就不动了,所以必须确认收到。
- *图解*:投手扔球,必须确认捕手接到了,没接到就重扔。

#### 2. History(历史记录):新数据来了,旧的留不留?

- **Keep Last (只留最新的)**:配合 `depth` 参数(例如 depth=1),只保留最后 N条数据。
- *场景*:里程计数据 (Odom)。通常我们只需要机器人当前在哪,1秒前的位置已经过时了。
- **Keep All (全部保留)**:保留所有历史数据,直到内存爆掉。
- *场景*:黑匣子日志、调试数据。

#### 3. Durability(持久性):迟到的订阅者能看到数据吗?

- **Volatile (易失)**:数据发出去那一刻,如果没有人订阅,数据就消失了。后来加入的订阅者收不到以前的数据。
- *场景*:机器人的瞬时速度。
- **Transient Local (局部持久化)**:发布者会保存最后发布的数据(类似“公告板”),无论订阅者何时上线,都能立即收到最后一条消息。
- *场景*:**静态地图 (Map)**。地图通常只发一次(Late-joiner problem)。如果不用 Transient Local,新启动的导航节点将永远收不到地图数据。

#### 4. Liveliness(活跃度):你还活着吗?

DDS 可以监测节点的“心跳”。如果一个传感器节点承诺“每秒至少发一次数据”,但突然哑火了,系统判定其死亡,并可以触发急停或其他安全策略。

### 代码:如何配置 QoS

光说不练假把式,我们看看在 Python (rclpy) 中如何定义一个“传感器专用”的 QoS:

```python
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy

# 定义一个类似“传感器数据”的 QoS 配置
# 目的:高吞吐低延迟,丢了不可惜,只看最新的
sensor_qos = QoSProfile(
reliability=ReliabilityPolicy.BEST_EFFORT, # 尽力而为
history=HistoryPolicy.KEEP_LAST, # 只留最新的
depth=1 # 队列深度为 1
)

# 创建发布者时应用该 QoS
pub = node.create_publisher(LaserScan, 'scan', sensor_qos)
```

### ⚠️ 避坑指南:兼容性陷阱 (Compatibility)

这是新手最容易踩的坑,**请务必注意**:
发布者 (Publisher) 和订阅者 (Subscriber) 的 QoS 必须**兼容**才能建立连接。

- **规则**:发布者的“承诺”必须满足订阅者的“要求”。
- **典型错误**:发布者是 `Best Effort`(比较随意),而订阅者要求 `Reliable`(非常严格)。这时 DDS 会认为“我满足不了你的要求”,导致连接无法建立。结果就是:`ros2 topic list` 能看到 topic,但 `ros2 topic echo` 啥也没有!

---

## 5. 进阶特性:DDS 带来的其他红利

- **实时性 (Real-time)**:很多 DDS 实现(如 Iceoryx 结合 CycloneDDS)支持**零拷贝 (Zero Copy)**。在大数据量传输(如 4K 摄像头图像)时,指针传递代替内存复制,极大降低了 CPU 占用和延迟。
- **安全性 (SROS 2)**:基于 DDS-Security 标准,ROS 2 原生支持加密和认证。没有证书的黑客即使接入网络,也无法解析数据或发送控制指令,防止机器人被恶意劫持。

---

## 6. 总结与展望

DDS 的引入,让 ROS 2 相比 ROS 1 变得更加**复杂**(配置项多了,门槛高了),但也让它变得无比**强大**(适应工业、自动驾驶、医疗等苛刻场景)。

**作为开发者的建议:**
不要只使用默认的 QoS 配置。在写代码前,先想一想这个 Topic 的数据特性:

- 它是“雷达点云”还是“控制指令”?
- 它是“瞬时状态”还是“全局配置”?
- 它需要“拼命发”还是“确认收”?

理解了 DDS,你就掌握了 ROS 2 的灵魂。
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Renode 是面向嵌入式与异构硬件的开源仿真平台,可在无实物硬件的情况下进行固件开发、系统级调试与自动化测试。

## 工业界运用

虽然在国内大众视野中 Renode 相对小众,但在全球嵌入式与半导体顶尖领域,它正逐渐成为标准工具栈的一部分,掌握它意味着接触最前沿的开发模式:

- **Google (TensorFlow Lite / Zephyr)**:Google 使用 Renode 进行 TensorFlow Lite for Microcontrollers (TFLM) 的持续集成测试,确保机器学习模型在不同嵌入式平台上的兼容性。同时,Zephyr RTOS 项目官方 CI 也大量使用 Renode 进行多架构(ARM, RISC-V, Xtensa等)的每日构建测试。
Expand All @@ -15,16 +16,22 @@ Renode 是面向嵌入式与异构硬件的开源仿真平台,可在无实物
> 现在教学上依然常用的Proteus则是玩具。

## 对个人的帮助

- **降低入门成本**:无需实体硬件即可学习与验证。
- **提升调试效率**:可重复的仿真环境便于问题定位。
- **支持自动化**:脚本化测试帮助构建个人级持续验证流程。

## 文档计划

1. 基本的Renode使用
2. Renode仿真SoC中的裸机开发
3. Renode仿真SoC中的RTOS开发
4. Renode仿真SoC中的神经网络模型部署
- [x] [基本的Renode使用](./(ZhaoCake-2026-02)Renode是怎样工作的.md)
- [ ] Renode仿真SoC中的裸机开发
- [ ] Renode仿真SoC中的RTOS开发
- [ ] Renode仿真SoC中的神经网络模型部署

完成这四个基本的文档作为例子之后我将会提出 doc request issue 来请求更多文档。

## 参考实验

实验仓库尚在开发中

[learning_renode](https://github.com/ZhaoCake/learning_renode)
Loading