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'}
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号