前言
ros中spin与spinOnce的区别
环境
系统环境
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
Linux version : 5.3.0-46-generic ( buildd@lcy01-amd64-013 )
Gcc version: 7.5.0 ( Ubuntu 7.5.0-3ubuntu1~18.04 )
软件信息
version :
None
正文
ros::spin()和ros::spinOnce()都是在订阅主题的时候使用的,区别在于ros::spinOnce()在完成订阅后直接返回,而ros::spin()会一直阻塞直到程序终结。 下面是两个例子:
ros::spinOnce()
ros::Rate r(10); // 10 hz
while (should_continue)
{
... do some work, publish some messages, etc. ...
ros::spinOnce();
r.sleep();
}
ros::spin()
ros::init(argc, argv, "my_node");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe(...);
...
ros::spin();
spin()和spinOnce()的联系
无论是spin()还是spinOnce()都是用于处理回调函数,这里的回调函数是指注册在ros默认callbackQueue的回调函数。在spin()中,将它看成一个循环,就是在不断在循环中处理所有注册的回调函数。而spinOnce()则是每一次执行的时候处理一次全部回调函数。
#include "ros/ros.h"
#include "ros/callback_queue.h"
#include "std_msgs/String.h"
#include <boost/thread.hpp>
void chatterCallbackMainQueue(const std_msgs::String::ConstPtr& msg){
ROS_INFO_STREAM("I heard: [ " << msg->data << "] in thread [" << boost::this_thread::get_id() << "] (Main thread)");
}
void chatterCallbackCustomQueue(const std_msgs::String::ConstPtr& msg){
ROS_INFO_STREAM("I heard: [ " << msg->data << "] in thread [" << boost::this_thread::get_id() << "]");
}
ros::CallbackQueue g_queue;
void callbackThread(){
ROS_INFO_STREAM("Callback thread id=" << boost::this_thread::get_id());
ros::NodeHandle n;
while (n.ok()){
g_queue.callAvailable(ros::WallDuration(0.01));
}
}
int main(int argc, char **argv){
ros::init(argc, argv, "listener_with_custom_callback_processing");
ros::NodeHandle n;
ros::SubscribeOptions ops =ros::SubscribeOptions::create<std_msgs::String>("chatter", 1000,chatterCallbackCustomQueue,ros::VoidPtr(), &g_queue);
ros::Subscriber sub = n.subscribe(ops);
ros::Subscriber sub2 = n.subscribe("chatter", 1000, chatterCallbackMainQueue);
boost::thread chatter_thread(callbackThread);
ROS_INFO_STREAM("Main thread id=" << boost::this_thread::get_id());
ros::Rate r(1);
while (n.ok()) {
ros::spinOnce();
r.sleep();
}
chatter_thread.join();
return 0;
}
看这程序,通过ros::SubscribeOptions注册一个订阅器,但是它的回调函数是注册在自己定义的一个ros::CallbackQueue中的,系统的ros::spinOnce()不会去调用这个回调函数,而是通过自己的g_queue.callAvailable()来调用其中的回调函数。