< >
Home » ROS入门教程 » ROS入门教程-1.1.12 编写简单的消息发布器和订阅器 (Python catkin)

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()函数里都会抛出异常。

编写订阅节点

代码

$ 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

纠错,疑问,交流: 请进入讨论区点击加入Q群

获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号


标签: ros入门教程, ros python