ROS | 话题通信的编程实现

2023-05-16

ROS | 话题通信的编程实现

  • 1. 创建功能包
  • 2. 节点编程与消息定义
    • 2.1 案例说明
    • 2.2 话题消息的定义
    • 2.3 创建.cpp文件
    • 2.4 话题发布者编程
    • 2.5 话题订阅者编程
  • 3. 配置与编译
    • 3.1 在CMaKeLists.txt中添加编译选项
    • 3.2 在package.xml中添加功能包依赖
    • 3.3 编译文件
  • 4. 话题可视化
  • 5. rostopic指令的使用
    • 常用指令1
    • 常用指令2
    • 常用指令3

1. 创建功能包

在ROS工作空间ROS_ws的src文件夹目录下创建一个功能包,命名为test_pkg,并编译完成。
在这里插入图片描述

2. 节点编程与消息定义

2.1 案例说明

定义一个发布者Publisher,通过自定义的消息Person将消息数据name、sex及age等发送到订阅者Subscriber,同时订阅者将消息内容打印到终端界面。
在这里插入图片描述

2.2 话题消息的定义

在功能包目录下创建一个新的文件夹,命名为msg,并在此文件夹中创建一个空文件Person.msg。可以使用鼠标右键New Document>Empty Document,或在src路径下通过终端命令符touch创建空文件。
在这里插入图片描述
在Person.msg文件中输入以下代码,定义话题消息。

string name
uint8 sex
uint8 age  
	
uint8 unknown = 0
uint8 male    = 1
uint8 female  = 2

2.3 创建.cpp文件

在功能包下面的src文件夹目录下创建一个空文件Publisher_test.cpp。

2.4 话题发布者编程

打开上述创建的文件Publisher_test,输入以下代码。

#include "ros/ros.h"
#include "test_pkg/Person.h"
	
int main(int argc, char **argv)
{
	//初始化ROS节点
	ros::init(argc, argv, "Publisher_test");
	
	//创建句柄
	ros::NodeHandle n;
	
	//创建一个发布者Publisher,发布名为/person_info的topic,消息类型为test_pkg::Person,队列长度为10
	ros::Publisher person_info_pub = n.advertise<test_pkg::Person>("/person_info", 10);
	
	//设置消息发布频率
	ros::Rate loop_rate(1);
	
	int count = 0;
	while(ros::ok())
	{
		//初始化消息内容
		test_pkg::Person person_msg;
		person_msg.name = "Tom";
		person_msg.age  = 18;
		person_msg.sex  = test_pkg::Person::male;
	
		//发布消息
		person_info_pub.publish(person_msg);
		
		ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d",
			  person_msg.name.c_str(), person_msg.age, person_msg.sex);
	
		//按照设置的频率延时
		loop_rate.sleep();
	
	}
}

说明:

  • 头文件ros/ros.h包含了标准ROS类的声明,在每一个ROS程序中都需要包含它。
  • 头文件test_pkg/Person.h是由Person.msg编译扩展得到,包含了针对C++类的定义等,它存放在工作空间的devel文件夹中。
  • main函数中ros::init(argc, argv, “Publisher_test”)的作用是初始化ROS节点,第三个参数表示节点名称,这个节点名是唯一的。
  • ros::NodeHandle n;的作用是创建句柄,启动ROS节点。
  • ros::Publisher person_info_pub = n.advertise<test_pkg::Person>(“/person_info”, 10);使用ros::Publisher类定义了一个发布者对象person_info_pub,发布的消息的数据类型为test_pkg::Person,用<>表示。/person_info表示发布消息数据的话题名,必须要与订阅者订阅的话题名相同。advertise()的第二个参数表示用于发布消息的消息队列长度,如果发布消息的速度快于底层响应的速度,则此处的数字指定在丢弃一些消息之前要缓冲多少条最新的消息。调用advertise()函数后,主节点(ROS Master)将通知任何试图订阅此话题名的节点,然后他们将与此节点协商对接。同时advertise()将返回一个Publisher对象,该对象使您可以通过调用publish()来发布有关该主题的消息。
  • ros::Rate loop_rate(1);的作用是设置消息发布频率为1Hz。
  • int count = 0;表明我们已发送多少条消息,用于为每个消息创建一个唯一的字符串。
  • 若ros::ok()返回false,则可能发生了以下事件:
    (1) SIGINT被触发(Ctrl-C);
    (2) 被另一同名节点踢出 ROS 网络;
    (3) ros::shutdown()被程序的另一部分调用;
    (4) 节点中的所有ros::NodeHandles 都已经被销毁。
test_pkg::Person person_msg;
person_msg.name = "Tom";
person_msg.age  = 18;
person_msg.sex  = test_pkg::Person::male;
  • 这部分的作用是对消息内容初始化,首先创建一个test_pkg::Person类的对象,之后设置这个对象中的name、age和sex。
  • person_info_pub.publish(person_msg);的作用是发布消息person_msg。
  • ROS_INFO()类似于C语言中的printf()函数,将内容打印在终端界面显示。
  • loop_rate.sleep();的作用是延时,以保证消息能够按照之前设置的发布频率发布出去。

综上所述,实现一个话题发布者的步骤大致可分为以下几点:

  1. 初始化ROS节点;
  2. 向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型;
  3. 按照一定频率循环发送消息。

2.5 话题订阅者编程

在src文件夹下再创建一个空文件Subscriber_test.cpp,输入以下代码。

#include "ros/ros.h"
#include "test_pkg/Person.h"
	
//收到消息时进入回调函数
void personInfoCallback(const test_pkg::Person::ConstPtr& msg)
{
	//打印消息
	ROS_INFO("Subscribe Person Info: name:%s  age:%d  sex:%d",
		      msg->name.c_str(), msg->age, msg->sex);
}
	
int main(int argc, char **argv)
{
	//初始化ROS节点
	ros::init(argc, argv, "Subscriber_test");
	
	//创建句柄
	ros::NodeHandle n;
	
	//创建一个订阅者Subscriber
	ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
	
	//循环接收消息
	ros::spin();
	
	return 0;
}

说明:

  • personInfoCallback(const test_pkg::Person::ConstPtr& msg)是一个回调函数,一旦订阅者接收到消息,则执行该回调函数。在该回调函数中,打印消息内容name、age和sex。
  • main函数中一开始跟发布者一样,初始化ROS节点,创建句柄。
  • ros::Subscriber person_info_sub = n.subscribe(“/person_info”, 10, personInfoCallback);使用ros::Subscriber类定义一个订阅者对象person_info_sub。subscribe()函数中的第一个参数表示需要订阅的话题名,第二个参数表示消息队列的长度,如果消息到达的速度快于处理速度,则开始丢弃最旧的消息之前将被缓冲的消息数。subscribe()函数的第三个参数是回调函数名,消息被传递到回调函数。
  • ros::spin()在调用后不会再返回,也就是主程序到这儿就不往下执行了,一般放在main函数最后,而不放在while()循环里。

综上所述,实现一个话题订阅者的步骤大致可分为以下几点:

  1. 初始化ROS节点;
  2. 订阅需要的话题;
  3. 循环等待话题消息,接收到消息后进入回调函数;
  4. 在回调函数中完成消息处理。

附相关资料:
(1) Publishers and Subscribers
(2) Writing a Simple Publisher and Subscriber (C++)

3. 配置与编译

3.1 在CMaKeLists.txt中添加编译选项

打开功能包中的CMaKeLists.txt文件。在如下位置的find_package中添加message_generation功能包,以便于(节点)调用它们生成消息。
在这里插入图片描述
在如下位置添加相关的.msg文件,确保了CMake在重新配置时知道这些新添加的.msg文件,同时添加 .msg文件在生成消息时的所有依赖项(功能包)。

add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)

在这里插入图片描述
将如下位置中CATLIN_DEPENDS前面的“#”去掉。
在这里插入图片描述
在如下位置进行配置,add_executable(Publisher_test src/Publisher_test.cpp)的作用是将src文件夹下的Publisher_test.cpp文件编译成名为Publisher_test的可执行文件。target_link_libraries(Publisher_test ${catkin_LIBRARIES})的作用是将Publisher_test可执行文件与ROS相关的库链接。add_dependencies(Publisher_test ${PROJECT_NAME}_generate_messages_cpp)的作用是将Publisher_test可执行文件与一些动态生成的文件链接。

add_executable(Publisher_test src/Publisher_test.cpp)
target_link_libraries(Publisher_test ${catkin_LIBRARIES})
add_dependencies(Publisher_test ${PROJECT_NAME}_generate_messages_cpp)
	
add_executable(Subscriber_test src/Subscriber_test.cpp)
target_link_libraries(Subscriber_test ${catkin_LIBRARIES})
add_dependencies(Subscriber_test ${PROJECT_NAME}_generate_messages_cpp)

在这里插入图片描述

3.2 在package.xml中添加功能包依赖

打开功能包中的package.xml文件,在如下位置添加功能包依赖。

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

在这里插入图片描述
说明:

<build_depend>message_generation</build_depend>

这条语句表示在编译时会依赖一个动态产生message的功能包。

<exec_depend>message_runtime</exec_depend>

这条语句表示在运行时会依赖message_runtime的功能包。

3.3 编译文件

在/ROS_ws文件夹路径下打开一个新的终端,输入以下代码进行编译。

$ catkin_make

在这里插入图片描述
编译完成后,输入以下代码运行主节点。

$ roscore

在这里插入图片描述
打开一个新的终端,首先配置环境变量,然后输入以下代码运行节点。

$ rosrun test_pkg Publisher_test

在这里插入图片描述
打开一个新的终端,首先配置环境变量,然后输入以下代码运行节点。

$ rosrun test_pkg Subscriber_test

在这里插入图片描述
若想停止运行,关闭终端,使用快捷键Ctrl+c即可。

4. 话题可视化

打开一个新的终端,输入以下代码。

$ rqt_graph

由此可以得到如下的基于Qt的GUI界面,直观地看到话题通信的发布订阅节点和消息。
在这里插入图片描述

5. rostopic指令的使用

常用指令1

$ rostopic list

使用上述指令能够列出所有当前正在订阅和发布的话题,效果如下图。
在这里插入图片描述

常用指令2

$ rostopic list -v

使用上述指令能够得到当前正在订阅和发布的话题的详细内容介绍,效果如下图。
在这里插入图片描述

常用指令3

更多关于rostopic指令的使用,可以通过以下代码获取。

$ rostopic --help

在这里插入图片描述

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

ROS | 话题通信的编程实现 的相关文章

  • 【无人驾驶】自动驾驶领域有哪些岗位可选?

    导读 想要进入自动驾驶这个领域 xff0c 便首先去调查了下这个领域的岗位 xff0c 希冀能从中找出自己最感兴趣且匹配度也比较高的方向 废话不多说 xff0c 见下 下图为自动驾驶方向的所有岗位 xff0c 总量的来说 xff0c 方向可

随机推荐

  • 01_搭建百度apollo环境实操可用

    搭建百度apollo环境 0 前言1 目标2 方法3 Apollo环境搭建3 1 CPU版3 1 1前置依赖硬件条件3 2 GPU版前置依赖软件1 安装 Ubuntu 18 042 安装 GIT3 安装 Docker 引擎 3 1 3克隆
  • 02_两小时了解自动驾驶

    02 两小时了解自动驾驶 目标你将学到什么什么是无人驾驶无人驾驶的运作方式参考车辆与硬件平台开源软件架构仿真环境地图简介高精地图与传统地图地图与定位 感知 规划的关系高精地图定位简介GNSS RTK惯性导航激光雷达定位视觉定位融合定位感知简
  • PCA9555的使用个人总结

    1 德州仪器PCA9555 简化PCB布线 xff0c 对处理器有限的IO口进行补充 2 带中断 xff0c 不带重启 3 24 引脚的CMOS器件 xff0c 提供I2C SMBus16位通用并行 xff08 GPIO xff09 的扩展
  • stm32掉电前的数据存储到flash

    对FLASH 的操作 FLASh 必须是先擦 后 写 下面的函数是分析案例 void FLASH WriteByte u32 addr u16 flashdata1 FLASH Status FLASHstatus 61 FLASH COM
  • SPI对外部w25Q64的读写

    SPI 1 SPI是串行外围设备接口 SPI的接口主要应用在EEPROM xff0c FLASH xff0c 实时时钟 xff0c AD 转换器 xff0c 还有数字信号处理器和数字信号 解码器之间 2 SPI xff0c 是一种高速的 x
  • Qt实战开发-仪表盘制作

    仪表盘制作 相关的基础知识 QPainter用来执行具体的绘图相关的操作 xff0c 用来画点 xff0c 线 xff0c 填充 xff0c 变换 xff0c alpha 阿尔法通道 xff08 透明度 xff09 Appha的值越大 xf
  • Qt实战开发-数字软键盘

    开发的思路 布局键盘界面每一个button对应一个槽函数把输入的字符返回到点击处的文本编辑框 开发过程首先定义功能button xff0c 在头文件中定义 QString getText QPushButton span class hlj
  • Qt图形视图框架封装-拿来就用

    简述 图形视图 xff08 Graphics View xff09 提供了一个平台 xff0c 用于大量自定义2D图元的管理与交互 xff0c 并提供了一个视图部件 xff08 view widget xff09 来显示可以缩放和旋转的图元
  • 带参数的宏定义

    带参数的宏定义的一般形式如下 xff1a define lt 宏名 gt xff08 lt 参数表 gt xff09 lt 宏体 gt 其中 xff0c lt 宏名 gt 是一个标识符 xff0c lt 参数表 gt 中的参数可以是一个 x
  • QT 视图(View)/委托(Delegate)/ 模型(Model)/项(Item) 之间的关系

    引言 在学习Qt 中此部分的使用是界面自定义出美观的重要部分 xff0c 熟练的使用 xff0c 可以制作出很好的效果 xff0c 在此梳理一下他们的关系 Model View xff08 模型 视图 xff09 视图 xff08 View
  • char(数字) 转换 int

    刷题遇到一个考点是 char型数字 转 int 进行计算的问题 一看就会 xff0c 一做就错 xff0c 显然是在这里的认识薄弱了 将一番搜索的结果记录下来 xff0c 以备再忘来打脸 char的定义参考 xff1a Java基本数据类型
  • ROS的ros_canopen调试(1)

    Ros canopen是ros支持can通信的package 链接 xff1a http wiki ros org ros canopen distro 61 indigo Ros canopen包结构如下 SocketCAN 是一组开源的
  • linux gcc编译错误:undefined reference to `aio_error‘解决方法

    include lt aio h gt void aiow completion handler sigval t sigval int ret struct aiocb req req 61 struct aiocb sigval siv
  • wait_event_interruptible_locked的使用方法

    wait event interruptible locked interface New wait event interruptible exclusive locked irq macros added They work just
  • printk在应用层的设置方式及读取内核打印信息的方法

    如果 printk 中没有加调试级别 xff0c 则使用默认的调试级别 注意 xff0c 调试级别和格式化字符串之间没有逗号 当前控制台的各打印级别可以通过下面的命令来查看 cat proc sys kernel printk 4 4 1
  • qt编译Qxlsx模块及安装

    主要参考如下地址 xff1a https www icode9 com content 4 715555 html 注意的点 xff1a 1 把下载的代码复制到根目录下 xff0c 路径不要有什么空格啥的 xff0c 否则你会发现perl老
  • GitLab 使用Tortoisegit询问“git@192.168.1.18‘s password“问题解决

    现象如下 xff1a 使用TortoiseGit去拉本地GitLab上建立的项目时 xff0c 一直提示输入密码 xff08 如下图 xff09 xff0c 这个密码又没有指定用户名 xff0c 就算你输入你用户名的密码也是失败 但是很诡异
  • 二代身份证读写器原理及开发

    身份证读写器的作用就是从身份证中读取身份信息 xff08 例如姓名 民族 身份证号等 xff09 xff0c 然后显示或者传输给其他模块使用 功能框架如下 xff1a 功能框图说明 xff1a 1 业务模块 负责向安全模块发送命令 xff0
  • JLINK V10 V11固件修复

    先去我的资源里面下载bootloader和app固件文件 步骤 xff1a 1 PC上安装JLINK V4 9工具 xff08 貌似不能使用太高版本的工具 xff0c 否则有问题 xff09 2 打开j flash v4 9 xff0c 新
  • ROS | 话题通信的编程实现

    ROS 话题通信的编程实现 1 创建功能包2 节点编程与消息定义2 1 案例说明2 2 话题消息的定义2 3 创建 cpp文件2 4 话题发布者编程2 5 话题订阅者编程 3 配置与编译3 1 在CMaKeLists txt中添加编译选项3