尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DDS通信中间件在智能汽车中的应用:原理、QoS与工程实践

DDS通信中间件在智能汽车中的应用:原理、QoS与工程实践 这两年只要做智驾域控或者中央计算平台DDS这个词总会高频出现。一次项目评审会上供应商方案里写着“基于DDS的SOA通信架构”台下领导第一句就问DDS到底是什么和SOME/IP比哪个更强实话讲这个问题背后藏着一整条智能汽车软件栈迭代的逻辑。DDS全称是Data Distribution Service数据分发服务它最早源自工业自动化和机器人领域后来被汽车行业看中成了汽车以太网上承载分布式实时通信的核心中间件之一。网上搜“DDS”会混进来不少同名概念比如DDS信号发生器、DDS图片格式这些跟汽车以太网协议其实没有任何关系。这篇文章只聊汽车和嵌入式场景下作为通信中间件的DDS把它从原理到落地一次讲透。如果你在做自动驾驶软件、整车通信设计或者刚接触SOA架构的软件工程师这篇文章应该能帮你少走不少弯路。1. 为什么智能汽车这台“移动数据中心”偏偏看中了DDS1.1 从CAN到以太网汽车通信架构的转折传统汽车通信主要靠CAN、LIN这类总线。CAN总线的特点是面向信号每个报文在开发阶段就被静态定义好了ID、周期、字节偏移全部固定。这在传统动力底盘场景下非常好用十几条报文就能把发动机转速、车速、刹车状态传得明明白白硬实时和确定性都很好。但到了智能驾驶时代传感器数据量完全不是CAN能扛的。一个激光雷达的点云数据每秒几十MB到上百MB一颗800万像素摄像头的原始图像动辄几MB一帧CAN总线那500kbps的带宽连零头都不够。以太网进入车载成为必然尤其是100BASE-T1、1000BASE-T1这样的车载以太网物理层标准逐渐成熟带宽瓶颈被打开了。以太网带来了灵活性和高带宽也带来了新问题TCP/IP协议栈本身不提供基于语义的数据分发能力。应用层收到一个IP报文还得自己去解析这个报文是谁发来的、里面是什么数据、该交给哪个模块处理。于是汽车以太网上就需要设计应用层的通信协议目前最常见的就是SOME/IP和DDS两条路线。这里顺便澄清一个概念业内聊“汽车以太网协议”有人指的是OSI模型底层也就是车载以太网的物理层和数据链路层标准但更多人指的反而是跑在以太网之上的应用层通信协议。DDS就是后者的典型代表它解决的是数据“怎么表达、怎么发现、怎么可靠传送”的问题。1.2 发布/订阅模型DDS解决的是“谁在找谁”的问题传统Client/Server模型里客户端要调用服务端必须提前知道服务端的IP地址、端口号、接口定义。在整车几十上百个ECU的分布式环境里这种点对点写死关系的方式维护成本极高。比如新增一个感知节点要改路由表、改服务地址、改调用关系牵一发动全身。DDS采用发布/订阅模型跟传统方式完全是两种思路。它定义了一个虚拟的“全局数据空间”发布者往某个Topic主题里写数据订阅者声明自己对某个Topic感兴趣剩下的事情由DDS中间件自己搞定。发布者不需要知道数据会发给谁、接收者在哪里订阅者也不需要知道发布者在哪里。这个模型可以用收音机来类比电台不知道现在有多少人在听听众也不知道电台的发射塔具体在哪个位置大家只要都对上同一个频率广播就能建立起来。DDS里的Topic就相当于频率数据内容就是广播节目。用DDS的术语说通信的基本单元叫Instance实例每个Topic里有多个Instance每个实例的一条数据叫Sample样本。举个自动驾驶里的例子Topic叫“/sensor/lidar_front”数据类型是PointCloud那么这辆车上装的前向激光雷达就是一个实例每帧点云数据就是一个样本。如果换成不同厂商的激光雷达只要Topic和数据类型不变上层感知模块不需要改逻辑这就是解耦的价值。1.3 DDS为什么会出现在自动驾驶场景自动驾驶软件架构普遍转向SOA面向服务架构核心思想是让各个功能模块之间按接口解耦、按能力复用。比如定位模块、感知模块、规划模块各自独立成服务服务之间通过标准化接口通信。这种架构下通信中间件需要具备动态发现、灵活组网、按需配置能力DDS天然契合这些需求。DDS还解决了自动驾驶对实时性要求的问题。传统CAN硬实时但带宽低TCP可靠性好但对有界延迟不友好UDP快但不管丢包。DDS相当于在传输层之上做了一层可配置的中间件你可以根据需要选择快还是准是容忍丢包还是必须逐个重传是数据一过期就直接丢掉还是需要缓存最新几帧。这种“既要又要还要”的弹性是传统协议给不了的。再加上车路协同、V2X这类跨平台场景一个路侧感知单元要同时向多个车端节点发布数据节点还可能在不断移动动态加入、动态退出DDS的发布/订阅模型和自动发现机制非常适合这种环境。这也是为什么自动驾驶行业在认真考虑DDS而不只是把它当作“又一个中间件”来看。2. 汽车DDS的协议栈不只是“一个协议”而是一整套规范2.1 DDSI-RTPS真正在以太网上跑的那个“线协议”很多人第一次接触DDS以为它就是一个简单的通信协议。实际上DDS由OMG对象管理组织维护着一整套规范其中最核心的分层是DCPS和DDSI-RTPS。DCPSData-Centric Publish-Subscribe数据为中心的发布订阅是DDS的编程模型层。工程师写的Publisher、Subscriber、Topic、DataWriter、DataReader这些API就是DCPS层的东西。你可以把它理解成“用户看到的DDS长什么样”。DDSI-RTPSReal-Time Publish-Subcribe Protocol实时发布订阅协议则是真正的“线协议”它定义了数据在网络上传送时的报文格式、发现算法、可靠性机制。DCPS层的调用最终都会被转换成RTPS报文打上UDP头从以太网口发出去。RTPS默认跑在UDP上注意这个选择背后的逻辑TCP的流量控制和拥塞重传机制对“有界延迟”并不友好。某个节点网络卡一下TCP可能反复重传下游数据迟迟到不了UDP本身没有这些繁重机制把可靠性和时效性的决策权交给应用层的DDS来管理。DDS可以在“要可靠”和“要实时”之间做细粒度选择这正是自动驾驶很多场景需要的。RTPS协议栈里还有一套参与者发现机制分为SPDPSimple Participant Discovery Protocol简单参与者发现协议和SEDPSimple Endpoint Discovery Protocol简单端点发现协议。节点启动后会通过多播或者配置好的单播地址发送自己的发现报文告诉其他节点“我来了我发布这些Topic订阅那些Topic”。这也是为什么DDS刚启动时Wireshark抓包里经常能看到一堆多播报文飘来飘去不了解这个机制的人会以为是网络风暴。2.2 QoS策略DDS最值钱的部分如果说DDS是家快递公司那QoS就是填写配送单。DDS之所以灵活核心竞争力就在QoSQuality of Service服务质量策略。它让你可以针对不同数据流定义完全不同的传输行为。常用的QoS策略有几个重点RELIABILITY可靠性分为BEST_EFFORT和RELIABLE。前者尽力而为丢了不补后者保证接收端能拿到全量数据丢了会触发重传。DURABILITY持久性分为VOLATILE、TRANSIENT_LOCAL、TRANSIENT和PERSISTENT。简单说就是新加入的订阅者能不能拿到历史数据。VOLATILE表示拿不到TRANSIENT_LOCAL表示能拿到缓存的历史样本。HISTORY历史KEEP_ALL表示缓存全部历史样本KEEP_LAST表示最多缓存最近N个样本。DEADLINE期限发布端必须在设定的时间周期内发送样本否则视为违反约定。LIVELINESS存活用来检测对端节点是不是还活着。实际工程里最常见的坑就是两端QoS不兼容。DDS规范规定发布端和订阅端的QoS策略必须能协商一致才能建立连接。比如发布端设置BEST_EFFORT订阅端要求RELIABLE前者满足不了后者双方就无法通信。反过来如果发布端是RELIABLE订阅端是BEST_EFFORT协商结果通常是取弱的那一方也就是BEST_EFFORT。QoS策略核心作用车载场景常见选择RELIABILITY是否保证不丢数据控制指令用RELIABLE感知数据用BEST_EFFORTDURABILITY晚加入的节点能否拿到历史数据小数据量配置TRANSIENT_LOCAL大流数据用VOLATILEHISTORY缓存多少历史样本与DURABILITY搭配使用通常KEEP_LAST 1~10DEADLINE最大发送周期约束对周期类数据可以设置实现超时告警LIVELINESS对端在线状态检测需要监控节点存活时开启一套性能优秀的DDS系统QoS配置必须基于数据流特征来设计。把感知高频大流量配成RELIABLE很容易把网络打满、内存打爆把控制指令配成BEST_EFFORT又可能因为一次丢包导致指令丢失。我在实际项目里见过“明明连上了却收不到数据”的问题最后定位下来就是Durability不匹配发布端是VOLATILE订阅端要求TRANSIENT_LOCAL自然拿不到历史数据。2.3 ROS 2与DDS开源生态怎样反哺车规很多工程师认识DDS其实是从ROS 2开始的。ROS 2把DDS作为默认的底层通信中间件用户不用改应用代码只需要配置一下RMWROS Middleware Implementation实现就能在Fast DDS、Cyclone DDS之间切换。这个设计让DDS在一夜之间获得了海量的开发者生态。这对汽车行业来说是个巨大红利。整个ROS 2生态里有大量公开示例、调试工具、踩坑文章一个做自动驾驶的工程师可以从ROS 2出发直接把DDS跑起来看到Topic通信、QoS配置、节点发现这些现象学习曲线平滑很多。但也要清醒一点ROS 2里的DDS配置只是DDS能力的一个子集ROS 2的应用模型和车规量产要求有差距。汽车量产要考虑功能安全认证、资源受限、长期稳定性、多域隔离这些在ROS 2里基本不需要考虑。我建议想搞清楚DDS的工程师先抛开ROS 2直接看原生DDS的例子。拿Fast DDS或者Cyclone DDS仓库里的hello world示例自己编译一遍、跑一遍再抓包看SPDP和SEDP报文。这个过程下来对DDS的理解会比在ROS 2里“黑盒使用”要深入得多。3. 车载DDS工程落地从开源验证到车规集成3.1 在AUTOSAR AP里集成DDS的典型路径现代智驾域控上AUTOSAR Adaptive PlatformAP经常作为基础软件运行ara::com是AP提供面向服务通信的接口模型。在实际项目里DDS并不是孤立存在它经常作为ara::com的底层传输之一或者自研通信模块的传输核心。集成路径一般分两种。一种是用商业协议栈供应商的方案Vector、ETAS等都有基于AP的DDS实现配置工具可以自动生成代码功能安全认证材料、支持文档都齐备。另一种是自研轻量级通信模块直接把Fast DDS或Cyclone DDS移植到Linux/QNX上基于POSIX socket和RTPS协议实现。无论选哪种都要注意几个关键点。第一是功能安全ISO 26262对通信中间件有ASIL等级要求不同等级下开发流程、验证覆盖度差别很大第二是资源限制域控的CPU和内存不像PC那么充裕DDS的发现协议、历史缓存、心跳线程都会吃资源第三是调度协调DDS的收发线程要跟AP的操作系统调度器配合不然容易出现优先级反转。完整落地流程大致是先梳理整车通信矩阵明确哪些数据走DDS、哪些走SOME/IP然后设计Topic和数据类型再逐条设定QoS策略接着做代码生成与集成最后做网络仿真和HIL测试。这个流程里通信矩阵设计往往决定了大方向Topic和QoS配置决定了性能和问题面。3.2 网络配置与QoS参数设置实例空谈概念没意思直接看一个配置示例。下面是一段Fast DDS风格的XML配置定义了一个面向自动驾驶场景的DataWriterdds profiles profile nameADAS_Control_Profile is_defaulttrue data_writer qos durability kindTRANSIENT_LOCAL/kind /durability reliability kindRELIABLE/kind /reliability history kindKEEP_LAST/kind depth3/depth /history deadline period sec0/sec nanosec20000000/nanosec /period /deadline /qos /data_writer /profile /profiles /dds这段配置的意图很明确这是控制类指令不允许丢所以用RELIABLE假设新节点上线时需要拿到最近几帧控制状态所以Durability用TRANSIENT_LOCALHistory只保留最近3帧避免缓存堆积DEADLINE设置20毫秒用来检测发送超时。网络侧也要有规划。最关键的是Domain ID域ID它把DDS通信划分成不同的虚拟网络。不同域ID的节点完全不可见可以用来隔离智驾域和座舱域的通信。多网卡场景下DDS默认可能会选择第一块网卡或所有网卡必须显式绑定到指定的以太网接口否则设备重启后IP地址发生变化节点就互相发现不了。还有一个车载环境常见的坑多播包。DDS默认通过多播做发现如果交换机的多播配置不完善或者担心多播风暴影响其他业务可以配置成单播发现。单播模式需要显式指定对端地址工程上要多一个维护地址表的动作但换来的是网络行为更可控。3.3 性能测试与实测数据解读DDS落地离不开量化评估。我的测试环境一般很简单两台x86工控机或者ARM开发板网线直连或者经过车载交换机装好Ubuntu、Cyclone DDS或Fast DDS直接用仓库自带的性能测试工具跑。Cyclone DDS自带一个叫ddsperf的工具可以测发布订阅模式的延迟和吞吐。Fast DDS则提供了专门的性能测试示例。测试前最好先用ethtool确认网卡协商速率确认IP和路由配置正确。然后跑一个简单的ping-pong测试得到Round-Trip TimeRTT数据再换算成单向时延。这里要强调不要只看平均时延一定要关注尾延迟也就是99.9%分位值。自动驾驶里的路径规划和碰撞规避对最坏情况延迟更敏感而不是对平均延迟敏感。实际测试中如果发现99.9%分位延迟抖动大先看看是否有其他进程抢占CPU、网卡中断合并coalesce是否开启、系统是否进入了低功耗模式。把这些因素全部排查完再回头看DDS配置。4. 常见问题与排查技巧实录4.1 明明同一个主题为什么就是收不到数据这个现象在DDS调试中太常见了。两个节点看起来配置都一样但数据就是不通排障思路要系统化。症状可能原因验证方法节点互相发现不了Domain ID不一致检查两端Domain ID是否相同发现正常但收不到数据Topic名称或类型名不完全一致确认大小写、命名空间、类型hash后启动节点拿不到历史数据Durability不匹配检查发布端和订阅端Durability策略能通但断断续续QoS不兼容导致协商降级抓包观察Heartbeat和ACK/NACK状态完全不通多播组包网卡绑定错误或交换机禁多播抓包确认SPDP是否发出多播包是否到达一个非常实用的排查技巧先把所有QoS策略改成默认值跑通之后再一个一个把所有QoS策略改回来每次只改一项观察通断变化。这样能快速定位是哪一项策略不兼容比对着规范猜要高效得多。另外很多嵌入式环境默认开了防火墙iptables把UDP端口挡了DDS自然不通。排查的时候先把这个可能性排除掉。4.2 通信延迟抖动大如何定位延迟抖动这个问题DDS自身配置只是其中一个因素更多时候是系统性的。我习惯按这个顺序排查第一步先测纯网络延迟。直接在两个节点之间跑ping如果Ping的RTT抖动都很大那问题出在物理层、驱动、网络负载或者交换机上跟DDS没关系。第二步再用ddsperf测DDS延迟对比纯网络延迟差额这个差值就是DDS协议栈和操作系统调度的开销。第三步看CPU占用和中断分布把DDS进程绑定到专用的CPU核通常能明显改善延迟抖动。还有一个经常被忽视的原因RELIABLE模式下的重传。如果链路层偶尔丢包DDS会触发NACK重传一次重传就能把原本微秒级的延迟拉到毫秒级。所以如果数据本身可以容忍少量漏采样BEST_EFFORT反而能提供更稳定的实时性。这个取舍要根据业务场景判断没有放之四海皆准的答案。4.3 DDS与SOME/IP共存时如何规划现在的车型上DDS和SOME/IP经常并存。SOME/IP通常负责服务发现、远程调用这类请求/响应式通信DDS负责高频数据流。两者互不干扰的前提是提前规划好端口和网络。SOME/IP的默认服务发现端口是30490SD报文也依赖这个约定DDS的RTPS协议会在一定端口范围内动态分配端口。如果两边都不规划端口冲突、广播风暴都是可能的。实测中我遇到过SOME/IP的服务发现广播包和DDS的SPDP包在同一VLAN里相互冲击网络被广播包吃满的问题。解决思路有两个层面。一是网段隔离把功能域划分到不同网段通过路由或VLAN隔离广播域二是QoS优先级在交换机上用802.1p给控制类报文打高优先级DDS大流量数据打较低优先级。两边共存并不恐怖关键是别等上线后再处理网络规划。5. 给正在选型或入坑的同行一点建议5.1 开源DDS与商业DDS怎么选学习阶段我强烈建议直接用开源实现。Fast DDS和Cyclone DDS都是活跃维护的开源项目文档齐全社区案例多拿来做Demo、做性能验证完全没问题。Fast DDS在ROS 2社区用户基数大中文资料相对丰富Cyclone DDS在小报文、低延迟场景口碑很好看实测数据表现很不错。到了量产阶段决策逻辑完全不同。不是代码跑得通就行要考虑几个问题协议栈是否有ISO 26262功能安全认证或独立安全要素证书是否适配你目标平台的操作系统和编译器比如QNX或Safety Linux供应商是否愿意做长期支持、现场跟车调试这些问题直接决定量产风险。我的建议是先用开源实现把通信矩阵、QoS策略、性能数据全部跑出来拿着结果去跟商业供应商谈效率会高很多。有了自研验证的数据支撑需求描述会更清楚议价时也更有底。5.2 团队快速上手的学习路线如果团队完全没接触过DDS我给的学习路径是这样的第一步搭一个最简单的pub-sub demo把一个Topic从发布到订阅完整跑通理解Publisher、Subscriber、DataWriter、DataReader这些基础概念。第二步打开Wireshark抓包观察SPDP和SEDP报文是怎么做的亲眼看一下“发现”到底发了什么。第三步起一个多点通信的测试用十几个节点同时通信看看网络流量、断线重连、动态发现会出什么问题。第四步再回到AUTOSAR AP或者自研中间件把DDS嵌入到真实软件架构里。学习资料不建议一上来就啃OMG规范原文太晦涩了。先跑代码有了感性认识之后再回头对照规范里对应的章节很多抽象的概念一下就通了。根据我个人的实测经验DDS真正难的不是敲一个publisher出来而是把QoS、网络、调度绑定在一起之后系统还稳不稳定。很多项目一开始觉得DDS很神奇最后发现坑全在网络规划和参数配置上。先别急着上量产的商业协议栈把每个QoS字段的含义搞清楚把抓包工具用熟比什么都有用。
返回列表