ROS入门教程-1.1.12 编写简单的消息发布器和订阅器 (Python catkin)
ROS入门教程-编写简单的消息发布器和订阅器 (Python catkin)
说明:
- 本教程将通过Python编写一个发布器节点和订阅器节点。
目录
- 编写发布节点
- 代码
- 解释
- 编写订阅节点
- 代码
- 解释
- 构建节点
编写发布节点
- “节点”是ROS术语,它连接到ROS网络的可执行文件。在这里,我们将创建发布器("talker")节点不断广播消息。
- 进入之前创建的beginner_tutorials包
$ roscd beginner_tutorials
代码
- 首先创建scripts目录存放Python代码:
$ mkdir scripts
$ cd scripts
- 下载例子脚本talker.py到scripts目录,并修改权限为可执行:
$ wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/talker.py
$ chmod +x talker.py
- 浏览和编辑:
$ rosed beginner_tutorials talker.py
- 内容如下:
#!/usr/bin/env python
# license removed for brevity
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while 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
- 每个Python的ROS节点会在顶部描述,第一行确保你的脚本是使用Python执行的脚本
import rospy
from std_msgs.msg import String
- 你需要导入rospy客户端库
- 导入std_msgs.msg 重用std_msgs/String消息类型
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
- 定义talker接口,pub = rospy.Publisher("chatter", String, queue_size=10)表示节点发布chatter话题,使用String字符类型,实际上就是类std_msgs.msg.String。queue_size表示队列的大小(适合hydro以后版本),如果队列消息处理不够快,就会丢弃旧的消息。
- rospy.init_node(NAME),初始化节点,开始跟ROS master通讯。
- 注意:保持节点名称在网络中是唯一的,不能包含斜杠"/"。
rate = rospy.Rate(10) # 10hz
- 创建Rate对象,与sleep()函数结合使用,控制话题消息的发布频率。
- 10hz表示每秒发布10次。
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
- loop 是rospy的标准结构,检查rospy.is_shutdown()标识没返回值就会一直运行。
- rospy.is_shutdown()返回false就会退出(例如按下Ctrl-C)
- 程序执行pub.publish(String(str)),在chatter话题发布String消息
- r.sleep()通过睡眠来,保持消息发送频率
- 你可以运行 rospy.sleep(),类似time.sleep()
- rospy.loginfo(str)函数在屏幕输出调试信息,同时写入到节点日志文件和rosout节点
- rosout节点对于调式来说是便利的方式。
- 可以通过rqt_console查看调式信息。
- std_msgs.msg.string是一个非常简单的消息类型,所以你可能想知道它看起来像发布更复杂的类型。
- 一般的规则是,构造函数的参数是在.msg文件有相同的顺序。
- 您也可以传递没有参数和直接初始化字段,例如:
msg = String()
msg.data = str
- 或者你能初始化某些字段,剩余保持默认值:
String(data=str)
- 你可能想知道最后的小段代码:
try:
talker()
except rospy.ROSInterruptException:
pass
- 标准的Python main检查,这个会捕获rospy.ROSInterruptException异常,当按下Ctrl-C或节点关闭的话,即使在rospy.sleep()和rospy.Rate.sleep()函数里都会抛出异常。
编写订阅节点
代码
- 下载listener.py到scripts目录
$ roscd beginner_tutorials/scripts/
$ wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/listener.py
- 文件内容如下:
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def callback(data):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
def listener():
# In ROS, nodes are uniquely named. If two nodes with the same
# node are launched, the previous one is kicked off. The
# anonymous=True flag means that rospy will choose a unique
# name for our 'listener' node so that multiple listeners can
# run simultaneously.
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
listener()
- 不要忘记增加可执行权限:
$ chmod +x listener.py
代码解释
- listener.py的代码类似talker.py,除了新增加的函数回调机制。
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("chatter", String, callback)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
这表示节点订阅话题chatter,消息类型是 std_msgs.msgs.String
当接受到新消息,回调函数就触发处理这些信息,并把消息作为第一个参数传递到函数里
还改变了调用rospy.init_node() ,增加anonymous=True关键词参数。
ROS要求每个节点要有唯一名称,如果相同的名称,就会中止之前同名的节点。
anonymous=True标识就会告诉rospy,要生成一个唯一的节点名称,因此你可以有多个listener.py同时运行。
最后rospy.spin()简单保持你的节点一直运行,直到程序关闭。
不像roscpp,rospy.spin()不影响到订阅的回调函数,因为他们有自己的独立线程。
构建节点
- 我们使用CMake作为构建系统,即使是Python节点也需要使用。
- 这确保针对消息和服务能自动生成Python代码
- 进入catkin工作空间,运行catkin_make:
$ cd ~/catkin_ws
$ catkin_make
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号