fastdds学习——fastdds+protobuf 试图用protobuffers代替idl文件

准备工作

参考博客:https://blog.csdn.net/qq_27865227/article/details/121747897
大家可以根据上面的链接安装fastdds,并下载博主提供的代码,这里再贴一下GitHub链接:

git clone https://github.com/fishros/dds_tutorial.git

之所以想到用谷歌的protobuf代替上面项目中的idl,是因为protobuf也类似idl,用户只需要写出简单的类似于结构体的定义,便可以通过protoc工具生成相应语言的代码。以下为idl和protobuffers的简单定义。

IDL(Interface Definition Language)即接口定义语言,是CORBA规范的一部分,是跨平台开发的基础。IDL提供一套通用的数据类型,并以这些数据类型来定义更为复杂的数据类型。可变化 IDL 基本类型 整数类型 OMG IDL 摒弃int类型在不同平台上取值范围不同带来的多义性的问题。常数定义常数可以是整数、字符、浮点数、字符串、Boolean、octet 或枚举型,不能是any 类型或用户定义的类型。OMG IDL数组类型IDL array 和sequence,可以轻易地被映射到实现语言中。序列可以包含所有类型的元素,不管是基本类型还是用户定义的类型。

protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。

操作步骤

  1. 在src文件夹下新建一个proto_generate文件夹,用于存放.proto文件及其生成的.h和.cc文件。
  2. 进入proto_generate,新建一个文件hello.proto,内容如下
syntax = "proto2";

message myMsg {
    optional string str = 1; //The message needed to send
    optional int32 index=2; //message index 
}
  1. 用protoc生成.h和.cc文件,如果没有protoc根据提示下载即可
protoc -I=./ --cpp_out=./ ./hello.proto
  1. 在proto_generate下新建一个CMakeLists.txt,用于生成动态库,内容如下:
SET(LIB_PROTOSRC hello.pb.cc) 
ADD_LIBRARY(hello_proto SHARED ${LIB_PROTOSRC})

install(FILES hello.pb.h DESTINATION include)
install(TARGETS hello_proto LIBRARY DESTINATION lib)

  1. 生成动态库、安装动态库,方便供其他源文件使用
mkdir build
cd build
cmake ..
make
make install
  1. 在src文件夹下新建一个CMakeLists.txt,将刚才新建的proto_generate文件夹包含进去,内容如下,只有一行
add_subdirectory(proto_generate)
  1. 改写01-hellofishros下的CMakeLists如下,目的是添加刚才生成的动态库,防止编译的时候找不到库
cmake_minimum_required(VERSION 3.12.4)

if(NOT CMAKE_VERSION VERSION_LESS 3.0)
    cmake_policy(SET CMP0048 NEW)
endif()

project(DDSHelloFishRos)

# 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()

message(STATUS "Configuring HelloFishRos publisher/subscriber example...")
file(GLOB DDS_HelloFishRos_SOURCES_CXX "src/idl_generate/*.cxx")




add_executable(DDSHelloFishRosPublisher src/HelloFishRosPublisher.cpp ${DDS_HelloFishRos_SOURCES_CXX} )
target_link_libraries(DDSHelloFishRosPublisher fastrtps fastcdr)
target_link_libraries(DDSHelloFishRosPublisher hello_proto)
target_link_libraries(DDSHelloFishRosPublisher protobuf)

add_executable(DDSHelloFishRosSubscribe src/HelloFishRosSubscribe.cpp ${DDS_HelloFishRos_SOURCES_CXX})
target_link_libraries(DDSHelloFishRosSubscribe fastrtps fastcdr)
target_link_libraries(DDSHelloFishRosSubscribe hello_proto)
target_link_libraries(DDSHelloFishRosSubscribe protobuf)
  1. 改写HelloFishRosPublisher.cpp,将发布者发布的内容以proto里的结构为基础(原先是idl文件内的结构),内容如下
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


#include "idl_generate/HelloFishRosPubSubTypes.h"
#include "proto_generate/hello.pb.h" //new add

#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>

using namespace eprosima::fastdds::dds;

class HelloWorldPublisher
{
private:

    HelloWorld hello_;
    myMsg msg; //new add

    DomainParticipant* participant_;

    Publisher* publisher_;

    Topic* topic_;

    DataWriter* writer_;

    TypeSupport type_;

    class PubListener : public DataWriterListener
    {
    public:

        PubListener()
            : matched_(0)
        {
        }

        ~PubListener() override
        {
        }

        void on_publication_matched(
                DataWriter*,
                const PublicationMatchedStatus& info) override
        {
            if (info.current_count_change == 1)
            {
                matched_ = info.total_count;
                std::cout << "Publisher matched." << std::endl;
            }
            else if (info.current_count_change == -1)
            {
                matched_ = info.total_count;
                std::cout << "Publisher unmatched." << std::endl;
            }
            else
            {
                std::cout << info.current_count_change
                        << " is not a valid value for PublicationMatchedStatus current count change." << std::endl;
            }
        }

        std::atomic_int matched_;

    } listener_;

public:

    HelloWorldPublisher()
        : participant_(nullptr)
        , publisher_(nullptr)
        , topic_(nullptr)
        , writer_(nullptr)
        , type_(new HelloWorldPubSubType())
    {
    }

    virtual ~HelloWorldPublisher()
    {
        if (writer_ != nullptr)
        {
            publisher_->delete_datawriter(writer_);
        }
        if (publisher_ != nullptr)
        {
            participant_->delete_publisher(publisher_);
        }
        if (topic_ != nullptr)
        {
            participant_->delete_topic(topic_);
        }
        DomainParticipantFactory::get_instance()->delete_participant(participant_);
    }

    //!Initialize the publisher
    bool init()
    {
        //hello_.index(0);
        //hello_.message("HelloFishRos!关注小鱼!学习机器人不迷路~");
        msg.set_index(99);
        msg.set_str("This is protobuf message!");

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

        if (participant_ == nullptr)
        {
            return false;
        }

        // Register the Type
        type_.register_type(participant_);

        // Create the publications Topic
        topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT);

        if (topic_ == nullptr)
        {
            return false;
        }

        // Create the Publisher
        publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr);

        if (publisher_ == nullptr)
        {
            return false;
        }

        // Create the DataWriter
        writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_);

        if (writer_ == nullptr)
        {
            return false;
        }
        return true;
    }

    //!Send a publication
    bool publish()
    {
        if (listener_.matched_ > 0)
        {
            //hello_.index(hello_.index() + 1);
            writer_->write(&msg);
            return true;
        }
        return false;
    }

    //!Run the Publisher
    void run(
            uint32_t samples)
    {
        uint32_t samples_sent = 0;
        while (samples_sent < samples)
        {
            if (publish())
            {
                samples_sent++;
                std::cout << "Message: " << msg.str() << " with index: " << msg.index()
                            << " SENT" << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
};

int main(
        int argc,
        char** argv)
{
    std::cout << "Starting publisher." << std::endl;
    int samples = 10;

    HelloWorldPublisher* mypub = new HelloWorldPublisher();
    if(mypub->init())
    {
        mypub->run(static_cast<uint32_t>(samples));
    }

    delete mypub;
    return 0;
}

到这里就可以重新编译整个项目了,发布者方效果如下:
在这里插入图片描述

当我做到这里我才发现发布者的cpp文件里的TypeSupport需要用到idl_generate里的类初始化,但是protobuf不会生成这种类,所以接收方一直无法接收内容,我再研究研究…

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值