ROS-ros::spin() and ros::spinOnce() Differences and Use

Original: http://www.cnblogs.com/liu-fa/p/5925381.html

Functional Meaning

First of all, the brothers are known as ROS message callback handlers. They usually appear in the main loop of ROS. Programs need to call ros::spin() or ros::spinOnce(). The difference between them is that the former will not return after calling, that is, your main program will not execute down here, and the latter can continue to execute after calling.

In fact, the principle of message callback processing function is very simple. We all know that ROS has a message publishing and subscribing mechanism. What? I do not know! I don't know if I'm going soon. http://wiki.ros.org/ROS/Tutorials (ROS Official Basic Course) Take a look.

Okay, let's go on. If your program writes a message subscription function, ROS will automatically accept subscription messages in the background in the format you specify, in addition to the main program, during the execution of the program. But the message received is not immediately processed, but must wait until ros::spin() or ros::spinOnce() is executed. It's the principle of message return function. How about it? Simple. Why is it so designed? Cough, well, there must be a reason for him...

Difference

As mentioned above, ros::spin() will not return after the call, that is, your main program will not execute down here, and ros::spinOnce() the latter can continue to execute after the call.

Actually, the name of the function can also understand a similar, one is called all the time; the other is called only once, if you want to call again, you need to add a loop.

It must be remembered here that the ros::spin() function generally does not appear in the loop, because the program will not call other statements after spin(), that is to say, the loop is meaningless, and that there must be no other statement (except return 0) after the spin() function, some of which will not be executed in vain. ros::spinOnce() is relatively flexible in use, but it often needs to consider the timing, frequency and size of the message pool, which should be coordinated according to the actual situation, otherwise it will cause data packet loss or delay errors.

Common usage methods

It should be emphasized here that if your program writes a message subscription function, don't forget to add ros::spin() or ros::spinOnce() function in the corresponding location, otherwise you will never get the data or messages sent by the other side, blogger's blood lessons, and you should remember them closely.

ros::spin()

ros::spin() function is relatively simple to use, usually at the end of the main program, add the statement. Examples are as follows:

Sender:

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>

int main(int argc, char **argv)
{
    ros::init(argc, argv, "talker");
    ros::NodeHandle n;
    ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
    ros::Rate loop_rate(10);

    int count = 0;
    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());

        /**
         * Send messages to Topic: chatter at 10 Hz (10 times per second); maximum capacity of message pool is 1000.
         */
        chatter_pub.publish(msg);

        loop_rate.sleep();
        ++count;
    }
    return 0;
}

Receiver:

#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);

    /**
     * ros::spin() The callback function chatterCallback() will be called all the time, and 1000 data will be called at a time.
     * When the user enters Ctrl+C or the ROS main process closes, it exits.
     */
    ros::spin();
    return 0;
}

ros::spinOnce()

The use of ros::spinOnce() is freer than ros::spin() and can appear in all parts of the program, but there are more factors to be noted. For example:

For some messages that transmit very fast, we should pay more attention to controlling the size of message pool and the execution frequency of ros::spinOnce() reasonably; for example, when the message delivery frequency is 10 Hz and the call frequency of ros::spinOnce() is 5 Hz, then the size of message pool must be larger than 2 to ensure that data is not lost and there is no delay.

/**Receiver**/<br>#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);
    while (ros::ok())
    {
        /*...TODO...*/ 

        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

2 ros::spinOnce() is very flexible and widely used, and the specific situation needs specific analysis. However, for user-defined periodic functions, it is better to execute side by side with ros:: spinOne, and it is not recommended to place them in callback functions.

/*...TODO...*/
ros::Rate loop_rate(100);

while (ros::ok())
{
    /*...TODO...*/
    user_handle_events_timeout(...);

    ros::spinOnce();                 
    loop_rate.sleep();
}

Added by jguy on Fri, 14 Jun 2019 22:50:19 +0300