ROS學(xué)習(xí)--7.寫(xiě)一個(gè)發(fā)布與訂閱節(jié)點(diǎn)

1.寫(xiě)一個(gè)publisher節(jié)點(diǎn)

“節(jié)點(diǎn)”是連接到ROS網(wǎng)絡(luò)的可執(zhí)行文件的ROS術(shù)語(yǔ)滤淳。在這里贤徒,我們將創(chuàng)建一個(gè)發(fā)布者(“ talker”)節(jié)點(diǎn)醉蚁,該節(jié)點(diǎn)將不斷廣播消息睛琳。

1.1 將目錄更改為在catkin工作區(qū)以前的教程中創(chuàng)建的beginner_tutorials包:

roscd beginner_tutorials

1.2 在beginner_tutorials包目錄中創(chuàng)建一個(gè)src目錄:

mkdir -p src

該目錄將包含我們beginner_tutorials包的所有源文件盒蟆。

1.3 在beginner_tutorials包中創(chuàng)建src / talker.cpp文件,并將以下內(nèi)容粘貼到其中:

// ros/ros.h是一個(gè)方便的工具掸掏,其中包括使用ROS系統(tǒng)最常見(jiàn)的公共部分所需的所有標(biāo)頭茁影。
#include "ros/ros.h"

// 這包括std_msgs / String消息,該消息駐留在std_msgs包中丧凤。
// 這是從該程序包中的String.msg文件自動(dòng)生成的標(biāo)頭募闲。有關(guān)消息定義的更多信息,請(qǐng)參見(jiàn)msg頁(yè)面愿待。
#include "std_msgs/String.h"

#include <sstream>

/**
* 本教程演示了如何通過(guò)ROS系統(tǒng)簡(jiǎn)單地發(fā)送消息浩螺。
*/

//        這是下面事情的精簡(jiǎn)版:
//          初始化ROS系統(tǒng)
//          宣傳我們將在chatter主題上向主服務(wù)器發(fā)布std_msgs / String消息
//          在將消息發(fā)布到聊天時(shí)每秒循環(huán)10次

int main(int argc, char** argv)
{
//    初始化ROS。這使ROS可以通過(guò)命令行進(jìn)行名稱重映射-目前尚不重要仍侥。
//    這也是我們指定節(jié)點(diǎn)名稱的地方要出。節(jié)點(diǎn)名稱在運(yùn)行的系統(tǒng)中必須唯一。
    ros::init(argc, argv, "talker");
    
//    創(chuàng)建此進(jìn)程的節(jié)點(diǎn)的句柄农渊。創(chuàng)建的第一個(gè)NodeHandle實(shí)際上將對(duì)節(jié)點(diǎn)進(jìn)行初始化患蹂,
//    而最后一個(gè)被破壞的節(jié)點(diǎn)將清理該節(jié)點(diǎn)正在使用的所有資源。
    ros::NodeHandle node_handle;
    
//    告訴管理員,我們將在主題討論中發(fā)布std_msgs / String類型的消息传于。
//    這樣囱挑,主服務(wù)器就可以告訴所有正在聊天的節(jié)點(diǎn),我們將發(fā)布有關(guān)該主題的數(shù)據(jù)沼溜。
//    第二個(gè)參數(shù)是發(fā)布隊(duì)列的大小平挑。在這種情況下,如果我們發(fā)布得太快系草,
//    它將最多緩沖1000條消息通熄,然后再開(kāi)始丟棄舊消息。

//    NodeHandle :: advertise()返回一個(gè)ros :: Publisher對(duì)象找都,
//    該對(duì)象有兩個(gè)作用:
//    1)它包含一個(gè)publish()方法唇辨,可用于將消息發(fā)布到其創(chuàng)建的主題上;
//    2)當(dāng)它超出范圍時(shí)檐嚣,它將自動(dòng)取消廣告助泽。
    ros::Publisher chatter_pub = node_handle.advertise<std_msgs::String>("chatter", 100);

//    ros :: Rate對(duì)象允許您指定要循環(huán)播放的頻率。
//    它將跟蹤自上次調(diào)用Rate::sleep()以來(lái)已等待了多長(zhǎng)時(shí)間嚎京,并睡眠了正確的時(shí)間嗡贺。
//    在這種情況下,我們告訴我們要以10Hz運(yùn)行鞍帝。
    ros::Rate loop_rate(10);

    int count = 0;
    
//    默認(rèn)情況下诫睬,roscpp將安裝SIGINT處理程序,
//    該處理程序提供Ctrl-C處理帕涌,如果發(fā)生這種情況摄凡,
//    將導(dǎo)致ros :: ok()返回false。

//    ros :: ok()將在以下情況下返回false:
//      收到SIGINT(Ctrl-C)
//      我們已經(jīng)被另一個(gè)同名節(jié)點(diǎn)踢出網(wǎng)絡(luò)
//      ros :: shutdown()已由應(yīng)用程序的另一部分調(diào)用蚓曼。
//      所有ros :: NodeHandles已被銷毀
//    一旦ros :: ok()返回false亲澡,所有ROS調(diào)用都會(huì)失敗。
    while (ros::ok())
    {
//        我們使用消息自適應(yīng)類在ROS上廣播消息纫版,該類通常是從msg文件生成的床绪。
//        可能有更復(fù)雜的數(shù)據(jù)類型,但是現(xiàn)在我們將使用標(biāo)準(zhǔn)的String消息其弊,
//        該消息具有一個(gè)成員:“ data”癞己。
        std_msgs::String msg;
        std::stringstream ss;

        ss << "hello world" << count;
        msg.data = ss.str();

//        ROS_INFO可以代替printf / cout。有關(guān)更多信息梭伐,請(qǐng)參見(jiàn)rosconsole文檔痹雅。
        ROS_INFO("%s", msg.data.c_str());

//        現(xiàn)在,我們實(shí)際上將消息廣播給了已連接的任何人糊识。
        chatter_pub.publish(msg);

//        對(duì)于這個(gè)簡(jiǎn)單的程序绩社,不需要在此處調(diào)用ros :: spinOnce()摔蓝,
//        因?yàn)槲覀儧](méi)有收到任何回調(diào)。但是愉耙,如果您要向此應(yīng)用程序添加訂閱项鬼,
//        并且在此處沒(méi)有ros :: spinOnce(),則將永遠(yuǎn)不會(huì)調(diào)用您的回調(diào)劲阎。
//        因此,請(qǐng)將其添加為良好的度量鸠真。
        ros::spinOnce();

//        現(xiàn)在悯仙,我們使用ros :: Rate對(duì)象休眠剩余時(shí)間,使我們達(dá)到10Hz的發(fā)布速率吠卷。
        loop_rate.sleep();
        ++count;
    }
    return 0;
}

2.寫(xiě)一個(gè)subscriber節(jié)點(diǎn)

  • 在beginner_tutorials包中創(chuàng)建src / listener.cpp文件锡垄,并將以下內(nèi)容粘貼到其中:
// ros/ros.h是一個(gè)方便的工具,其中包括使用ROS系統(tǒng)最常見(jiàn)的公共部分所需的所有標(biāo)頭祭隔。
#include "ros/ros.h"

// 這包括std_msgs / String消息货岭,該消息駐留在std_msgs包中。
// 這是從該程序包中的String.msg文件自動(dòng)生成的標(biāo)頭疾渴。有關(guān)消息定義的更多信息千贯,請(qǐng)參見(jiàn)msg頁(yè)面。
#include "std_msgs/String.h"

/**
本教程演示了通過(guò)ROS系統(tǒng)簡(jiǎn)單接收消息的過(guò)程搞坝。
*/

//當(dāng)在chatter主題上收到新消息時(shí)搔谴,將調(diào)用此回調(diào)函數(shù)。
// 該消息在boost shared_ptr中傳遞桩撮,
// 這意味著您可以根據(jù)需要將其存儲(chǔ)起來(lái)敦第,
// 而不必?fù)?dān)心它下面的內(nèi)容被刪除,也無(wú)需復(fù)制基礎(chǔ)數(shù)據(jù)店量。
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
    ROS_INFO("I heard: [%s]", msg->data.c_str());
}

//  同樣芜果,這是正在發(fā)生的事情的精簡(jiǎn)版:
//      初始化ROS系統(tǒng)
//      訂閱聊天主題
//      旋轉(zhuǎn),等待消息到達(dá)
//      消息到達(dá)時(shí)融师,將調(diào)用chatterCallback()函數(shù)

int main(int argc, char** argv)
{
//    初始化ROS右钾。這使ROS可以通過(guò)命令行進(jìn)行名稱重映射-目前尚不重要。
//    這也是我們指定節(jié)點(diǎn)名稱的地方诬滩。節(jié)點(diǎn)名稱在運(yùn)行的系統(tǒng)中必須唯一霹粥。
    ros::init(argc, argv, "listener");
    
//    創(chuàng)建此進(jìn)程的節(jié)點(diǎn)的句柄。創(chuàng)建的第一個(gè)NodeHandle實(shí)際上將對(duì)節(jié)點(diǎn)進(jìn)行初始化疼鸟,
//    而最后一個(gè)被破壞的節(jié)點(diǎn)將清理該節(jié)點(diǎn)正在使用的所有資源后控。
    ros::NodeHandle node_handle;
    
//    訂閱與主機(jī)的聊天主題。每當(dāng)有新消息到達(dá)時(shí)空镜,ROS就會(huì)調(diào)用chatterCallback()函數(shù)浩淘。
//    第二個(gè)參數(shù)是隊(duì)列大小捌朴,以防萬(wàn)一我們不能足夠快地處理消息。
//    在這種情況下张抄,如果隊(duì)列達(dá)到1000條消息砂蔽,我們將在新消息到達(dá)時(shí)開(kāi)始丟棄舊消息。

//    NodeHandle :: subscribe()返回ros :: Subscriber對(duì)象署惯,
//    您必須保留該對(duì)象直到要取消訂閱為止左驾。破壞Subscriber對(duì)象后,
//    它將自動(dòng)取消訂閱chatter主題极谊。

//    NodeHandle :: subscribe()函數(shù)有多種版本诡右,
//    可讓您指定類成員函數(shù),甚至可以指定Boost.Function對(duì)象可以調(diào)用的任何函數(shù)轻猖。
    ros::Subscriber sub = node_handle.subscribe("chatter", 100, chatterCallback);

//    ros :: spin()進(jìn)入循環(huán)帆吻,并盡可能快地調(diào)用消息回調(diào)。
//    不過(guò)咙边,請(qǐng)不要擔(dān)心猜煮,如果沒(méi)有什么可做的,則不會(huì)占用太多CPU败许。
//    一旦ros :: ok()返回false王带,ros :: spin()將退出,
//    這意味著ros :: shutdown()已被默認(rèn)Ctrl-C處理程序市殷,
//    主程序告訴我們關(guān)閉或被調(diào)用了手動(dòng)辫秧。
    ros::spin();
    
    return 0;
}

3.編譯節(jié)點(diǎn)

您在上一教程中使用過(guò)catkin_create_pkg,該教程為您創(chuàng)建了package.xml和CMakeLists.txt文件被丧。 生成的CMakeLists.txt應(yīng)該如下所示(對(duì)“創(chuàng)建Msgs和Srvs”教程進(jìn)行了修改盟戏,并刪除了未使用的注釋和示例):

   1 cmake_minimum_required(VERSION 2.8.3)
   2 project(beginner_tutorials)
   3 
   4 ## Find catkin and any catkin packages
   5 find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)
   6 
   7 ## Declare ROS messages and services
   8 add_message_files(DIRECTORY msg FILES Num.msg)
   9 add_service_files(DIRECTORY srv FILES AddTwoInts.srv)
  10 
  11 ## Generate added messages and services
  12 generate_messages(DEPENDENCIES std_msgs)
  13 
  14 ## Declare a catkin package
  15 catkin_package()

不必?fù)?dān)心修改注釋的(#)示例,只需將以下幾行添加到CMakeLists.txt的底部:

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)
  • 生成的CMakeLists.txt文件應(yīng)如下所示:
   1 cmake_minimum_required(VERSION 2.8.3)
   2 project(beginner_tutorials)
   3 
   4 ## Find catkin and any catkin packages
   5 find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)
   6 
   7 ## Declare ROS messages and services
   8 add_message_files(FILES Num.msg)
   9 add_service_files(FILES AddTwoInts.srv)
  10 
  11 ## Generate added messages and services
  12 generate_messages(DEPENDENCIES std_msgs)
  13 
  14 ## Declare a catkin package
  15 catkin_package()
  16 
  17 ## Build talker and listener
  18 include_directories(include ${catkin_INCLUDE_DIRS})
  19 
  20 add_executable(talker src/talker.cpp)
  21 target_link_libraries(talker ${catkin_LIBRARIES})
  22 add_dependencies(talker beginner_tutorials_generate_messages_cpp)
  23 
  24 add_executable(listener src/listener.cpp)
  25 target_link_libraries(listener ${catkin_LIBRARIES})
  26 add_dependencies(listener beginner_tutorials_generate_messages_cpp)

這將創(chuàng)建兩個(gè)可執(zhí)行文件甥桂,talker和listener柿究,默認(rèn)情況下它們將進(jìn)入開(kāi)發(fā)空間的package目錄,默認(rèn)情況下位于?/ catkin_ws / devel / lib / <package name>黄选。

  • 請(qǐng)注意蝇摸,您必須將可執(zhí)行目標(biāo)的依賴項(xiàng)添加到消息生成目標(biāo):
target_link_libraries(talker ${catkin_LIBRARIES})

您可以直接調(diào)用可執(zhí)行文件,也可以使用rosrun調(diào)用它們办陷。它們沒(méi)有放在'<prefix> / bin'中貌夕,因?yàn)樵趯④浖惭b到系統(tǒng)時(shí),這會(huì)污染PATH民镜。

  • 現(xiàn)在運(yùn)行catkin_make編譯:
# In your catkin workspace
cd ~/catkin_ws
catkin_make  

4.測(cè)試你的節(jié)點(diǎn)(兩種方式)

  1. 打開(kāi)三個(gè)終端分別運(yùn)行:
roscore
source ~/catkin_ws/devel/setup.bash
rosrun beginer_tutorials talker
source ~/catkin_ws/devel/setup.bash
rosrun beginer_tutorials listener
  1. 打開(kāi)三個(gè)終端分別運(yùn)行:
roscore
~/catkin_ws/devel/lib/beginer_tutorials/talker
~/catkin_ws/devel/lib/beginer_tutorials/listener

最后結(jié)果:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啡专,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子制圈,更是在濱河造成了極大的恐慌们童,老刑警劉巖畔况,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異慧库,居然都是意外死亡跷跪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)齐板,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吵瞻,“玉大人,你說(shuō)我怎么就攤上這事甘磨√螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵宽档,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我庵朝,道長(zhǎng)吗冤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任九府,我火速辦了婚禮椎瘟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侄旬。我一直安慰自己肺蔚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布儡羔。 她就那樣靜靜地躺著宣羊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汰蜘。 梳的紋絲不亂的頭發(fā)上仇冯,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音族操,去河邊找鬼苛坚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛色难,可吹牛的內(nèi)容都是我干的泼舱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼枷莉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼娇昙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起笤妙,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涯贞,失蹤者是張志新(化名)和其女友劉穎枪狂,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宋渔,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡州疾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了皇拣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片严蓖。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖氧急,靈堂內(nèi)的尸體忽然破棺而出颗胡,到底是詐尸還是另有隱情,我是刑警寧澤吩坝,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布毒姨,位于F島的核電站,受9級(jí)特大地震影響钉寝,放射性物質(zhì)發(fā)生泄漏弧呐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一嵌纲、第九天 我趴在偏房一處隱蔽的房頂上張望俘枫。 院中可真熱鬧,春花似錦逮走、人聲如沸鸠蚪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)茅信。三九已至,卻和暖如春墓臭,著一層夾襖步出監(jiān)牢的瞬間汹押,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工起便, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棚贾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓榆综,卻偏偏與公主長(zhǎng)得像妙痹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鼻疮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容