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

news2024/11/23 3:20:06

前言

本文记录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 python

import rospy
from plumbing_pub_sub.msg import Person

if __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 = 10
    p.height = 10.1
    rate = 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.coloradmin.cn/o/91275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kotlin小菜——基础语言教程

概述 Kotlin是JetBrains推出的一种编程语言&#xff0c;JetBrains是最智能的Java IDE的官方设计器&#xff0c;名为Intellij IDEA。这是在JVM上运行的强静态类型语言。2017年&#xff0c;谷歌宣布Kotlin是Android开发的官方语言。Kotlin是一种开源编程语言&#xff0c;它将面向…

会话Cookie跟踪技术

会话 用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开连接&#xff0c;会话结束。在一次会话中可以包含多次请求和响应。 从浏览器发出请求到服务端响应数据给前端之后&#xff0c;一次会话(在浏览器和服务器之间)就被建立了 …

产品设计:Material Design 学习笔记二

​5、图标 桌面图标 桌面图标尺寸是48dp X 48dp。 桌面图标建议模仿现实中的折纸效果&#xff0c;通过扁平色彩表现空间和光影。注意避免以下问题&#xff1a; ①不要给彩色元素加投影 ②层叠不要超过两层 ③折角不要放在左上角 ④带投影的元素要完整展现&#xff0c;不能…

Debug怎么用

文章目录前言一、打断点运行Debug二、页面重新运行功能三、回到代码看断点前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 因为最近有个项目注册不好使&#xff0c;想看看哪的问题&#xff0c;所以用debug看看程序走到了哪 提示&#xff1a;以下是本篇文…

docker部署mysql初始化数据库

一、前言 在使用docker部署mysql服务时&#xff0c;往往需要在创建容器时新建database&#xff0c;在需要在创建实例的过程中希望初始化sql脚本。 mysql官方镜像支持在容器初次启动时自动执行指定的sql脚本或shell脚本&#xff08;注意&#xff1a;只有初次启动时才能自动执行&…

【正点原子I.MX6U-MINI】通过tftp从Ubuntu中下载zImage 和设备树文件 | 从网络启动Linux系统

从网络启动linux系统的唯一目的就是为了调试&#xff01;不管是为了调试linux系统还是linux下的驱动。每次修改linux系统文件或者linux下的某个驱动以后都要将其烧写到EMMC中去测试&#xff0c;这样太麻烦了。我们可以设置linux从网络启动&#xff0c;也就是将 linux 镜像文件和…

【OpenCV-Python】教程:5-3 光流

OpenCV Python Optical Flow (光流) 【目标】 了解光流的概念和用 Lucas-Kanade 算法估计光流我们将使用cv2.calcOpticalFlowPyrLK()这样的函数来跟踪视频中的特征点。们将使用cv2.calcOpticalFlowFarneback()方法创建一个密集的光流场&#xff0c;可以用于前景检测。 【理论…

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

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

Java+SSH实验室预约系统(含源码+论文+答辩PPT等)

该项目采用技术&#xff1a; 后台&#xff1a;SpringSpringmvcHibernate 前台JqueryMy97DatePickercssjs 使用了MySQLTomcat等相关技术 项目含有源码、文档、配套开发软件、软件安装教程、项目发布教程等 本系统的用户可以分为三种&#xff1a;管理员、教师、学生。以下针对三种…

协同共进 | 中睿天下入会工业信息安全产业发展联盟

近日&#xff0c;中睿天下加入“工业信息安全产业发展联盟”&#xff0c;成为新一批会员单位。 工业信息安全是网络安全、国家安全的重要组成部分&#xff0c;涉及工业领域各个环节,涵盖工业控制系统安全、工业互联网安全、工业数据安全等各领域&#xff0c;直接关系到经济发展…

u盘出现fat32如何恢复文件?告诉你两种好方法

u盘由于体积小、内存大等优势&#xff0c;在日常生活领域应用的很多&#xff0c;但是使用过程中&#xff0c;总会遇到这样或那样的问题&#xff0c;比如u盘显示fat32打开啥都没有了&#xff1f;或者u盘出现fat32而无法访问的情况&#xff0c;这时如果里面有重要的数据怎么办呢&…

Activiti 工作流引擎

一、什么是工作流&#xff1f; 工作流:指业务过程的部分或整体在计算机应用环境下的自动化。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。在计算机中&#xff0c;工作流属于计算机支持的协同工作&#xff08;CSCW&#xff09;的一部分&#xff0c;后者是普遍研究…

win7无损合并分区,win7合并磁盘分区

电脑的操作系统是win7的&#xff0c;如果磁盘分区太小或者说磁盘分区不合理&#xff0c;需要对磁盘分区重新分区&#xff0c;其中合并磁盘分区就是解决方法之一&#xff0c;那么&#xff0c;有没有关于win7无损合并分区的操作方法呢&#xff1f; 一、利用Windows自带的功能来合…

Matlab|基于BP神经网络进行电力系统短期负荷预测

目录 摘要 一、电力负荷数据导入 二、输入输出数据归一化 三、建立和训练BP神经网络 四、 使用测试数据进行负荷预测 五、Matlab代码实现 摘要 使用BP神经网络实现简单的电力负荷回归预测任务。主要的步骤为&#xff1a;导入数据、数据归一化、建立BP神经网络、训练BP神…

熹乐科技范维肖CC:基于开源 YoMo 框架构建“全球同服”的 Realtime Metaverse Application

前言 在「RTE2022 实时互联网大会」中&#xff0c;熹乐科技创始人 & CEO 范维肖CC 以《基于开源 YoMo 框架构建“全球同服”的 Realtime Metaverse Application》为题进行了主题演讲。 本文内容基于演讲内容进行整理&#xff0c;为方便阅读略有删改。 大家好&#xff0c;…

chatGPT的爆火,是计算机行业这次真的“饱和”了?

近日&#xff0c;chatGPT这一生成式AI爆火&#xff0c;这款号称神仙级别的自动语言生成式AI发布短短5天内&#xff0c;就吸引了100万用户&#xff0c;在官方描述中&#xff0c;chatGPT是一个“可以连续回答问题、承认自己的错误、挑战不正确的前提并拒绝不适当的要求”的对话模…

【GO】 K8s 管理系统项目[API部分--Deployment]

K8s 管理系统项目[API部分–Deployment] 1. 实现接口 service/dataselector.go package serviceimport ("sort""strings""time"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1" )// dataselector 用于排序,过滤…

第11讲:vue脚手架集成ElementUI

一、创建vue路由项目并添加ElementUI支持 ElementUI官方网站&#xff1a;ElementUI组件 创建路由项目请参考&#xff1a;路由开发 使用如下命令集成ElementUI npm i element-ui -S在src/main.js文件中引用ElementUI import Vue from vue import App from ./App.vue import …

创建第一个QT程序demo

双击Qt Creator 9.0.0 (Community)图标&#xff0c;打开软件。该图标所处位置为&#xff08;如果是默认安装到C盘下面的话&#xff09;&#xff1a;C:\Qt\Tools\QtCreator\bin\qtcreator.exe 或者从开始菜单栏启动&#xff08;开始菜单栏的启动图标本质上也是一个快捷方式&…

记录windows上的VSCODE 远程到linux编译代码机器上的一些问题

设置windows SSH 到linux时免密码登录的方法&#xff1a; 将C:\Users\Administrator.ssh\id_rsa.pub中的公钥字符串复制&#xff0c;追加到linux ~/.ssh/authorized_keys文件中。 问题&#xff1a; rootlocalhost:~/.vscode-server/bin/6261075646f055b99068d3688932416f2346d…