前言
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()来调用其中的回调函数。
