fastdds:编译、安装并运行helloworld

fastdds安装可以参考官方文档:

3. Linux installation from sources — Fast DDS 3.1.0 documentation

从INSTALLATION MANUAL这一节可以看出来,fastdds支持的操作系统包括linux、windows、qnx、MAC OS。本文记录通过源码和cmake的方式来安装fastdds的过程,也就是3.1.4节的安装过程:

1安装fastdds

1.1安装步骤

使用源码和cmake安装fastdds之前,需要先安装一些依赖,可以参考requirements和dependencies两节来安装。

camke、g++、pip3、wget、git这是常用一些工具
asioasynchronous io,异步io库。fastdds作为一个通信中间件,底层的通信就是基于asio实现的
tinyxml2fastdds的配置文件格式为xml,tinyxml2用来解析xml文件
openssl用于加密

1、在家目录下创建一个文件夹

2、安装foonathan memory和fast cdr

foonathan memory提供内存管理功能,fast cdr提供序列化和反序列化。

CMAKE_INSTALL_PREFIX指定安装目录的前缀,如下的install指令,把xxx安装在lib目录下,实际的安装目录会在lib前加上前缀,以上边的命令为例,xxx实际会被安装到~/Fast-DDS/install/lib目录下。

install(TARGETS xxx DESTINATION lib)

3、安装fastdds

如果我们安装fastdds是为了学习或者调试,那么可以编译debug版本,也就是CMAKE_BUILD_TYPE=Debug;需要编译examples,则需要将examples打开,也就是COMPILE_EXAMPLES=ON。

cmake .. -DCMAKE_INSTALL_PREFIX=~/Fast-DDS/install -DCOMPILE_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Debug

1.2打印日志

在默认情况下编译的fasdds动态库,是不打印日志的,而我们在学习调试的时候,希望打印的日志越详细越好。需要对编辑脚本进行修改。

参考:

cFastDDS打开log开关,输出log_fastdds log-CSDN博客

Fast-DDS/CMakeLists.txt:

OFF改为ON

option(EPROSIMA_BUILD "Activate internal building" OFF)

else分支,OFF改为ON

if(CMAKE_BUILD_TYPE MATCHES "^([Dd][Ee][Bb][Uu][Gg])$"  # single config generator
   OR ("Debug" IN_LIST CMAKE_CONFIGURATION_TYPES))      # multi config generator
    option(LOG_NO_INFO ${LOG_NO_INFO_HELP} OFF)
else()
    option(LOG_NO_INFO ${LOG_NO_INFO_HELP} OFF) 

如下两个OFF改为ON

cmake_dependent_option(
    FASTDDS_ENFORCE_LOG_INFO
    "The LOG_NO_INFO option must be enforced regardless of selected configuration"
    OFF
    "NOT LOG_NO_INFO"
    OFF)   

Fast-DDS/src/cpp/CMakeLists.txt:

OFF改为ON

ption(INTERNAL_DEBUG "Activate developer debug messages" OFF)

2helloworld

2.1fastdds应用的组成

helloworld是fastdds一个最简单的应用,一个fasttdds的应用往往包括以下几个部分:

 topic:话题

topic也表示一个通道,表示reader和writer之间通信的通道,类似于我们的手机号、微信号、抖音号。topic需要在一个domain内保持唯一。topic在实际使用中用一个字符串来表示。helloword中使用的topic是hello_world_topic。

idl:interface definition language

helloworld的idl定义如下,可以看到,很像我们使用c/c++编程的时候使用的结构体。在具体使用的时候,idl不能直接用,要先使用fastddsgen工具将idl生成.h文件和.cpp。

idl定义了通信的数据内容,是writer和reader之间的通信的内容。

fastddsgen是用java开发的工具,用于将idl文件生成编程语言可以使用的格式。fastddsgen的安装说明如下:

3. Linux installation from sources — Fast DDS 3.1.0 documentation

如下是使用fastddsgen将HelloWorld.idl生成了.hpp,.cxx等文件

Publisher和Subscriber:

Publisher发布数据,Subscriber订阅数据。

xml

xml是fastdds应用使用的配置文件。xml中可以配置使用哪些传输层、qos配置、domain id配置、白名单配置等。如果想要使用配置文件,那么需要设置环境变量FASTDDS_DEFAULT_PROFILES_FILE。

<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com" >
    <participant profile_name="hello_world_participant_profile" is_default_profile="true">
        <domainId>0</domainId>
        <rtps>
            <name>hello_world_participant</name>
        </rtps>
    </participant>
    <data_writer profile_name="hello_world_datawriter_profile" is_default_profile="true">
        <qos>
            <durability>
                <kind>TRANSIENT_LOCAL</kind>
            </durability>
            <reliability>
                <kind>RELIABLE</kind>
            </reliability>
        </qos>
        <topic>
            <historyQos>
                <kind>KEEP_LAST</kind>
                <depth>100</depth>
            </historyQos>
            <resourceLimitsQos>
                <max_samples>100</max_samples>
                <max_instances>1</max_instances>
                <max_samples_per_instance>100</max_samples_per_instance>
            </resourceLimitsQos>
        </topic>
    </data_writer>

    <data_reader profile_name="hello_world_datareader_profile" is_default_profile="true">
        <qos>
            <durability>
                <kind>TRANSIENT_LOCAL</kind>
            </durability>
            <reliability>
                <kind>RELIABLE</kind>
            </reliability>
        </qos>
        <topic>
            <historyQos>
                <kind>KEEP_LAST</kind>
                <depth>100</depth>
            </historyQos>
            <resourceLimitsQos>
                <max_samples>100</max_samples>
                <max_instances>1</max_instances>
                <max_samples_per_instance>100</max_samples_per_instance>
            </resourceLimitsQos>
        </topic>
    </data_reader>
</profiles>

topic定义了通信的通道,类似于手机号

idl定义了数据内容,类似于打电话的双方之间通话的内容

Publisher和Subsciber是通信的双方

2.2ListenerSubscriber和WaitsetSubscriber

数据的订阅侧有两种实现方式:

ListenerSubscriber1、使用简单,继承fastdds提供的基类

DataReaderListener,实现其中的接口on_subscription_matched、on_data_available,当有publisher和这个subscriber匹配的时候,on_subscription_matched会被调用;当有新的订阅数据到来的时候,on_data_available会被调用。

2、不够灵活,函数on_subscription_matched、on_data_available在哪个线程中调用,线程的调度参数是怎么配置的,一个Subscriber使用一个线程,还是多个Subscriber使用同一个线程,我们不能控制。

WaitsetSubsriber

1、不需要继承fastdds提供的基类,使用灵活,subscriber运行在哪个线程中,线程的调度参数怎么配置,我们可以灵活的进行配置。

2、不如ListenerSubscriber使用简单

如下是helloworld中使用waitset的代码,waitset的使用分为如下3步:

①attach_condition,指定waitset关心哪些条件

②wait,等待条件到来

③使用一个for循环来遍历条件,在for循环中根据条件的类型进行对应的处理

看到这里,如果我们用过epoll的话,可以看到waitset的使用方式和epoll的使用方式是类似的,epoll的使用也可以分为如下3步:

①epoll_ctl,添加关心的事件

②epoll_wait,等待事件到来

③for循环处理事件,根据事件类型做对应处理

wait_set_.attach_condition(reader_->get_statuscondition());
wait_set_.attach_condition(terminate_condition_);

void WaitsetSubscriberApp::run()
{
    while (!is_stopped())
    {
        ReturnCode_t ret_code = wait_set_.wait(triggered_conditions, eprosima::fastdds::dds::c_TimeInfinite);
        if (RETCODE_OK != ret_code)
        {
            EPROSIMA_LOG_ERROR(SUBSCRIBER_WAITSET, "Error waiting for conditions");
            continue;
        }
        for (Condition* cond : triggered_conditions)
        {
            StatusCondition* status_cond = dynamic_cast<StatusCondition*>(cond);
            if (nullptr != status_cond)
            {
                Entity* entity = status_cond->get_entity();
                StatusMask changed_statuses = entity->get_status_changes();
                if (changed_statuses.is_active(StatusMask::subscription_matched()))
                {
                    ...
                }
                if (changed_statuses.is_active(StatusMask::data_available()))
                {
                    ...   
                }
            }
        }
    }
}

2.3Publisher/Subscriber创建步骤

从helloworld的代码来看,创建Publisher和Subscriber的步骤是类似的:

①创建participant

②创建publisher或subscriber

③创建topic

④创建writer/reader

domain

域,domain是fastdds中一个范围最大的概念,一个domain用一个domain id来区分,只有同一个domain内的参与者才可以通信,不同参与者之间的对象不能通信。这给业务隔离带来了方便,比如我们实际使用中,业务A和业务B之间不需要通信,那么就可以将业务A和业务B分别部署在两个domain内。

participant

参与者,一个domain内可以有多个参与者,一个参与者只能属于一个domain。

publisher/subscriber

一个participant可以创建多个publisher/subscriber。

writer/reader

一个publisher可以创建多个writer,一个subscriber可以创建多个reader。

idl定义的数据类型,也就是通信的内容,和topic是绑定的,在创建topic的时候,需要指定type,这里的type就是idl中定义的数据类型。

topic_ = participant_->create_topic(topic_name, type_.get_type_name(), topic_qos);

topic和writer/reader是绑定的,在创建writer/reader的时候需要指定topic:

writer_ = publisher_->create_datawriter(topic_, writer_qos, this, StatusMask::all());

qos,也就是服务质量,在创建publisher/subscriber、topic、writer/reader时均需要配置qos。

2.4运行helloworld

在两个终端分别启动subscriber和publisher,运行结果如下两张图所示。可以看出,当puhlisher和subscriber匹配的时候,会打印日志;当其中一方退出的时候,另一方也会打印unmatched日志。如果subscriber侧要使用waitset方式,可以执行./hello_world subscriber -w。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值