ROS话题queue_size的含义与设置技巧

ROS1中发布和订阅话题时,都需要设置queue_size,参考:

roscpp/Overview/Publishers and Subscribers - ROS Wiki

rospy/Overview/Publishers and Subscribers - ROS Wiki

1. 发布话题

# roscpp
ros::Publisher publisher = nh.advertise<std_msgs::String>("topic_name", 10)
# rospy
pub = rospy.Publisher('topic_name', std_msgs.msg.String, queue_size=10)

以上publisher中的10就是queue_size,大小并不太重要,一般设置为超过1就行。

roscpp的publish()是异步的(不阻塞),rospy中的publish()在指定了queue_size后也是异步的(否则默认是同步的)。这意味着publish(msg)并不会阻塞程序。

需要发布的消息msg被publish(msg)后,需要经过序列化(serialize)存入缓冲区(queue),然后缓冲区的消息依次发送。异步模式下,当你“publish消息的速度/频率”比“序列化和发送消息的速度/频率”更快时,缓冲区就会逐渐被填满达到queue_size,然后旧的消息就会被丢弃。这会导致实际发送的消息并不是最新的,而是积压了一个queue之前的。

但事实上,一般话题消息序列化和本地TCP发送所需的时间很短,你publish消息的频率很难超过序列化和发送的处理能力,因此queue_size设置为大概10就行。

如果话题消息内容很大,比如是图像或者点云,那么为了保证发布和订阅的实时性,一般要另外使用nodelet来实现节点间消息传输的零拷贝,即略去了序列化和反序列化过程。

2. 订阅话题

# roscpp
ros::Subscriber sub = nh.subscribe("topic_name", 1, callback, ros::TransportHints().tcpNoDelay())
# rospy
rospy.Subscriber("topic_name", std_msgs.msg.String, callback, queue_size=1)

以上subscriber中的1就是queue_size,大小很重要,需要最新消息的时候queue_size要设置成1,不能遗漏消息时queue_size要设置大一些。

新消息收到后,会触发callback()函数执行,但是callback()函数是我们自己定义的,可能执行所需时间较长,就会阻塞住这个接收线程,之后新来的消息会存入queue中。对于不断传输的实时数据流,如果接收消息的频率大于处理的能力(callback函数运行的最高频率),那么queue中的消息就会积压,满了之后旧消息就会被丢弃。这会导致callback当前处理的消息是队列中积压已久的之前的消息。

对于数据实时性要求高的应用,callback函数要写的尽可能简单,避免执行时间过长。同时queue_size要设置成1。

对于非实时数据流、不能遗漏任何一次消息的情况,比如发送的一些指令话题,queue_size要设置尽可能的大,比如rospy中默认设置成为None,roscpp中设置成0,都意味着queue_size无穷大(危险,尽量不要这么设置)。

还要特别注意,rospy中Subscriber默认queue_size不设置时是None,即队列无穷大,一般需要手动设置为1。而且rospy的Subscriber的queue_size只能设置为1或者None,设置为其他数时并不是依次丢弃旧数据,而是一次性接收queue_size个数据!

参考:rospy.topics.Subscriber

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值