ROS CallBack函数和spinOnce()的触发机制,和消息队列的理解

ROS中的ROSSubscriber的callback函数在spinOnce()调用时触发,依据消息队列大小决定执行次数。若消息队列为1,则只获取最新数据;大于1时,可存储多帧数据,避免丢失。publisher的消息队列用于存储待发送消息,不会阻塞publish调用,确保消息发送取决于队列大小。大消息队列可防止数据丢失,确保完整发送所有数据。
摘要由CSDN通过智能技术生成

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消息队列足够大的话,是不会漏发任何一帧本该发送的数据的。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值