ROS

ros spin & spinOnce Difference

"ros spin & spinOnce difference"

Posted by Stephen on January 8, 2020

前言

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

后记

Callbacks and Spinning