当前位置: 首页 > news >正文

2.ROS编程学习:话题通信c++

ros—melodic vocode开发

话题通信机制

 ROS Master通过roscore实现,故通过编程实现的是发布者、订阅者、和消息,如海龟的计算图。

1.首先建立功能包

功能包的名字为sub_pub,在src中建立两个cpp文件。

 2.c++发布者实现:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

头文件:

(1)调用ros库

(2)调用标准信息库中的字符串

(3)进行字符串拼接用到的string stream字符串流。

主函数:

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    ros::init(argc,argv,"publisher");
    ros::NodeHandle n;
    ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);
    std_msgs::String msg;
    ros::Rate rate(10);
    int count = 0;
    while (ros::ok())
    {
        count++;
        std::stringstream ss;
        ss << "hello -->" << count;
        msg.data = ss.str();
        pub.publish(msg);
        ROS_INFO("发布数据:%s", msg.data.c_str());
        rate.sleep();
    }
    return 0;
}
int main(int argc, char  *argv[])

注意用main自动补齐需要去掉const。

setlocale(LC_ALL, "");

防止ROS_INFO在终端出现中文乱码现象。

    ros::init(argc,argv,"publisher");
    ros::NodeHandle n;

创建节点并初始化,创建节点句柄管理节点。

ros::Publisher pub = n.advertise<std_msgs::String>("chongfu",1000);

在ROS Master中注册publisher(发布者),发布以chongfu为话题的string字符串类型的消息(通过泛型操作<std_msgs::String>),其中pub和chongfu可以自定义名称。1000,如果出现网络阻塞,会让最新的1000个消息储存在队列中。

std_msgs::String msg;

初始化string类型的消息,其中此类型在标准消息类型库中调用。

ros::Rate rate(10);
rate.sleep();

两行代码配合控制循环的延时(发布频率),HZ为单位,10,每秒十次。

while (ros::ok())

while循环的条件为ros::ok(),用来检查ros系统状态,是否运行。

int count = 0;
count++;

为了记下循环次数,声明变量,同时每次while循环右加1,先赋值在加。

        std::stringstream ss;
        ss << "hello -->" << count;
        msg.data = ss.str();

通过stringstream拼接字符串,同时给消息赋值。

pub.publish(msg);

发布消息。

ROS_INFO("发布数据:%s", msg.data.c_str());

终端显示,需要转化为c语言的字符串。

3.c++订阅方实现

#include "ros/ros.h"
#include "std_msgs/String.h"

void huidiao(const std_msgs::String::ConstPtr & msggg)
{
    ROS_INFO("订阅的数据为:%s", msggg->data.c_str());
}

int main(int argc, char  *argv[])
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "subscriber");
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("chongfu", 1000, huidiao);
    ros::spin();
    return 0;
}

与发布者不同的是:

(1)订阅者有回调函数,函数作用是将从发布者收集到的string消息打印出来。

void huidiao(const std_msgs::String::ConstPtr & msggg)
{
    ROS_INFO("订阅的数据为:%s", msggg->data.c_str());
}

(2)创建了一个订阅者

ros::Subscriber sub = n.subscribe("chongfu", 1000, huidiao);

其中话题名必须和发布者相同,同时1000的作用与发布者类似,接收消息队列的大小,最后一个参数是回调函数。(这里不需要泛型操作去设定消息的类型,与发布者不同)

尝试加上了<std_msgs::String>,没出现问题。

ros::Subscriber sub = n.subscribe<std_msgs::String>("chongfu", 1000, huidiao);

(3)spin急转身

ros::spin();

不像发布者通过一个while循环通过ros::ok()条件不停的发布消息,需要不停的回头重复订阅才能不断地接收到消息,如果不回头,直接return 0运行结束了。

4.CMakeList.txt配置

add_executable(pub src/pub.cpp)
add_executable(sub src/sub.cpp)

 第一个参数定可执行文件名称,第二个参数定参与编译.cpp文件位置。

target_link_libraries(pub
  ${catkin_LIBRARIES}
)
target_link_libraries(sub
  ${catkin_LIBRARIES}
)

设置链接库,全是默认的链接库。

5.通过catkin_make编译,roscore,rosrun运行

(1)开一个终端,开启ros master

roscore

(2)在工作空间catkin_ws下开一个终端,编译。

catkin_make

(3) 在工作空间catkin_ws下开一个终端,运行发布者。

source ./devel/setup.bash 
rosrun sub_pub pub

 (4) 在工作空间catkin_ws下开一个终端,运行订阅者。

source ./devel/setup.bash 
rosrun sub_pub sub

 

 通过尝试订阅者先运行发布者后运行、发布者先运行订阅者后运行、发布者运行中断再运行,皆能运行没有报错。

但会出现一个问题,先开启订阅者后开启发布者还会出现消息数据丢失(不是从1开始),解决方法:再消息发布之前(while循环之前)加入:

ros::Duration(3.0).sleep();

加入一个延时三秒即可。 

6.启动计算图

rqt_graph

7.总结

发布者实现流程

头文件 -->ROS 节点--> ROS 句柄-->建立发布者-->发布消息

订阅者实现流程
头文件 -->ROS 节点--> ROS 句柄-->建立订阅者-->处理消息

注意的点

怎么解决控制台乱码问题?

c++必须进行CMakeList.txt配置后进行编译。

ros::spin();不停回头,循环等待回调函数。

ros::ok();作为发布者whlie的循环条件。

相关文章:

  • 【python】计算偏度和峰度
  • 单片机原理指令系统习题超详细讲解
  • 使用Python,Keras和TensorFlow训练第一个CNN
  • Flutter: Dart 参数,以及 @required 与 required
  • 基于JAVA网上商城系统演示录像计算机毕业设计源码+数据库+lw文档+系统+部署
  • 【复杂网络】关于复杂网络中的动力学系统重构的文献资料整理
  • 应对数据安全典型薄弱点,这家医院“外防内控”筑牢屏障
  • 嵌入式开发:注释C代码的10个技巧
  • Qt5开发从入门到精通——第九篇一节( Qt5 文件及磁盘处理—— 读写文本文件)
  • ⌈Linux_ 感受系统美学⌋ 抛开图形化界面,深入探索命令行操作系统
  • 09-28 周三 使用朴素贝叶斯进行垃圾邮件处理
  • python+cuda编程(二)
  • 攻防世界-filemanager
  • 软件项目管理简答题
  • Spring源码分析(二):底层架构核心概念解析
  • js中forEach回调同异步问题
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • Ruby 2.x 源代码分析:扩展 概述
  • SpiderData 2019年2月16日 DApp数据排行榜
  • ViewService——一种保证客户端与服务端同步的方法
  • v-if和v-for连用出现的问题
  • 闭包,sync使用细节
  • 如何实现 font-size 的响应式
  • 微信小程序设置上一页数据
  • 一个JAVA程序员成长之路分享
  • 在Mac OS X上安装 Ruby运行环境
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • #include<初见C语言之指针(5)>
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • #Z2294. 打印树的直径
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (js)循环条件满足时终止循环
  • (七)理解angular中的module和injector,即依赖注入
  • (原創) 未来三学期想要修的课 (日記)
  • ***详解账号泄露:全球约1亿用户已泄露
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .htaccess 强制https 单独排除某个目录
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET 中让 Task 支持带超时的异步等待
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .NET中的十进制浮点类型,徐汇区网站设计
  • [ 常用工具篇 ] POC-bomber 漏洞检测工具安装及使用详解
  • []利用定点式具实现:文件读取,完成不同进制之间的
  • [2669]2-2 Time类的定义
  • [ABC294Ex] K-Coloring
  • [AutoSar]BSW_Memory_Stack_003 NVM与APP的显式和隐式同步
  • [BZOJ1178][Apio2009]CONVENTION会议中心
  • [C++随笔录] 红黑树
  • [CareerCup] 2.1 Remove Duplicates from Unsorted List 移除无序链表中的重复项