Fast DDS入门六、Fast DDS的动态类型及示例程序

2023-11-02

上一节《Fast DDS入门五、在Windows平台创建一个简单的FastDDS示例程序》,该示例程序介绍了采用Fast DDS-Gen工具通过接口定义语言(IDL)来生成数据结构类,该数据结构类具备序列化反序列化处理,用户只需要关注编写IDL的结构体接口以及在发布类和订阅类处理好结构体类数据的发送和接收就可以了。

本节介绍一个更直接、更灵活的数据类型构造方法,在发布类和订阅类中直接构造动态类型,可以省略IDL的繁琐生成过程以及系列数据结构类文件。本节的动态类型方式实现了如下IDL结构体同等效果:

struct HelloWorld
{
    unsigned long index;
    string message;
};

我们直接采用Fast DDS的一个动态类型实例DynamicHelloWorldExample,可以看到只有发布类、订阅类和main主函数cpp文件,少了很多结构体类相关文件:

1、Main主函数源码分析:

int main(int argc,char** argv)
{
   std::cout << "Starting " << std::endl;
   if(!parseArgs(argc, argv))
   {
       usage();
       return 0;
   }
   switch (type)
   {
       case 1:
       {
            HelloWorldPublisher mypub;
            if (mypub.init())
            {
                mypub.run(count, sleep);
            }
            break;
       }
       case 2:
       {
            HelloWorldSubscriber mysub;
            if (mysub.init())
            {
                mysub.run();
            }
            break;
       }
   }
   Domain::stopAll();
   Log::Reset();
   return 0;
}

首先通过命令行方式,判断用户输入“publisher”或“subscriber”字符,判断启动发布过程还是订阅过程。发布过程:初始化发布类对象,之后运行发布类的run()函数,实际是启动了一个发送数据的线程。订阅过程:初始化订阅类对象,之后运行订阅类的run()函数,该run()函数不是一个线程,只是输出提示订阅过程已经开始。

2、发布类源码分析:

发布类主要有两个函数,一个是init()初始化函数,一个是run()函数。

bool HelloWorldPublisher::init()
{
   // Create basic builders
   DynamicTypeBuilder_ptr struct_type_builder(DynamicTypeBuilderFactory::get_instance()->create_struct_builder());
   // Add members to the struct.
   struct_type_builder->add_member(0, "index", DynamicTypeBuilderFactory::get_instance()->create_uint32_type());
   struct_type_builder->add_member(1, "message", DynamicTypeBuilderFactory::get_instance()->create_string_type());
   struct_type_builder->set_name("HelloWorld");
 
   DynamicType_ptr dynType= struct_type_builder->build();
   m_DynType.SetDynamicType(dynType);
   m_DynHello = DynamicDataFactory::get_instance()->create_data(dynType);
   m_DynHello->set_uint32_value(0, 0);
   m_DynHello->set_string_value("HelloWorld", 1);
 
   ParticipantAttributes PParam;
   PParam.rtps.setName("DynHelloWorld_pub");
   mp_participant = Domain::createParticipant(PParam, (ParticipantListener*)&m_part_list);
 
   if(mp_participant == nullptr)
   {
       return false;
   }
 
   //REGISTER THE TYPE
   Domain::registerDynamicType(mp_participant,&m_DynType);
 
   //CREATE THE PUBLISHER
   PublisherAttributes Wparam;
   Wparam.topic.topicKind = NO_KEY;
   Wparam.topic.topicDataType = "HelloWorld";
   Wparam.topic.topicName = "HelloWorldTopic";
   mp_publisher = Domain::createPublisher(mp_participant, Wparam, (PublisherListener*)&m_listener);
   if(mp_publisher == nullptr)
   {
       return false;
   }
   return true;
}

Init()函数,首先构造了结构体builder,在结构体builder中添加了两个成员index和message,然后通过结构体builder设置动态发布订阅类型DynamicPubSubType m_DynType,并生成动态发布订阅数据DynamicData m_DynHello。创建participant之后,注册动态发布订阅类型DynamicPubSubTypem_DynType,最后创建publisher。

void HelloWorldPublisher::run(uint32_t samples,uint32_t sleep)
{
   stop = false;
   std::threadthread(&HelloWorldPublisher::runThread, this, samples, sleep);
   if (samples == 0)
   {
       std::cout << "Publisher running. Please press enter to stop thePublisher at any time." << std::endl;
       std::cin.ignore();
       stop = true;
   }
   else
   {
       std::cout << "Publisher running " << samples << " samples." << std::endl;
   }
   thread.join();
}

run()函数启动了一个线程,该线程的工作内容是不断发送m_DynHello数据,每发送一次数据,m_DynHello的index成员变量增1,如下:

bool HelloWorldPublisher::publish(bool waitForListener)
{
   if(m_listener.firstConnected || !waitForListener || m_listener.n_matched > 0)
   {
       uint32_t index;
       m_DynHello->get_uint32_value(index, 0);
       m_DynHello->set_uint32_value(index + 1, 0);
       mp_publisher->write((void*)m_DynHello);
       return true;
   }
   return false;
}

3、订阅类源码分析:

订阅类也主要有两个函数,一个是init()初始化函数,一个是监听类SubListener::onNewDataMessage ()函数。

bool HelloWorldSubscriber::init()
{
   ParticipantAttributes PParam;
   PParam.rtps.setName("DynHelloWorld_sub");
   mp_participant = Domain::createParticipant(PParam, (ParticipantListener*)&m_part_list);
   if(mp_participant == nullptr)
   {
       return false;
   }
 
   // Create basic types and add members to the struct.
   DynamicTypeBuilder_ptr created_type_ulong = DynamicTypeBuilderFactory::get_instance()->create_uint32_builder();
   DynamicTypeBuilder_ptr created_type_string = DynamicTypeBuilderFactory::get_instance()->create_string_builder();
   DynamicTypeBuilder_ptr struct_type_builder = DynamicTypeBuilderFactory::get_instance()->create_struct_builder();
   struct_type_builder->add_member(0, "index", created_type_ulong.get());
   struct_type_builder->add_member(1, "message", created_type_string.get());
   struct_type_builder->set_name("HelloWorld");
   DynamicType_ptr dynType= struct_type_builder->build();
   m_DynType.SetDynamicType(dynType);
   m_listener.m_DynHello = DynamicDataFactory::get_instance()->create_data(dynType);
 
   //REGISTER THE TYPE
   Domain::registerDynamicType(mp_participant,&m_DynType);
 
   //CREATE THE SUBSCRIBER
   SubscriberAttributes Rparam;
   Rparam.topic.topicKind = NO_KEY;
   Rparam.topic.topicDataType = "HelloWorld";
   Rparam.topic.topicName = "HelloWorldTopic";
 
   mp_subscriber = Domain::createSubscriber(mp_participant, Rparam, (SubscriberListener*)&m_listener);
   if(mp_subscriber == nullptr)
   {
       return false;
   }
   return true;
}

订阅类的初始化函数与发布类型的初始化函数基本类似。首先构造了结构体builder,在结构体builder中添加了两个成员index和message,然后通过结构体builder设置动态发布订阅类型DynamicPubSubType m_DynType,并生成动态发布订阅数据DynamicData m_DynHello。创建participant之后,注册动态发布订阅类型DynamicPubSubTypem_DynType,最后创建subscriber,同时设置好监听实例m_listener,监听实例实现了SubListener::onNewDataMessage ()回调函数,可以接收订阅的数据。

void HelloWorldSubscriber::SubListener::onNewDataMessage(
       Subscriber* sub)
{
   if (sub->takeNextData((void*)m_DynHello,&m_info))
   {
       if(m_info.sampleKind == ALIVE)
       {
            this->n_samples++;
            // Printyour structure data here.
            std::string message;
           m_DynHello->get_string_value(message, 1);
            uint32_t index;
           m_DynHello->get_uint32_value(index, 0);
            std::cout << "Message:" << message << " with index:" << index << "RECEIVED" << std::endl;
       }
   }
}

监听类SubListener::onNewDataMessage ()函数,实现了DynamicData m_DynHello数据的接收,分别取出index和message字段数据,并输出显示屏。

4、运行动态类型示例程序

将所需的库拷贝到Debug目录下:

命令行分别运行Debug目录下的exe程序,通过后面附加“subscriber”或“publisher”分别启动订阅程序和发布程序,publisher将连续发送10条数据,subscriber全部收到,如下图所示:

CSDN下载:免费下载Fast DDS动态类型示例程序源码

github下载:git clone https://github.com/FantasticSaltedFish/Fast-DDS.git

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Fast DDS入门六、Fast DDS的动态类型及示例程序 的相关文章

  • 又是第一!GBASE南大通用蝉联中国分析型数据库管理系统市场TOP1

    报告指出 大数据时代 用户对数据分析的需求不断提升 希望从大量数据中获得新的数据价值 数据分析需求不断上升 分析型数据库市场保持稳定增长 GBASE南大通用作为分析型数据库市场的代表企业 位居本土厂商第一名 在分析型数据库市场 GBASE自
  • 插件分享

    前言 要问我Goby怎么样 我会坚定回答你 最强实时网络空间测绘 没有之一 初次发现Goby还是来自于同事 hq404的推荐 看完第一反应 真漂亮 我馋了 我要xxxxxx 其Logo和UI做的相当棒 当然不仅拥有华丽的外表 更让我深爱又离

随机推荐

  • python爬取新发地菜价

    import requests from bs4 import BeautifulSoup import csv url http www xinfadi com cn marketanalysis 0 list 1 shtml respo
  • 【机试练习】【C++】【PAT A1053】Path of Equal Weight(玄学一样的“段错误”)

    此题有较大的玄学 如果将cmp函数的默认返回值更改为true 则会出现最后一个测试用例的 段错误 在代码中以 我的天 玄学 标识出 include
  • Java阻塞队列

    目录 一 阻塞队列的特点 二 生产者 消费者 存在问题 三 阻塞队列 Java实现 属性 方法 put方法 生产者 线程专门调用的方法 get方法 消费者 线程专门调用的方法 执行顺序分析 图解 在我们上图的代码当中 如果把while改成i
  • Sharding-JDBC(八)5.3 系列升级解读

    目录 一 背景 二 影响范围 1 Maven 坐标调整 2 自定义算法调整 3 事务调整 4 配置文件调整 三 升级指导 1 新的 ShardingSphereDriver 数据库驱动 2 正在使用 Spring Boot Starter
  • 2023华为OD机试真题【找朋友/单调栈】

    题目描述 在学校中 N个小朋友站成一队 第i个小朋友的身高为height i 第i个小朋友可以看到的第一个比自己身高更高的小朋友j 那么j是i的好朋友 要求j gt i 请重新生成一个列表 对应位置的输出是每个小朋友的好朋友位置 如果没有看
  • python爬虫系列5--xpath

    教程地址 http www runoob com xpath xpath tutorial html XPath在python的爬虫学习中 起着举足轻重的地位 对比正则表达式re两者可以完成同样的工作 实现的功能也差不多 但XPath明显比
  • 用 STM32 通用定时器做微秒延时函数(STM32CubeMX版本)

    概述 在使用 DHT11 的时候 时序通信需要微秒来操作 STM32CubeMX 自带一个系统时钟 但是实现的是毫秒级别的 因此就自己用通用计时器实现一个 文章目录 概述 1 配置定时器时钟 2 计数器时钟频率及计数模式 预分频系数 计数器
  • tomcat调优的几个方面

    和早期版本相比最新的Tomcat提供更好的性能和稳定性 所以一直使用最新的Tomcat版本 现在本文使用下面几步来提高Tomcat服务器的性能 增加JVM堆内存大小 修复JRE内存泄漏 线程池设置 压缩 数据库性能调优 Tomcat本地库
  • css画间距可控制的虚线

    借助linear gradient dash div margin left 50px margin right 50px height 10px background linear gradient to left transparent
  • linux git代码明明是最新版本的,status为啥全是modified?

    解决办法 依次执行以下两句代码 git rm cached r git reset hard
  • 使用 PyTorch 对自定义数据集进行二分类(基于Vision Transformer)

    内容 简短描述 ViT 的简短描述 编码部分 使用 ViT 对自定义数据集进行二分类 附录 ViT hypermeters 解释 简短描述 视觉转换器是深度学习领域中流行的转换器之一 在视觉转换器出现之前 我们不得不在计算机视觉中使用卷积神
  • 【Python】turtle海龟画图练习

    Turtle 方法查看 turtle 海龟绘图 同心圆 import turtle i 1 r 0 while i lt 6 r 30 自己设 turtle circle r 画个圆 turtle penup 起笔 turtle sety
  • 前后端RSA加解密

    前端vue RSA加密 一 安装 npm install jsencrypt save dev 二 创建js文件 在src目录下创建util文件夹 然后在util文件夹下创建 security js 文件 1 引入jsencrypt 引入加
  • Java数据类型转换

    1 基本数据类型 byte short char int long float double boolean 2 引用类型数据 String 枚举 数组 接口 枚举 3 基本数据和引用类型数据的区别 1 基本数据类型变量 存的是值的本身 2
  • APP从苹果开发者A账号转移到B账号的流程

    今天把公司的一个APP从苹果开发者A账号转移到B账号 在这里记录具体操作流程 准备好开发者账号A APP所在的原账号 开发者账号B APP迁移目标账号 登录A账号 选择 App Store Connect 点击 Go to App Stor
  • Linux相关关机命令及服务器关机后如何进行开机操作

    linux一般用在服务器上 很少遇到关机的情况 毕竟关机服务就会中断 除非特殊情况不得已才会关闭 正确的关机流程 sync gt shutdown或reboot或halt 无论重启还是关机 都需要先sync将内存数据同步到硬盘中 避免数据丢
  • 抽象数据类型Polynomial 的实现(第二章 P40-43 算法2.22,2.23)

    抽象数据类型Polynomial 的实现 多项式的加法 乘法 typedef int Status Status是函数的类型 其值是函数结果状态代码 如OK等 typedef int Boolean Boolean是布尔类型 其值是TRUE
  • vue关于json数据格式的展示<pre>标签的使用

    起因 需要把字符串按json格式展示到页面上 直接展示或者利用JSON parse 展示页面上数据都会挤成一坨 解决方法 利用
  • 重构——在对象之间搬移特性(1)

    我们都知道 类往往因为承担过多的责任而变得臃肿不堪 这种情况下 一般会使用 提炼类 这种手法将一部分责任分离出去 如果一个类变得 不负责任 一般会使用 内联类 这种手法将它融入另一个类 如果一个类使用了另一个类 一般会运用 隐藏委托关系 手
  • Fast DDS入门六、Fast DDS的动态类型及示例程序

    上一节 Fast DDS入门五 在Windows平台创建一个简单的FastDDS示例程序 该示例程序介绍了采用Fast DDS Gen工具通过接口定义语言 IDL 来生成数据结构类 该数据结构类具备序列化反序列化处理 用户只需要关注编写ID