< >
Home » ROS与Python入门教程 » ROS与Python入门教程-深入发布和订阅

ROS与Python入门教程-深入发布和订阅

ROS与Python入门教程-深入发布和订阅

说明

  • 本节深入介绍发布和订阅及相关参数

发布主题

发布主题的常见方式:

pub = rospy.Publisher('topic_name', std_msgs.msg.String, queue_size=10)
pub.publish(std_msgs.msg.String("foo"))
  • 通过rospy.Publisher类构建对象
  • 通过publish类函数发布主题

rospy.Publisher类定义:

rospy.Publisher(topic_name, msg_class, queue_size)
  • topic_name, msg_class, queue_size是必需的
  • queue_size是Hydro之后的版本才有效

配置Publisher的高级选项:

  • subscriber_listener=rospy.SubscribeListener
    • 通过rospy.subscribelistener实例时,新用户连接和断开接收回调。
  • tcp_nodelay=False
    • 激活TCP_NODELAY,在TCPROS链接里会禁用Nagle algorithm
    • This results in lower latency publishing at the cost of efficiency.
  • latch=False
    • 激活锁定链接,但链接锁定,最后的信息就会保存和发布到未来链接的订阅器。
    • 对于改变少的数据或静态地图数据有用。
  • headers=None (dict)
    • 增加额外的key-value对
  • queue_size=None (int)
    • Hydro版本新添加
    • 异步发布时候的信息队列的信息数目。
    • 在后面的如何选择queue_size有详细介绍

Publisher.publish()函数

  • 三种提供Message实例的方法:
    • 明确方式:
pub.publish(std_msgs.msg.String("hello world"))
  • 有序参数的隐式风格:
    • 例如:std_msgs.msg.String,只有String字段,你可以调用
pub.publish("hello world")
  • 例如:std_msgs.msg.ColorRGBA 4个字段 (r, g, b, a),你可以调用
pub.publish(255.0, 255.0, 255.0, 128.0)
  • 带有关键字参数的隐式风格:
    • 提供关键词和值,其他关键词使用默认值。
    • 例如:std_msgs.msg.String,只有data关键词
pub.publish(data="hello world")
  • 例如:std_msgs.msg.ColorRGBA 4个字段 (r, g, b, a),你可以调用
pub.publish(b=255)

publish() behavior and queuing 发布行为和排队

  • 发布默认采用同步方式(向后兼容的原因)
  • 这意味在下面两步处理前,调用会出现阻塞
    • 消息已经序列化到缓存里
    • 缓存数据已经传输到目前所有的订阅器
  • 如果出现连通性问题会导致无法确定的阻塞问题。
  • 从Hydro开始,推荐使用异步发布行为,这更像roscpp的发布行为。
  • 使用异步,需要传递关键词参数queue_size到subscribe()函数,它定义队列最大消息数目。
  • 当pubulish调用,进行序列化到缓存是同步发生,缓存信息传送到不同线程的订阅器是异步发生。订阅器有连通性问题,也还是会收不到信息。
  • 如果发布频率比发送速率快太多,rospy就会丢弃旧的信息。
  • 注意,也有可能是一个操作系统级别的队列在传输层,如TCP/UDP发送缓冲区。

选择合适的队列数目

  • 很难提供一个通用法则,因为它取决于你的系统的许多变量。
  • 如果以固定速率发送信息,可以使用小的发布频率。
  • 如果你在一个突发发送多个消息,你应该确保队列的大小是足够大,以包含所有这些消息。否则很可能会丢失消息。
  • 一般来说,使用一个更大的queue_size会更多的内存,实际处理,建议选择比它需要更大点的值。
  • 如果队列太大,排队的消息太多,会导致订阅器收到信息很慢。因为队列采用先进先出机制。
  • queue_size省略:会传入none。对于Groovy之前版本就是同步处理,对于Indigo版本会在终端打印警告信息。
  • queue_size设置None:不推荐,发布同步处理,如果一个订阅阻塞会导致所有的发布阻塞。对于Indigo版本会在终端打印警告信息。
  • queue_size设置One, Two, Three:如果您的系统没有超载,你可以说,一个队列的消息应该由调度线程在十分之一秒进行处理。因此,使用10赫兹速度发送的话,设置为3/2/1的队列大小是很合适的。
  • queue_size设置One,对于有了新信息就不发送旧信息的地方是合适的。比如传感器的数据,通常希望得到都是最新的。
  • queue_size设置10或大于10:一个例子,使用一个大的队列的大小,如10或更高,是用户界面的信息(例如digital_io,按钮状态),会从一个更大的queue_size利于防止遗漏值的改变。另一个例子是当您想记录所有已发布的值,包括在发布高速率/小队列大小时将被删除的值。

发布的代码例子

import rospy
from std_msgs.msg import String

pub = rospy.Publisher('topic_name', String, queue_size=10)
rospy.init_node('node_name')
r = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
   pub.publish("hello world")
   r.sleep()

订阅的代码例子:

import rospy
from std_msgs.msg import String

def callback(data):
    rospy.loginfo("I heard %s",data.data)
    
def listener():
    rospy.init_node('node_name')
    rospy.Subscriber("chatter", String, callback)
    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

连接信息

  • 订阅器可以访问"connection header(连接的头信息)",它包含调试信息,如谁发送的信息或信息是否被锁定。
  • 连接信息保存在_connection_header变量。
  • 例如:
$ print m._connection_header
{'callerid': '/talker_38321_1284999593611',
 'latching': '0',
 'md5sum': '992ce8a1687cec8c8bd883ec73ca41d1',
 'message_definition': 'string data\n\n',
 'topic': '/chatter',
 'type': 'std_msgs/String'}

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

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


标签: ros与python入门教程