分布式仿真实时通信协议实例:DDS(Data Distribution Service)
首先,我们需要定义一个在进程间传输的数据结构。这通常使用接口定义语言(IDL) 完成。long id;//本文章使用的是以下命令,可以生成一个完整的使用示例文件此命令会生成以下文件,其中包含了用于序列化和反序列化的C++类。这个实例展示了DDS通信的核心流程。DDS通过其以数据为中心的架构丰富的QoS策略和去中心化的自动发现机制,为构建复杂、可靠、实时的分布式仿真系统提供了坚实基础。深入QoS:
DDS(数据分发服务)是一种专为分布式实时系统设计的高性能通信中间件。下面我将通过一个具体的实例,展示如何使用 Fast DDS (一个流行的开源DDS实现) 来创建发布者和订阅者,并涵盖从环境搭建到代码运行的完整流程。
为了帮助您快速建立整体概念,下图概括了 DDS 的核心通信模型(DCPS)及其实例中各个组件的协作关系。
flowchart TD
A[发布者应用程序] -->|创建| B[Publisher]
A -->|创建| C[DataWriter]
D[订阅者应用程序] -->|创建| E[Subscriber]
D -->|创建| F[DataReader]
B -->|管理| C
E -->|管理| F
C -->|写入数据| G[HelloWorld Topic]
F -->|读取数据| G
G -->|基于| H[Msg.id<br/>Msg.message]
I[DomainParticipant] -->|发现并匹配| J[DomainParticipant]
B -->|隶属于| I
E -->|隶属于| J
subgraph K [DDS全局数据空间]
I
J
G
end

上图的逻辑在实例中体现为:发布者和订阅者作为DomainParticipant加入同一个域(例如ID为0的域),并通过名为HelloWorldTopic的Topic进行数据连接。DataWriter和DataReader分别负责数据的写入和读取,并通过DDS内置的自动发现机制建立通信。
CMake版本升级:
# 卸载旧版本
sudo apt remove --purge cmake
# 安装依赖
sudo apt update
sudo apt install -y software-properties-common lsb-release
# 下载 Kitware 的 GPG 密钥
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
# 添加 Kitware 仓库
echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/kitware.list
# 更新并安装最新 CMake
sudo apt update
sudo apt install -y cmake
# 验证安装
cmake --version
第一步:环境搭建与Fast DDS安装
在开始编写代码前,需要先安装Fast DDS及其依赖库。以Ubuntu系统为例,具体操作如下表所示:
|
步骤 |
命令/操作 |
说明 |
|---|---|---|
|
1. 安装依赖 |
|
获取编译工具和必要的库文件。 |
|
2. 安装FastCDR |
|
Fast DDS依赖的序列化库。 |
|
3. 安装Foonathan Memory |
|
Fast DDS依赖的内存管理库。 |
|
4. 安装Fast DDS |
|
编译并安装核心的Fast DDS库。 |
|
5. 验证安装 |
执行 |
确保头文件和库链接正确。 |
提示:如果在
cmake阶段遇到类似“Asio版本过低”的错误,可能需要手动升级Asio库。 在Windows系统上,过程类似,但通常使用Visual Studio的开发者命令提示符和CMake GUI进行编译,并需确保环境变量设置正确。
第二步:编写DDS应用程序代码
安装好环境后,就可以编写DDS应用程序了。一个典型的DDS应用包含三个部分:数据定义、发布者和订阅者。
1. 定义数据类型(IDL文件)
首先,我们需要定义一个在进程间传输的数据结构。这通常使用接口定义语言(IDL) 完成。
// HelloWorld.idl
module HelloWorld {
struct Msg {
long id;
string message;
};
};
使用Fast DDS提供的代码生成工具,可以将这个IDL文件转换成C++代码:
# fastddsgen HelloWorld.idl
//本文章使用的是以下命令,可以生成一个完整的使用示例文件
fastddsgen -example CMake HelloWorld.idl
如果fastddsgen命令不存在,需要安装Fast DDS Gen,编译完的fastddsgen在Fast-DDS-Gen/scripts路径下:
~$ cd fastdds-workspace
~/fastdds-workspace$ sudo apt install openjdk-17-jdk
~/fastdds-workspace$ git clone --recursive https://github.com/eProsima/Fast-DDS-Gen.git
~/fastdds-workspace$ cd Fast-DDS-Gen
~/fastdds-workspace/Fast-DDS-Gen$ ./gradlew assemble
此命令会生成 以下文件,其中包含了用于序列化和反序列化的C++类。

第三步:编译与运行
编译
使用CMake来管理编译过程是最佳实践。
编译命令:
mkdir build && cd build
cmake ..
make -j$(nproc)
这个示例只编译出一个可执行文件HelloWorld,这个程序包含了发布者和订阅者的功能。

运行
-
在一个终端启动订阅者,它将开始监听数据:
./HelloWorld subscriber # 运行为订阅者
-
在另一个终端启动发布者,它将开始发送数据:
./HelloWorld publisher # 运行为发布者
如果一切正常,你将在订阅者终端看到接收到的消息。这就是DDS自动发现机制在起作用:发布者和订阅者无需知道彼此的地址,只要在同一个域内,订阅同一主题,就能自动建立连接。
第四步:核心概念与进阶应用
理解服务质量(QoS)
DDS的强大之处在于其丰富的QoS策略,你可以像下面这样配置它们,以满足不同的可靠性需求:
// 配置一个可靠的、持久化的DataWriter
DataWriterQos writer_qos;
writer_qos.reliability().kind = RELIABLE_RELIABILITY_QOS; // 确保数据送达
writer_qos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS; // 新订阅者能获取最后一条消息
writer_qos.history().kind = KEEP_LAST_HISTORY_QOS; // 保留最后N条历史记录
writer_qos.history().depth = 10;
DataWriter* reliable_writer = publisher->create_datawriter(topic, writer_qos);
分布式仿真中的应用
在分布式仿真中,DDS的这些特性至关重要:
-
实时性:极低的延迟和确定性延迟保证,满足仿真系统苛刻的时序要求。
-
可扩展性:去中心化的架构允许轻松添加新的仿真节点(如新的传感器、控制器模型)。
-
可靠性:通过QoS确保关键控制指令和状态更新绝不丢失。
-
互操作性:DDS是一个开放标准,不同厂商开发的仿真组件可以通过DDS进行通信。
总结与建议
这个实例展示了DDS通信的核心流程。DDS通过其以数据为中心的架构、丰富的QoS策略和去中心化的自动发现机制,为构建复杂、可靠、实时的分布式仿真系统提供了坚实基础。
如果想进一步探索,可以从这几个方面入手:
-
深入QoS:尝试不同的QoS策略组合,观察其对数据传输行为的影响。
-
使用XML配置:将QoS等配置外置到XML文件中,使应用更灵活。
-
性能测试:利用
perftest等工具测试DDS在不同网络条件下的吞吐量和延迟。
更多推荐


所有评论(0)