1. 话题 topic & 消息 message

参考:Understanding ROS Topics
ROS/Tutorials/ Writing a Simple Publisher and Subscriber (Python)

topic 实现了一种 发布/订阅(publish/subscribe)通信机制,这是一种在分布式系统中常用的数据交换方式。对于实时性、周期性的消息,使用topic来传输是最佳的选择。节点在发送数据到话题上之前,必须先声明(advertise)话题名和发布到该话题上的消息所具有的类型,然后就可以开始发布数据到这个话题上了。想要从话题上接收信息的节点可以通过向 ros Master 发出请求来订阅这个话题。订阅之后,该话题上的所有消息都会被转发到发出订阅请求的节点上。

一个节点可以订阅或发布多个话题,而不需要去了解另一个节点的具体细节。这种机制提供了一种方便的进程间通信方式,有效实现了不同功能节点之间的解耦。

消息是一种数据结构,支持多种数据类型(整形、浮点、布尔型、数组等),同时也支持消息的嵌套定义。ROS提供了大量的系统默认消息供用户使用,如geometry_msgs、sensor_msgs等,同时也支持用户定义专属数据结构的消息类型。

Communication on topics happens by sending ROS messages between nodes. For the publisher and subscriber to communicate, the publisher and subscriber must send and receive the same type of message. This means that a topic type is defined by the message type published on it.

话题就像一块黑板,publishers 将 message 写到黑板上,subscribers 就可以接收到黑板上的内容了。message 则规定了写到黑板上的内容的格式。

topic通信机制建立过程如下:

  1. Publisher 和 Subscriber 在节点管理器ROS Master 注册
    在系统中,节点与节点是没有任何关系的,都靠节点管理器来处理相关的请求与服务。publisher 节点需要向节点管理器ROS Master注册相关信息,包括节点的信息、需要发布的话题名等,然后节点管理器会记录下来相应的节点信息。同理 Subscriber 也需要向节点管理器ROS Master注册相关信息,这其实是启动两个节点时候就已经做了的事情。

  2. ROS Master 进行话题匹配
    因为 Publisher 与 Subscriber 节点都在 ROS Master 注册了信息,那么 ROS Master 就会发现二者有相同的话题信息,此时它就会向 Subscriber 发送 Publisher 节点的RPC地址信息,将订阅与发布话题的两个节点匹配在一起。

  3. Subscriber 向 Publisher 发送连接请求
    Subscriber 知道 Publisher 后,就会通过 RPC 主动向 Publisher 发送连接请求,传输订阅的话题名、消息类型以及通信协议。

  4. Publisher 确认连接请求
    Publisher 接收到 Subscriber 的连接请求后,继续通过RPC向 Subscriber 确认连接信息,同时发送自身相关的信息。

  5. Subscriber 尝试与 Publisher 建立网络连接
    Subscriber 接收到确认信息后,使用TCP尝试与 Publisher 建立网络连接。

  6. Publisher 向 Subscriber 发布消息
    成功建立连接后,Publisher开始向 Subscriber 发送话题消息数据。

在节点与节点建立连接前,他们的通信协议都是RPC,而这主要都是依赖于节点管理器的,在节点与节点建立连接后,就直接是使用TCP协议进行数据传输,而不需要依赖节点管理器,此时节点管理器允许被关闭,但在关闭后,其他节点就不能订阅、发布这个话题消息了。总之节点管理器ROS Master在节点建立连接的过程中起到了重要作用,但是并不参与节点之间最终的数据传输。
参考:深入了解ROS话题通信机制的过程

2. 编写一个 Publiser Node (python)

首先要在工作空间创建一个package:

cd ~/catkin_ws/src/
catkin_create_pkg topic_tutorials std_msgs rospy  # std_msgs rospy 是依赖项

例程 talker.py :创建一个 Publisher 节点 talker,持续向chatter 话题广播一条 message。

  1. 在 package 中创建一个 scripts 文件夹,来存放 python 脚本文件。
  2. 编写 talker.py
#!/usr/bin/env python
# -*- coding: utf-8
import rospy
from std_msgs.msg import String  def talker():# ros 节点初始化,节点名为'talker'。# ros 中要求节点名是唯一的,如果启动了两个同名的 node,前一个 node 会被剔除。# anonymous=True 表示让 rospy 给该节点一个唯一的标记名,以确保不被新启动的 talker 节点剔除。rospy.init_node('talker', anonymous=True)# 创建一个Publisher。发布名为 `chatter` 的 topic。消息类型为 String (实际为std_msgs.msg.String),# 队列长度为 10. 如果订阅者没有快速接收已经排队的消息,为维持队列长度,前期进入队列的消息会被舍弃。pub = rospy.Publisher('chatter', String, queue_size=10)# 设置循环的频率rate = rospy.Rate(10) # 10hzwhile not rospy.is_shutdown():hello_str = "hello world %s" % rospy.get_time()rospy.loginfo(hello_str)# 在话题上发布消息pub.publish(hello_str)# 按照循环频率延时rate.sleep()if __name__ == '__main__':  try:talker()except rospy.ROSInterruptException:pass

脚本注释:
第一行: #!/usr/bin/env python ,这就是所谓的 shebang,每个 Python ROS 节点的顶部都会有此声明。 告诉操作系统这是一个 python 文件,应该传递给一个 python 解释器。
第二行:# -*- coding: utf-8,防止因代码中出现中文注释而报错 SyntaxError: Non-ASCII character ‘\xe2’ in file。

  1. 配置 CMakeLists.txt的编译规则。确保安装了正确的 python 脚本,并且使用了正确的 python 解释器。
catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.pyDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

上述程序顺便添加了订阅者节点程序 scripts/listener.py。

  1. 在 package.xml 添加依赖。下述语句在功能包创建时已经自动添加。
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend><build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend><exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>

by the way,上述语句相当于:

<depend>rospy</depend><depend>std_msg</depend>
  1. 编译功能包:
cd ~/catkin_ws
catkin_make
  1. 运行 Publisher 节点。注意:如果你手写了这个节点文件,运行这个文件前需要在终端使用chmod 命令给他增加运行权限:chmod +x talker.py
roscore
# new terminal
rosrun topic_tutorials talker.py
rostopic -h # 查看 rostopic 指令的帮助信息
rostopic list  # 查看系统中有哪些可用话题
rostopic echo topic_name -n 5 # 查看话题上发布的消息, -n 5 表示只打印 5 条消息。
rostopic hz topic_name # 查看发布频率
rostopic info topic_name # 查看 topic 的属性信息

也可以使用命令行工具发布消息到一个话题上:

rostopic pub topic_name topic_type message

rosrun rqt_plot rqt_plot 绘制 topic 消息曲线。

3. 编写一个 Subscriber Node (python)

订阅者使用回调函数 (callback) 处理接收到的消息。一旦一个节点订阅了一个话题,每次消息到达时,相应的回调函数就会被调用,并使用接收到的消息作为它的参数。

例程 listener.py:创建一个 listener 节点 订阅 chatter话题。

#!/usr/bin/env python
# -*- coding: utf-8
import rospy
from std_msgs.msg import Stringdef my_callback(data):rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)def listener():rospy.init_node('listener', anonymous=True)# 创建一个 Subscriber,订阅 ”chatter“ 话题,消息类型为 String,回调函数为 my_callback。# 在幕后,Subscriber 会将这些信息传递给节点管理器,并尝试与 Publisher 建立连接。# 如果订阅的话题不存在,或者存在类型错误,将不会输出任何报错信息,节点将只是等待。rospy.Subscriber("chatter", String, my_callback)# spin() simply keeps python from exiting until this node is stopped# 循环等待会话题消息,若接收到消息进入 callback 回调函数rospy.spin()if __name__ == '__main__':listener()

增加运行权限:chmod +x listener.py。运行 listener.py 文件

rosrun topic_tutorials listener.py

4. 消息的定义与使用

ROS 的 std_msgscommon_msgs 包提供了丰富的内建消息类型,在std_msgs中定义了一些基本的类型,在 ros wiki msg 页面有详细文档。其他消息类型都是由这些基本类型构成的。有时候内建消息类型不够用,我们也可以定义自己的消息类型。

ros 消息由每个 ros 包的 msg 目录中的消息定义文件说明。这些文件将会编译成与语言相关的消息文件,这样你就能在代码中使用了。这意味着 如果你定义了自己的消息类型,即使你使用的是解释型语言,如 python,你仍然需要运行 catkin_make,否则 python 将无法找到你定义的消息类型。

4.1 定义一个自己的消息类型

消息定义文件通常放在功能包的 msg 文件夹下,后缀名为.msg。消息定义文件包含一系列构成此消息的类型,这些类型可以是 ros 内建的消息类型也可以是自定义的消息类型。

自定义话题消息的主要流程:

  1. msg文件中定义好数据类型;
  2. 在package.xml中添加功能包依赖;
  3. 在CMakeLists.txt添加编译选项;
  4. catkin_make编译即可使用。

例如:定义一个描述个人信息的消息类型:

  1. 在功能包的文件夹下创建一个 Person.msg 文件(通常 ROS 消息名称都是首字母大写且没有下划线的):
string name
uint8  age
uint8  sexuint8 unknown = 0
uint8 male    = 1
uint8 female  = 2
  1. 在package.xml中添加两个依赖:编译依赖和执行依赖。确保告知构建系统新消息的定义。
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
  1. 在 CMakeLists.txt 文件中添加编译选项。
    1)在find_package()末尾添加message_generation,这样 catkin 就知道去找寻message_generation 包了。
    2)告知 catkin 我们将在运行时使用消息,即在catkin_package()调用末尾添加 message_runtime
    3)在add_message_files()末尾添加消息定义文件,来告知catkin 我们想要编译的消息。
    4)确保generate_messages()包含了消息所依赖的所有依赖项。
find_package(catkin REQUIRED COMPONENTSroscpprospystd_msgsmessage_generation  # add message_generation here
)
...
catkin_packages(CATKIN_DEPENDS message_runtime # this will not be the only thing here
...
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
  1. 到 catkin 工作空间的根目录,运行 catkin_make。这将产生一个和消息定义文件同名的消息类型。
    在工作空间 devel/include 文件夹中有了一个Person.h的头文件。

4.2使用自定义的消息类型

C++

include ”package_name/Person.h“

Python

from package_name.msg import Person

5. 让话题发布者与订阅者协同工作

一个节点也可以同时是发布者和订阅者。或同时拥有多个订阅和发布。实际上ros节点最常做的事情技术就是传递消息,并在消息上进行运算。例如,一个节点可能会订阅一个摄像机图像的话题,检测其中的人脸后在另一个节点上发布人脸的位置。
例程:接收到一个数字后,将数字翻倍,然后发布出去。

#!/usr/bin/env python
import rospy
from std_msg.msg import Int32rospy.init_node('doubler')def callback(msg):doubled = Init32()doubled.data = msg.data * 2pub.publisth(doubled)sub = rospy.Subscriber('number',Int32,callback)
pub = rospy.Publisher('doubled',Int32)rospy.spin()

ROS学习笔记(三)—— 话题 topic详解相关推荐

  1. [读书笔记]C#学习笔记三: C#类型详解..

    前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...

  2. Arduino学习笔记三之函数详解及使用范例

    输入输出函数 pinMode(pin, mode) 将数位脚位(digital pin)指定为输入或输出. 范例 :pinMode(7,INPUT); // 将脚位 7 设定为输入模式 digital ...

  3. java 检查bytebuf长度_Java学习笔记16-Netty缓冲区ByteBuf详解

    Java学习笔记16-Netty缓冲区ByteBuf详解 Netty自己的ByteBuf ByteBuf是为解决ByteBuffer的问题和满足网络应用程序开发人员的日常需求而设计的. JDK Byt ...

  4. spring学习笔记03-spring-DI-依赖注入详解(通过xml配置文件来配置依赖注入)

    spring学习笔记03-spring-DI-依赖注入详解 1.概念 2.构造函数注入 3.set方法注入 4.集合的注入 需要被注入的实体对象 package com.itheima.service ...

  5. 【学习笔记】线段树详解(全)

    [学习笔记]线段树详解(全) 和三个同学一起搞了接近两个月的线段树,头都要炸了T_T,趁心态尚未凉之前赶快把东西记下来... [目录] [基础]作者:\((Silent\)_\(EAG)\) [懒标记 ...

  6. [原创]Saltstack学习笔记:命令参数详解以及配置文件说明

    很久没有更新saltstack的文章了,今天还是来更新一点,又开始对saltstack复习了一下. 前边写了一点<saltstack入门概述(1)>以及<Saltstack如何安装( ...

  7. Laravel学习笔记汇总——Collection方法详解

    ## Laravel学习笔记汇总--Collection方法详解 本文参考:https:// laravel.com/docs/8.x/collections // 返回整个底层的数组 collect ...

  8. ROS学习笔记三:创建ROS软件包

    ,# ROS学习笔记三:创建ROS软件包 catkin软件包的组成 一个软件包必须满足如下条件才能被称之为catkin软件包: 这个软件包必须包含一个catkin编译文件package.xml(man ...

  9. Mybatis源码学习(三)SqlSession详解

    前言 上一章节我们学习了SqlSessionFactory的源码,SqlSessionFactory中的方法都是围绕着SqlSession来的.,那么SqlSession又是什么东东呢?这一章节我们就 ...

  10. Android学习笔记——Android 签名机制详解

    Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...

最新文章

  1. 利用 JQuery的load函数动态加载页面
  2. 华为推CPU Turbo,荣耀Note10突破3000档
  3. 数字图像处理5:几何变换
  4. 互联网大厂高频重点面试题
  5. Qt使用信号与槽时出现的错误“Incompatible sender/receiver arguments”
  6. AndroidOkhttp3上传单个文件
  7. unicode字符大全可复制_说说Excel不可见字符的那些事
  8. 【追一科技】NLG技术:文本生成技术多样化应用的探索之路
  9. smarty3.1.30 模板引擎的使用
  10. 12-【istio】-【流量管理】-【流量管理原理】istio Sidecar的两种注入方式、注入原理
  11. 【MATLAB笔记】对矩阵进行满秩分解
  12. 跨年巨作 13万字 腾讯高工手写JDK源码笔记 带你飙向实战
  13. 易飞8无销售报价的BOM成本参考
  14. IDEA 2018.3.6 修改背景图片
  15. CAD制图怎么使用CAD修剪命令呢?
  16. 黄油安卓_寻找可爱,定义外观为黄油皇家字符
  17. LED驱动器满足功率、空间和成本挑战
  18. 采集快手APP的10个经典方法
  19. wss数据的获取与请求
  20. 想做APP 改版练习,这儿有高手的15个经验总结

热门文章

  1. 微信会员卡跳转小程序实现
  2. linux的webui服务,Aria2控制前端WebUI客户端安装教程
  3. 计算机创造奇迹的英语作文,大学英语作文:创造奇迹-Creating-Miracle.docx
  4. 【2015DTCC】专访永洪科技CEO:商业智能搬运大数据之谜
  5. 抑制广播风暴 各种发包
  6. 定时任务实现方式对比
  7. 三国志战略版:Daniel_兵无常势分析
  8. android恢复短信中心号码,短信中心号码设置解决安卓手机不能发短信问题,教你设置解决异地发不了短信问题...
  9. 算法注册机编写扫盲之续篇--第一课
  10. oracle官网(中文)