熊猫阿宝

中级会员
  • 主题:19
  • 回复:49
  • 金钱:317
  • 积分:376
ROS学习----Python下的消息发布器和订阅器

1.1编写发布节点
“Node”(节点)是ROS术语,表示被连接到ROS网络的可执行文件。在这里,我们将创建发布者("talker")节点,这将持续的广播一个消息。
目录更改为beginner_tutorials包,你在前面的教程中创建一个package(包):
  1. $ roscd beginner_tutorials
复制代码
1.1.1 代码
首先让我们创建一个“脚本”文件夹来存储我们的Python脚本:
  1. $ mkdir scripts
  2. $ cd scripts
复制代码
那么示例脚本下载talker.py到新的脚本,目录,使其可执行:
$ wget https://raw.github.com/ros/ros_t ... _listener/talker.py$ chmod +x talker.py
您可以查看和编辑文件 $ rosed beginner_tutorials talker.py 或者看下面。

  1. 切换行号显示
  2.     #!/usr/bin/env python
  3.     # license removed for brevity
  4.     import rospy
  5.     from std_msgs.msg import String
  6.    
  7.     def talker():
  8.     pub = rospy.Publisher('chatter', String, queue_size=10)
  9.     rospy.init_node('talker', anonymous=True)
  10.     rate = rospy.Rate(10) # 10hz
  11.     while not rospy.is_shutdown():
  12.     hello_str = "hello world %s" % rospy.get_time()
  13.     rospy.loginfo(hello_str)
  14.     pub.publish(hello_str)
  15.     rate.sleep()
  16.    
  17.    if __name__ == '__main__':
  18.    try:
  19.       talker()
  20.       except rospy.ROSInterruptException:
  21.       pass
复制代码
1.1.2 代码解释
现在,让我们来解释代码。
  1.    #!/usr/bin/env python
复制代码
每个Python ROS 节点都会有这样的声明在顶部。确保放置在你的的Python脚本的第一行。
  1.    import rospy
  2.    from std_msgs.msg import String
复制代码
如果你正在写一个ROS 节点,需要导入rospy。该std_msgs.msg导入,使我们可以重新使用std_msgs /String消息类型(一个简单的字符串容器)进行发布。
  1.      pub = rospy.Publisher('chatter', String, queue_size=10)
  2.    rospy.init_node('talker', anonymous=True)
复制代码
这部分的代码定义了话题的到ROS的接口。
pub = rospy.Publisher("chatter", String, queue_size=10)声明你的节点发布到话题使用消息类型是String。String这里实际上是std_msgs.msg.String类。该queue_size参数是在新的ROS hydro中, 若subscriber (订阅者)接收并不是足够的快的情况下 ,限制队列消息的数量。在旧的ROS发行只是省略该参数。
下一行,rospy.init_node(NAME) ,是非常重要的,因为它会告诉rospy节点的名称—直到rospy有这方面的信息,就不能开始与ROS Master(ROS控制器)通信。在这种情况下,您的节点将命名为talker. 。注:该名称必须是一个基本名称,即它不能包含任何斜杠“/” 。
  1.   rate = rospy.Rate(10) # 10hz
复制代码
该行创建了一个Rate的对象。其为了方便实现sleep()方法,它提供了一个便捷的途径在所需的速度下循环。随着它的参数10,我们应该预料到每秒10次经过一个循环(只要我们处理时间不超过0.1s!)
  1. while not rospy.is_shutdown():
复制代码
这个循环是一个很标准的rospy结构:检查rospy.is_shutdown()标志位,然后进入while循环。你必须察看is_shutdown()来检查你的程序应该退出(例如,如果有一个按Ctrl-C或其他方式)。在这种情况下,“work”是一个调用pub.publish(String(STR))用新创建的主题字符串消息发布给我们的话题。循环调用r.sleep() ,其中休眠刚刚长到足以保持通过循环所需的速率。
(读者还可以通过运行rospy.sleep() ,其类似于time.sleep(),其不同之处在于它与模拟时间的工程,以及(详见时钟)。)
这个循环还呼吁rospy.loginfo(str),它有三个用途:将信息输出到屏幕上,用于写入该节点的日志文件,用于写入rosoutrosout是一个方便的调试:你可以使用rqt_console获得消息而不必找到与您节点的输出控制台窗口。
std_msgs.msg.String是一个非常简单的消息类型,所以你可能想知道它发布更为复杂的类型是什么样的。一般的经验规律是,构造函数的args是和.msg文件一样的规律。您也可以尝试在没有参数的情况下直接初始化,如


  1. msg = String()
  2. msg.data = str
复制代码
或者你可以初始化一些字段并保留其默认值:
  1. String(data=str)
复制代码
你可能想知道最后的一点:
  1.      try:
  2. talker()
复制代码
除了​​标准的 Python __main__ check之外,还将获得一个rospy.ROSInterruptException,当按下Ctrl-C键被按下或当节点关闭时,可以通过rospy.sleep()和rospy.Rate.sleep()方法关闭节点。这引发异常的原因是为了在执行代码 sleep() 后继续执行。
现在,我们需要编写一个节点接收的消息。

1.2编写用户节点
1.2.1 代码
下载listener.py文件到您的scripts目录:

  1. $ roscd beginner_tutorials/scripts/
  2. $ wget https://raw.github.com/ros/ros_tutorials/indigo-devel/rospy_tutorials/001_talker_listener/listener.py
复制代码
该文件的内容看起来接近:
  1. #!/usr/bin/env python
  2.    import rospy
  3.    from std_msgs.msg import String

  4.    def callback(data):
  5.        rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
  6.       
  7.    def listener():
  8.    
  9.      # In ROS, nodes are uniquely named. If two nodes with the same
  10.       # node are launched, the previous one is kicked off. The
  11.       # anonymous=True flag means that rospy will choose a unique
  12.      # name for our 'listener' node so that multiple listeners can
  13.      # run simultaneously.
  14.       rospy.init_node('listener', anonymous=True)

  15.      rospy.Subscriber("chatter", String, callback)
  16.   
  17.       # spin() simply keeps python from exiting until this node is stopped
  18.       rospy.spin()
  19.   
  20.   if __name__ == '__main__':
  21.       listener()
复制代码
不要忘了让该节点生成可执行文件:
$ chmod +x listener.py
1.2.2代码解释
对于代码listener.py类似于talker.py,但我们用到了一个新的基于回调机制订阅消息。

  1.      rospy.init_node('listener', anonymous=True)

  2.     rospy.Subscriber("chatter", String, callback)

  3.     # spin() simply keeps python from exiting until this node is stopped
  4.    rospy.spin()
复制代码
这个声明,您的节点订阅了话题是std_msgs.msgs.String类型。当接收到消息时,回调被调用,其消息作为第一个参数。
我们还改变了调用rospy.init_node()。我们已经添加了anonymous=Tru关键字参数。ROS要求每个节点具有唯一的名称。如果具有相同名称的节点出现,它对覆盖前一个。这是这样,发生故障的节点可以很容易地被移出网络。anonymous=True标志告诉rospy生成一个唯一的节点名称,以便您可以有多个listener.py节点运行。
最后此外,rospy.spin()只是保持你的节点退出,从直到节点已关闭。不像roscpp,rospy.spin()不影响该用户回调函数,有自己的线程。

1.3构建节点
我们使用CMake的为我们的编译系统,是的,你必须使用它甚至对Python的节点。这是为了确保这段自动生成的Python代码用于创建消息和服务的。
转到您的工作空间catkin和运行catkin_make:
  1. $ cd ~/catkin_ws
  2. $ catkin_make
复制代码
现在,你已经写了一个简单的消息发布器和订阅器,让我们来看看简单的消息发布器和和订阅器


注:翻译自维基百科