【古月居《ros入门21讲》学习笔记】10_话题消息的定义与使用

2023-11-29 09:45

本文主要是介绍【古月居《ros入门21讲》学习笔记】10_话题消息的定义与使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

说明:

1. 话题模型

2. 实现过程(C++)

自定义话题消息

Person.msg文件内容

Person.msg文件内容说明

编译配置

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

在CMakeLists.txt中添加编译选项

编译生成语言相关文件

创建发布者代码(C++)

创建订阅者代码(C++)

配置代码编译规则

配置内容说明

编译并运行

编译

运行

扩展

3. 实现过程(Python)

创建发布者代码(Python)

创建订阅者代码(Python)

运行


说明:

1. 本系列学习笔记基于B站:古月居《ROS入门21讲》课程,且使用的Ubuntu与ROS系统版本与课程完全一致;

虚拟机版本Linux系统版本ROS系统版本
VMware WorkStation Pro 16Ubuntu18.04Melodic


2. 课程中的所有示例代码均已跑通,且对Pyhon版本的代码也都做了运行验证,并附带验证过程(错误均已修正);

3. 本节是整个笔记的第10节,对应视频课程的第12节,请自行对应学习;

4. 整个系列笔记基本已经完结,但部分章节仍需润色修改 ,后面会陆续发布,请大家持续关注,      创作不易,感谢支持!
 


1. 话题模型

image-20230525103444411

2. 实现过程(C++)

自定义话题消息

cd ~/catkin_ws/src/learning_topic
mkdir msg
cd msg
touch Person.msg

Person.msg文件内容
string name // 名字
uint8 sex   // 性别:分为3种,男、女、未知,下面以012宏定义做表示判断
uint8 age   // 年龄
​
uint8 unknown = 0 
uint8 male = 1    
uint8 female = 2
Person.msg文件内容说明

Person.msg文件里定义的内容跟语言无关的,这既不是c++,也不是python,这里面的string uint8表示在不同的程序里面扩展成对应该种程序的表示方法,可以类比单片机里无符号整型变量类型unsigned int来理解,缩写就是uint。

cd ~/catkin_ws/src/learning_topic
mkdir msg

注意:新建的这个文件夹名字不能随便命名,只能叫msg,否则编译会报错,CMakeList文件中有说明,要放在名叫msg文件夹中。

image-20230525105802095

cd msg
touch Person.msg

(注意:这里的文件名首字母P一定要大写!否则后面会报错)

打开Person.msg文件,把定义的内容复制到文件里并保存,

(注意:输入的内容中,注释不要,空格不能用tab键缩进,否则后面也会报错)

image-20230525143629177

编译配置

路径:~/catkin_ws/src/learning_topic

在package.xml文件中添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

build_depend:编译依赖

exec_depend:运行依赖

image-20230525134244239

在CMakeLists.txt中添加编译选项
find_package(......message_generation)

image-20230525142005844

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

add_message_files: 把我们定义的Person.msg文件,做为我们定义的接口;

generate_messages:编译Person.msg文件的时候需要用到一些依赖于ROS已有的库或包,

我们这里用到的依赖是std_msgs,我们前面看到的string,uint8都是在std_msgs里面做定义的

image-20230525142153143

catkin_package(......message_runtime)

image-20230525142706463

编译生成语言相关文件
cd ~/catkin_ws
catkin_make

image-20230525144332516

编译成功之后可以在~/catkin_ws/devel/include/learning_topic下看到Person.msg文件编译生成的C++的头文件Person.h

image-20230525145008343

创建发布者代码(C++)

cd ~/catkin_ws/src/learning_topic/src
touch person_publisher.cpp

  • 初始化ROS节点;

  • 向ROS Master注册节点信息,包括发布消息的话题名,话题中的消息类型;

  • 创建消息数据;

  • 按照一定频率循环发布消息,

/*** 该例程将发布/person_info话题,自定义消息类型learning_topic::Person*/#include <ros/ros.h>
#include "learning_topic/Person.h"
​
int main(int argc, char **argv)
{// ROS节点初始化ros::init(argc, argv, "person_publisher");
​// 创建节点句柄ros::NodeHandle n;
​// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
​// 设置循环的频率ros::Rate loop_rate(1);
​int count = 0;while (ros::ok()){// 初始化learning_topic::Person类型的消息learning_topic::Person person_msg;person_msg.name = "Tom";person_msg.age  = 18;person_msg.sex  = learning_topic::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();}
​return 0;
}

image-20230525152240349

创建订阅者代码(C++)

cd ~/catkin_ws/src/learning_topic/src
touch person_subscriber.cpp

初始化ROS节点;

订阅需要的话题;

循环等待话题消息,接收到消息后进入回调函数;

在回调函数中完成消息处理。

/*** 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person*/#include <ros/ros.h>
#include "learning_topic/Person.h"
​
// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{// 将接收到的消息打印出来ROS_INFO("Subcribe 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, "person_subscriber");
​// 创建节点句柄ros::NodeHandle n;
​// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbackros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
​// 循环等待回调函数ros::spin();
​return 0;
}

image-20230525154634297

配置代码编译规则

将下面6行内容复制到CMakeLists.txt文件中,

add_executable(person_publisher src/person_publisher.cpp)
target_link_libraries(person_publisher ${catkin_LIBRARIES})
add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)
​
add_executable(person_subscriber src/person_subscriber.cpp)
target_link_libraries(person_subscriber ${catkin_LIBRARIES})
add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)
配置内容说明

add_executable:

将person_publisher.cpp和person_subscriber.cpp代码文件编译成person_publisher与person_subscriber可执行文件;

target_link_libraries:

把编译生成的可执行文件person_publisher与person_subscriber跟ROS相关的一些库做连接的,比如调用的C++的接口;

add_dependencies:

有一些代码是动态生成的,而可执行文件也需要与动态生成的程序产生依赖关系,所以这个就是用来动态的和刚才生成的头文件Person.h产生依赖关系的;

复制到CMakeLists.txt文件中的位置如下:

image-20230525155453179

编译并运行

编译
cd ~/catkin_ws
catkin_make

image-20230525160916698

运行
roscore
rosrun learning_topic person_subscriber
rosrun learning_topic person_publisher

第一步:打开ROS Master;

第二步:运行订阅者person_subscriber,让其先等待着发布者发布消息数据,

第三步:运行发布者person_publisher,让其发布消息数据,

image-20230525162541324

扩展

如果把启动ROS_Master的roscore关掉,发布者与订阅者依然在发布和接收消息数据,此时ROS_Master的结束对两者并无影响,

因为ROS_Master是帮助节点建立连接的,一旦连接创立,ROS_Master在这里的作用就不再存在了,但关掉ROS_Master后,

如果有第三个节点要加入进来的话,是无法再建立连接的。

image-20230526155216489

3. 实现过程(Python)

创建发布者代码(Python)

cd ~/catkin_ws/src/learning_topic/scripts
touch person_publisher.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
​
import rospy
from learning_topic.msg import Person
​
def velocity_publisher():# ROS节点初始化rospy.init_node('person_publisher', anonymous=True)
​# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)
​#设置循环的频率rate = rospy.Rate(10) 
​while not rospy.is_shutdown():# 初始化learning_topic::Person类型的消息person_msg = Person()person_msg.name = "Tom";person_msg.age  = 18;person_msg.sex  = Person.male;
​# 发布消息person_info_pub.publish(person_msg)rospy.loginfo("Publsh person message[%s, %d, %d]", person_msg.name, person_msg.age, person_msg.sex)
​# 按照循环频率延时rate.sleep()
​
if __name__ == '__main__':try:velocity_publisher()except rospy.ROSInterruptException:pass

image-20230526161126127

创建订阅者代码(Python)

cd ~/catkin_ws/src/learning_topic/scripts
touch person_subscriber.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
​
import rospy
from learning_topic.msg import Person
​
def personInfoCallback(msg):rospy.loginfo("Subcribe Person Info: name:%s  age:%d  sex:%d", msg.name, msg.age, msg.sex)
​
def person_subscriber():# ROS节点初始化rospy.init_node('person_subscriber', anonymous=True)
​# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallbackrospy.Subscriber("/person_info", Person, personInfoCallback)
​# 循环等待回调函数rospy.spin()
​
if __name__ == '__main__':person_subscriber()

image-20230526162129583

注意:给person_publisher.py 和 person_subscriber.py文件赋予作为程序文件执行的权限,

点击person_publisher.py文件,右键,属性,权限,勾选(允许作为程序文件执行),

person_subscriber.py文件操作同上,python文件不需要编译,直接运行即可。

image-20230526162441381

运行

roscore
rosrun learning_topic person_subscriber.py
rosrun learning_topic person_publisher.py

第一步:打开ROS Master;

第二步:运行订阅者person_subscriber.py,让其先等待着发布者发布消息数据,

第三步:运行发布者person_publisher.py,让其发布消息数据,

image-20230526163111027

这篇关于【古月居《ros入门21讲》学习笔记】10_话题消息的定义与使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/432352

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传