• fastdds的快速使用


    1.1。什么是 DDS

    数据分发服务 (DDS)是一种以 数据为中心的通信协议,用于分布式软件应用程序通信。它描述了支持数据提供者和数据消费者之间通信的通信应用程序编程接口 (API) 和通信语义。

    由于它是一个以数据为中心的发布订阅 (DCPS) 模型,因此在其实现中定义了三个关键应用实体:发布实体,定义信息生成对象及其属性;订阅实体,它定义了信息消费对象及其属性;和配置实体,定义作为主题传输的信息类型,并使用其服务质量 (QoS) 属性创建发布者和订阅者,确保上述实体的正确性能。

    DDS 使用 QoS 来定义 DDS 实体的行为特征。QoS 由单独的 QoS 策略(源自 QoSPolicy 的类型的对象)组成。这些在Policy中描述。

    1.1.1。DCPS 概念模型

    在 DCPS 模型中,为开发通信应用系统定义了四个基本要素。

    出版商。它是负责创建和配置其实现的DataWriters的 DCPS 实体。DataWriter是负责实际发布消息的实体。每个人都有一个分配的主题,在该主题下发布消息。有关详细信息,请参阅发布者。

    订户。它是 DCPS 实体,负责接收在其订阅的主题下发布的数据。它为一个或多个DataReader对象提供服务,这些对象负责将新数据的可用性传达给应用程序。有关详细信息,请参阅订阅者。

    主题。它是绑定发布和订阅的实体。它在 DDS 域中是唯一的。通过TopicDescription,它允许发布和订阅的数据类型的统一。有关详细信息,请参阅主题。

    域。这是用于链接所有发布者和订阅者的概念,属于一个或多个应用程序,它们在不同主题下交换数据。这些参与域的单个应用程序称为DomainParticipant。DDS 域由域 ID 标识。DomainParticipant 定义域 ID 以指定它所属的 DDS 域。具有不同 ID 的两个 DomainParticipants 不知道彼此在网络中的存在。因此,可以创建多个通信通道。这适用于涉及多个DDS应用程序的场景,它们各自的DomainParticipants相互通信,但这些应用程序不得干扰。域参与者充当其他 DCPS 实体的容器,充当 发布者、订阅者和主题实体的工厂,并在域中提供管理服务。有关详细信息,请参阅域。
    在这里插入图片描述

    1.2. 什么是 RTPS

    为支持 DDS 应用程序而开发的实时发布订阅 (RTPS)协议是一种发布订阅通信中间件,它通过 UDP/IP 等尽力传输传输。此外,Fast DDS 还支持 TCP 和共享内存 (SHM) 传输。

    它旨在支持单播和多播通信。

    在继承自 DDS 的 RTPS 顶部,可以找到域,它定义了一个单独的通信平面。几个域可以同时独立地共存。一个域包含任意数量的RTPSParticipants,即能够发送和接收数据的元素。为此,RTPSParticipants 使用他们的Endpoints:

    RTPSWriter:能够发送数据的端点。

    RTPSReader:能够接收数据的端点。

    RTPSParticipant 可以有任意数量的写入器和读取器端点。
    在这里插入图片描述
    通信围绕主题进行,主题定义和标记正在交换的数据。主题不属于特定参与者。参与者通过 RTPSWriters 对主题下发布的数据进行更改,并通过 RTPSReaders 接收与其订阅的主题相关的数据。通信单元称为Change,它表示在 Topic 下写入的数据的更新。 RTPSReaders/RTPSWriters在其History上注册这些更改,这是一种用作最近更改缓存的数据结构。

    在eProsima Fast DDS的默认配置中,当您通过 RTPSWriter 端点发布更改时,会在后台执行以下步骤:

    更改将添加到 RTPSWriter 的历史缓存中。

    RTPSWriter 将更改发送到它知道的任何 RTPSReaders。

    接收到数据后,RTPSReaders 用新的变化更新他们的历史缓存。

    但是,Fast DDS 支持多种配置,允许您更改 RTPSWriters/RTPSReaders 的行为。修改 RTPS 实体的默认配置意味着 RTPSWriters 和 RTPSReaders 之间的数据交换流发生变化。此外,通过选择服务质量 (QoS) 策略,您可以通过多种方式影响这些历史缓存的管理方式,但通信循环保持不变。您可以继续阅读RTPS 层部分,了解更多关于快速 DDS 中 RTPS 协议的实现。

    1.3. 编写一个简单的 C++ 发布者和订阅者应用程序

    1.3.1。背景

    DDS 是实现 DCPS 模型的以数据为中心的通信中间件。该模型基于发布者的开发,这是一个数据生成元素;和一个订阅者,一个数据消费元素。这些实体通过主题进行通信,主题是绑定两个 DDS 实体的元素。发布者在主题下生成信息,订阅者订阅同一主题以接收信息

    1.3.2. 先决条件

    首先,您需要按照安装手册中列出的步骤安装 eProsima Fast DDS及其所有依赖项。您还需要完成安装手册中列出的安装 eProsima Fast DDS-Gen工具的步骤。此外,本教程中提供的所有命令都针对 Linux 环境进行了概述。

    1.3.4。导入链接库及其依赖项

    DDS 应用程序需要 Fast DDS 和 Fast CDR 库。根据安装过程,使这些库可用于我们的 DDS 应用程序的过程将略有不同。在 Linux 上,可以在目录/usr/include/fastrtps/和 /usr/include/fastcdr/中分别找到 Fast DDS 和 Fast CDR 的头文件。两者的编译库都可以在目录/usr/lib/中找到

    1.3.5。配置 CMake 项目

    cmake_minimum_required(VERSION 3.12.4)
    
    if(NOT CMAKE_VERSION VERSION_LESS 3.0)
        cmake_policy(SET CMP0048 NEW)
    endif()
    
    project(DDSHelloWorld)
    
    # Find requirements
    if(NOT fastcdr_FOUND)
        find_package(fastcdr REQUIRED)
    endif()
    
    if(NOT fastrtps_FOUND)
        find_package(fastrtps REQUIRED)
    endif()
    
    # Set C++11
    include(CheckCXXCompilerFlag)
    if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG OR
            CMAKE_CXX_COMPILER_ID MATCHES "Clang")
        check_cxx_compiler_flag(-std=c++11 SUPPORTS_CXX11)
        if(SUPPORTS_CXX11)
            add_compile_options(-std=c++11)
        else()
            message(FATAL_ERROR "Compiler doesn't support C++11")
        endif()
    endif()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    IDL通过生成的数据文件为:

    这必须生成以下文件:
    
    HelloWorld.cxx:HelloWorld 类型定义。
    
    HelloWorld.h:HelloWorld.cxx 的头文件。
    
    HelloWorldPubSubTypes.cxx:HelloWorld 类型的序列化和反序列化代码。
    
    HelloWorldPubSubTypes.h:HelloWorldPubSubTypes.cxx 的头文件。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    pub端的代码

    // Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
      2//
      3// Licensed under the Apache License, Version 2.0 (the "License");
      4// you may not use this file except in compliance with the License.
      5// You may obtain a copy of the License at
      6//
      7//     http://www.apache.org/licenses/LICENSE-2.0
      8//
      9// Unless required by applicable law or agreed to in writing, software
     10// distributed under the License is distributed on an "AS IS" BASIS,
     11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12// See the License for the specific language governing permissions and
     13// limitations under the License.
     14
     15/**
     16 * @file HelloWorldPublisher.cpp
     17 *
     18 */
     19
     20#include "HelloWorldPubSubTypes.h"
     21
     22#include 
     23#include 
     24#include 
     25#include 
     26#include 
     27#include 
     28
     29using namespace eprosima::fastdds::dds;
     30
     31class HelloWorldPublisher
     32{
     33private:
     34
     35    HelloWorld hello_;
     36
     37    DomainParticipant* participant_;
     38
     39    Publisher* publisher_;
     40
     41    Topic* topic_;
     42
     43    DataWriter* writer_;
     44
     45    TypeSupport type_;
     46
     47    class PubListener : public DataWriterListener
     48    {
     49    public:
     50
     51        PubListener()
     52            : matched_(0)
     53        {
     54        }
     55
     56        ~PubListener() override
     57        {
     58        }
     59
     60        void on_publication_matched(
     61                DataWriter*,
     62                const PublicationMatchedStatus& info) override
     63        {
     64            if (info.current_count_change == 1)
     65            {
     66                matched_ = info.total_count;
     67                std::cout << "Publisher matched." << std::endl;
     68            }
     69            else if (info.current_count_change == -1)
     70            {
     71                matched_ = info.total_count;
     72                std::cout << "Publisher unmatched." << std::endl;
     73            }
     74            else
     75            {
     76                std::cout << info.current_count_change
     77                        << " is not a valid value for PublicationMatchedStatus current count change." << std::endl;
     78            }
     79        }
     80
     81        std::atomic_int matched_;
     82
     83    } listener_;
     84
     85public:
     86
     87    HelloWorldPublisher()
     88        : participant_(nullptr)
     89        , publisher_(nullptr)
     90        , topic_(nullptr)
     91        , writer_(nullptr)
     92        , type_(new HelloWorldPubSubType())
     93    {
     94    }
     95
     96    virtual ~HelloWorldPublisher()
     97    {
     98        if (writer_ != nullptr)
     99        {
    100            publisher_->delete_datawriter(writer_);
    101        }
    102        if (publisher_ != nullptr)
    103        {
    104            participant_->delete_publisher(publisher_);
    105        }
    106        if (topic_ != nullptr)
    107        {
    108            participant_->delete_topic(topic_);
    109        }
    110        DomainParticipantFactory::get_instance()->delete_participant(participant_);
    111    }
    112
    113    //!Initialize the publisher
    114    bool init()
    115    {
    116        hello_.index(0);
    117        hello_.message("HelloWorld");
    118
    119        DomainParticipantQos participantQos;
    120        participantQos.name("Participant_publisher");
    121        participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);
    122
    123        if (participant_ == nullptr)
    124        {
    125            return false;
    126        }
    127
    128        // Register the Type
    129        type_.register_type(participant_);
    130
    131        // Create the publications Topic
    132        topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
    133
    134        if (topic_ == nullptr)
    135        {
    136            return false;
    137        }
    138
    139        // Create the Publisher
    140        publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);
    141
    142        if (publisher_ == nullptr)
    143        {
    144            return false;
    145        }
    146
    147        // Create the DataWriter
    148        writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_);
    149
    150        if (writer_ == nullptr)
    151        {
    152            return false;
    153        }
    154        return true;
    155    }
    156
    157    //!Send a publication
    158    bool publish()
    159    {
    160        if (listener_.matched_ > 0)
    161        {
    162            hello_.index(hello_.index() + 1);
    163            writer_->write(&hello_);
    164            return true;
    165        }
    166        return false;
    167    }
    168
    169    //!Run the Publisher
    170    void run(
    171            uint32_t samples)
    172    {
    173        uint32_t samples_sent = 0;
    174        while (samples_sent < samples)
    175        {
    176            if (publish())
    177            {
    178                samples_sent++;
    179                std::cout << "Message: " << hello_.message() << " with index: " << hello_.index()
    180                            << " SENT" << std::endl;
    181            }
    182            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    183        }
    184    }
    185};
    186
    187int main(
    188        int argc,
    189        char** argv)
    190{
    191    std::cout << "Starting publisher." << std::endl;
    192    int samples = 10;
    193
    194    HelloWorldPublisher* mypub = new HelloWorldPublisher();
    195    if(mypub->init())
    196    {
    197        mypub->run(static_cast(samples));
    198    }
    199
    200    delete mypub;
    201    return 0;
    202}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202

    每一部分的功能:

    DomainParticipantFactory. 允许创建和销毁 DomainParticipant 对象。
    
    DomainParticipant. 充当所有其他实体对象的容器以及发布者、订阅者和主题对象的工厂。
    
    TypeSupport. 为参与者提供序列化、反序列化和获取特定数据类型的密钥的功能。
    
    Publisher. 它是负责创建 DataWriters 的对象。
    
    DataWriter. 允许应用程序设置要在给定主题下发布的数据的值。
    
    DataWriterListener. 允许重新定义 DataWriterListener 的功能。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    派生类的私有成员

    类的私有数据成员,hello_数据成员被定义为 HelloWorld类的一个对象,它定义了我们用 IDL 文件创建的数据类型。接下来定义参与者、发布者、主题、DataWriter和数据类型对应的私有数据成员。类的type_对象TypeSupport是将用于在 DomainParticipant 中注册主题数据类型的对象

    PubListener通过从该类继承来定义DataWriterListener该类。此类覆盖默认的 DataWriter 侦听器回调,允许在发生事件时执行例程。当检测到新的 DataReader 正在侦听 DataWriter 正在发布的主题时,重写的回调on_publication_matched() 允许定义一系列操作。检测与 DataWriter 匹配的 DataReader的info.current_count_change()这些更改。这是MatchedStatus允许跟踪订阅状态更改的结构中的成员。最后,listener_类的对象被定义为 的实例PubListener

    类的公共构造函数和析构函数HelloWorldPublisher定义如下。构造函数将类的私有数据成员初始化nullptr为 ,TypeSupport 对象除外,它被初始化为HelloWorldPubSubType类的实例。类析构函数删除这些数据成员,从而清理系统内存

    初始化函数

    初始化 HelloWorld 类型hello_结构成员的内容。
    
    通过 DomainParticipant 的 QoS 为参与者分配名称。
    
    使用DomainParticipantFactory创建参与者。
    
    注册 IDL 中定义的数据类型。
    
    为出版物创建主题。
    
    创建发布者。
    
    使用先前创建的侦听器创建 DataWriter。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    为了发布,实现了公共成员功能publish()。在 DataWriter 的侦听器回调中,表明 DataWriter 已与侦听发布主题的 DataReader 匹配,数据成员matched_被更新。它包含发现的 DataReader 的数量。因此,当发现第一个 DataReader 时,应用程序开始发布。这只是由 DataWriter 对象写入更改

    sub订阅者

    // Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
      2//
      3// Licensed under the Apache License, Version 2.0 (the "License");
      4// you may not use this file except in compliance with the License.
      5// You may obtain a copy of the License at
      6//
      7//     http://www.apache.org/licenses/LICENSE-2.0
      8//
      9// Unless required by applicable law or agreed to in writing, software
     10// distributed under the License is distributed on an "AS IS" BASIS,
     11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12// See the License for the specific language governing permissions and
     13// limitations under the License.
     14
     15/**
     16 * @file HelloWorldSubscriber.cpp
     17 *
     18 */
     19
     20#include "HelloWorldPubSubTypes.h"
     21
     22#include 
     23#include 
     24#include 
     25#include 
     26#include 
     27#include 
     28#include 
     29#include 
     30
     31using namespace eprosima::fastdds::dds;
     32
     33class HelloWorldSubscriber
     34{
     35private:
     36
     37    DomainParticipant* participant_;
     38
     39    Subscriber* subscriber_;
     40
     41    DataReader* reader_;
     42
     43    Topic* topic_;
     44
     45    TypeSupport type_;
     46
     47    class SubListener : public DataReaderListener
     48    {
     49    public:
     50
     51        SubListener()
     52            : samples_(0)
     53        {
     54        }
     55
     56        ~SubListener() override
     57        {
     58        }
     59
     60        void on_subscription_matched(
     61                DataReader*,
     62                const SubscriptionMatchedStatus& info) override
     63        {
     64            if (info.current_count_change == 1)
     65            {
     66                std::cout << "Subscriber matched." << std::endl;
     67            }
     68            else if (info.current_count_change == -1)
     69            {
     70                std::cout << "Subscriber unmatched." << std::endl;
     71            }
     72            else
     73            {
     74                std::cout << info.current_count_change
     75                        << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl;
     76            }
     77        }
     78
     79        void on_data_available(
     80                DataReader* reader) override
     81        {
     82            SampleInfo info;
     83            if (reader->take_next_sample(&hello_, &info) == ReturnCode_t::RETCODE_OK)
     84            {
     85                if (info.valid_data)
     86                {
     87                    samples_++;
     88                    std::cout << "Message: " << hello_.message() << " with index: " << hello_.index()
     89                                << " RECEIVED." << std::endl;
     90                }
     91            }
     92        }
     93
     94        HelloWorld hello_;
     95
     96        std::atomic_int samples_;
     97
     98    } listener_;
     99
    100public:
    101
    102    HelloWorldSubscriber()
    103        : participant_(nullptr)
    104        , subscriber_(nullptr)
    105        , topic_(nullptr)
    106        , reader_(nullptr)
    107        , type_(new HelloWorldPubSubType())
    108    {
    109    }
    110
    111    virtual ~HelloWorldSubscriber()
    112    {
    113        if (reader_ != nullptr)
    114        {
    115            subscriber_->delete_datareader(reader_);
    116        }
    117        if (topic_ != nullptr)
    118        {
    119            participant_->delete_topic(topic_);
    120        }
    121        if (subscriber_ != nullptr)
    122        {
    123            participant_->delete_subscriber(subscriber_);
    124        }
    125        DomainParticipantFactory::get_instance()->delete_participant(participant_);
    126    }
    127
    128    //!Initialize the subscriber
    129    bool init()
    130    {
    131        DomainParticipantQos participantQos;
    132        participantQos.name("Participant_subscriber");
    133        participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);
    134
    135        if (participant_ == nullptr)
    136        {
    137            return false;
    138        }
    139
    140        // Register the Type
    141        type_.register_type(participant_);
    142
    143        // Create the subscriptions Topic
    144        topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);
    145
    146        if (topic_ == nullptr)
    147        {
    148            return false;
    149        }
    150
    151        // Create the Subscriber
    152        subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr);
    153
    154        if (subscriber_ == nullptr)
    155        {
    156            return false;
    157        }
    158
    159        // Create the DataReader
    160        reader_ = subscriber_->create_datareader(topic_, DATAREADER_QOS_DEFAULT, &listener_);
    161
    162        if (reader_ == nullptr)
    163        {
    164            return false;
    165        }
    166
    167        return true;
    168    }
    169
    170    //!Run the Subscriber
    171    void run(
    172        uint32_t samples)
    173    {
    174        while(listener_.samples_ < samples)
    175        {
    176            std::this_thread::sleep_for(std::chrono::milliseconds(100));
    177        }
    178    }
    179};
    180
    181int main(
    182        int argc,
    183        char** argv)
    184{
    185    std::cout << "Starting subscriber." << std::endl;
    186    int samples = 10;
    187
    188    HelloWorldSubscriber* mysub = new HelloWorldSubscriber();
    189    if(mysub->init())
    190    {
    191        mysub->run(static_cast(samples));
    192    }
    193
    194    delete mysub;
    195    return 0;
    196}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196

    Subscriber. 它是负责创建和配置 DataReader 的对象。

    DataReader. 它是负责实际接收数据的对象。它在应用程序中注册标识要读取的数据的主题(TopicDescription)并访问订阅者接收到的数据。

    DataReaderListener. 这是分配给数据读取器的侦听器。

    DataReaderQoS. 定义 DataReader 的 QoS 的结构。

    SampleInfo. 它是伴随每个样本“读取”或“获取”的信息。
    从类的私有数据成员开始,值得一提的是数据读取监听器的实现。类的私有数据成员将是参与者、订阅者、主题、数据读取器和数据类型。与数据写入器的情况一样,侦听器实现了要在事件发生时执行的回调。SubListener 的第一个被覆盖的回调是on_subscription_matched(),它类似于on_publication_matched()DataWriter 的回调

    void on_subscription_matched(
            DataReader*,
            const SubscriptionMatchedStatus& info) override
    {
        if (info.current_count_change == 1)
        {
            std::cout << "Subscriber matched." << std::endl;
        }
        else if (info.current_count_change == -1)
        {
            std::cout << "Subscriber unmatched." << std::endl;
        }
        else
        {
            std::cout << info.current_count_change
                    << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    第二个被覆盖的回调是on_data_available(). 在此,数据读取器可以访问的下一个接收到的样本被获取并处理以显示其内容。在这里SampleInfo定义了类的对象,它决定了一个样本是否已经被读取或获取。每次读取样本时,接收样本的计数器都会增加

    void on_data_available(
            DataReader* reader) override
    {
        SampleInfo info;
        if (reader->take_next_sample(&hello_, &info) == ReturnCode_t::RETCODE_OK)
        {
            if (info.valid_data)
            {
                samples_++;
                std::cout << "Message: " << hello_.message() << " with index: " << hello_.index()
                            << " RECEIVED." << std::endl;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    信贷风控指南丨人工智能专家直播解析信贷评分卡模型
    黄灰色鱼骨流程图图表合集PPT模板
    【OpenCV-Python】教程:4-3 Shi-Tomasi 角点检测
    视频怎么做成二维码?在线教学视频码的制作技巧
    【上传图片,文件,视频功能合集】vue-elementul简单实现上传文件,上传图片,上传视频功能【详细注释,简单易用】
    搭建hexo个人博客
    SpringIoc方案二不使用配置文件开发(课时十二)
    掉瓶子小游戏
    【C++风云录】辐射现代大数据景观:从Apache Arrow到Thrust的全方位探索
    newstarctf
  • 原文地址:https://blog.csdn.net/neuzhangno/article/details/127768384