天天看點

ros spin spinone 詳細解釋

函數意義:

先了解這個 http://wiki.ros.org/roscpp/Overview/Publishers%20and%20Subscribers ros的消息訂閱和釋出機制官方教程,最簡單的模闆如下:

//Publishing to a Topic
    ros::Publisher pub = nh.advertise<std_msgs::String>("topic_name", );
    std_msgs::String str;
    str.data = "hello world";
    pub.publish(str);

    //check errors in pub
    if (!pub)
    {
    ...
    }
   ros::Publisher advertise(const std::string& topic, uint32_t **queue_size**, bool latch = false); 
    ...
//Subscribing to a Topic
    void callback(const std_msgs::StringConstPtr& str)
    {
    ...
    }
   ros::Subscriber sub = nh.subscribe("my_topic", , callback);
           

關于std_msgs::StringConstPtr& str的了解

避免了複制,節省了時間,以下是元解釋。

**When messages are automatically generated into C++ code, there are several typedefs defined. One of them is ::Ptr, which is typedef-ed to be a boost::shared_ptr, and another is ::ConstPtr which is boost::shared_ptr

By passing a const pointer into the callback, we avoid doing a copy. While this might not make much difference for std_msgs::String, it can make a huge difference for sensor_msgs::PointCloud2.**

& 表示引用

ROS消息回調處理函數。它倆通常會出現在ROS的主循環中,程式需要不斷調用ros::spin() 或 ros::spinOnce(),兩者差別在于前者調用後不會再傳回,也就是你的主程式到這兒就不往下執行了,而後者在調用後還可以繼續執行之後的程式。

好,我們繼續,如果你的程式寫了相關的消息訂閱函數,那麼程式在執行過程中,除了主程式以外,ROS還會自動在背景按照你規定的格式,接受訂閱的消息,但是所接到的消息并不是立刻就被處理,而是必須要等到ros::spin()或ros::spinOnce()執行的時候才被調用,這就是消息回到函數的原理。

差別

就像上面說的,ros::spin() 在調用後不會再傳回,也就是你的主程式到這兒就不往下執行了,而 ros::spinOnce() 後者在調用後還可以繼續執行之後的程式。

其實看函數名也能了解個差不多,一個是一直調用;另一個是隻調用一次,如果還想再調用,就需要加上循環了。

這裡一定要記住,ros::spin()函數一般不會出現在循環中,因為程式執行到spin()後就不調用其他語句了,也就是說該循環沒有任何意義,還有就是spin()函數後面一定不能有其他語句(return 0 除外),有也是白搭,不會執行的。ros::spinOnce()的用法相對來說很靈活,但往往需要考慮調用消息的時機,調用頻率,以及消息池的大小,這些都要根據現實情況協調好,不然會造成資料丢包或者延遲的錯誤。

常見使用方法

這裡需要特别強調一下,如果大兄弟你的程式寫了相關的消息訂閱函數,那千萬千萬千萬不要忘了在相應位置加上ros::spin()或者ros::spinOnce()函數,不然你是永遠都得不到另一邊發出的資料或消息的,部落客血的教訓,萬望緊記。。。

publish client

#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", );
    ros::Rate loop_rate();

    int count = ;
    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();
        ++count;
    }
    return ;
}
           

subscribe client:

#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", , chatterCallback);

    /**
     * ros::spin() 将會進入循環, 一直調用回調函數chatterCallback(),每次調用1000個資料。
     * 當使用者輸入Ctrl+C或者ROS主程序關閉時退出,
     */
    ros::spin();
    return ;
}
           

ros::spinOnce()

對于ros::spinOnce()的使用,雖說比ros::spin()更自由,可以出現在程式的各個部位,但是需要注意的因素也更多。比如:

1 對于有些傳輸特别快的消息,尤其需要注意合理控制消息池大小和ros::spinOnce()執行頻率; 比如消息送達頻率為10Hz, ros::spinOnce()的調用頻率為5Hz,那麼消息池的大小就一定要大于2,才能保證資料不丢失,無延遲。

/接收端/

#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", , chatterCallback);

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

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

ros::spinOnce()用法很靈活,也很廣泛,具體情況需要具體分析。但是對于使用者自定義的周期性的函數,最好和ros::spinOnce并列執行,不太建議放在回調函數中;

/*...TODO...*/

ros::Rate loop_rate();

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

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

Reference:https://www.cnblogs.com/liu-fa/p/5925381.html

ros