【ROS2實(shí)踐】系列(一 )——FastDDS的安裝使用

目錄

一、FastDDS和Fast-RTPS區(qū)別

eProsima Fast RTPS 是一個(gè)高性能的發(fā)布訂閱框架,使用基于發(fā)布者、訂閱者和數(shù)據(jù)主題的解耦模型在分布式系統(tǒng)中共享數(shù)據(jù)。 Fast RTPS 實(shí)現(xiàn)了許多 DDS 規(guī)范,例如 DDS 安全性、DDS-XTypes、RPC over DDS、DDS TCP PSM 和現(xiàn)代 C DDS 映射,但Fast RTPS中一些核心 DDS API 尚未完全符合標(biāo)準(zhǔn)。

在過去幾年中,eProsima 不斷致力于新功能、創(chuàng)新工具和標(biāo)準(zhǔn) API 的開發(fā),以使 Fast RTPS 成為當(dāng)今最完整的開源 DDS 中間件。

現(xiàn)在(2020.5),eProsima 可以自豪地說,eProsima Fast RTPS 實(shí)施符合 OMG DDS 1.4 和 RTPS 2.2 標(biāo)準(zhǔn)。

作為這一刻的象征,F(xiàn)ast RTPS 更名為 Fast DDS!

以上來源eProsima官網(wǎng)新聞。

二、FastDDS安裝

2.1 安裝包下載

FastDDS提供了三種安裝方式,分別是bin、Sourcedocker image 3 種方式。

推薦使用bin安裝方式,F(xiàn)astDDS的bin安裝方式實(shí)際也是源碼編譯安裝。

在官網(wǎng)填寫信息后,選擇bin安裝方式,進(jìn)入下載界面(該鏈接不需要填寫信息?。螺d安裝包eProsima Fast DDS 2.8.1 - Linux (32 & 64)

該安裝包有install.sh腳本,install.sh會(huì)自動(dòng)apt安裝各種依賴,然后進(jìn)入src目錄下,分別從源碼構(gòu)建foonathan_memory_vendor、fastcdr、fastrtps、fastddsgen。

  • foonathan_memory_vendor,一個(gè) STL 兼容的 C++ 內(nèi)存分配器 庫。
  • fastcdr,一個(gè)根據(jù) CDR 標(biāo)準(zhǔn)進(jìn)行數(shù)據(jù)序列化的 C++ 庫。
  • fastrtps,eProsima Fast DDS庫的核心庫。
  • fastddsgen,一個(gè)使用 IDL 文件中定義的數(shù)據(jù)類型生成源代碼的 Java 應(yīng)用程序。

如果這些組件中的任何一個(gè)不需要,可以簡單地重命名或從src 目錄中刪除。

2.2 安裝步驟

注意編譯需要CMake3.11以上的版本,安裝編譯需要時(shí)間比較久,大概15分鐘(8代i7編譯)。

下載該安裝包到Download目錄后,解壓縮至新建文件夾并安裝
cd Download
mkdir fastdds2.8.1
tar -zxvf eProsima_Fast-DDS-v2.8.1-Linux.tgz -C fastdds2.8.1/
sudo ./install.sh

注意,如果要測(cè)試FastDDS中的examples,需要在install.sh腳本腳本中打開該選項(xiàng),默認(rèn)為OFF。

install.sh腳本首先安裝各種依賴,包括git、build-essential、cmake、libssl-dev、libasio-dev、libtinyxml2-dev、openjdk-8-jre-headless。

接著install.sh腳本編譯安裝foonathan_memory_vendor。

然后install.sh腳本編譯安裝fastcdr。

隨后install.sh腳本編譯安裝fastrtps(Fast DDS)。

最后install.sh腳本拷貝fastddsgen二進(jìn)制文件到系統(tǒng)目錄中。

2.3 測(cè)試

  • IDL文件生成接口文件
git clone https://github.com/wanghuohuo0716/fastdds_helloworld.git
cd fastdds_helloworld
mkdir -p include/idl_generate/
cd idl/
fastddsgen -d ./../include/idl_generate/  HelloWorld.idl# -d選項(xiàng)指示生成的頭文件保存目錄
  • 編譯FastDDS的程序

根據(jù)IDL文件生成接口文件后,同一個(gè)終端內(nèi)接著編譯FastDDS程序。

cd ..
mkdir build && cd build
cmake .. 
make
  • 運(yùn)行Publisher和Subscriber
cd build/
./DDSHelloWorldPublisher
cd build/
./DDSHelloWorldSubscriber

可以看到終端輸出

2.4 添加環(huán)境變量

如果2.3步驟可以正常執(zhí)行,不需要再手動(dòng)添加環(huán)境變量了。


當(dāng)使用eProsima Fast DDS運(yùn)行應(yīng)用程序?qū)嵗龝r(shí),它必須與安裝包的庫鏈接,可以臨時(shí)添加環(huán)境變量

export LD_LIBRARY_PATH=/usr/local/lib/

也可以永久添加

echo 'export LD_LIBRARY_PATH=/usr/local/lib/' >> ~/.bashrc

2.5 卸載

該安裝包同樣提供/uninstall.sh卸載腳本,直接執(zhí)行該腳本即可:

cd fastddss2.8.1
sudo ./uninstall.sh

注意:如果任何其他組件已經(jīng)以某種其他方式安裝在系統(tǒng)中,它們也將被刪除。為避免這種情況,請(qǐng)?jiān)趫?zhí)行之前編輯./uninstall.sh腳本。

三、FastDDS使用

3.1 創(chuàng)建CMake工程項(xiàng)目

新建一個(gè)CMake工程項(xiàng)目,在fastdds_helloworld目錄中創(chuàng)建idl文件夾、src文件夾和include文件夾,接著在include文件夾中創(chuàng)建idl_generate文件夾。

mkdir -p fastdds_helloworld/src
cd fastdds_helloworld
mkdir idl
mkdir -p include/idl_generate

工作區(qū)目錄結(jié)構(gòu)如下,

其中idl文件夾存放idl文件,include/idl_generate文件夾存放idl文件生成的頭文件。

3.2 編寫IDL文件

3.2.1 定義IDL數(shù)據(jù)類型

創(chuàng)建IDL文件

cd idl && touch HelloWorld.idl

定義 HelloWorld 數(shù)據(jù)類型,它有兩個(gè)元素:

  • 類型為uint32_tindex
  • 類型為std::stringmessage
struct HelloWorld
{
    unsigned long index;
    string message;
};

3.2.2 生成定義數(shù)據(jù)類型的源代碼

接著利用fastdds的工具fastddsgen,生成在 C++中實(shí)現(xiàn)此數(shù)據(jù)類型的源代碼,在idl/ 目錄運(yùn)行以下命令:

fastddsgen -d ./../include/idl_generate/ HelloWorld.idl

其中-d選項(xiàng)指定生成源代碼存放的目錄路徑./../include/idl_generate/。

fastddsgen是一個(gè)Java應(yīng)用程序(已經(jīng)在前述安裝步驟中成功安裝),用來解析idl文件,生成數(shù)據(jù)類型定義的的源代碼。

3.2.3 生成類型源碼解析

fastddsgen工具會(huì)為HelloWorld.idl文件生成四個(gè)文件,分別是

  • HelloWorld.h
  • HelloWorld.cxx
  • HelloWorldPubSubTypes.h
  • HelloWorldPubSubTypes.cxx

其中HelloWorld.h,HelloWorld.cxx中會(huì)根據(jù)idl文件中定義的結(jié)構(gòu)體生成對(duì)應(yīng)的類,即 類型定義

class HelloWorld
{
public:
    ****
private:
    uint32_t m_index;
    std::string m_message;
};

其中HelloWorldPubSubTypes.h,HelloWorldPubSubTypes.cxx文件在定義HelloWorld類的基礎(chǔ)上添加了一些了對(duì)HelloWorld 類型的序列化和反序列化代碼:

#include "HelloWorld.h"

class HelloWorldPubSubType : public eprosima::fastdds::dds::TopicDataType
{
public:

    typedef HelloWorld type;

    eProsima_user_DllExport HelloWorldPubSubType();
    eProsima_user_DllExport virtual ~HelloWorldPubSubType() override;
    ***
    unsigned char* m_keyBuffer;
};

3.3 Publisher代碼

3.1節(jié)的基礎(chǔ)上,利用fastdds實(shí)現(xiàn)一個(gè)Publisher還需要以下三個(gè)步驟:

  • 包含頭文件
  • 實(shí)現(xiàn)Publisher的類
  • 實(shí)例化Publisher并發(fā)布數(shù)據(jù)

其中實(shí)現(xiàn)Publisher的類是核心!

3.3.1 頭文件

3.3.1.1 包含數(shù)據(jù)類型頭文件

包含HelloWorldPubSubTypes.h文件,該文件定義了數(shù)據(jù)類型的序列化和反序列化函數(shù),并且已經(jīng)包含了數(shù)據(jù)類型定義的頭文件#include "HelloWorld.h"。

#include "HelloWorldPubSubTypes.h"

3.3.1.2 包含F(xiàn)astDDS頭文件

這些頭文件提供了使用 Fast DDS的API。

#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/DataWriterListener.hpp>
  • DomainParticipantFactory允許創(chuàng)建和銷毀 DomainParticipant 對(duì)象。
  • DomainParticipant充當(dāng)所有其他實(shí)體對(duì)象的容器,并充當(dāng)發(fā)布者、訂閱者和主題對(duì)象的工廠。
  • TypeSupport為participant提供序列化、反序列化和獲取特定數(shù)據(jù)類型的key的函數(shù)。
  • Publisher是負(fù)責(zé)創(chuàng)建 DataWriter的對(duì)象。
  • DataWriter允許應(yīng)用程序設(shè)置要在給定主題下發(fā)布的數(shù)據(jù)的值。
  • DataWriterListener允許重新定義 DataWriterListener 的功能。

3.3.1.3 命名空間

添加在應(yīng)用程序中使用的eProsima Fast DDS 類和函數(shù)的命名空間。

using namespace eprosima::fastdds::dds;

3.3.2 創(chuàng)建Publisher類

fastdds根據(jù)DDS規(guī)范提供了相應(yīng)概念的類定義,如DomainParticipant,PublisherTopicDataWriter等。

在使用這些實(shí)體類之前,需要理解這些實(shí)體類之間的關(guān)系,根據(jù)下圖進(jìn)行分析。

fastdds對(duì)這些DDS概念實(shí)例化是分層的,這些實(shí)體之間的關(guān)系如下圖:

fastdds提供DomainParticipant類創(chuàng)建participant

topic是由participant創(chuàng)建和管理,創(chuàng)建時(shí)設(shè)置topic的名稱和綁定對(duì)應(yīng)得數(shù)據(jù)類型以及Qos配置。

datawriter是由publisher創(chuàng)建和管理的,datawriter是負(fù)責(zé)往topic上寫數(shù)據(jù)的。publisher在創(chuàng)建datawriter時(shí)會(huì)將對(duì)應(yīng)的topic綁定到datawriter上。

每個(gè)participant最多只能擁有一個(gè)publisher,而一個(gè)publisher可以管理多個(gè)datawriter,對(duì)于不同的datawriter而言,Publisher是公共的。

3.3.2.1 類定義與成員變量聲明

定義HelloWorldPublisher類,并聲明類成員變量

class HelloWorldPublisher
{
private:
    HelloWorld hello_;
    DomainParticipant* participant_;
    Publisher* publisher_;
    Topic* topic_;
    DataWriter* writer_;
    TypeSupport type_;
  • DomainParticipant充當(dāng)所有其他實(shí)體對(duì)象的容器,并充當(dāng)發(fā)布者、訂閱者和主題對(duì)象的工廠。
  • Publisher是負(fù)責(zé)創(chuàng)建 DataWriter的對(duì)象。
  • DataWriter允許應(yīng)用程序設(shè)置要在給定主題下發(fā)布的數(shù)據(jù)的值。
  • TypeSupport為participant提供序列化、反序列化和獲取特定數(shù)據(jù)類型的key的函數(shù)。
  • DataWriterListener允許重新定義 DataWriterListener 的功能。

3.3.2.2 創(chuàng)建participant

利用DomainParticipantFactory創(chuàng)建participant,participant所在的Domain ID0,采用默認(rèn)的participantQos策略。

DomainParticipantQos participantQos;
participantQos.name("Participant_publisher");
participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);
  • DomainParticipantFactory允許創(chuàng)建和銷毀 DomainParticipant 對(duì)象。

3.3.2.3 register數(shù)據(jù)類型并創(chuàng)建topic

IDL接口文件中定義的數(shù)據(jù)類型需要在participant中注冊(cè),把數(shù)據(jù)類型注冊(cè)到participant上,這樣participant在創(chuàng)建topic時(shí),才能使用該數(shù)據(jù)類型。

type_ = new HelloWorldPubSubType()
type_.register_type(participant_);
topic_ = participant_->create_topic("HelloWorldTopicName", "HelloWorld", TOPIC_QOS_DEFAULT);

participant根據(jù)默認(rèn)Qos參數(shù)TOPIC_QOS_DEFAULT創(chuàng)建topic。

type_變量的值是IDL接口文件中數(shù)據(jù)類型。

type_TypeSupport類型,可以為participant提供序列化、反序列化和獲取特定數(shù)據(jù)類型的key的函數(shù)。

3.3.2.4 創(chuàng)建publisher

participant根據(jù)PUBLISHER_QOS_DEFAULT創(chuàng)建publisher

publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);

3.3.2.5 創(chuàng)建writer

publisher根據(jù)DATAWRITER_QOS_DEFAULT通過先前創(chuàng)建的listener_進(jìn)而創(chuàng)建datawtriter。

writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_);

3.3.3 使用Publisher對(duì)象發(fā)送數(shù)據(jù)

HelloWorldPublisher類需要定義publishrun兩個(gè)函數(shù),前者是將數(shù)據(jù)發(fā)布出去,后者可以限定指定條件,如定時(shí)發(fā)送等,這樣設(shè)計(jì)更加利于程序后期的拓展性。

3.3.3.1 publish函數(shù)

publisher發(fā)布數(shù)據(jù)實(shí)際是調(diào)用datawriterwrite函數(shù)將數(shù)據(jù)發(fā)送出去。

bool publish()
{
    hello_.index(hello_.index() + 1);
    if (writer_->write(&hello_))
        return true;
    return false;
}

3.3.3.2 run函數(shù)

void run(uint32_t samples)
{
    uint32_t samples_sent = 0;
    while (samples_sent < samples)
    {
        if (publish())
        {
            samples_sent++;
            std::cout << "Message: " << hello_.message() << " with index: " << hello_.index()
                        << " SENT" << std::endl;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
}

上述的demo代碼有兩個(gè)缺陷,data是private,外部無法修改變量。
應(yīng)該在publish函數(shù)中接收更新后的數(shù)據(jù)然后發(fā)布出去。
publisher類中是否要定義數(shù)據(jù)類型還是僅僅定義類型的指針???

PubListener這個(gè)類中的matched_表示與該datawriter通過topic建立連接的subscriber的數(shù)量,當(dāng)新建連接或斷開連接時(shí),就會(huì)觸發(fā)on_publication_matched()回調(diào)函數(shù),demo中利用該回調(diào)打印輸出,提示連接的建立與否。

可以通過matched_參數(shù)判斷是否有DataReader建立連接,若有才publish,沒有就不發(fā)布。

程序結(jié)束時(shí),清理內(nèi)存,銷毀的時(shí)候也是分層,從下往上,先銷毀datawriter,然后是publisher以及同級(jí)的topic,最后是participant

3.4 Subscriber代碼

3.4.1 頭文件

3.4.1.1 包含數(shù)據(jù)類型頭文件

包含HelloWorldPubSubTypes.h文件,該文件定義了數(shù)據(jù)類型的序列化和反序列化函數(shù),并且已經(jīng)包含了數(shù)據(jù)類型定義的頭文件#include "HelloWorld.h"。

#include "HelloWorldPubSubTypes.h"

3.4.1.2 包含F(xiàn)astDDS頭文件

這些頭文件提供了使用 Fast DDS的API。

#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
#include <fastdds/dds/subscriber/SampleInfo.hpp>
  • DomainParticipantFactory允許創(chuàng)建和銷毀 DomainParticipant 對(duì)象。
  • DomainParticipant充當(dāng)所有其他實(shí)體對(duì)象的容器,并充當(dāng)發(fā)布者、訂閱者和主題對(duì)象的工廠。
  • TypeSupport為participant提供序列化、反序列化和獲取特定數(shù)據(jù)類型的key的函數(shù)。
  • Subscriber它是負(fù)責(zé)創(chuàng)建和配置 DataReader 的對(duì)象。
  • DataReader它是負(fù)責(zé)實(shí)際接收數(shù)據(jù)的對(duì)象。它在應(yīng)用程序中注冊(cè)標(biāo)識(shí)要讀取的數(shù)據(jù)的主題(TopicDescription),并訪問訂閱者接收到的數(shù)據(jù)。
  • DataReaderListener這是分配給數(shù)據(jù)讀取器的偵聽器。
  • DataReaderQoS定義 DataReader 的 QoS 的結(jié)構(gòu)。
  • SampleInfo“read”或“taken”的是每個(gè)SampleInfo附帶的信息。

3.4.1.3 命名空間

添加在應(yīng)用程序中使用的eProsima Fast DDS 類和函數(shù)的命名空間。

using namespace eprosima::fastdds::dds;

3.4.2 創(chuàng)建Subscriber類

與Publisher類類似。

fastdds根據(jù)DDS規(guī)范提供了相應(yīng)概念的類定義,如DomainParticipantSubscriber,TopicDataReader等。

在使用這些實(shí)體類之前,需要理解這些實(shí)體類之間的關(guān)系,根據(jù)下圖進(jìn)行分析。

fastdds對(duì)這些DDS概念實(shí)例化是分層的,這些實(shí)體之間的關(guān)系如下圖:

fastdds提供DomainParticipant類創(chuàng)建participant

topic是由participant創(chuàng)建和管理,創(chuàng)建時(shí)設(shè)置topic的名稱和綁定對(duì)應(yīng)得數(shù)據(jù)類型以及Qos配置。

datareader是由subscriber創(chuàng)建和管理的,datareader是負(fù)責(zé)讀topic上的數(shù)據(jù)。subscriber在創(chuàng)建datareader時(shí)會(huì)將對(duì)應(yīng)的topic綁定到datareader上。

每個(gè)participant最多只能擁有一個(gè)subscriber,而一個(gè)subscriber可以管理多個(gè)datareader,對(duì)于不同的datareader而言,subscriber是公共的。

3.4.2.1 類定義與成員變量聲明

定義HelloWorldSubscriber類,并聲明類成員變量

class HelloWorldSubscriber
{
private:
    DomainParticipant* participant_;
    Subscriber* subscriber_;
    Topic* topic_;
    DataReader* reader_;
    TypeSupport type_;
    class SubListener : public DataReaderListener
    {
        HelloWorld hello_;
        ***
    } listener_;
    ***
}
  • DomainParticipant充當(dāng)所有其他實(shí)體對(duì)象的容器,并充當(dāng)發(fā)布者、訂閱者和主題對(duì)象的工廠。
  • Subscriber是負(fù)責(zé)創(chuàng)建 DataReader 的對(duì)象。
  • DataReader它是負(fù)責(zé)實(shí)際接收數(shù)據(jù)的對(duì)象。
  • TypeSupport為participant提供序列化、反序列化和獲取特定數(shù)據(jù)類型的key的函數(shù)。
  • DataReaderListener這是分配給數(shù)據(jù)讀取器的偵聽器。

注意:這里的HelloWorld數(shù)據(jù)類型變量的聲明是在SubListener子類中定義的,并不是在HelloWorldSubscriber類中定義。

上述變量聲明中最核心的是聲明了一個(gè)listener_變量,該變量是SubListener子類的實(shí)例化對(duì)象。

SubListener子類公共繼承DataReaderListener類,從而可以在datareaderdatawriter建立連接以及接收到新數(shù)據(jù)等事件時(shí)觸發(fā)相應(yīng)的回調(diào)函數(shù),進(jìn)而在SubListener子類內(nèi)部執(zhí)行相應(yīng)的處理邏輯。

3.4.2.2 創(chuàng)建participant

利用DomainParticipantFactory創(chuàng)建participant,participant所在的Domain ID0,采用默認(rèn)的participantQos策略。

DomainParticipantQos participantQos;
participantQos.name("Participant_subscriber");
participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);

3.4.2.3 register數(shù)據(jù)類型并創(chuàng)建topic

IDL接口文件中定義的數(shù)據(jù)類型需要在participant中注冊(cè),把數(shù)據(jù)類型注冊(cè)到participant上,這樣participant在創(chuàng)建topic時(shí),才能使用該數(shù)據(jù)類型。

type_ = new HelloWorldPubSubType()
type_.register_type(participant_);
topic_ = participant_->create_topic("HelloWorldTopicName", "HelloWorld", TOPIC_QOS_DEFAULT);

3.4.2.4 創(chuàng)建subscriber

participant根據(jù)SUBSCRIBER_QOS_DEFAULT創(chuàng)建subscriber

subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr);

3.4.2.5 創(chuàng)建reader

subscriber根據(jù)DATAREADER_QOS_DEFAULT通過先前創(chuàng)建的listener_進(jìn)而創(chuàng)建datareader。

reader_ = subscriber_->create_datareader(topic_, DATAREADER_QOS_DEFAULT, &listener_);

3.4.3 使用Subscriber對(duì)象接收數(shù)據(jù)

class HelloWorldSubscriber
{
private:
    ***
    class SubListener : public DataReaderListener
    {
        HelloWorld hello_;
        ***
    } listener_;
    ***
}

上述變量聲明中最核心的是聲明了一個(gè)listener_變量,該變量是SubListener子類的實(shí)例化對(duì)象。

SubListener子類公共繼承DataReaderListener類,從而可以在datareaderdatawriter建立連接以及接收到新數(shù)據(jù)等事件時(shí)觸發(fā)相應(yīng)的回調(diào)函數(shù),進(jìn)而在SubListener子類內(nèi)部執(zhí)行相應(yīng)的處理邏輯。

SubListener子類的第一個(gè)覆蓋(override)回調(diào)函數(shù)是 on_subscription_matched,當(dāng)datareaderdatawriter建立連接時(shí),會(huì)觸發(fā)該回調(diào)函數(shù)。

        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;
            }
        }

第二個(gè)覆蓋(override)回調(diào)函數(shù)是on_data_available,當(dāng)datareader接收到datawriter發(fā)送的新數(shù)據(jù)時(shí),會(huì)觸發(fā)該回調(diào)函數(shù)。

        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;
                }
            }
        }

這里定義了SampleInfo類的對(duì)象info,它確定新收到的數(shù)據(jù)狀態(tài),如數(shù)據(jù)是否已被讀取或采集。

3.5 CMakeList.txt

3.5.1 新建工程

cmake_minimum_required(VERSION 3.12.4)
project(DDSHelloWorld)
add_compile_options(-std=c++11)

在官方給的demo示例中,添加了C++版本至少為11,實(shí)際測(cè)試中去掉此項(xiàng)仍可正常編譯通過。

3.5.2 添加依賴

find_package(fastcdr REQUIRED)
find_package(fastrtps REQUIRED)

使用FastDDS只需要依賴fastcdrfastrtps兩個(gè)庫即可,這兩個(gè)庫根據(jù)前面的安裝步驟,安裝在了/usr/local/share下。

3.5.3 生成IDL數(shù)據(jù)類型的庫文件

file(GLOB DDS_HELLOWORLD_SOURCES_CXX "./include/idl_generate/*.cxx")
add_library(HelloWorld_IDL_lib ${DDS_HELLOWORLD_SOURCES_CXX})

利用CMake中的file命令,將數(shù)據(jù)類型的源碼文件列表保存在CMake變量中,然后將fastddsgen生成的這些數(shù)據(jù)類型源碼編譯生成靜態(tài)庫文件。

將數(shù)據(jù)類型單獨(dú)編譯,能解耦可執(zhí)行文件編譯時(shí)源碼和類型文件一起編譯,有助于提高編譯效率,僅需要在運(yùn)行時(shí)鏈接數(shù)據(jù)類型的庫文件即可。

3.5.4 生成可執(zhí)行文件

# Publisher
add_executable(DDSHelloWorldPublisher src/HelloWorldPublisher.cpp)
target_link_libraries(DDSHelloWorldPublisher 
    HelloWorld_IDL_lib
    fastrtps 
    fastcdr
)

# Subscriber
add_executable(DDSHelloWorldSubscriber src/HelloWorldSubscriber.cpp)
target_link_libraries(DDSHelloWorldSubscriber     
    HelloWorld_IDL_lib    
    fastrtps 
    fastcdr
)

生成PublisherSubscriber可執(zhí)行文件。

參考:
官方C++版helloworldhttps://fast-dds.docs.eprosima.com/en/v2.3.3/fastdds/getting_started/simple_app/simple_app.html
官方python版helloworldhttps://fast-dds.docs.eprosima.com/en/v2.3.3/fastddsgen/pubsub_app/pubsub_app.html#fastddsgen-pubsub-app
官方快速開始教程:https://fast-dds.docs.eprosima.com/en/latest/fastdds/getting_started/getting_started.html
官方二進(jìn)制安裝教程https://fast-dds.docs.eprosima.com/en/latest/installation/binaries/binaries_linux.html
官方代碼helloworld示例https://github.com/eProsima/Fast-DDS-docs/blob/master/code/Examples
魚香ros的cmake工程:https://github.com/fishros/dds_tutorial
靜態(tài)編譯的cmake工程:https://blog.csdn.net/briblue/article/details/124081170
fastdds的helloworld代碼解釋:https://blog.csdn.net/u012739527/article/details/124705821
eProsima Fast DDS-Gen介紹:https://fast-dds.docs.eprosima.com/en/latest/fastddsgen/introduction/introduction.html

待做:
fastdds如何通過同一個(gè)類使用不同類型的數(shù)據(jù)接口,利用模板類?
是否已有一些基本類型可供fastdds的程序使用,不用自己新建idl文件?
fastdds的subscriber必須在listener中編寫回調(diào)函數(shù)么,不能像ROS一樣,在創(chuàng)建topic時(shí)綁定回調(diào)函數(shù)?
動(dòng)態(tài) HelloWorld 示例學(xué)習(xí):https://fast-dds.docs.eprosima.com/en/latest/fastdds/dynamic_types/examples.html
動(dòng)態(tài)主題類型:https://fast-dds.docs.eprosima.com/en/latest/fastdds/dynamic_types/dynamic_types.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • fastdds安裝測(cè)試 依賴庫安裝 準(zhǔn)備工作 如果支持apt,則預(yù)先:brew install cmake pyt...
    咖喱雞蛋閱讀 2,042評(píng)論 0 0
  • JAVA題目 常見的數(shù)據(jù)結(jié)構(gòu)的特點(diǎn)、優(yōu)缺點(diǎn)、實(shí)現(xiàn)原理,應(yīng)用場景。 回答這類問題,一定要回歸原點(diǎn),回歸該數(shù)據(jù)結(jié)構(gòu)的底...
    普通的程序員閱讀 1,872評(píng)論 2 3
  • 前言 在Android開發(fā)中我們經(jīng)常要進(jìn)行各種網(wǎng)絡(luò)訪問,比如查看各類新聞、查看各種圖片。但有一種情形就是我們每次重...
    SnowDragonYY閱讀 6,429評(píng)論 2 11
  • 前言 關(guān)于okhttp的緩存,網(wǎng)上有大量的文章,或相同,或不同,方式不一,但都八九不離十,原理都是通過CacheC...
    Jafir閱讀 15,558評(píng)論 42 182
  • 1-Java基礎(chǔ) 1.1-String和StringBuffer區(qū)別,為什么是可變的,不可變的 String 類中...
    楊慶祥閱讀 1,030評(píng)論 0 0

友情鏈接更多精彩內(nèi)容