DDS(Data Distribution Service)————Publisher(1)
1.什么是Publisher与DataWriter
Publisher是与DataWriter相关联来使用的,DataWriter是由Publisher创建的,Publisher可以对应多个DataWriter,而DataWriter只能一对一绑定到一个Topic上,并且数据的传递都是由DataWriter实现的。
以下是类的关系图:
Notes:其中0…1的表示为只能有0个或者1个对应的实例。
2.PublisherQos的配置
PublisherQos控制对应的Publisher,以下是相关示例:
/* 创建DomainParticipant */
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0,PARTICIPANT_QOS_DEFAULT);
if (participant == nullptr)
{
return 1;
}
/* 创建Publisher */
Publisher* publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT);
if (nullptr == publisher)
{
return 1;
/* code */
}
/* 获取对应实例的Qos */
PublisherQos p_qos = publisher->get_qos();
p_qos.partition();
/* 获取Publisher的默认Qos */
PublisherQos publisherQos = participant->get_default_publisher_qos();
PublisherQos publisherQosDefault = participant->get_default_publisher_qos();
/* Modify the default default_PublisherQos */
/* 修改 participant默认的Qos,不会改变已经实例化的Publisher */
participant->set_default_publisher_qos(publisherQosDefault);
3.PublisherQos中的属性和使用场景
3.1 PresentationQosPolicy的属性与使用场景
以下是PublisherQos的属性如下:
PresentationQosPolicy
是Data Distribution Service (DDS)中用于控制数据的表示和发布行为的一种QoS策略。它定义了数据在发布者和订阅者之间如何进行传递的规则。PresentationQosPolicy
主要有三个属性:access_scope
、coherent_access
和、ordered_access
。下面详细解释每个属性及其作用:
3.1.1access_scope
access_scope
定义了数据的访问范围,决定了数据在何种范围内是一致的。它有三个可能的值:
INSTANCE
:- 数据的一致性仅限于单个数据实例。
- 数据的顺序和一致性仅在每个数据实例内部维护。
- 数据可以独立处理,适合于对每个实例单独处理的应用场景。
TOPIC
:- 数据的一致性扩展到整个主题。
- 数据的顺序和一致性在主题级别上维护。
- 确保在一个主题内,所有数据实例的更新顺序一致。
GROUP
:- 数据的一致性扩展到整个订阅者或发布者组。
- 数据的顺序和一致性在组级别上维护。
- 适用于需要跨多个主题或实例维持一致性的应用场景。
以下为各种类型的兼容性 {\color{red}以下为各种类型的兼容性} 以下为各种类型的兼容性
S c e n a r i o 1 : I N S T A N C E A c c e s s S c o p e S c e n a r i o 1 : I N S T A N C E A c c e s s S c o p e {\color{red}Scenario 1: INSTANCE Access ScopeScenario 1: INSTANCE Access Scope} Scenario1:INSTANCEAccessScopeScenario1:INSTANCEAccessScope
-
发布数据:
writerA.write(data1_instance1); // TopicA, Instance1 writerA.write(data2_instance1); // TopicA, Instance1 writerB.write(data1_instance2); // TopicB, Instance2 writerB.write(data2_instance2); // TopicB, Instance2
-
读取数据:
readerA
会按顺序读取data1_instance1
和data2_instance1
。readerB
会按顺序读取data1_instance2
和data2_instance2
。- 不保证
data1_instance1
和data1_instance2
之间的顺序。 就是不保证 I n s t a n c e 1 与 I n s t a n c e 2 之间的顺序 {\color{red}就是不保证Instance1与Instance2之间的顺序} 就是不保证Instance1与Instance2之间的顺序
S c e n a r i o 2 : T O P I C A c c e s s S c o p e {\color{red}Scenario 2: TOPIC Access Scope} Scenario2:TOPICAccessScope
-
发布数据:
writerA.write(data1_instance1); // TopicA writerA.write(data2_instance1); // TopicA writerB.write(data1_instance2); // TopicB writerB.write(data2_instance2); // TopicB
-
读取数据:
readerA
会按顺序读取data1_instance1
和data2_instance1
,并保证所有TopicA
实例的顺序。readerB
会按顺序读取data1_instance2
和data2_instance2
,并保证所有TopicB
实例的顺序。- 不保证
TopicA
和TopicB
之间的顺序。
S c e n a r i o 3 : G R O U P A c c e s s S c o p e {\color{red}Scenario 3: GROUP Access Scope} Scenario3:GROUPAccessScope
-
发布数据:
cpp复制代码writerA.write(data1_instance1); // TopicA writerA.write(data2_instance1); // TopicA writerB.write(data1_instance2); // TopicB writerB.write(data2_instance2); // TopicB
-
读取数据:
readerA
和readerB
会按顺序读取所有数据,保证TopicA
和TopicB
之间的顺序。- 数据读取顺序为:
data1_instance1
,data2_instance1
,data1_instance2
,data2_instance2
。
总结 {\color{green}总结} 总结
- INSTANCE:数据一致性和顺序限制在单个实例内。
- TOPIC:数据一致性和顺序扩展到整个主题。
- GROUP:数据一致性和顺序扩展到所有关联的主题和实例。
3.1.2 coherent_access
在DDS(Data Distribution Service)中,一致性(coherent_access)是指确保在分布式系统中发布和接收的数据的一致性。特别是在PresentationQosPolicy
中,通过设置coherent_access
属性,可以确保一组相关的操作(如一系列的写操作)被视为一个原子操作,要么被订阅者完整地看到,要么完全看不到。
简单来说在写数据的时候,如果在过程中发生错误,没有将所有需要写入的数据一同写入,发生了问题,则会进行相关处理,防止发生数据不一致的情况。
// 开始一致访问
writer.publisher().begin_coherent_changes();
writer.write(sample1);
writer.write(sample2);
// 结束一致访问
writer.publisher().end_coherent_changes();
3.1.3 ordered_access
确保订阅者接收到的数据顺序与发布者发送的数据顺序一致。 与 3.1 中举的例子一致 {\color{green}与3.1中举的例子一致} 与3.1中举的例子一致
3.1.4 设置PresentationQosPolicy
/* 对于 access_scope 的可选类型 */
enum PresentationQosPolicyAccessScopeKind : fastrtps::rtps::octet
{
INSTANCE_PRESENTATION_QOS,
TOPIC_PRESENTATION_QOS,
GROUP_PRESENTATION_QOS
};
/* 设置Qos */
presentationQos.access_scope = INSTANCE_PRESENTATION_QOS;
presentationQos.coherent_access = true;
presentationQos.ordered_access = true;
3.2 PartitionQosPolicy
PartitionQosPolicy
是 DDS(Data Distribution Service)中的一种策略,用于对主题(Topic)进行逻辑分区,使得同一物理网络上的多个应用能够通过不同的逻辑分区隔离和组织数据流。通过使用分区,发布者和订阅者可以在同一个物理网络中进行数据隔离,从而避免不必要的数据传输。
PartitionQosPolicy
可以应用于 Publisher
和 Subscriber
,通过设置分区名称来控制数据流的分隔。
PartitionQosPolicy partition = p_qos.partition();
/* 设置最大的分区名称的数量,其实就是相当于多少了Vlan */
partition.set_max_size(17);
/* 获取这个partition中逻辑分区名字列表 */
std::vector<std::string> part = partition.names();
/* 增加对应的分区名称 */
part.push_back("Part1");
part.push_back("Part2");
/* 重新赋值 */
p_qos.partition(partition);
3.3 GroupDataQosPolicy
GroupDataQosPolicy
是 DDS (Data Distribution Service) 中的一种 QoS(Quality of Service)策略,用于为数据传输组提供附加的、用户定义的信息。这些信息可以在 Publisher
或 Subscriber
之间共享,以便实现特定的功能,例如数据过滤、数据分组、应用程序级别的信息传递等。
GroupDataQosPolicy
的主要作用是允许用户在 Publisher
和 Subscriber
之间传递应用程序特定的二进制数据,这些数据可以用来实现:
- 数据分组:将相关的数据划分为组,以便接收方能够识别和处理特定组的数据。
- 元数据传递:传递额外的信息,如版本号、应用标识等。
- 过滤机制:通过在接收方根据这些数据来过滤不需要的数据。
3.3.1 传递的数据类型
其中:octet 是原型unsigned char
3.3.2 使用举例
/* 创建数据类型 */
std::vector<eprosima::fastrtps::rtps::octet> vec;
/* 输入值 */
vec.push_back('H');
vec.push_back('L');
vec.push_back('L');
vec.push_back('O');
/* 赋值到group_data */
p_qos.group_data().setValue(vec);
3.4 EntityFactoryQosPolicy
EntityFactoryQosPolicy
是 DDS(Data Distribution Service)中的一种 QoS(Quality of Service)策略,用于控制实体(Entity)作为工厂(Factory)时,创建实体时,是否对于实体进行激活
3.4.1 EntityFactoryQosPolicy的成员属性使用
N o t e s : {\color{red}Notes:} Notes:
- 默认情况下为:true,在创建实例后,自动激活创建的实例。
- 若设置为:false,则需要手动激活。
3.4.2 具体使用
EntityFactoryQosPolicy entity_qos = p_qos.entity_factory();
/* 修改属性 */
entity_qos.autoenable_created_entities = false;
DataWriter* writer = publisher->create_datawriter(0,DATAWRITER_QOS_DEFAULT);
/* 使实体激活 */
writer->enable();
3.4.2 具体使用
EntityFactoryQosPolicy entity_qos = p_qos.entity_factory();
/* 修改属性 */
entity_qos.autoenable_created_entities = false;
DataWriter* writer = publisher->create_datawriter(0,DATAWRITER_QOS_DEFAULT);
/* 使实体激活 */
writer->enable();