
面试的时候被问过ROS2为什么要用DDS不用别的中间件我当时说了句因为DDS比较成熟。面试官显然不满意追问成熟体现在哪它解决了什么具体问题这个问题考的是你对ROS2底层架构的理解深度。光会用ROS2的API不够你得知道它为什么这么设计以及这个设计带来了什么好处。什么是DDSDDS的全称是Data Distribution Service数据分发服务。它是OMGObject Management Group组织在2004年发布的一个通信中间件标准。注意这是一个标准不是某个具体的软件实现。就像HTTP是协议标准Apache和Nginx是不同的实现。DDS最初是为国防和航空航天领域设计的。美国国防部搞了一个叫JTRS联合战术无线电系统的项目需要几十种不同类型的设备互相通信有的在地面有的在空中有的在水下。网络环境复杂设备随时加入和离开数据有优先级之分。DDS就是为这种场景设计的。后来DDS被广泛应用到自动驾驶、医疗设备、智能电网、金融交易这些对可靠性和实时性要求很高的领域。DDS的核心概念DDS有几个核心概念理解了这些就能明白ROS2为什么选它。以数据为中心。DDS不关心谁发给谁它关心的是数据是什么。发布者声明我要发布什么数据订阅者声明我要接收什么数据DDS负责把数据从发布者送到订阅者。发布者不知道订阅者是谁订阅者也不知道发布者是谁。这种解耦是去中心化的基础。举个例子在机器人系统里激光雷达节点发布点云数据。它不需要知道谁在接收——可能是导航模块可能是避障模块可能是可视化模块。激光雷达只管发谁需要谁来订阅。如果将来加了一个新模块也要用点云数据不需要改激光雷达的代码新模块直接订阅就行。自动发现。节点启动后通过UDP组播自动发现网络中的其他节点。不需要中心服务器不需要手动配置。你启动十个节点它们会在几秒钟内互相发现并建立连接。发现协议会交换每个节点的信息它发布什么topic、订阅什么topic、数据的类型是什么。QoS策略。这是DDS最强大的特性之一。你可以为每种数据流单独配置传输策略。可靠性方面可以选择RELIABLE保证送达用TCP类似的重传机制或者BEST_EFFORT尽力而为不保证送达但更快。历史深度方面可以配置缓存最近几份数据新加入的订阅者可以收到之前的数据。超时时间方面可以设置消息的有效期超时的自动丢弃。分布式系统模型。DDS把整个系统看作一个全局数据空间。所有节点往这个空间里写数据和读数据不需要知道对方的地址。这跟ROS1的点对点连接模型完全不同。为什么选DDS而不是其他中间件面试的时候这个问题也很常见。通信中间件不止DDS一个为什么ROS2偏偏选了它ZeroMQ是个轻量级的消息队列库性能好、使用简单。但它缺乏QoS策略也没有标准化的数据模型。对于机器人系统来说不同模块的数据格式和传输需求差异很大ZeroMQ太底层了。MQTT是物联网领域常用的协议轻量、省电。但它基于broker模式需要一个中心服务器来转发消息。这和ROS1的master问题类似又是单点故障。gRPC是Google的远程调用框架适合服务间的同步通信。但机器人系统大量使用的是发布-订阅模式的数据流gRPC不太适合这个场景。DDS的优势在于它同时支持发布-订阅和请求-响应两种模式内建QoS策略去中心化有标准化的数据模型而且经过了国防和工业领域几十年的验证。虽然配置复杂一些但对于机器人这种需要高可靠性的场景来说这些特性是值得的。ROS2是怎么用DDS的ROS2在DDS之上封装了一层叫rclROS Client Library的接口。rcl再往上就是rclcppC和rclpyPython也就是你写ROS2节点时用的API。架构层次是这样的你的代码rclcpp/rclpy ↓ rclROS Client LibraryC语言实现 ↓ rmwROS Middleware抽象接口层 ↓ DDS实现Fast DDS / Cyclone DDS / Connext DDS ↓ 网络传输UDP/TCP/共享内存注意中间那个rmw层。它是一个抽象接口下面可以接不同的DDS实现。这意味着你不用改一行代码就能切换底层用的DDS。只需要在编译时指定export RMW_IMPLEMENTATIONrmw_cyclonedds_cpp这个设计非常聪明。它让ROS2不会被绑定在某一个DDS实现上哪个DDS有bug或者性能不好换一个就行。去中心化意味着什么ROS1有一个rosmaster所有节点通过它来发现彼此。ROS2没有这个master。每个节点启动后自己通过DDS的发现协议找到其他节点。去中心化带来的好处没有单点故障。一个节点挂了不影响其他节点通信。新节点加入也不需要通知谁它自己就能融入网络。支持多机通信。不同机器上的节点只要在同一个网络里就能自动发现和通信。不需要配置master的地址不需要设置ROS_MASTER_URI。支持动态拓扑。节点可以随时加入和离开系统自动调整。这对机器人系统特别重要因为传感器可能随时掉线重连节点可能需要动态重启。但去中心化也有代价。发现过程需要几秒钟不像ROS1的master那样即时。在节点数量特别多的时候比如几百个发现过程可能更慢。另外调试也更复杂因为没有中心节点可以查询系统状态得用ros2 cli工具来排查。面试中怎么聊架构面试官问ROS2架构你可以这样回答ROS2选择DDS作为底层通信中间件主要考虑三点一是去中心化解决了ROS1的master单点故障问题二是QoS策略让开发者能精细控制不同数据流的传输行为三是DDS本身在工业领域经过了几十年的验证可靠性有保障。ROS2在DDS之上加了rmw抽象层支持切换不同的DDS实现这个设计让系统很灵活。这种回答好在有选择原因、有技术细节、有架构理解。组件化设计把多个Node放进一个进程ROS2还有一个重要的架构特性值得了解组件Component。默认情况下每个Node运行在独立进程里进程间通信有序列化和反序列化的开销。如果你的系统有很多Node需要频繁交换大数据比如点云、图像可以把它们加载到同一个进程里通过共享内存直接传递数据零拷贝。// 把Node注册为组件 #include rclcpp_components/register_node_macro.hpp RCLCPP_COMPONENTS_REGISTER_NODE(MyProcessor, my_package::MyProcessor)然后用ros2 component load把组件加载到容器进程里。这种方式在性能敏感的场景下非常有用比如视觉pipeline里的图像预处理和目标检测节点之间省掉序列化开销后延迟能降低一半。架构理解对开发的影响很多初学者只是机械地使用ROS2的API不理解底层架构。但当你遇到节点发现不了、话题消息丢失等问题时架构知识就派上用场了。比如理解了DDS的QoS机制你就能判断该用RELIABLE还是BEST_EFFORT理解了executor的工作方式你就能合理分配回调函数到不同的回调组。面试中如果能从架构层面分析问题会让面试官刮目相看。给你的建议不需要去读DDS的规范文档那太厚了。但建议了解一下DDS的几个核心概念Topic、DataWriter、DataReader、QoS。理解了这些你再看ROS2的API就知道它为什么长这样了。试试切换不同的DDS实现。装一个Cyclone DDSsudo apt install ros-humble-rmw-cyclonedds-cpp然后设置环境变量切换过去跑跑你的程序感受一下有没有区别。在节点数量多的时候不同DDS实现的性能差异会比较明显。Fast DDS是ROS2的默认实现功能最全但内存占用较大Cyclone DDS更轻量适合嵌入式平台Connext DDS是商业产品性能最好但要付费。了解这些差异面试的时候能聊得更深入。上一篇第108篇 ROS2安装与第一个Hello World程序下一篇预告第110篇 DDS通信原理——ROS2底层是怎么传数据的