现代智能汽车系统——SOME/IP与DDS2

摘要:RTPS(实时发布订阅协议)作为DDS的核心通信协议,实现了跨平台、跨厂商的无障碍通信。其关键技术包括:1)采用PIM/PSM分离架构,支持从嵌入式到服务器的多平台部署;2)使用CDR编码解决字节序差异;3)高效报文结构支持多子消息封装;4)通过PDP和EDP实现去中心化自动发现。开发验证可通过Python(快速原型)或C++(工业级实现),配合Wireshark进行协议分析。RTPS的三大解耦特性(供应商、网络、时间)使其成为车载通信等实时系统的理想选择。(149字)

如果说 DDS 是上层的"调度大脑",那么 RTPS (Real-Time Publish-Subscribe) 就是它那双"强健的腿"。

RTPS 是由 OMG 组织定义的 线缆协议(Wire Protocol) 。它的核心使命只有一个:确保不同厂家开发的 DDS(如 RTI Connext, eProsima FastDDS, CycloneDDS)能在同一个网络里无障碍地"对话"。


1. 跨平台通信的秘诀:PIM 与 PSM 的分离

RTPS 之所以能跨越 Windows、Linux、QNX 甚至是无系统的嵌入式环境,是因为它在设计上采用了平台无关模型 (PIM)平台特定映射 (PSM) 的分离架构。

  • PIM (Platform Independent Model): 定义了 DDS 的逻辑行为(比如:数据怎么分发、QoS 怎么生效、心跳包怎么发)。这一层不关心你是用 UDP 还是串口。

  • PSM (Platform Specific Mapping): 定义了逻辑包如何变成真正的比特流。目前最主流的映射是 RTPS over UDP/IP


2. 数据的"统一语言":CDR 序列化

不同计算机存储数据的方式不同(比如大端小端 字节序)。为了实现跨平台,RTPS 采用了 CDR (Common Data Representation) 编码。

  • 对齐规则: CDR 规定了基本数据类型(int, float 等)在流中的对齐方式。

  • 自适应字节序: 在 RTPS 报文头中有一个标志位,告诉接收方:"这包数据是用小端格式写的"。如果接收方是高大端的架构(如某些车载微控制器),它会自动进行字节翻转。这保证了 Intel 芯片的 PC 能听懂 NXP 芯片的 ECU 在说什么。


3. RTPS 报文的"套娃"结构

RTPS 的报文结构非常高效,它将复杂的指令拆解为一个个 子消息 (Submessages)

  • Global Header (16 字节): 包含协议版本、供应商 ID(如 0x010f 代表 eProsima)以及 GUID Prefix(唯一标识一个设备/参与者)。

  • Submessages: 一个 UDP 包里可以塞进多个子消息:

    • DATA: 携带实际的业务数据。

    • INFO_TS: 携带时间戳。

    • HEARTBEAT: 告诉订阅者:"我发完数据了,你收到了吗?"

    • ACKNACK: 订阅者回话:"第 5 号包没收到,请重发。"


4. 自动发现机制:PDP 与 EDP

DDS 不需要像 SOME/IP 那样依赖一个中心化的 SD 服务。RTPS 通过两层发现流程实现"自组织网络":

A. PDP (Participant Discovery Protocol)

  • 动作: 节点启动时,向预定义的组播地址发送 DATA(p) 报文。

  • 目的: "打招呼"。告诉大家:我的 IP 是多少,我叫什么名字。

B. EDP (Endpoint Discovery Protocol)

  • 动作: 互相认识后,节点开始交换具体的 DATA(r)DATA(w)

  • 目的: "对暗号"。告诉对方:我有一个名为 Vehicle/Speed 的话题(Topic),数据类型是 float,我的可靠性要求是 RELIABLE。如果双方的 QoS 匹配,连接就正式建立了。


5. 跨平台调试工具:Wireshark 过滤器

在分析 TBox 或智驾域控制器的 DDS 流量时,你可以使用以下 Wireshark 过滤器:

  • rtps: 过滤所有的 RTPS 报文。

  • rtps.sm.id == 0x15 : 只看 DATA 子消息(业务数据)。

  • rtps.sm.id == 0x07 : 只看 HEARTBEAT(检查链路是否稳定)。

  • rtps.parameter.topicName == "YourTopicName": 精确查找某个话题的发现报文。


💡 总结

RTPS 的伟大之处在于它实现了"解耦":

  1. 供应商解耦: A 公司的 DDS 能跟 B 公司的 DDS 通信。

  2. 网络解耦: 只要有 UDP,不管物理层是 5G 还是以太网,逻辑都一样。

  3. 时间解耦: 通过心跳和重传机制,即便网络偶尔波动,数据也能可靠送达。

要在 VS Code 中运行 DDS Demo,最简单的方式是使用 Python (适合快速验证逻辑)或 C++(适合高性能车载开发)。

由于 DDS 是"以数据为中心"的,我们需要定义一个数据类型(IDL)。为了简化,我们以车载场景中的"车速(VehicleSpeed)"为例。


1. Python 版:最快上手 (使用 Cyclone DDS)

Python 不需要复杂的编译过程,非常适合在 VS Code 中配合终端直接运行。

第一步:安装"引擎"与插件

  1. 终端安装库: pip install cyclonedds

  2. VS Code 插件: 确保已安装 Python 插件。

第二步:编写代码

创建一个文件 dds_demo.py,它既可以作为发布者,也可以作为订阅者:

Python

复制代码
from cyclonedds.domain import DomainParticipant
from cyclonedds.topic import Topic
from cyclonedds.pub import DataWriter
from cyclonedds.sub import DataReader
from cyclonedds.idl import IdlStruct
import time

# 1. 定义数据结构 (类似于车载 IDL)
@IdlStruct
class VehicleSpeed(IdlStruct):
    speed: float

# 2. 初始化 DDS 参与者
dp = DomainParticipant()
topic = Topic(dp, "VehicleSpeedTopic", VehicleSpeed)

def run_publisher():
    dw = DataWriter(dp, topic)
    print("发布者已启动,正在发送车速数据...")
    s = 0.0
    while True:
        sample = VehicleSpeed(speed=s)
        dw.write(sample)
        print(f"发送数据: {s} km/h")
        s += 5.5
        time.sleep(1)

def run_subscriber():
    dr = DataReader(dp, topic)
    print("订阅者已启动,等待数据...")
    while True:
        for sample in dr.take():
            print(f"收到数据: {sample.speed} km/h")
        time.sleep(0.5)

# 提示:你可以通过修改这里来切换身份
if __name__ == "__main__":
    import sys
    if len(sys.argv) > 1 and sys.argv == "sub":
        run_subscriber()
    else:
        run_publisher()

第三步:在 VS Code 终端运行

  1. Ctrl + ~ 打开终端。

  2. 启动订阅者: 输入 python dds_demo.py sub

  3. 拆分终端 (点击终端右上角 | 图标),在新窗口启动发布者: 输入 python dds_demo.py

  4. 你会看到两个终端开始通过 DDS 进行实时通信。


2. C++ 版:工业级标准 (使用 eProsima Fast DDS)

C++ 的实现更符合车载 TBox 的真实开发环境,但步骤较多,需要用到 CMake

第一步:环境准备

  1. 安装 Fast DDS: 在 Linux (WSL/Ubuntu) 下使用 sudo apt install libfastrtps-dev

  2. VS Code 插件: 安装 C/C++CMake Tools

第二步:定义 IDL (VehicleSpeed.idl)

DDS 强制要求先定义接口描述文件:

代码段

复制代码
struct VehicleSpeed {
    float speed;
};

在终端运行 fastddsgen VehicleSpeed.idl,它会自动生成一堆 C++ 头文件和源代码。

第三步:核心代码片段 (Publisher)

在 VS Code 中编写 main.cpp,利用生成的代码:

C++

复制代码
// 简化后的逻辑伪代码
auto participant = DomainParticipantFactory::get_instance()->create_participant(0, PQOS);
auto topic = participant->create_topic("VehicleSpeedTopic", "VehicleSpeed", TOPIC_QOS);
auto publisher = participant->create_publisher(PUBLISHER_QOS);
auto writer = publisher->create_datawriter(topic, DATAWRITER_QOS);

VehicleSpeed my_speed;
my_speed.speed(60.5);
writer->write(&my_speed); // 数据通过 RTPS 协议发出

3. 为什么在 VS Code 里做这个实验很有意义?

  1. 观察 RTPS 流量: 运行 Demo 时,打开 Wireshark,使用过滤器 rtps,你可以清晰地看到 DATA 包和 HEARTBEAT 包在后台跳动。

  2. 验证跨语言通信: 你可以用 C++ 写发布者 ,用 Python 写订阅者 。只要它们的 Topic NameIDL 结构 一致,它们就能完美对话。这正是 RTPS 跨平台能力的体现。

  3. 模拟网络丢包: 尝试关闭发布者,观察订阅者的状态。或者在分布式环境下(两台电脑),你会发现只要在同一个局域网,它们会自动发现对方。


💡 进阶建议

如果你在运行中发现收不到数据,通常是因为 QoS(服务质量) 不匹配。比如发布者要求"可靠传输(RELIABLE)",而订阅者设置为"尽力而为(BEST_EFFORT)",连接就无法建立。

相关推荐
汽车仪器仪表相关领域4 小时前
液力传动精准标定 + 智能换挡控制,动力总成测试新高度:GZCVL T‑IV 变矩器变速箱测试系统实战全解
功能测试·单元测试·汽车·压力测试·可用性测试·安全性测试
计算机学姐9 小时前
基于SpringBoot的汽车美容保养系统
java·spring boot·后端·spring·tomcat·汽车·mybatis
marteker12 小时前
“亚洲飞人”苏炳添代言小米汽车
汽车
Godspeed Zhao1 天前
现代智能汽车系统——SOME/IP与DDS0
网络协议·tcp/ip·汽车
LONGZETECH1 天前
新能源汽车维护仿真软件技术架构解析+ 教学落地实操
大数据·c语言·人工智能·架构·汽车·汽车仿真教学软件·汽车教学软件
Luminbox紫创测控1 天前
准直光模拟技术:汽车车顶太阳能板辐照测试的应用
人工智能·计算机视觉·汽车
中华网商业1 天前
浙江润鑫STW-18汽车轮重测量仪 稳定可靠守护车辆运行安全
安全·汽车
GlobalInfo1 天前
汽车电感式位置传感器行业单项冠军申请趋势分析报告
大数据·人工智能·汽车
GOWIN革文品牌咨询2 天前
汽车软件品牌升级实践框架:如何把”可控感”落到架构、证据与场景中
汽车·b2b品牌策划·b2b品牌设计