Ros订阅者未更新
我写了一个ROS的订阅者,用来接收一个图像主题的信息。我把我的缓冲区设置成了1,代码是:
subscriber =rospy.Subscriber("/camera/rgb/image_mono/compressed",CompressedImage, callback, queue_size=1)
可是我的订阅者还是跟不上。你们觉得这可能是什么原因呢?我设置的队列大小对吗?
4 个回答
出现明显延迟的原因很可能是你的回调函数花费了很多时间。如果有可能的话,尽量去优化这个函数。把队列大小设置为1,实际上就是在告诉ROS只处理它能保持的那些帧。
把队列大小设置得大一些,比如5或10。这样的话,(希望如果处理延迟不是太严重)你所有的帧都会被处理,但它们会有时间上的滞后。也就是说,视频处理会稍微落后几步,但不会出现“卡顿”或者丢帧的情况。
这里有一个关于为什么缓冲区大小很重要的补充说明。
另外,官方文档也可以帮助解释导致延迟的另一个原因,主要是从发布者的角度来看。
在rospy中,publish()默认是同步的(这是为了兼容以前的版本),这意味着调用这个方法时会被阻塞,直到:
消息被序列化到一个缓冲区中,并且这个缓冲区里的内容已经写入到每个当前订阅者的传输通道中。
我之前也遇到过同样的问题(问题不是卡顿的帧率,而是真正的延迟)。当我停止发布图像源(比如rosbag、摄像头驱动等)时,我的节点仍然会处理大约5到10帧即使在源被停止后(而且我确定我设置了queue_size=1
)。
这是我在GitHub上提的一个问题,后来得到了解决。结果发现涉及到多个队列(不仅仅是你设置的那个队列)。在我的情况下,默认的buff_size
比我的图像要小,所以我的节点处理这些图像的速度不够快,导致总是有一些图像在某个队列里堆积。
总结一下
增加你订阅者的buff_size
,就像我在这里做的那样。这样对我有效 :)
队列是用来排队接收消息的。这意味着,如果你的回调函数处理消息的时间比新消息到达的时间要长,那么只有队列大小
会被保留,其他的消息就不会被你的节点处理了。
我建议在发布节点中,在发布消息之前打印一条信息,并在你的回调方法的开头也打印一条信息。这样你就可以准确测量ros处理消息所需的时间。其他的时间问题可能都是由你的回调方法引起的。