【ROS话题通信】发布者和订阅者

news/2024/11/30 0:49:53/

前言

本文记录ROS话题通信的学习过程,便于后续复习。首先明确,ROS中的话题通信,在ROS通信中非常重要,实现了分布式发布接收消息,也是实现了不同编程语言间的解耦,下面记录下自己学习过程中的相关代码和配置。
学习环境:VSCode Ubuntu18.04
主要分为话题订阅和发布标准信息和自定义信息两个部分,每个部分会记录下C++和Python的实现

1 标准信息格式下的话题通信

1.1 C++版

发布者逻辑:

1 引入头文件
2 初始化ROS节点
3 定义句柄
4 创建发布者对象
5 定义发布的消息及消息发布的一些设置

发布者代码:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char *argv[]){//控制中文不乱码setlocale(LC_ALL,"");//1 初始化ros节点ros::init(argc,argv,"publisher");//2 创建句柄ros::NodeHandle nh;//3 创建发布者对象ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);//4 编写发布逻辑并发布数据// 创建被发布的信息std_msgs::String msg;//定义频率ros::Rate rate(10);//设置编号int count=0;//可让发送数据前 休眠3秒 当作是注册到roscore的时间//这样可保证订阅者 可 接收到前几个信息ros::Duration(3).sleep();//循环发布while(ros::ok()){count++;std::stringstream ss;ss << "hello ---> " << count;msg.data = ss.str();pub.publish(msg);//添加日志ROS_INFO("发布的数据为: %s",ss.str().c_str());rate.sleep();//官方建议 主要用于调用回调函数ros::spinOnce();}return 0;
}

订阅者逻辑:

1 引入头文件
2 初始化ROS节点
3 创建订阅者对象及消息回调函数

订阅者代码:

#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr &msg){ROS_INFO("subcribe msg: %s", msg->data.c_str());
}
int main(int argc, char *argv[]){setlocale(LC_ALL,"");//1 初始化ros节点ros::init(argc,argv,"subcribe");//2 创建句柄ros::NodeHandle nh;//3 创建发布者对象ros::Subscriber sub = nh.subscribe("fang",10,doMsg);//为了处理上面的回调函数ros::spin();return 0;
}

相关配置和调用测试
1)整个项目的整体配置,这里先设置 tasks.json
在这里插入图片描述

{"version": "2.0.0","tasks": [{"label" : " catkin_make: debug", //代表提示的描述性信息 "type": "shell","command": "catkin_make","args": [], //可以使用ctrl+shift+B进行编译项目"group": {"kind": "build", "isDefault": true},"presentation":{"reveal":"always"//可选silence和always代表输出信息},"problemMatcher": "$msCompile"/* "type": "catkin_make","args": ["--directory","此处为项目目录/Documents/learn/ros/ros_ws_demo1","-DCMAKE_BUILD_TYPE=RelWithDebInfo"],"problemMatcher": ["$catkin-gcc"],"group": "build","label": "catkin_make: build"*/}]
}

2)首先看下文件夹的构成,及根目录为ROS_WS_DEMO,话题通信的代码在plumbing_pub_sub文件夹下(功能包):
在这里插入图片描述
上方每个文件夹的含义:
include:包含一些头文件和编译后的信息
msg:自定义的消息类型文件夹
scripts:Python 脚本文件夹
src:C++源代码文件夹
CMakeList.txt:项目执行配置文件
package.xml:一些依赖库文件
3)写好的代码需要在文件夹下的 CMakeList.txt进行配置
在这里插入图片描述
在这里插入图片描述
配置好后,其实就可以进行编译我们写好的项目了,如果您配置了项目根目录下的tasks.json,直接进行 ctrl+shift+B即可进行编译。如果没出错:
在这里插入图片描述
4)运行过程
4.1 首先打开一个终端,输入下面的命令,启动主节点:

roscore

在这里插入图片描述
4.2 然后打开另一个新终端,分别输入下方的命令,即可得到发布 订阅节点

#激活环境配置
source ./devel/setup.bash
#运行节点
rosrun plumbing_pub_sub sub_node

在这里插入图片描述
4.3 然后打开另一个新终端,分别输入下方的命令,即可得到发布 消息发布节点

#激活环境配置
source ./devel/setup.bash
#运行节点
rosrun plumbing_pub_sub pub_node

在这里插入图片描述
4.4 如果想看下话题的发布情况,也可以重新打开一个终端,输入

rqt_graph#可对当前发布的话题进行可视乎

1.2 Python版

在项目下面新建 scripts 文件夹,用来存储py的脚本
在这里插入图片描述

发布者代码:

#! /usr/bin/env python
import rospy
from std_msgs.msg import String # 发布的消息类型
"""使用python实现消息发布:1.导包;2.初始化ros节点3.创建发布者对象4.编写发布逻辑并发布数据
"""
if __name__ == "__main__":# 2.初始化ros节点rospy.init_node("sanDai") # 传入节点名称# 3.创建发布者对象pub = rospy.Publisher("che",String, queue_size = 10) # che是话题名称,类型是String,消息队列大小为10# 4.编写发布逻辑并发布数据# 4.1 创建数据类型msg = String()# 4.2 指定发布频率rate = rospy.Rate(1)# 4.3 设置计数器count = 0# 休眠3s,完成在master下面的注册rospy.sleep(3)# 4.4 循环发布数据while not rospy.is_shutdown(): # 判断当前节点是否已经关闭,没有关闭则发布数据count += 1 # 如果要将count追加到hello后面,则需要将其变为字符串msg.data = "hello" + str(count)# 4.5 发布数据pub.publish(msg)# 4.6 添加日志输出rospy.loginfo("发布的数据:%s",msg.data)rate.sleep()

订阅者代码:

#! /usr/bin/env python
import  rospy
from std_msgs.msg import String
"""订阅实现流程:1.导包2.初始化ROS节点3.创建订阅者对象4.回调函数处理数据5.spin()
"""
def doMsg(msg): #将订阅到的数据传进来rospy.loginfo("订阅的数据:%s",msg.data) #data是数据
if __name__ == "__main__":# 2.初始化ROS节点rospy.init_node("huaHua")# 3.创建订阅者对象sub = rospy.Subscriber("fang",String,doMsg,queue_size = 10)# sub = rospy.Subscriber("fang",String,doMsg,queue_size = 10) 跨语言通信# 4.回调函数处理数据# 5.spin()rospy.spin()

在Scripts下面编写的Python文件需要增加可执行权限,打开终端,切换到Scripts文件夹下,然后运行命令:

chmod +x *.py#让python文件增加可执行权限

配置过程
在CMakeList.txt中:
在这里插入图片描述
记得编译,然后运行的过程如下:
同样先启动 roscore 然后重新打开终端,执行下面的操作

启动发布者节点:

#激活环境配置
source ./devel/setup.bash
#运行节点
rosrun plumbing_pub_sub pub_node_py.py

在这里插入图片描述
启动订阅者节点:

#激活环境配置
source ./devel/setup.bash
#运行节点
rosrun plumbing_pub_sub sub_node_py.py

在这里插入图片描述

1.3 C++和Python间发布者和订阅者的解耦操作

ROS系统的强大之处在于不同的编程语言间,只要符合话题通信的机制,可以进行互相发布和订阅,只要保证两者发布和订阅的话题一样,不用考虑对应的程序语言实现,即可以按照下面的步骤实现C++和Python语言的解耦通信。
在这里插入图片描述
在这里插入图片描述
则以上两者话题只要保持一致,即可实现通信。相关过程,和上面的运行一样。

2 自定义消息类型的话题通信

以上过程使用的是ROS系统中内置的标准数据类型,但是在实际的项目实践中,往往需要自定义消息类型,这个是在本部分需要注意的内容。

2.1 自定义信息

在这里插入图片描述
内容:

string name
int32 age
float32 height

然后配置package.xml中的依赖文件
在这里插入图片描述
增加下面的语句:

<!-- 自定义消息文件依赖 --><build_depend>message_generation</build_depend><!-- 自定义消息文件依赖 --><exec_depend>message_runtime</exec_depend>

然后在CMakeList.txt中也需要配置 Msg的配置:
在这里插入图片描述
在这里插入图片描述
生成消息时,依赖于std_msgs
在这里插入图片描述
下面的内容中增加 message_runtime 即执行过程中的依赖
在这里插入图片描述
在这里插入图片描述
以上配置完全后,可以进行编译,这时候会发现项目中出现了自定义的 Person.msg
在这里插入图片描述
以上说明后续的代码中,我们可以使用自定义的消息类型了。
另外,为保证我们在源文件编写过程中,有所提示,可以引用到生成的新消息类型,我们需要完成下面的配置:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 C++版

发布者代码:

#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"int main(int argc, char *argv[])
{setlocale(LC_ALL,"");ROS_INFO("this is the publisher...");ros::init(argc,argv,"ros_pub");ros::NodeHandle nh;ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("chat",10);plumbing_pub_sub::Person person;person.name = "123";person.age = 10;person.height = 10.3;//定义发送频率每次发1条ros::Rate rate(1);while(ros::ok()){pub.publish(person);ROS_INFO("this is the publisher...%s,%d,%.2f",person.name.c_str(),person.age,person.height);rate.sleep();ros::spinOnce();}return 0;}

订阅者代码:

#include "ros/ros.h"
#include "plumbing_pub_sub/Person.h"void doMsg(const plumbing_pub_sub::Person::ConstPtr& person){ROS_INFO("subcribe msg:%s,%d,%.2f",person->name.c_str(),person->age,person->height);
}
int main(int argc, char *argv[]){setlocale(LC_ALL,"");ROS_INFO("this is a subcribe ... ");ros::init(argc,argv,"sub_person");ros::NodeHandle nh;ros::Subscriber sub = nh.subscribe("chat",10,doMsg);ros::spin();return 0;
}

CMakeList.txt中:
在这里插入图片描述

add_dependencies(pub_person ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(sub_person ${PROJECT_NAME}_generate_messages_cpp)

在这里插入图片描述
在这里插入图片描述
执行过程和上面标准信息格式的 C++版本一样

2.3 Python版本

发布者代码:

#! /usr/bin/env pythonimport rospy
from plumbing_pub_sub.msg import Personif __name__=="__main__":print("===",Person)rospy.init_node("pub_person_py")pub = rospy.Publisher("chat_py",Person,queue_size = 10)p = Person()p.name = "hh"p.age = 10p.height = 10.1rate = rospy.Rate(1)while not rospy.is_shutdown():pub.publish(p)rospy.loginfo("the msgs:%s,%d,%.2f",p.name,p.age,p.height)rate.sleep()

订阅者代码:

#! /usr/bin/env python
import rospy
from plumbing_pub_sub.msg import Person
def doMsg(p):rospy.loginfo("the info:%s,%d,%.2f",p.name,p.age,p.height)
if __name__=="__main__":rospy.init_node("sub_person_py")sub = rospy.Subscriber("chat_py",Person,doMsg,queue_size=10)rospy.spin()

CMakeLists.txt配置:
在这里插入图片描述
运行过程和上面的 Python版本一样, 注意编写完py文件后,需要 chmod +x *.py 即增加可执行权限


http://www.ppmy.cn/news/3943.html

相关文章

【数据结构】树以及二叉树的概念

作者&#xff1a;一个喜欢猫咪的的程序员 专栏&#xff1a;《数据结构》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 树的概念&#xff1a; 树的相关概念&#xff1a; 树如何表示&#xff…

Docker入门(基础篇)

Docker入门Docker相关概念为什么需要DockerDocker的理念容器与虚拟机的比较Docker的安装与使用安装Dockerdocker 的三要素Docker常用命令Docker相关概念 为什么需要Docker 为什么会出现Docker了&#xff1f;现在我们假设你在开发一个项目&#xff0c;你使用的是一台笔记本电脑…

Windows 下 MongoDB 6 详细安装教程(图文结合)

​ MongoDB是一个基于分布式文件存储 [1] 的数据库。由C语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。 ​ MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。它支持的数据结构非常…

PyTorch笔记 - ResNet: Deep Residual Learning for Image Recognition

欢迎关注我的CSDN:https://blog.csdn.net/caroline_wendy 本文地址:https://blog.csdn.net/caroline_wendy/article/details/128341408 Paper:ResNet - Deep Residual Learning for Image Recognition Kaiming He,Microsoft Research工程:TIMM,https://github.com/rwight…

Java——布隆过滤器

在上一篇博客中讲到位图是用来判定一个正整数是否存在的。对于一个负数&#xff0c;我们可以统一规定让他们加上一个数&#xff0c;变成正数&#xff0c;然后用位图的方式存储。但是对于字符串&#xff0c;我们就没办法存储了。因此发明了布隆过滤器 概念 对于网络上很多需要…

[附源码]Python计算机毕业设计高校学生管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等…

win7 nvm-window 安装图解

序&#xff1a; 1、博主不是没试过装nvmw&#xff0c;但是npm install nvmw下来&#xff0c;发现切换不了的&#xff0c;就算独立下载nvmw下来配置也试过了&#xff0c;也是不行&#xff0c;最重要的一点nvmw已经停更了&#xff01;&#xff01;&#xff01;&#xff01; 2、删…

java的垃圾回收浅谈

目录 并发标记问题 三色算法问题 浮动垃圾问题 漏标问题 cms的解决方式 g1的解决方式 跨代(区)引用 CMS垃圾回收日志 G1垃圾回收日志 垃圾回收过程其实都包含两步&#xff1a;标记回收。 标记算法&#xff1a; 引用计数&#xff1a;每个对象都有一个计数器&#xff…