ROS回调函数与spin()方法

首先给一个简单的ROS订阅者程序

#include <ros/ros.h>
#include <topic_demo/gps.h>
#include <std_msgs/Float32.h>
void gpsCallback(const topic_demo::gps::ConstPtr &msg)
{
	std_msgs::Float32 distance; //计算离原点(0,0)的距离
	distance.data = sqrt(pow(msg->x,2)+pow(msg->y,2));
	ROS_INFO("Listener: Distance to origin = %f, state: %s",distance.data,msg->state.c_str()); //输出
} 
int main(int argc, char **argv)
{
	ros::init(argc, argv, "listener");
	ros::NodeHandle n;
	ros::Subscriber sub = n.subscribe("gps_info", 1, gpsCallback); //设置回调函数gpsCallback
	ros::spin(); //ros::spin()用于调用所有可触发的回调函数, 将进入循环, 不会返回, 类似于在循环里反复调用spinOnce()
	//而ros::spinOnce()只会去触发一次
	return 0;
}

在topic接收方, 有一个比较重要的概念, 就是回调(CallBack), 在本例中, 回调就是预先给 gps_info 话题传来的消息准备一个回调函数, 你事先定义好回调函数的操作, 本例中是计算到原点的距离。 只有当有消息来时, 回调函数才会被触发执行。 具体去触发的命令就是 ros::spin() , 它会反复的查看有没有消息来, 如果有就会让回调函数去处理。

因此千万不要认为, 只要指定了回调函数, 系统就回去自动触发, 你必须 ros::spin() 或者 ros::spinOnce() 才能真正使回调函数生效。

回调函数作为参数被传入到了另一个函数中( 在本例中传递的是函数指针) , 在未来某个时刻( 当有新的message到达) , 就会立即执行。 Subscriber接收到消息, 实际上是先把消息放到一个队列中去, 如下图所示。 队列的长度在Subscriber构建的时候设置好了。 当有spin函数执行, 就会去处理消息队列中队首的消息。

在这里插入图片描述
消息订阅器一旦知道话题里面有消息到达,就会将这消息作为参数传入callback函数中,但是此时还没有执行callback函数,而是把callback函数放到了回调函数队列中。所以当发布器不断发送消息到话题上面时,就会有相应的callback函数进入队列中,它们函数名一样,只是实参不一样。

那么什么时候才会执行callback函数呢?就是ros::spin()和ros::spinOnce()的事了。

当spinOnce函数被调用时,spinOnce就会调用回调函数队列中第一个callback函数,此时callback函数才被执行,然后等到下次spinOnce函数又被调用时,回调函数队列中第二个callback函数就会被调用,以此类推。

所以,这会有一个问题。因为回调函数队列的长度是有限的,如果发布器发送数据的速度太快,spinOnce函数调用的频率太少,就会导致队列溢出,一些callback函数就会被挤掉,导致没被执行到。

而对于spin函数,一旦进入spin函数,它就不会返回了,相当于它在自己的函数里面死循环了。只要回调函数队列里面有callback函数在,它就会马上去执行callback函数。如果没有的话,它就会阻塞,不会占用CPU。

  • 19
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

触不可及<>

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值