Open Splice DDS 个人学习
opensplice的架构是,首先定义好每个信息(topic),将信息存储到GDS(Global Data Space)中,然后动态的分配publisher与subscriber。虽然数据在程序执行之初已经静态分配,但可以动态的分配publisher与subscriber。从而实现去中心化,可以部分实现动态建立拓扑结构。
1.建立域
这是一个相当于空间的概念,你想两个或多个设备互相通信,首先需要建立空间。
按照ioscpp2标准,生成的参与者的代码应该为:
dds::domain::DomainParticipant dp(0);
对于多个参与者订阅者,想要互相发数据接收数据,都需要建立同样的域,上述代码就是将域设置为0。
2.建立Topic
Topic支持很多vendors,比如IDL、XML、protobuf等。我主要用的是IDL格式。
(1)Topic是由一个type、一个唯一的name和一系列的services组成。
Topic type是由IDL(Interface Definition Language[1])表示,如下代码就是一个简单的HelloWorldData.idl文件。(这个文件在软件的example有。路径:HDE/x86_64.linux/examples/dcps/HelloWorld/idl)
module HelloWorldData { struct Msg { /** User ID */ long userID; /** message */ string message; }; #pragma keylist Msg userID };
这个.idl文件是不是很熟悉,很像C++中的class的感觉,里面包含了struct,HelloWorldData是指idl的范围(scope);Msg是指idl的数据内容(包含的信息);#pragma keylist指明了DataCommType的键值(keys),每个键值将标识特定的数据流; 更准确地说,在DDS中,每个键值都标识一个Topic实例。第一步虽然是在一个域下面,但是多种数据,又需要用topic区分开,
dds::topic::Topic<HelloWorldData::Msg> topic(dp,
"DDataComm"
);
"DDataComn"这个名字对于publisher和scriber要设定一样,不然互相找不到,dp就是你自己的域名。
3.写数据
好的,你现在既在一个域和一个topic下面了,应该就能互相发送数据了。(其实还会有一个Partion,这个目前不是很熟,后面熟悉了再解释)
dds::pub::Publisher pub(dp); dds::pub::DataWriter<DataComm::DataCommType> dw(pub, topic);
参与者dp2是数据的publisher,同时定义了写数据dw。(有点像定义一个画家和笔一样的感觉)
将数据写入topic,数据写入topic的方式主要由两种:
HelloWorldData::Msg msg(1, "hello world") dw.write(msg)
先将数据存入变量,然后写到dw中区
或者
dw<< HelloWorldData::Msg (1, "hello world");
将数据按照数据流的方式写入dw里面去。
4.读数据
和写数据差不多
dds::sub::Subscriber sub(dp); dds::sub::DataReader<HelloWorldData::Msg> dr(sub, topic);
然后通过dw.read()读取数据,你可以将读出来的数据放到变量里面,打印出来,看看是不是想要的
5.Topic介绍
(1)pragma keylist
这个topic里面有个pragma keylist,后面你可以跟参数也可以不跟,区别是:比如跟个id,不同的id,相当于创建不同的实例,而这样的话,在系统中就会占据多个资源,好像是坏处,但其实,你可以将不同的id看作现实中不同的硬件,不同硬件传递不同参数,这样的话,在系统运行的过程中,每由一个设备接入,系统会监测到,同时为设个设备分配相应的topic instance。如果你只有一个硬件设备,那么就可以不设,节省资源
(2)分区
上面有提到partion,根据网上的资料:域可以进一步组织成分区,其中每个分区可以表示topic的逻辑分组。
dds::pub::qos::PublisherQos pubQos = dp.default_publisher_qos() << dds::core::policy::Partition("room1")
目前实践可以这么使用,和topic一样,要想在分布订阅数据,分区名也要一样。
6.Qos介绍
Qos可以理解为数据发送者和接收者之间的合约,Qos基本负责DDS中的所有配置,像我们熟知的心跳机制,消息可靠性,流量控制,等等,所以想要保证顺利接受到发送方发的数据,我们要保证Qos的策略要兼容(可以理解为接受方的策略严格程度小于发送方)。
(1)数据可用性服务(Data availability)
Opensplice为域的参与者提供了一些数据可用行服务,包括如下:
VOLATILE:
dds::core::policy::Durability::Volatile()
一旦设定,当前发布者发布的数据只提供给现有的订阅者,后面再加入的订阅者就收不到信息了,这是默认设置。
PERSISTENT:
dds::core::policy::Durability::Persistent()
一旦设定,永久保存数据,后面的订阅者仍然能够获得数据,即使系统发生重启,源码里面解释会将数据存入例如硬盘的存储空间里。
TRANSIENT:
dds::core::policy::Durability::Transient();
一旦设定,GDS保存数据,后面的订阅者仍然能够获得数据。
TRANSIENT_LOCAL:
dds::core::policy::Durability::TransientLocal();
一旦设定,如果publisher还存在,为了接下来的subscriber得到最新发布的数据,TRANSIENT_LOCAL服务保证publisher需要将数据存储在本地。
对于这些策略,个人理解是, 对于一个DDS系统,里面有多个发布者和订阅者,对于这些订阅者,不一定是同时启动,有的快,有的慢,如果使用默认的VOLATILE策略那么后启动的订阅者则会失去一些信息,而使用其他模式,其实你是后启动的或者离线重新连接的,由于这些数据是存储在本地的,所以仍然会接收到。
(2) 数据传输服务(Data delivery)
以下策略是控制数据的交付方式:
dds::core::policy::Presentation() :控制着想subscriber提供信息变更的方式,它下面有好几种方式,主要是这两种:coherent_access和ordered_access 第一个就是接收方的信息都收到,程序才能访问,第二个就是应用程序按照数据到达顺序访问。此QoS可控制数据更新的排序和一致性。应用范围由访问范围定义,访问范围可以是INSTANCE,TOPIC或GROUP级别之一。
dds::core::policy::Reliability():控制与数据扩散相关的可靠性级别。可能的选择是RELIABLE和BEST_EFFORT分配。reliable就是可靠送达,另一个就是尽力送达,前者比较耗资源。
dds::core::policy::Partition():同上分区介绍。
dds::core::policy::DestinationOrder():控制publisher对给定topic的某个instance所做的更改的顺序。 DDS允许根据源或目标时间戳排序不同的更改。ReceptionTimestamp和SourceTimestamp,一个以接受端最后收到的数据为准,一个是以发送端发送的最后的数据为准。
dds::core::policy::Ownership():控制哪个writer拥有topic的访问权,当有多个writers要求访问topic,且topic是EXCLUSIVE(独占)。仅仅拥有最高OWNERSHIP_STRENGTH(拥有权)的writer可以publish数据。如果OWNERSHIP QoS是共享的那么可以由多个writer访问topic,因此有助于管理相同数据的复制发布者。当系统中存在针对同一个数据实例的多个Datawriter时,可以通过设置每个Datawriter的"强度"来控制Datawriter的写入权限(“强度”最高的DataWriter拥有写入权限)
比如:有两套传感器(冗余)只使用一个,一个发生故障(高强度),切换到另一个传感器(次强度)
这些DDS数据传输服务控制数据的可靠性和可用性,从而允许在正确的时间将正确的数据传送到正确的位置。
(3) 数据及时性服务(Data timeliness)
下面的这些策略是控制分布式数据的时效性:
dds::core::policy::DeadLine:可以定义的最大到达时间值。当任务错过最大时间到达值,Opensplice可以配置通知任务已经错过。设置deadline注意要将接收端的deadline>=发送方的,不然会不兼容!
dds::core::policy::LatencyBudget:可以为任务提供了一种通知Opensplice传输数据相关的紧急程度的方法。这个服务指定DDS必须分发信息的时间段。此时间段从publisher写入数据的那一刻开始,直到subscriber的数据缓存中可用,以供读者使用。
dds::core::policy::TransportPriority :允许任务控制topic或者topic instance的重要程度,从而允许处理任务优先处理相对重要的topic。里面设置数值,越大表示优先级越高。
(4) Resources (计算资源)
DDS定义了以下Qos策略来控制满足数据分发要求所必需的网络和计算资源:
1、TimeBasedFilter
设置该参数意味着在指定时间周期内只期望收到一个data sample,过多的data sample将被DataReader丢弃该参数有助于优化网络负载及节点的计算资源。
比如:默认情况发送方能发送得很快(1秒108个),接受方只要求1秒5个,就可以设置这个参数控制发送速度,减小本地系统资源。
2、ResourceLimits
用于限制DDS可以分配的系统内存
(5) 组态(Configuration)
未完待续。。。。。。。。。。。。。