ROS Subscriber的callback函数的触发条件
当循环到spinOnce()函数时,会调用subscriber的callback函数,此时会检查订阅到的消息队列的大小,
如果此时subscriber的消息队列的size为n,则会执行n次callback
ROS消息队列的理解
主要分以下几种情况,
subscriber的消息队列为1时
sub方的消息队列size为1,callback函数永远只拿到最新的数据
subscriber的消息队列为10(>1)时
sub方的消息队列size为10,callback函数会被触发10次,依次读取缓存收到的所有数据,如果这个消息队列足够大的话,是不会漏掉任何pub方发布的任一帧数据的。
publisher的消息队列为1时
pub方的消息队列size为1,每次publish只会发布此次循环中最新的数据
publisher的消息队列为10(>1)时
publisher的消息队列size大于1的情况会比较tricky,首先得先讲讲publish
函数的机制,当pub方调用publish
函数时,其实系统并不会阻塞直至消息真正发送出去,而是会将此次要发送的msg存入一个队列(此队列即为publisher的消息队列),然后立即返回,什么时候真正发送消息是由ros说了算。考虑以下代码:
#include <ros/ros.h>
#include <std_msgs/UInt32.h>int main(int argc, char** argv) {ros::init(argc, argv, "pub_node");ros::NodeHandle n;// ros::Publisher chatter_pub = n.advertise<std_msgs::UInt32>("chatter", 1);ros::Publisher chatter_pub = n.advertise<std_msgs::UInt32>("chatter", 20);ros::Rate loop_rate(10);while (ros::ok()) {static int count = 0;static std_msgs::UInt32 msg;msg.data = count;for (int i = 0; i < 10; ++i) {chatter_pub.publish(msg);}loop_rate.sleep();++count;}return 0;
}
注意到代码中的for循环,for循环执行了10次publish操作,直觉上会认为在一个while循环周期,此publisher发布了10次消息,但根据我们刚才讲的,publish
函数并不会阻塞直至消息真正发送,而是将此msg存入一个publish队列,所以如果publish队列很短的话,如1,则很有可能一个while循环周期并不会执行10次publish操作(在我的机器上大概只有2次),因为还没等到ros真正发送消息,队列里的老消息就被新消息顶掉了。但如果我们将这个publish队列设置成20,那么一个while循环周期将会确确实实地执行10次publish操作,因为队列的size是20,大于for循环的10次,所以老消息不会被挤掉。
因此,如果这个publisher消息队列足够大的话,是不会漏发任何一帧本该发送的数据的。