最近在研究XRCE-DDS的时候,被师兄问了两个关于DDS的问题,一个都没答上来,很惭愧,所以想回过头普及一下DDS的相关知识,很幸运找到了Paul大佬的《DDS与FastRTPS》一文,受益匪浅,在这里结合自己搜集到的其他资料和对协议原文的阅读,做一些总结。
DDS(数据分发服务)是一套通信协议和API标准,以数据为中心是他的特点,它基于发布-订阅模型进行设计。而FastRTPS是eProsima公司对DDS的一个开源实现。
DDS是一套中间件,提供介于操作系统和应用程序之间的功能,提供了低延迟、高可靠的通信以及可扩展的架构。
DDS其实分为两部分,一部分是DDS规范,一部份则是DDSI-RTPS协议,是一个互操作性协议,也就是真正实现通讯机制的部分,在ROS2中,也正是这部分,取代了ROS1的TCPROS和UDPROS。
所谓互操作性协议,就是为了满足互操作性而产生的一个协议,互操作性就是指两个实体的通信能力,如果两个实体之间能够在任何情况下都无误解的进行通信,那么我们就说这两个实体可以正确的互操作。
DDS的架构是这个样子的:
或者说是这个样子的:
在DDS规范中,有两个描述标准的文档
- DDS Specification
- DDSI-RTPS
DDS Specification
DDS规范主要是描述了用于分布式应用程序通信和集成的以数据为中心的发布-订阅(DCPS模型)。定义了应用程序接口(API)和通信语义(行为和服务质量),他们可以有效地将信息从信息生产者传递给匹配的消费者。DDS规范的目的可以概括为”在正确的时间将正确的信息有效且稳健地传递到正确的位置“。
DCPS定义应用程序用于发布和订阅数据对象值地功能,它允许:
- 发布应用程序以标识要发布的数据对象,然后为这些对象提供值
- 订阅应用程序以识别他们感兴趣的数据对象,然后访问其数据值
- 应用程序用于定义主题,将类型信息附加到主题,创建发布者、订阅者实体,将QoS策略附加到所有这些实体,使所有这些实体运行。
主要包括两部分
- 平台无关模型(PIM)
- 基于PIM地OMG IDL平台的平台特定模型(PSM)
DDSI-RTPS
DDSI_RTPS主要描述了RTPS(Real Time Publish Subscribe Protocol)协议。该协议通过UDP等不可靠传输,实现最大努力(Best-Effort)和可靠的发布-订阅通信。RTPS是DDS实现的标准协议,它的目的和范围是确保基于不同DDS供应商的应用程序可以实现互操作。
RTPS协议旨在能够在多播和无连接的尽力传输方式(例如UDP/IP)上运行。 RTPS协议的主要特点包括:
- 性能和服务质量属性,通过标准IP网络为实时应用程序提供尽力而为和可靠的发布订阅通信。
- 容错,允许创建没有单点故障的通信网络。
- 可延展性,允许使用新服务来扩展和增强协议,同时不破坏向下兼容性和互操作性。
- 即插即用连接,以便自动发现新的应用程序和服务,应用程序可以随时加入和离开网络,无需重新配置。
- 可配置性,平衡数据传输的可靠性和及时性需求。
- 模块化,允许简单设备实现协议的子集并加入网络。
- 可扩展性,使系统可以扩展到非常大的网络。
- 类型安全,以防止应用程序编程错误影响远程节点的运营。
RTPS协议主要包括三部分
- RTPS平台无关模型(PIM)
- RTPS平台有关模型(PSM)
- RTPS传输模型
RTPS PIM
包括四个模块:结构模块、消息模块、行为模块和发现模块
结构模块定义通信端点
所有RTPS实体都与RTPS域相关联,RTPS域表示包含一组参与者(Participants)的单独通信平面。 参与者包含本地端点(Endpoints)。 有两种类型的端点:读取者(Readers) 和写入者(Writers)。读取者和写入者是通过发送RTPS消息来传达信息的参与者。写入者告知数据的存在并将数据域(Domain)上的本地可用数据发送给读取者,读取者可以请求和确认数据。
RTPS协议中的活动者和DDS实体一一对应,这是通信产生的原因。
消息模块定义这些断电可以交换的消息集合
消息模块定义RTPS写入者和读取者之间的原子信息交换的内容。消息(Message)由一个报文头(Header)后跟一些子消息(Submessage)组成。每个消息都是由一系列元素构建的。选择此结构是为了允许扩展子消息的内容和每个子消息的组成,同时保持向下兼容性。
行为模块定义了合法交互集以及他们如何影响通信端点的状态。
行为模块描述了可以在RTPS写入者和读取者之间交换的消息序列,以及时间和每条消息引起的写入者和读取者状态的变化。
互操作性所需的行为是根据实现必须遵循的最小规则集来描述的,以便实现互操作。实际实现可能表现出超出这些最低要求的不同行为,具体取决于他们希望如何权衡扩展性,内存要求和带宽使用。
为了说明这个概念,行为模块定义了两个参考实现。一个参考实现基于有状态写入者(StatefulWriters)和有状态读取者(StatefulReaders),另一个基于无状态写入者(StatelessWriters)和无状态读取者(StatelessReaders)。两种参考实现都满足互操作的最低要求,因此可以互操作,但由于它们存储在匹配的远程实体上的信息不同,因此表现出略微不同的行为。 RTPS协议的实际实现的行为可以是参考实现的完全匹配或组合。
发现模块定义如何自动发现和配置实体
发现模块描述了使参与者(Participants)能够获取域中所有其他参与者(Participants)和端点(Endpoints)的存在和属性信息的协议。这种元通信(metatraffic)使每个参与者(Participant)能够获得域中所有参与者(Participants),读取者(Readers)和写入者(Writers)的完整信息,并配置本地写入者与远程读取者进行通信,以及本地读取者与远程写入者进行通信。
发现是一个单独的模块。发现的独特需求,即写入者和读取者进行匹配所需的所有信息需要通过透明地即插即用传播,使得单个架构或协议不可能满足各种各样的可扩展性,性能和将部署DDS的异构网络的嵌入性需求。从此以后,引入多种发现机制是有意义的,这些机制从简单和有效(但不是很可扩展)到更复杂的分层(但更具可扩展性)机制。
RTPS平台特定模型(PSM)
特定于平台的模型将RTPS PIM映射到特定的底层平台。它定义了所有RTPS类型和消息的位和字节的精确表示以及专属于平台的其他信息。可能支持多个PSM,但是DDS的所有实现必须是在UDP/IP之上实现PSM。
RTPS传输模型
RTPS支持各种传输方式和传输QoS。该协议旨在能够在多播和尽力而为的传输方式(例如UDP/IP)上运行,并且只需要该传输方式提供非常简单的服务。实际上传输方式提供能够最大限度地发送数据包的无连接服务就足够了。也就是说传输方式不需要保证每个数据包会到达其目的地或者数据包按顺序传送。如果需要,RTPS在传输接口以上实现数据传输和状态的可靠性。这并不排除RTPS在可靠的传输方式之上实现。它使得支持更广泛的底层传输方式成为可能。
如果可以的话,RTPS还可以利用传输机制的多播功能,来自发送方的一条消息可以到达多个接收方。RTPS旨在促进底层通信机制的确定性。该协议提供了确定性和可靠性之间的公开权衡。
RTPS对底层传输方式的一般要求可归纳如下:
- 传输具有单播地址(长度应在16字节以内)的通用概念。
- 传输具有端口(长度应在4字节以内)的通用概念,例如可以是UDP端口或者共享存储器段中的偏移等。
- 传输可以将数据报(未解释的八位字节序列)发送到特定的地址/端口。
- 传输可以在特定地址/端口接收数据报。
- 如果传输过程中消息不完整或已损坏,传输将丢弃消息(即RTPS假定消息已完成且未损坏)。
- 传输提供推断接收消息大小的方法。
DDSI-RTPS之PIM
发现模块
RTPS行为模块(前一章讲了行为模块)假定已正确配置RTPS端点,并与匹配的远程端点配对。 它不对如何进行此配置进行任何假设,仅定义如何在这些端点之间交换数据。
为了能够配置端点,实现必须获取有关远程端点的存在及其属性的信息。
为了获取此信息是发现模块的主题,发现模块定义了RTPS发现协议。 发现协议的目的是允许每个RTPS参与者发现其他相关参与者及其端点。 一旦发现远程端点,实现可以相应地配置本地端点以建立通信。
DDS规范同样依赖于发现机制的使用,以在匹配的DataWriter和DataReader之间建立通信。 DDS实现必须在加入和离开网络时自动发现远程实体的存在。 用户可以通过DDS内置topic访问此发现信息。
本模块中定义的RTPS发现协议为DDS提供了必需的发现机制。
概述
RTPS规范将发现协议分为两个独立的协议:
- 参与者发现协议(Participant Discovery Protocol ,PDP)
- 端点发现协议(Endpoint Discovery Protocol ,EDP)
参与者发现协议(PDP)指定参与者如何在网络中彼此发现。一旦两个参与者发现彼此,他们就会使用端点发现协议(EDP)在其包含的端点上交换信息。除了这种因果关系,可以考虑两种协议是相互独立的。
实现可以选择支持多个PDP和EDP,可能是特定于供应商的。只要两个参与者至少具有一个共同的PDP和EDP,他们就可以交换所需的发现信息。
为了实现互操作性,所有RTPS实施都必须至少提供以下发现协议:
- 简单参与者发现协议(Simple Participant Discovery Protocol,SPDP)
- 简单端点发现协议(Simple Endpoint Discovery Protocol,SEDP)
两者都是基本的发现协议,适用于中小型网络。面向更大网络的其他PDP和EDP可能会添加到该规范的未来版本中。
最后,发现协议的作用是提供有关发现的远程端点的信息。参与者如何使用此信息来配置其本地端点取决于RTPS协议的实际实现,而不是发现协议规范的一部分。例如,对于8.4.7中引入的参考实现,在远程端点上获得的信息允许实现配置:
- 与每个RTPS StatelessWriter关联的RTPS ReaderLocator对象。
- 与每个RTPS StatefulWriter关联的RTPS ReaderProxy对象。
- 与每个RTPS StatefulReader关联的RTPS WriterProxy对象。
发现模块的组织方式如下:
- SPDP和SEDP依靠预定义的RTPS内置Writer和Reader端点进行交换发现信息。 8.5.2引入了这些RTPS内置端点。
- 在8.5.3中讨论了SPDP。
- 在8.5.4中讨论了SEDP
RTPS内置发现端点
DDS规范指定使用带有预定义主题和QoS的“内置” DDS DataReader和DataWriter进行发现。
有四个预定义的内置主题:“ DCPSParticipant”,“ DCPSSubscription”,“ DCPSPublication”和“ DCPSTopic”。 与这些主题相关联的数据类型也由DDS规范指定,并且主要包含实体QoS值。
对于每个内置主题,都有一个对应的DDS内置DataWriter和DDS内置DataReader。内置的DataWriter用于向网络其余部分通告本地DDS参与者和其包含的DDS实体(DataReaders,DataWriters和Topics)的存在和QoS。同样,内置的DataReader从远程参与者收集此信息,然后DDS实现将其用于标识匹配的远程实体。内置的DataReader充当常规DDS DataReader,并且用户也可以通过DDS API对其进行访问。
RTPS简单发现协议(SPDP和SEDP)采用的方法类似于内置实体概念。 RTPS将每个内置DDS DataWriter或DataReader映射到关联的内置RTPS端点。这些内置端点充当常规的Writer和Reader端点,并提供了使用行为模块中定义的常规RTPS协议在参与者之间交换所需发现信息的方法。
SPDP涉及参与者之间如何发现对方,它为“ DCPSParticipant”主题映射了DDS内置实体。 SEDP指定了如何交换有关本地主题,DataWriters和DataReader的发现信息,它为“ DCPSSubscription”,“ DCPSPublication”和“ DCPSTopic”主题映射了DDS内置实体。
SPDP
PDP的目的是发现网络上其他参与者的存在及其属性。
参与者可以支持多个PDP,但是出于互操作性的目的,所有实现都必须至少支持简单参与者发现协议。
一般方法
RTPS简单参与者发现协议(SPDP)使用一种简单方法来宣布和检测域中参与者的存在。
对于每个参与者(Participant),SPDP将创建两个RTPS内置端点:SPDPbuiltinParticipantWriter和SPDPbuiltinParticipantReader。
SPDPbuiltinParticipantWriter是RTPS尽力而为的StatelessWriter。 SPDPbuiltinParticipantWriter的HistoryCache包含一个类型为SPDPdiscoveredParticipantData的数据对象。该数据对象的值是从参与者的属性中设置的。如果属性更改,则数据对象为
更换。
SPDPbuiltinParticipantWriter会定期将此数据对象发送到预先配置的定位器列表,以宣布参与者在网络上的存在。这是通过定期调用StatelessWriter :: unsent_changes_reset来实现的,它使StatelessWriter将其HistoryCache中存在的所有更改重新发送给所有定位器。SPDPbuiltinParticipantWriter发送SPDPdiscoveredParticipantData的周期速率默认为PSM指定的值。此时间段应小于在SPDPdiscoveredParticipantData中指定的leaseDuration(另请参见8.5.3.3.2)。
预先配置的定位器列表可以包括单播和多播定位器。端口号由每个PSM定义。这些定位器仅代表网络中可能的远程参与者,实际上不需要参与者。通过定期发送SPDPdiscoveredParticipantData,参与者可以以任何顺序加入网络。
SPDPbuiltinParticipantReader从远程参与者接收SPDPdiscoveredParticipantData公告。所包含的信息包括远程参与者支持哪些端点发现协议。然后使用正确的端点发现协议与远程参与者交换端点信息。
通过响应于从先前未知的参与者接收到此数据对象而发送附加的SPDPdiscoveredParticipantData,实现可以将任何启动延迟最小化,但是此行为是可选的。
实施方式还可以使用户选择是否使用来自新发现的参与者的新定位器自动扩展定位器的预配置列表。 这将启用非对称定位器列表。 最后两个功能是可选的,出于互操作性的目的不是必需的。
SEDP
端点发现协议(EDP)定义了两个参与者之间必需的信息交换,以便发现彼此的Writer端点和Reader端点。
参与者可以支持多个EDP,但是出于互操作性的目的,所有实现都必须至少支持简单端点发现协议。
一般方法
与SPDP相似,简单端点发现协议使用预定义的内置端点。使用预定义的内置端点意味着,一旦一个参与者知道另一个参与者的存在,它就可以假设存在由远程参与者提供的内置端点,并建立与本地匹配的内置端点的关联。
内置端点之间进行通信的协议与应用程序定义的端点所使用的协议相同。因此,通过读取内置的读取器端点,协议虚拟机可以发现属于任何远程参与者的DDS实体的存在和QoS。同样,通过编写内置的Writer端点,参与者可以将本地DDS实体的存在和QoS通知其他参与者。
因此,在SEDP中使用内置主题将整个发现协议的范围缩小到确定系统中存在哪些参与者以及与这些内置端点相对应的ReaderProxy和WriterProxy对象的属性值参加者。一旦知道了,其他一切都将由RTPS协议的应用到内置RTPS读取器和写入器之间的通信产生。
原文链接: https://zijian.wang/2021/04/08/DDS/
版权声明: 转载请注明出处.