Ros订阅者未更新

5 投票
4 回答
8031 浏览
提问于 2025-04-28 01:11

我写了一个ROS的订阅者,用来接收一个图像主题的信息。我把我的缓冲区设置成了1,代码是:

subscriber =rospy.Subscriber("/camera/rgb/image_mono/compressed",CompressedImage, callback,  queue_size=1)

可是我的订阅者还是跟不上。你们觉得这可能是什么原因呢?我设置的队列大小对吗?

暂无标签

4 个回答

-1

出现明显延迟的原因很可能是你的回调函数花费了很多时间。如果有可能的话,尽量去优化这个函数。把队列大小设置为1,实际上就是在告诉ROS只处理它能保持的那些帧。

把队列大小设置得大一些,比如5或10。这样的话,(希望如果处理延迟不是太严重)你所有的帧都会被处理,但它们会有时间上的滞后。也就是说,视频处理会稍微落后几步,但不会出现“卡顿”或者丢帧的情况。

1

这里有一个关于为什么缓冲区大小很重要的补充说明。
另外,官方文档也可以帮助解释导致延迟的另一个原因,主要是从发布者的角度来看。

在rospy中,publish()默认是同步的(这是为了兼容以前的版本),这意味着调用这个方法时会被阻塞,直到:

消息被序列化到一个缓冲区中,并且这个缓冲区里的内容已经写入到每个当前订阅者的传输通道中。

8

我之前也遇到过同样的问题(问题不是卡顿的帧率,而是真正的延迟)。当我停止发布图像源(比如rosbag、摄像头驱动等)时,我的节点仍然会处理大约5到10帧即使在源被停止后(而且我确定我设置了queue_size=1)。

这是我在GitHub上提的一个问题,后来得到了解决。结果发现涉及到多个队列(不仅仅是你设置的那个队列)。在我的情况下,默认的buff_size比我的图像要小,所以我的节点处理这些图像的速度不够快,导致总是有一些图像在某个队列里堆积。

总结一下 增加你订阅者的buff_size,就像我在这里做的那样。这样对我有效 :)

3

队列是用来排队接收消息的。这意味着,如果你的回调函数处理消息的时间比新消息到达的时间要长,那么只有队列大小会被保留,其他的消息就不会被你的节点处理了。

我建议在发布节点中,在发布消息之前打印一条信息,并在你的回调方法的开头也打印一条信息。这样你就可以准确测量ros处理消息所需的时间。其他的时间问题可能都是由你的回调方法引起的。

撰写回答