ROS机器人入门第四课:话题通信_ros虚拟机话题通信-机器人姿态-程序员宅基地

技术标签: 机器人  ROS  

ROS机器人入门第四课:话题通信

一、话题通信概述

话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。话题通信的应用场景也极其广泛,比如下面一个常见场景:

机器人在执行导航功能,使用的传感器是激光雷达,机器人会采集激光雷达感知到的信息并计算,然后生成运动控制信息驱动机器人底盘运动。

在上述场景中,就不止一次使用到了话题通信。

  • 以激光雷达信息的采集处理为例,在 ROS 中有一个节点需要时时的发布当前雷达采集到的数据,导航模块中也有节点会订阅并解析雷达数据。
  • 再以运动消息的发布为例,导航模块会根据传感器采集的数据时时的计算出运动控制信息并发布给底盘,底盘也可以有一个节点订阅运动信息并最终转换成控制电机的脉冲信号。

以此类推,像雷达、摄像头、GPS… 等等一些传感器数据的采集,也都是使用了话题通信,换言之,话题通信适用于不断更新的数据传输相关的应用场景。

(一)概念

以发布订阅的方式实现不同节点之间数据交互的通信模式。

(二)作用

用于不断更新的、少逻辑处理的数据传输场景。

二、话题通信基本操作

需求:

编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布文本消息,订阅方订阅消息并将消息内容打印输出。

分析:

在模型实现中,ROS master 不需要实现,而连接的建立也已经被封装了,需要关注的关键点有三个:

  1. 发布方
  2. 接收方
  3. 数据(此处为普通文本)

流程:

  1. 编写发布方实现;
  2. 编写订阅方实现;
  3. 为python文件添加可执行权限;
  4. 编辑配置文件;
  5. 编译并执行。

(一)发布方

这段代码是一个使用ROS(Robot Operating System,机器人操作系统)的Python脚本示例,旨在创建一个名为talker_p的节点,该节点周期性地向名为chatter的话题发送包含字符串的消息。它是一个简单的发布者(Publisher)节点,演示了ROS中发布消息的基本模式。下面对代码进行详细注释,并解释其中使用的关键ROS函数。

#! /usr/bin/env python
# - coding: utf-8 -*-

# 导入 rospy 库,rospy 是 ROS 在 Python 中的客户端库,用于使Python代码能与ROS通信。
import rospy
# 从 std_msgs 包中导入 String 消息类型,std_msgs 包含了许多标准的消息类型,String 是其中用于传输文本信息的一个类型。
from std_msgs.msg import String

# 判断此脚本是直接被执行而不是被导入到其他文件中时,下面的代码块将被执行。
if __name__ == "__main__":
    # 初始化ROS节点,命名为 "talker_p"。
    # 每个ROS节点都必须有一个唯一的名称,这样其他节点就可以与之通信。
    rospy.init_node("talker_p")
    
    # 实例化发布者对象。
    # 这一步创建了一个发布者对象,它能够向名为 "chatter" 的话题发布 String 类型的消息。
    # queue_size 参数是发布队列的大小,用于限制未处理消息的数量,防止内存消耗过大。
    pub = rospy.Publisher("chatter", String, queue_size=10)
    
    # 创建一个 String 类型的消息对象。
    msg = String()
    # 准备消息的前缀文本。
    msg_front = "hello 你好"
    # 初始化计数器,用于生成消息序列。
    count = 0
    
    # 设置消息发布的频率,这里是每秒1次。
    rate = rospy.Rate(1)
    # 在 ROS 节点未被关闭的情况下循环。
    while not rospy.is_shutdown():
        # 拼接字符串,将前缀和计数器的值合成为最终的消息内容。
        msg.data = msg_front + str(count)

        # 发布消息到 "chatter" 话题。
        pub.publish(msg)
        # 根据之前设置的频率暂停,确保按照设定的频率发布消息。
        rate.sleep()
        # 将发布的消息内容记录到 ROS 日志信息中,便于调试和记录。
        rospy.loginfo("写出的数据:%s", msg.data)
        # 更新计数器,为下一条消息准备。
        count += 1
解释一些关键的ROS函数和概念:
  • rospy.init_node("talker_p"):该函数用于初始化一个ROS节点,这是启动任何ROS节点的第一步。这里的"talker_p"是节点的名称,它必须在ROS系统中唯一。

  • rospy.Publisher("chatter", String, queue_size=10):这个函数创建一个发布者对象,用于向特定的话题(这里是chatter)发布消息。String是消息类型,而queue_size参数用于控制发布者消息队列的大小,有助于处理网络延迟或处理速度慢时消息的积压问题。

  • rospy.Rate(1):这个函数创建一个Rate对象,用于控制循环的速率。这里设置为1Hz,意味着循环每秒运行一次。

  • rospy.is_shutdown():这是一个检查ROS节点是否收到了终止信号(如Ctrl+C)的函数。如果是,则返回True,循环将停止。

  • pub.publish(msg):通过之前创建的发布者对象pub调用publish方法来发布消息。msg是要发布的消息对象。

  • rate.sleep():这个方法使当前循环休眠足够的时间,以保持循环运行在设定的频率上。

  • rospy.loginfo():这个函数用于将信息记录到ROS日志里,类似于Python的print函数,但是它提供了更丰富的日志管理功能。


如若不写订阅方的代码想直接查看发布方的消息,可以使用如下命令:
rostopic echo 话题
在这里插入图片描述


(二)订阅方

这段代码展示了如何在ROS(Robot Operating System,机器人操作系统)中创建一个订阅者节点,监听并处理来自特定话题(chatter)的消息。下面对代码进行详细注释,并解释其中使用的关键ROS函数。

# 导入 rospy 库,rospy 是 ROS 在 Python 中的客户端库,允许Python代码与ROS通信。
import rospy
# 从 std_msgs 包中导入 String 消息类型,这是一个用于传输文本信息的标准消息类型。
from std_msgs.msg import String

# 定义回调函数,这个函数将在节点收到新消息时被调用。
# msg 参数是收到的消息对象。
def doMsg(msg):
    # 在 ROS 日志中记录信息,这里记录的是收到的消息内容。
    rospy.loginfo("I heard:%s", msg.data)

# 检查这个脚本是否是主程序,而不是被其他文件导入。
if __name__ == "__main__":
    # 初始化 ROS 节点,节点名为 "listener_p"。
    # 每个节点必须有一个唯一的名称,以便在 ROS 网络中被识别。
    rospy.init_node("listener_p")
    
    # 实例化订阅者对象。
    # 这一步创建了一个订阅者对象,它将监听名为 "chatter" 的话题,
    # 并且每当有新消息时,就会调用 doMsg 函数。
    # String 指定了话题消息的类型,queue_size 用于限制消息队列的大小。
    sub = rospy.Subscriber("chatter", String, doMsg, queue_size=10)
    
    # 进入循环,等待消息到来。
    # rospy.spin() 使得Python脚本保持运行状态,并在收到新消息时调用回调函数。
    # 它是一个阻塞调用,直到节点被明确地关闭或接收到终止信号(例如Ctrl+C)。
    rospy.spin()

关键ROS函数和概念的解释:

  • rospy.init_node("listener_p"):该函数用于初始化一个ROS节点。这是启动任何ROS节点的必要步骤。这里的"listener_p"是节点的名称,它在ROS网络中必须是唯一的。

  • rospy.Subscriber("chatter", String, doMsg, queue_size=10):这个函数创建了一个订阅者对象,用于订阅特定的话题(这里是chatter)并指定当收到新消息时所调用的回调函数(这里是doMsg)。String参数指定了订阅的消息类型,而queue_size参数用于控制消息队列的大小,有助于处理网络延迟或处理速度慢时消息的积压问题。

  • doMsg(msg):这是一个用户定义的回调函数,每当订阅的话题有新的消息时,这个函数就会被调用。msg参数是收到的消息对象。在这个函数内部,使用rospy.loginfo来记录消息内容。

  • rospy.spin():这个函数会让节点进入等待循环,等待并处理回调函数。它是一个阻塞(blocking)调用,意味着除非节点被关闭,否则程序将停在这里。这是订阅者节点保持激活并响应话题消息的常用方法。

  • rospy.loginfo():这个函数用于在ROS日志中记录信息,对于调试和跟踪节点行为非常有用。


注意: 二者需要设置相同的话题

比如上面的发布方和订阅方都订阅了相同的话题:chatter


(三)添加可执行权限

终端下进入 scripts 执行:chmod +x *.py

在这里插入图片描述

(四)配置 CMakeLists.txt

catkin_install_python(PROGRAMS
  scripts/talker_p.py
  scripts/listener_p.py
  DESTINATION ${
    CATKIN_PACKAGE_BIN_DESTINATION}
)

在这里插入图片描述

(五)执行

  1. 启动 roscore;

  2. 启动发布节点;

  • 先启动命令行source ./devel/setup.bash
  • 再启动命令行rosrun 包名 自定义文件名.py
  1. 启动订阅节点。
  • 先启动命令行source ./devel/setup.bash
  • 再启动命令行rosrun 包名 自定义文件名.py

在这里插入图片描述
运行结果如图所示:

在这里插入图片描述


因为发布方是软起动,需要先在master里注册,注册过程中可能就已经把消息发出去了,即使先打开订阅方,再打开发布方也一样会丢失数据,所以我们可以先确保发布方注册完,再发送信息

即在发布方的代码中设置一个休眠函数rospy.sleep(3),我这里是休眠3秒再发送数据

在这里插入图片描述


注意:可以使用 rqt_graph 查看节点关系。

在这里插入图片描述

(六)ROS解耦合

即便你使用不同的语言编写的节点,那么他们之间也是可以实现数据交换

在话题通信中,只要话题一致,C++和python写的代码就可以相互通信

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_73841621/article/details/137022401

智能推荐

基于Kepler.gl 和 Google Earth Engine 卫星数据创建拉伸多边形地图-程序员宅基地

文章浏览阅读965次,点赞18次,收藏21次。现在我们有了 2021 年和 2023 年的 NDVI 数据帧,我们需要从 2021 年的值中减去 2023 年的值以捕获 NDVI 的差异。该数据集包括像素级别的植被值,我们将编写一个自定义函数来根据红色和绿色波段的表面反射率计算 NDVI。在我的上一篇文章中,我演示了如何将单个多边形分割/镶嵌为一组大小均匀的六边形。现在我们有了植被损失数据,让我们使用 Kepler.gl 可视化每个六边形的植被损失。将地图保存为 HTML 文件,在浏览器中打开 HTML 以获得更好的视图。现在我们将调用该函数并使用、

Echarts绘制任意数据的正态分布图_echarts正态分布图-程序员宅基地

文章浏览阅读3.3k次,点赞6次,收藏5次。正态分布,又称高斯分布或钟形曲线,是统计学中最为重要和常用的分布之一。_echarts正态分布图

Android中发送短信等普通方法_android bundle.get("pdus");-程序员宅基地

文章浏览阅读217次。首先要在Mainfest.xml中加入所需要的权限:[html] view plain copyprint?uses-permission android:name="android.permission.SEND_SMS"/> uses-permission android:name="android.permission.READ_SMS"/> _android bundle.get("pdus");

2021-07-26 WSL2 的安装和联网_wsl2 联网-程序员宅基地

文章浏览阅读2.6k次。0、说明最近在学习 Data Assimilation Research Testbed (DART) 相关内容,其软件是在 Unix/Linux 操作系统下编译和运行的 ,由于我的电脑是 Windows 10 的,DART 推荐可以使用 Windows Subsystem For Linux (WSL) 来创建一个 Windows 下的 Linux 子系统。以下的内容主要介绍如何安装 WSL2,以及 WSL2 的联网。1、如何在 Windows 10 下安装WSL具体的安装流程可以在 microso_wsl2 联网

DATABASE_LINK 数据库连接_添加 database link重复的数据库链接命-程序员宅基地

文章浏览阅读1k次。DB_LINK 介绍在本机数据库orcl上创建了一个prod_link的publicdblink(使用远程主机的scott用户连接),则用sqlplus连接到本机数据库,执行select * from scott.emp@prod_link即可以将远程数据库上的scott用户下的emp表中的数据获取到。也可以在本地建一个同义词来指向scott.emp@prod_link,这样取值就方便多了..._添加 database link重复的数据库链接命

云-腾讯云-实时音视频:实时音视频(TRTC)-程序员宅基地

文章浏览阅读3.1k次。ylbtech-云-腾讯云-实时音视频:实时音视频(TRTC)支持跨终端、全平台之间互通,从零开始快速搭建实时音视频通信平台1.返回顶部 1、腾讯实时音视频(Tencent Real-Time Communication,TRTC)拥有QQ十几年来在音视频技术上的积累,致力于帮助企业快速搭建低成本、高品质音视频通讯能力的完整解决方案。..._腾讯实时音视频 分享链接

随便推点

用c语言写个日历表_农历库c语言-程序员宅基地

文章浏览阅读534次,点赞10次,收藏8次。编写一个完整的日历表需要处理许多细节,包括公历和农历之间的转换、节气、闰年等。运行程序后,会输出指定年份的日历表。注意,这个程序只是一个简单的示例,还有很多可以改进和扩展的地方,例如添加节气、节日等。_农历库c语言

FL Studio21.1.1.3750中文破解百度网盘下载地址含Crack补丁_fl studio 21 注册机-程序员宅基地

文章浏览阅读1w次,点赞28次,收藏27次。FL Studio21.1.1.3750中文破解版是最优秀、最繁荣的数字音频工作站 (DAW) 之一,日新月异。它是一款录音机和编辑器,可让您不惜一切代价制作精美的音乐作品并保存精彩的活动画廊。为方便用户,FL Studio 21提供三种不同的版本——Fruity 版、Producer 版和签名版。所有这些版本都是独一无二的,同样具有竞争力。用户可以根据自己的需要选择其中任何一种。FL Studio21.1.1.3750中文版可以说是一站式综合音乐制作单位,可以让您录制、作曲、混音和编辑音乐。_fl studio 21 注册机

冯.诺伊曼体系结构的计算机工作原理是,冯 诺依曼型计算机的工作原理是什么...-程序员宅基地

文章浏览阅读1.3k次。冯诺依曼计算机工作原理冯 诺依曼计算机工作原理的核心是 和 程序控制世界上不同型号的计算机,就其工作原理而言,一般都是认为冯 诺依曼提出了什么原理冯 诺依曼原理中,计算机硬件系统由那五大部分组成的 急急急急急急急急急急急急急急急急急急急急急急冯诺依曼结构计算机工作原理的核心冯诺依曼结构和现代计算机结构模型 转载重学计算机组成原理 一 冯 诺依曼体系结构从冯.诺依曼的存储程序工作原理及计算机的组成来..._简述冯诺依曼计算机结构及工作原理

四国军棋引擎开发(2)简单的事件驱动模型下棋-程序员宅基地

文章浏览阅读559次。这次在随机乱下的基础上加上了一些简单的处理,如进营、炸棋、吃子等功能,在和敌方棋子产生碰撞之后会获取敌方棋子大小的一些信息,目前采用的是事件驱动模型,当下完一步棋界面返回结果后会判断是否触发了相关事件,有事件发生则处理相关事件,没有事件发生则仍然是随机下棋。1.事件驱动模型首先定义一个各种事件的枚举变量,目前的事件有工兵吃子,摸暗棋,进营,明确吃子,炸棋。定义如下:enum MoveE..._军棋引擎

STL与泛型编程-第一周笔记-Geekband-程序员宅基地

文章浏览阅读85次。1, 模板观念与函数模板简单模板: template< typename T > T Function( T a, T b) {… }类模板: template struct Object{……….}; 函数模板 template< class T> inline T Function( T a, T b){……} 不可以使用不同型别的..._geekband 讲义

vb.net正则表达式html,VB.Net常用的正则表达式(实例)-程序员宅基地

文章浏览阅读158次。"^\d+$"  //非负整数(正整数 + 0)"^[0-9]*[1-9][0-9]*$"  //正整数"^((-\d+)|(0+))$"  //非正整数(负整数 + 0)"^-[0-9]*[1-9][0-9]*$"  //负整数"^-?\d+$"    //整数"^\d+(\.\d+)?$"  //非负浮点数(正浮点数 + 0)"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0..._vb.net 正则表达式 取html中的herf