摘要:本文主要讲解下,ros::spin()和ros::spinOnce()的使用细节,以及他们的区别。
先来一个直观的例子,然后根据例子来分析。
#include "ros/ros.h"
#include "std_msgs/String.h"
#include
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
//1000 为queue_size大小,设置为1:实时性,只保留最新的。0:表示为无穷大。
//关于queue_size的详解:https://blog.csdn.net/handsome_for_kill/article/details/81984428
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
// 向 Topic: chatter 发送消息, 发送频率为10Hz(1秒发10次);消息池最大容量1000。
chatter_pub.publish(msg);
loop_rate.sleep();
}
return 0;
}
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);//1000为回调函数的队列长度
ros::spin();
return 0;
}
根据上面的实例,我们来捋一捋处理流程:
那什么时候处理回调函数队列中的回调函数了?这就是 ros::spin() 需要做的工作了。
消息的发送和上面是一样的,这里只说一下消息的订阅。
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
/*...TODO...*/
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 2, chatterCallback);
ros::Rate loop_rate(5); //频率为5hz
while (ros::ok())
{
/*...TODO...*/
ros::spinOnce();
loop_rate.sleep(); //配合执行频率,sleep一段时间,然后进入下一个循环。
}
return 0;
}
回调函数的队列的创建和上面的分析是一样的,这里讲一讲ros::spinOnce() 的处理流程:
那我们如何控制执行的速度了,也就是执行的频率。从上面的实例中,我们看到多了:
通过这样的设置,我们就可以设计自己的监听频率了,而不用完全被动的接收topic了。
上面其实已经分析到了一个主要区别
ros::Rate loop_rate(10);
while(ros::ok())
{
// can add some function
ros::spinOnce();
loop_rate.sleep();
}
如果退化成下面这样的化,其实和ros::spin()是一样的。
while(ros::ok())
{
ros::spinOnce();
}
从上面的对比中,其实可以看出,ros::spin()和ros::spinOnce() 还有一个重要的区别就是:
实例:
可以看出,不仅仅在处理回调函数,与此同时,也可以处理print()函数。