1.2 ROS学习笔记之主题与订阅器

导览

你将从该单元学到:

什么是ROS主题?如何管理它们?
什么是发布器?如何创建一个发布器?
什么是主题消息?它们是如何工作的?    
什么是订阅器?如何创建一个消息订阅器?
如何创建自己的消息?

keyword:管理主题,创建发布器,主题消息的工作方式,创建消息订阅器,创建自定义信息


课前总结

主题


  • 主题是*ROS节点发布和读取消息的通道*
  • 节点使用主题向其他节点 发布信息,进行通信
  • 节点创建发布器,发布器在某主题上发布消息,消息具有某种结构(称为类型)
  • rostopic info /counter :获取主题的相关信息,包括发布到该主题上的节点,发布到该主题上的消息类型(例如Int32)
  • rostopic list | grep ‘/counter’ :过滤出该主题
  • rostopic echo /counter ,查看主题的实时输出(即正在发布到该主题的消息)
  • rostopic echo -n1 读取发布到主题上的最后一条消息

消息


  • 主题通过消息处理信息,消息有各种类型
  • 消息定义在 .msg 文件中,该文件位于msg目录
  • 获取消息结构(包含哪些变量等) rosmsg show std_msgs/Int32
    • Int32消息来自于功能包 std_msgs,它位于 msg目录中

发布器与订阅器


  • 发布器是实现向某节点发布信息的节点
  • 订阅器是实现从主题读取信息功能的节点
  • rostopic pub 向指定的主题发布具有特定数据类型的消息
  • 创建自定义消息五步走
  • rospy.Publisher(‘/counter’, Int32, queue_size=1)
  • sub = rospy.Subscriber(‘/counter’, Int32, callback)
  • rospy.Publisher(‘counter’, Int32)

发布器

点击IPython notebook右上角的“play”按钮,运行下面的Python代码
通过[CTRL]+[Enter] 快捷键运行

#! /usr/bin/env python

import rospy
from std_msgs.msg import Int32 

rospy.init_node('topic_publisher')
pub = rospy.Publisher('/counter', Int32, queue_size=1)
#创建主题
rate = rospy.Rate(2)
count = Int32()
count.data = 0

while not rospy.is_shutdown(): 
  pub.publish(count)
  #发布整数
  count.data += 1
  rate.sleep()
  • 程序:创建了一个名为/counter 的主题,并通过它发布了一个无限增加的整数

  • 主题就像一个管道。 节点使用主题向其他节点发布信息 ,进行通信

使用rostopic list查看系统中主题的数量。也可以查看某个特定的主题

rostopic list

  • 获取ROS系统中可用的主题列表

  • 查看一个名为 ‘/counter’的主题

    rostopic list | grep ‘/counter’

解释:列出了所有正在运行的主题,并使用grep命令过滤出/counter的那个主题

rostopic info

获取一个主题的信息(理解为结构)

user ~ $ rostopic info /counter
Type: std_msgs/Int32

Publishers:
 * /topic_publisher (http://ip-172-31-16-133:47971/)

Subscribers: None

输出表明,发布信息的类型为(std_msgs/Int32), 发布该信息的节点为 (/topic_publisher),是否有节点在监听该消息(无)

rostopic echo

  • 查看主题的实时输出或称读取一个主题中正在发布的消息

  • 该命令将会输出发布到该主题中的所有消息, 有时这样是很烦人的(例如,当消息很多时,或者消息结构很大时)。在这种情况下,你可以使用下面的命令读取发布到某一主题上的最后一条消息

rostopic echo -n1

code review

#! /usr/bin/env python

import rospy                               # 导入ROS的Python库
from std_msgs.msg import Int32             # 从std_msgs功能包导入Int32消息

rospy.init_node('topic_publisher')         # 初始化一个名为'topic_publisher'的节点
pub = rospy.Publisher('counter', Int32)    # 创建一个发布器对象,将在/count主题上发布类型为Int32的消息


rate = rospy.Rate(2)                       # 设置发布频率为2 Hz
count = Int32()                            # 创建一个类型为Int32的变量,即创建一个消息的实例
count.data = 0                             # 初始化'count' 变量

while not rospy.is_shutdown():             # 创建一个循环,当有人停止程序执行时循环结束
  pub.publish(count)                       # 发布变量 'count'值
  count.data += 1                          # 变量'count' 值增加
  rate.sleep()                             # 确保发布频率维持在2 Hz

总的来说,这段代码 初始化一个节点创建一个发布器,该发布器不停地向’/counter’ 主题发布一连串的连续整数。 因此,发布器是一个不停地向某一主题发布消息的节点。 那么,什么是主题?

主题是一个ROS节点发布和读取消息的通道

主题相关命令

查看 rostopic 命令的不同选项

rostopic -h

消息

主题通过消息处理信息。在ROS中,有许多不同类型的消息。

在前面执行的代码中,消息类型为std_msgs/Int32。除了ROS提供的标准消息,你也可以创建自定义的消息,但我们推荐使用ROS默认的消息类型
消息定义在 .msg 文件中,它位于一个功能包的msg目录中

rosmsg show

获取一个消息的信息(属性)

实例

rosmsg show std_msgs/Int32  #获取std_msgs/Int32消息的信息

#输出结果
user ~ $ rosmsg show std_msgs/Int32
[std_msgs/Int32]:
int32 data

该例中,Int32 消息只有一个类型为int32,名为data的变量。Int32消息来自于功能包 std_msgs,它位于 msg目录中。 如果你想查看Int32.msg文件的内容,执行下面的命令:

roscd std_msgs/msg/

创建自己的发布器使机器人移动

待补

订阅器

  • 主题是节点发布或读取信息的通道。使用发布器向主题发布数据。
  • 发布器实现发布信息
  • 订阅器实现读取信息
    实现从一个主题读取信息的功能的工具叫做订阅器。 订阅器是一个从某一主题读取信息的节点(发布器是向某主题发布信息的节点)
user ~ $ rostopic echo /counter
WARNING: no messages received and simulated time is active.
Is /clock being published?

意味着 没有人向/counter主题发布消息, 因此没有信息可以读取。接下来,让我们向该主题发布一些信息,看看会发生什么。实现该功能需要一个新的命令:

rostopic pub

该命令将向指定的主题发布具有特定数据的特定类型的消息

rostopic pub /counter std_msgs/Int32 5

user ~ $ rostopic echo /counter
WARNING: no messages received and simulated time is active.
Is /clock being published?
data:
5
---

表明你发布的数据已被你的订阅器程序(该数据值打印在屏幕上)接收

#! /usr/bin/env python

import rospy                                          
from std_msgs.msg import Int32 

def callback(msg):                                    # 定义一个名为callback的函数用来接收msg参数

    print msg.data                                    # 输出"msg"参数中的"data"值

rospy.init_node('topic_subscriber')                   # 初始化一个名为'topic_subscriber'的节点

sub = rospy.Subscriber('/counter', Int32, callback)   # 创建一个订阅器对象,监听/counter主题。每当从该主题读取到消息时,调用"callback"函数


rospy.spin()                                          # 创建一个使程序保持运行的循环。
  • 查看运行的代码输出:
    5

创建了一个订阅器对象来监听/counter主题。每当它从该主题读取到消息时,它就调用一个打印msg的函数。刚开始时,由于没有向/counter主题发布消息,所以它什么都没做。当你运行rostopic pub命令后,你向/counter主题发布了一条消息,因此该订阅器在IPython的输出中打印了该消息中的数值,你还可以在 rostopic echo的输出中看到该消息。

创建自定义信息

准备CMakeLists.txt和package.xml 来进行自定义主题和消息的编译

如果我需要发布一些其他类型的数据(非int32),我该使用什么类型的消息? 你可以使用ROS定义的所有消息类型(rosmsg list) 。如果这些消息都不能满足你的需要,你可以自己创建一个新的。

创建步骤

在你的功能包中创建一个名为"msg"的目录
在该目录中,创建一个名为Name_of_your_message.msg的文件(详见下面)
修改 CMakeLists.txt 文件 (详见下面)
修改package.xml 文件 (详见下面)
编译
在程序中使用该消息

S1:

roscd
mkdir msg

S2:

float32 years
float32 months
float32 days

S3:
编辑CMakeLists.txt中的四个函数,如下:

find_package()
add_message_files()
generate_messages()
catkin_package()

  • find_package()

为了编译主题、服务和行为的消息,所有功能包都需要该函数。 在package.xml, 你必须把它们声明为 build_depend

find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
message_generation # 这里添加 message_generation,在其他功能包的后面
)

  • add_message_files()

该函数包含了该功能包所要编译的全部消息(在msg文件夹中)。该文件看起来是这样的:

add_message_files(
FILES
Age.msg
) # 别忘了去掉括号和add_message_files前面的注释符号

  • generate_messages()

导入消息编译需要的功能包

generate_messages(
DEPENDENCIES
std_msgs
) # 别忘了去掉前面的注释

  • catkin_package()

声明所有需要的功能包。 这里声明的所有功能包必须在package.xml设置为run_depend

catkin_package(
CATKIN_DEPENDS rospy message_runtime # This will NOT be the only thing here
)

S4:下方代码添加到package.xml文件
message_generation
message_runtime

S5:
编译该msg文件

roscd; cd ..
catkin_make
source devel/setup.bash

注释:

  • 当你编译新的消息以及使用这些消息之前还有一个额外的步骤。你必须在WebShell中切换到 catkin_ws 目录,然后输入命令 source devel/setup.bash。
  • 该命令运行bash文件,设置创建的新消息
  • source你将使用的ALL the webwhells,以便ROS能够找到该消息
  • 如果不这样做,可能会出现python导入错误,说找不到生成的消息。

避免Python文件和它所在的功能包的名称相同

激光扫描仪的消息结构

user ~ $ rosmsg show sensor_msgs/LaserScan
std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
float32 angle_min
float32 angle_max
float32 angle_increment
float32 time_increment
float32 scan_time
float32 range_min
float32 range_max
float32[] ranges <-- Use only this one
float32[] intensities

避免Python文件和它所在的功能包的名称相同。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值