ROS入门教程 (写一个简单的消息发布器和订阅器 (Python))

Note: This tutorial assumes that you have completed the previous tutorials: 创建ROS消息和ROS服务.

Description: 本教程将通过Python编写一个发布器节点和订阅器节点。

1. 写发布节点

“节点”是连接到ROS网络的可执行文件的ROS术语。在这里,我们将创建发布者(“talker”)节点,该节点将持续广播消息。

将目录更改为在早期教程中创建的初学者教程包,创建一个包 http://wiki.ros.org/cn/ROS/Tutorials/CreatingPackage

$ roscd beginner_tutorials

1.1 代码

首先,让我们创建一个“scripts”文件夹来存储我们的python脚本:

$ mkdir scripts
$ cd scripts

将示例script talker.py下载到新的脚本目录并使其可执行:

$ wget https://raw.github.com/ros/ros_tutorials/kinetic-devel/rospy_tutorials/001_talker_listener/talker.py
$ chmod +x talker.py

You can view and edit the file with  $ rosed beginner_tutorials talker.py  or just look below.

#!/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

1.2 代码解释

#!/usr/bin/env python

每个python ROS节点的顶部都有这个声明。第一行确保脚本作为Python脚本执行。

import rospy
from std_msgs.msg import String

如果要编写一个ROS节点,则需要导入ROSPY。std-msgs.msg导入是为了让我们可以重用std-msgs/string消息类型(一个简单的字符串容器)进行发布。

pub = rospy.Publisher('chatter', String, queue_size=10)
    rospy.init_node('talker', anonymous=True)

这段代码定义了说话者与其他ROS的接口。pub=rospy.publisher(“chatter”,string,queue_size=10”)声明您的节点正在使用消息类型字符串发布到chatter主题。这里的字符串实际上是std msgs.msg.string类。在ROS hydro中,queue-size参数是新的,它限制了排队消息的数量(如果任何订户没有足够快地接收到这些消息)。在旧的ROS分布中,只需省略这个参数。

下一行,rospy.init_node(name,…)非常重要,因为它告诉rospy您的节点的名称——除非rospy有此信息,否则它无法开始与rospy主机通信。在这种情况下,您的节点将使用名称talker。注意:名称必须是基名称,即不能包含任何斜杠“/”。

anonymous=true通过在名称末尾添加随机数来确保节点具有唯一的名称。有关节点初始化选项的更多信息,请参阅Rospy文档中的初始化和关闭-初始化您的ROS节点。

rate = rospy.Rate(10) # 10hz

此行创建速率对象速率。借助其方法sleep(),它提供了以所需速率循环的方便方法。参数为10时,我们希望每秒通过10次循环(只要我们的处理时间不超过1/10秒!)

while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()
        rospy.loginfo(hello_str)
        pub.publish(hello_str)
        rate.sleep()

这个循环是一个相当标准的rospy构造:检查rospy.is_Shutdown()标志,然后执行工作。您必须检查is_shutdown()以检查程序是否应该退出(例如,如果存在ctrl-c或其他)。在这种情况下,“工作”是对pub.publish(hello_str)的调用,它将字符串发布到Chatter主题。循环调用rate.sleep(),它的睡眠时间刚好足够维持循环中所需的速率。

(您也可以运行rospy.sleep(),它与time.sleep()类似,只是它也可以与模拟时间一起工作(参见时钟)。

这个循环还调用rospy.loginfo(str),它执行三重任务:消息被打印到屏幕上,它被写入节点的日志文件,然后被写入rosout。Rosout对于调试是很方便的:您可以使用RQT控制台调出消息,而不必查找带有节点输出的控制台窗口。

std msgs.msg.string是一种非常简单的消息类型,因此您可能想知道发布更复杂的类型是什么样子的。一般的经验法则是,构造函数参数的顺序与.msg文件中的顺序相同。您还可以不传入任何参数并直接初始化字段,例如

msg = String()
msg.data = str

或者,您可以初始化某些字段并将其余字段保留为默认值:

String(data=str)

你可能想知道最后一点:

try:
        talker()
    except rospy.ROSInterruptException:
        pass

除了标准的 Python __main__ check 检查之外,这还会捕获一个rospy.ROSInterruptException 异常,当按下ctrl-c或关闭节点时,rospy.sleep()和rospy.rate.sleep()方法会抛出异常。引发此异常的原因是,您不会在sleep()之后意外地继续执行代码。

现在我们需要编写一个节点来接收消息。

2. 写入订阅服务器节点

2.1 代码

将listener.py文件下载到脚本目录中:

$ 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
    # name 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()

别忘了要让节点executable:

$ chmod +x listener.py

2.2 代码解释

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()

这声明您的节点订阅了类型为std_msgs.msgs.string的chatter主题。当接收到新消息时,将使用消息作为第一个参数调用回调。

我们还稍微改变了对rospy.init_node()的调用。我们添加了anonymous=true关键字参数。ROS要求每个节点都有一个唯一的名称。如果出现同名节点,它将与前一个节点发生碰撞。这样就可以很容易地将出现故障的节点从网络中踢出。anonymous=true标志告诉rospy为节点生成一个唯一的名称,这样您就可以轻松地运行多个listener.py节点。

最后一个添加是rospy.spin(),它只是在关闭节点之前阻止您的节点退出。与roscpp不同,rospy.spin()不会影响订户回调函数,因为它们有自己的线程。

3. 构建你的节点

我们使用cmake作为构建系统,是的,您甚至必须将其用于Python节点。这是为了确保为消息和服务创建了自动生成的python代码。

Go to your catkin workspace and run catkin_make:

$ cd ~/catkin_ws
$ catkin_make

既然你写完了一个简单的消息发布器和订阅器,让我们来测试消息发布器和订阅器.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值