国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開發(fā) > JS > 正文

ros::spin() 和 ros::spinOnce()函數(shù)的區(qū)別及詳解

2024-05-06 16:32:12
字體:
供稿:網(wǎng)友

1 函數(shù)意義

首先要知道,這倆兄弟學(xué)名叫ROS消息回調(diào)處理函數(shù)。它倆通常會(huì)出現(xiàn)在ROS的主循環(huán)中,程序需要不斷調(diào)用ros::spin() 或 ros::spinOnce(),兩者區(qū)別在于前者調(diào)用后不會(huì)再返回,也就是你的主程序到這兒就不往下執(zhí)行了,而后者在調(diào)用后還可以繼續(xù)執(zhí)行之后的程序。

其實(shí)消息回調(diào)處理函數(shù)的原理非常簡(jiǎn)單。我們都知道,ROS存在消息發(fā)布訂閱機(jī)制,什么?不知道?不知道還不快去:http://wiki.ros.org/ROS/Tutorials (ROS官方基礎(chǔ)教程) 瞅瞅。

好,我們繼續(xù),如果你的程序?qū)懥讼嚓P(guān)的消息訂閱函數(shù),那么程序在執(zhí)行過程中,除了主程序以外,ROS還會(huì)自動(dòng)在后臺(tái)按照你規(guī)定的格式,接受訂閱的消息,但是所接到的消息并不是立刻就被處理,而是必須要等到ros::spin()或ros::spinOnce()執(zhí)行的時(shí)候才被調(diào)用,這就是消息回到函數(shù)的原理,怎么樣,簡(jiǎn)單吧,至于為什么這么設(shè)計(jì)?咳咳,嗯,肯定有他的道理。。。

2 區(qū)別

就像上面說的,ros::spin() 在調(diào)用后不會(huì)再返回,也就是你的主程序到這兒就不往下執(zhí)行了,而 ros::spinOnce() 后者在調(diào)用后還可以繼續(xù)執(zhí)行之后的程序。

其實(shí)看函數(shù)名也能理解個(gè)差不多,一個(gè)是一直調(diào)用;另一個(gè)是只調(diào)用一次,如果還想再調(diào)用,就需要加上循環(huán)了。

這里一定要記住,ros::spin()函數(shù)一般不會(huì)出現(xiàn)在循環(huán)中,因?yàn)槌绦驁?zhí)行到spin()后就不調(diào)用其他語(yǔ)句了,也就是說該循環(huán)沒有任何意義,還有就是spin()函數(shù)后面一定不能有其他語(yǔ)句(return 0 除外),有也是白搭,不會(huì)執(zhí)行的。ros::spinOnce()的用法相對(duì)來說很靈活,但往往需要考慮調(diào)用消息的時(shí)機(jī),調(diào)用頻率,以及消息池的大小,這些都要根據(jù)現(xiàn)實(shí)情況協(xié)調(diào)好,不然會(huì)造成數(shù)據(jù)丟包或者延遲的錯(cuò)誤。

3 常見使用方法

這里需要特別強(qiáng)調(diào)一下,如果大兄弟你的程序?qū)懥讼嚓P(guān)的消息訂閱函數(shù),那千萬千萬千萬不要忘了在相應(yīng)位置加上ros::spin()或者ros::spinOnce()函數(shù),不然你是永遠(yuǎn)都得不到另一邊發(fā)出的數(shù)據(jù)或消息的,博主血的教訓(xùn),萬望緊記。。。

3.1 ros::spin()

ros::spin()函數(shù)用起來比較簡(jiǎn)單,一般都在主程序的最后,加入該語(yǔ)句就可。例子如下:

發(fā)送端:

#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());    /**     * 向 Topic: chatter 發(fā)送消息, 發(fā)送頻率為10Hz(1秒發(fā)10次);消息池最大容量1000。     */    chatter_pub.publish(msg);    loop_rate.sleep();    ++count;  }  return 0;}

接收端:

#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() 將會(huì)進(jìn)入循環(huán), 一直調(diào)用回調(diào)函數(shù)chatterCallback(),每次調(diào)用1000個(gè)數(shù)據(jù)。   * 當(dāng)用戶輸入Ctrl+C或者ROS主進(jìn)程關(guān)閉時(shí)退出,   */  ros::spin();  return 0;}

3.2 ros::spinOnce()

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

1 對(duì)于有些傳輸特別快的消息,尤其需要注意合理控制消息池大小和ros::spinOnce()執(zhí)行頻率; 比如消息送達(dá)頻率為10Hz, ros::spinOnce()的調(diào)用頻率為5Hz,那么消息池的大小就一定要大于2,才能保證數(shù)據(jù)不丟失,無延遲。

/**接收端**/<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()用法很靈活,也很廣泛,具體情況需要具體分析。但是對(duì)于用戶自定義的周期性的函數(shù),最好和ros::spinOnce并列執(zhí)行,不太建議放在回調(diào)函數(shù)中;

/*...TODO...*/ros::Rate loop_rate(100);while (ros::ok()){  /*...TODO...*/  user_handle_events_timeout(...);  ros::spinOnce();           loop_rate.sleep();}

 

 

注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JavaScript/Ajax教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 长海县| 岐山县| 吴江市| 云龙县| 开原市| 乌鲁木齐市| 绥江县| 湘阴县| 盐山县| 会泽县| 黄浦区| 洛阳市| 勃利县| 荔波县| 泰顺县| 宣化县| 岱山县| 瓦房店市| 会同县| 贡嘎县| 本溪| 吴忠市| 独山县| 从化市| 洪湖市| 宁夏| 当涂县| 涞水县| 博爱县| 阜平县| 扶沟县| 舟曲县| 容城县| 化德县| 莒南县| 双城市| 绩溪县| 汝阳县| 灵武市| 阳原县| 龙岩市|