拓冰建站拓冰建站
首页 / 资讯中心 / 正文

汽车以太网中的DDS通信中间件:从核心机制到量产部署避坑指南

最近两个月我几乎每周都会被拉去讨论同一件事智能驾驶域控和中央计算单元之间的通信到底用什么中间件。聊座舱方案会聊到DDS聊智驾方案也会聊到DDS。汽车以太网协议栈发展到今天DDSData Distribution Service数据分发服务基本上已经成了SOA架构里绕不开的选项。但你要真去搜索引擎里搜“DDS”头几条大概率是“dds图片格式怎么打开”“texconv网页版在线dds转换器”“dds信号发生器”这类东西跟汽车通信完全不在一个次元。这篇文章我想把汽车以太网场景下的DDS讲透它解决什么问题、核心机制是什么、工程上怎么选型和部署、实际量产项目中会遇到哪些坑。同时也会花一小节把网上那些同名不同义的“DDS”做个区分免得大家搜资料时被带偏。无论你是刚转行做车载软件还是已经在做通信中间件选型这篇文章应该都能给你一些能直接落地的参考。1. DDS为什么会出现在汽车以太网里架构变化与协议选型逻辑1.1 电子电气架构变了通信方式也得跟着变先看背景。过去十几年一辆车的电子电气架构基本是分布式的几十上百个ECU用CAN、LIN、FlexRay串在一起。CAN总线的带宽一般就500kbpsLIN更低这种带宽决定了它只能传刹车状态、车速、车门开关这一类小报文而且通信模型是“周期发送信号打包”跟“服务”两个字完全不沾边。但现在不一样了。新一代车型基本都在往域集中式架构走智驾域、座舱域、车身域、底盘域再到后面中央计算加区域控制器。域控制器之间、传感器与计算单元之间要传的东西从原来的几个字节变成了海量数据激光雷达点云、800万像素摄像头图像、高精地图切片、传感器融合结果。这些数据动辄每秒几十MB甚至上百MBCAN那点带宽连个零头都不够。带宽解决之后第二个问题是怎么组织软件。传统AUTOSAR CP走的是“信号运行实体静态配置”的路子所有通信矩阵在开发阶段就要定死。但软件定义汽车时代软件要能OTA升级、要能动态部署服务、要能跨域复用。于是整个行业都在往SOA面向服务架构迁移通信不再是一对一硬编码的信号而是“服务发布方”和“服务订阅方”之间按需发现、动态绑定。这个时候就需要一个具备服务发现、动态解耦、灵活QoS能力的通信中间件DDS就是在这种背景下进入汽车视野的。1.2 为什么不能只靠TCP/UDP裸奔很多人会问以太网底层不就是IP吗我直接用TCP/UDP socket不行吗说实话小规模原型还真能这么干但放到量产车上就会遇到一串问题。先看UDP。UDP是尽力而为的不保证不丢包不保证顺序没有流控。摄像头图像丢几帧还能忍但刹车指令、转向控制这类报文丢一帧可能是安全事故。很多团队会在UDP上面自己写重传、排序、超时检测最后写出来的东西就是一个残缺的可靠通信协议——而你正在重复发明一个比DDS差得多的轮子。再看TCP。TCP解决了可靠性和顺序问题但它是“流式”的一帧数据和下一帧数据之间没有天然边界接收方要自己拆包。更重要的是TCP是点对点的车里面有20个节点要共享同一份传感器数据TCP就得建20条连接每条连接各自维护状态资源开销大不说新增一个节点还得改发送方的代码。还有一个更致命的问题TCP的拥塞控制里包含了超时重传和滑动窗口这在高实时性场景下会造成“线头阻塞”。某个包丢了后面所有数据都得等它重传成功哪怕你的控制指令只晚了10毫秒可能就已经过了执行窗口。DDS的设计思路跟TCP/UDP完全不同。它站在发布订阅模型上把网络抽象成一个“全局数据空间”。任何节点想发数据往这个空间里“写”就行任何节点想收数据声明自己“读”哪个主题就行。至于谁在哪儿、用什么IP、怎么发现、怎么保证可靠性、要不要缓存历史数据这些都是DDS框架替你解决的问题。底层仍然走UDP或共享内存但暴露给应用层的是一个干净、松耦合、可配置的接口。1.3 先别搞混图片DDS、信号源DDS和总线DDS刚才说到网上搜到的“DDS”五花八门这里专门掰扯清楚后面内容才不会被绕晕。第一种是DDS图片格式。它是微软DirectDraw Surface的缩写游戏贴图常用的一种纹理格式扩展名通常是.dds。你看到的“texconv网页版在线dds转换器”“如何打开dds图片”都属于这一类。跟汽车通信半毛钱关系都没有。第二种是DDS信号发生器。这里DDS是Direct Digital Synthesizer直接数字频率合成的缩写是一种用数字方式生成正弦波、方波的电子技术常见于实验室仪器、射频电路里。FPGA开发里经常用到的Vivado DDS IP核也是这个东西用来做频率合成、调制解调不是通信协议。第三种才是我们要聊的DDSData Distribution Service是OMG组织发布的一套分布式数据分发标准工业物联网、机器人、自动驾驶都在用。ROS2底层的通信中间件就是DDS/RTPS所以“ros2 dds”这个热搜词实际上也就是指它。判断一个资料是不是你要找的看上下文就知道如果它在聊image、texture、frequency那都是另外两个DDS如果它在聊domain、topic、QoS、DataWriter、DataReader那才是汽车以太网要用的DDS。2. DDS的核心机制全局数据空间、发布订阅与QoS2.1 全局数据空间从点对点通信变成“数据黑板”DDS最核心的抽象概念叫“全局数据空间”Global Data Space。你可以把它理解成一块分布在各节点内存里、但逻辑上共享的“黑板”。所有节点都可以往黑板上贴数据也可以从黑板上取数据不需要知道数据是谁贴的、也不需要知道有谁会来取。在这个空间里几个关键概念你需要先记住Domain域相当于一个独立的通信边界。只有属于同一个域的参与者才能互相通信版本、配置都匹配才行。类比一下就像同一套Wi-Fi网络里不同VLAN之间默认不通一样Domain是做隔离用的第一层。DomainParticipant域参与者一个进程或一个通信实体在域里的代表。你要收发数据必须先创建一个Participant。Topic主题数据分类的标识。DDS通过Topic名称来区分不同的数据流比如/camera/raw、/vehicle/speed、/sensor/lidar。Topic不仅要名字匹配还要数据类型匹配。Publisher/Subscriber发布者/订阅者对应通信的发起方向。Publisher下挂DataWriterSubscriber下挂DataReader。DataWriter/DataReader数据写入者/数据读取者真正执行读写操作的对象。一个Topic可以有多个Writer和多个ReaderDDS负责把它们一对一、一对多、多对一地组织起来。这套模型最大的好处是多对多通信。比如5个摄像头各自向/topics/raw_image写数据3个不同算法模块同时订阅这个TopicDDS会自动把5路数据分发到这3个模块不需要谁去单独建连接。以后新增一个处理模块只要它订阅同一个Topic老节点完全不用改。2.2 QoS是DDS的灵魂每个策略到底在控制什么只做发布订阅的话很多消息中间件都能干。DDS真正的护城河是QoS——Quality of Service一套非常细粒度的通信行为控制策略。我见过的很多项目事故到最后都指向一件事QoS策略没配好。先说最关键的几个。第一个是RELIABILITY可靠性策略。它有两个取值BEST_EFFORT和RELIABLE。BEST_EFFORT保证“尽力送达”丢包不会重传速度快但可能有遗漏。RELIABLE保证“不丢”底层会缓存和重传。注意RELIABLE不等于“实时性好”反而在丢包严重的网络里延迟会更大。因为重传要时间。第二个是DURABILITY持久性策略。它决定了一个晚来的订阅者能不能收到发布者之前发出的历史数据。取值有VOLATILE不保留历史、TRANSIENT_LOCALWriter端的缓存重启后消失、TRANSIENT跨Writer进程重启的存在于网络中的持久化缓存通常需要额外服务、PERSISTENT落盘。车里面很多场景需要这个某个算法模块启动晚了但它希望一启动就能拿到车辆当前的姿态角、速度、地图版本这些“最新状态”。如果Publisher配置的是TRANSIENT_LOCAL它启动后无需等待下一帧立刻能拿到最新值。第三个是HISTORY历史记录策略。它配合DURABILITY使用控制“最多保留多少条历史数据”。KEEP_LAST(N)表示保留最近N条KEEP_ALL表示一条不丢全部保留。注意KEEP_ALL在持续高频发布场景下很容易把发送端缓存撑爆——因为接收端如果处理不过来数据全堆在发送端等重传。第四个是DEADLINE截止时间策略。这是很多实时系统的救命策略。它会声明“这个Topic的数据必须在xx毫秒内至少来一次”。如果Publisher没在这个时间内发布新数据DDS会报告错过截止时间的回调如果Subscriber没在这个时间内收到数据同样会触发回调。这样你就能在感知系统“还在正常工作”的时候提前发现它已经卡了。还有几个常用的LIVELINESS活性策略检测节点是否还活着PARTITION分区策略在同一个Topic里再做一层逻辑分区RESOURCE_LIMITS资源限制策略限定缓存队列的长度、内存上限TRANSPORT_PRIORITY给不同的Topic配置网络优先级配合TSN时可以给关键控制指令最高优先级。我自己的经验是QoS不是配得越严格越好也不是统一设成RELIABLE就万事大吉。摄像头原始图像这种每秒传输几十帧的大payload用RELIABLEKEEP_ALL一旦网络抖动延迟和内存都会爆炸而控制指令这种低频但关键的数据用BEST_EFFORT就是在拿生命开玩笑。正确做法是每个Topic按数据特征单独配QoS而且要提前跟算法团队对齐。2.3 动态发现机制节点上线后怎么互相找到DDS的另一个特点就是“去中心化的动态发现”。传统以太网通信里A要跟B通信要么静态配置IP和端口要么靠一个中心化的服务注册中心。DDS不一样它在底层实现了RTPSReal-Time Publish-Subscribe协议节点之间通过多播地址自动互相发现。简单来说当一个新的Participant启动时它会在固定的多播端口上发送SPDPSimple Participant Discovery Protocol消息宣告自己的存在。其他Participant收到后双方交换各自包含哪些Topic、支持哪些QoS的信息这个过程叫SEDPSimple Endpoint Discovery Protocol。全部走协议自动完成不需要人工配置。动态发现在车间测试时非常好用节点拔了插上重新启动数据自动通。但上了整车量产或者跨网段部署就得多长个心眼RTPS默认依赖IP多播有些车载以太网交换机为了控制流量风暴会禁止多播帧穿透或者网段隔离之后发现消息根本过不来。这时候就需要配置发现的对端静态地址列表initial peers或者调整RTPS的发现周期。这个坑后面排查章节再细说。3. 工程实施与选型要点从代码到部署的参数级建议3.1 典型车载软件栈里的DDS部署形态在车上做DDS跟服务器集群里做DDS环境差异非常大。车载场景通常是每个域控制器一台“小型服务器”上面跑Linux或QNX里面有多个进程比如感知进程、规划进程、底盘控制进程。每个进程都可以作为独立的Participant接入同一个Domain。我见过两种部署风格。一种是“每个进程一个Participant”好处是网络结构清晰每个进程可以独立配置不同的QoS和安全属性坏处是Participant数量多发现消息开销大。另一种是“一个进程只创建少量Participant多个线程共用”好处是资源占用低坏处是配置和调优时相互影响一个线程改QoS可能影响到同Participant的其他线程。还有一个细节是传输方式。在同一个域控内部的多个进程之间传数据完全没必要走网卡出去绕一圈。很多DDS实现会做Shared Memory传输的自动判断发送和接收在同一个主机上时底层自动切换到共享内存延迟能降到微秒级。Fast DDS和Cyclone DDS都支持这个特性配置时要把shared memory传输组件打开量产交付检查清单里务必加上这一项。另外现在很多智驾方案里是DDS和SOME/IP混合使用SOME/IP负责AUTOSAR AP的标准化服务接口、诊断、车辆控制DDS负责高频数据流和算法模块之间的灵活通信。两者都是IP之上跑的可以共存。具体怎么分一般是所有需要上AUTOSAR AP正式服务框架的走SOME/IP感知融合、点云分发、图像共享这类大数据走DDS。3.2 主流DDS实现对比Fast DDS、Cyclone DDS、RTI ConnextDDS是一套规范实际落地要看具体实现。目前车载圈用的比较多的就三家。eProsima Fast DDS是很多自动驾驶团队的首选原因很简单它开源、免费、社区活跃而且ROS2默认用的就是它后来ROS2也支持Cyclone DDS做RMW实现。代码用C写的支持QoS全集、共享内存传输、安全插件DDS Security。如果你们项目预算有限又想快速上车Fast DDS是比较稳的选择。Cyclone DDS是Eclipse基金会下面的开源项目源自ADLINK的Vortex系列。它的特点是架构极简、内存占用低、在某些性能测试里延迟表现很惊艳。ROS2认它工业场景里也有不少人在用。如果你对实时性敏感、设备算力又有限可以重点测一下Cyclone DDS。RTI Connext DDS是商业产品在AUTOSAR、军工、航天里占有率很高。它强在成熟度、技术支持和工具链配套有RTI Recording Service、Monitoring Library调试方便。缺点就是贵License费用对很多车企的零部件供应商来说是一笔不小的成本。还有一个需要提的是Eclipse Zenoh严格来说它不是DDS RFC的实现但很多人拿它来替代DDS做车云一体通信有兴趣可以单独研究。对比维度Fast DDSCyclone DDSRTI Connext DDSLicenseApache 2.0商业友好Eclipse Public License 2.0商业许可ROS2支持默认RMW之一生态最广支持性能表现优秀支持目标场景机器人、自动驾驶、工业实时系统、嵌入式航空航天、AUTOSAR、军工工具链提供fastdds工具、代码生成器提供CycloneDDS源码和示例提供完整IDE、监控和录制工具功能安全认证社区版未认证商业版可谈未直接认证提供ASIL D相关认证支撑选型时我的建议是先拿你们最核心的两个高频Topic在两个开源实现上各做一轮延迟、抖动、CPU占用对比再决定要不要上商业版。商业版买的不只是代码而是支持体系和认证材料如果你们目标是量产且有功能安全要求留一笔预算给许可证是值得的。3.3 网络规划与关键参数别等上了车再调DDS的应用层看似简单下面毕竟还是要走IP网络。我强烈建议在项目初期就把网络规划做进架构设计里而不是等联调时才发现通信不通。第一VLAN切割。汽车以太网现在一般有多个VLAN诊断VLAN、智驾VLAN、座舱VLAN、控制VLAN。DDS的Domain要和VLAN对应起来。没有对应的业务需求时不要让智驾域的数据流把座舱域的控制VLAN带宽塞满。第二多播地址规划。RTPS默认使用固定的多播组但不同Topic如果都走同一个多播组会产生大量无关流量。合理做法是每个高频Topic分配独立的Topic多播地址和端口低频服务走单播。地址规划表要维护好我自己被多播地址填错导致“数据互不可见”的坑绊倒过两次。第三流量控制。DDS本身没有内置“节流”机制Publisher按业务频率发多少就会推出去多少。如果多个传感器叠加后瞬时流量超过交换机和网卡能力就是大规模丢包。要在网络设备和DDS两个层面都做流量管控交换机上做带宽保证CBSDDS层面对非关键Topic设置发布频率上限或批量合并发送。3.4 一套实用的QoS参数模板下面给一套我实际项目里用过的默认QoS模板覆盖了三类典型Topic你们做方案时可以直接抄作业再改。Topic类型典型示例ReliabilityDurabilityHistoryDeadlineLivelines说明高频感知数据摄像头图像、雷达点云BEST_EFFORTVOLATILEKEEP_LAST(1)100msAUTOMATIC丢帧可接受追求最低延迟低频控制指令纵向控制、转向控制RELIABLETRANSIENT_LOCALKEEP_LAST(10)10msMANUAL_BY_PARTICIPANT必须不丢及时性优先状态与配置车辆姿态、地图版本RELIABLETRANSIENT_LOCALKEEP_LAST(5)1000msAUTOMATIC新加入节点需拿到最新状态关于LIVELINESS我多说一句。MANUAL_BY_PARTICIPANT适合控制指令这类周期性“心跳”消息因为它的活性判断跟数据发送频率解耦甚至可以靠单独的活性信号来维持不容易误判。AUTOMATIC则更适合数据本身就持续高频的场景有数据就活性正常没数据就判定为掉线。4. 实操中的常见问题与排查技巧实录4.1 数据丢了但不报错QoS不匹配是头号坑先讲一个我自己踩过的坑。有一次联调A进程发图像数据B进程订阅B端一直能收到数据但是收到的是几秒前的旧数据。查网络、查时间同步都没问题。最后打开两端配置一对比才发现A的DURABILITY配的是TRANSIENT_LOCALB的DURABILITY配的是VOLATILE两边RELIABILITY又不一致。DDS的规则是订阅方的QoS只能比发布方“更严格或相等”如果订阅方要求更低级别的保障配对时就可能出现一种“半通不通”的状态。更坑的是DDS的QoS不匹配并不会直接给你抛一个“禁止通信”的异常它可能只是“安静地不给你发数据”或者在底层选了一条看起来能用但不是最优的路径。排查这个问题的标准动作就是把发布方和订阅方各自的QoS配置全部打印出来逐项核对匹配矩阵。Fast DDS提供了fastdds tool可以查看Topic、Writer、Reader的内部状态强烈建议在开发环境里把工具链提前搭好。4.2 节点发现慢、发现不到对端多半是多播问题前面说过RTPS依赖多播做自动发现。在实际车厂北向实验室里网络环境千奇百怪有的交换机开启了IGMP Snooping但配置了快速离开多播组成员频繁变动导致发现消息反复丢失有的网管为了“安全”把所有多播都禁了还有的跨网段部署两个域控在不同子网多播包根本不在网段间转。排查方法有几个。第一用tcpdump抓包看交换机和网卡上有没有周期性SPDP报文到达。第二看防火墙是不是挡了7400到7500这段的UDP多播端口很多团队为了方便开了一堆iptables规则结果把DDS的发现端口也拦掉了。第三如果环境实在不允许多播就一定要用Initial Peers配置把对端Participant的单播地址列表显式写进去。这样DDS会直接在单播上做发现虽然灵活性下降但可靠性和可预测性大幅提升。4.3 CPU占用高、延迟抖动大别让DDS线程成了系统瓶颈DDS实现一般会起多个后台线程去处理接收、发送、发现和重传。高频大数据的拓扑下后台线程跑满CPU是常见事。我之前在一个项目里发现两个图像Topic一发布整机CPU占用直接涨了60%后面查出来是同一台机器上多个Participant重复接收同一份镜像数据还各自做了反序列化。优化思路是同一进程内跨模块的数据共享优先考虑共享内存通道DDS的分发配置让同一份数据只被解码一次。另外DDS的线程优先级在Linux下默认往往不是实时优先级。如果你的系统用了PREEMPT_RT补丁或者有实时核记得把DDS关键线程的affinity绑定到实时核、优先级设高。这个配置看起来不起眼但延迟抖动的影响经常就是从这里来的。4.4 常见问题速查表现象可能原因首选处理思路订阅方完全收不到数据两端Domain ID不一致、Topic名称不一致、QoS不匹配对比Domain、Topic、类型、QoS四项配置偶尔能收到数据但会断多播被交换机丢弃、Discovery周期过长打开抓包确认SPDP/SEDP调整多播或配置Initial Peers收到数据延迟明显大量数据走了RELIABLE重传、接收队列太长该Topic改用BEST_EFFORT或加大KEEP_LAST容量、启用巨型帧CPU占用异常高多份数据重复反序列化、接收线程无优先级共享内存传输线程亲和配置减少跨Participant数量新节点启动后拿不到最新状态DURABILITY配成VOLATILE发布方改配TRANSIENT_LOCAL并确保HISTORY能保留足够数据QoS配置看起来一样但无法匹配不同实现之间对默认值处理有差异显式写出所有QoS字段不要依赖任一实现的默认值5. 写在后面一个小技巧和一点体会最后再分享一个我最近才养成的习惯所有DDS工程的代码仓库里一定要有一份“Topic登记表”。不要只把Topic和相关类定义写在代码注释里单独提一个YAML文件记录每个Topic的名字、数据类型、Publication/Subscription节点的归属、QoS模板编号、带宽预估、多播地址分配。这份登记表既是设计文档也是排查故障的第一手依据。我遇到过太多次新同事接手项目后花两周时间在代码里翻Topic定义最后发现两个进程的Topic名只差一个下划线。这几年做车载通信中间件我最大的感受是DDS本身不是银弹。它只是把网络通信的设计从“我该怎么把数据从A传给B”变成了“我应该怎么描述这条数据流、保障它的什么特性”。后者想清楚了DDS的所有配置自然就有了解法。如果你们团队正准备把通信架构迁到DDS不要上来就写代码先花两个下午把每类数据流的QoS特性和网络边界列出来再去动工程。这个前置投入后面能帮你省下无数加班的夜晚。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门