机器人操作系统ROS Indigo 入门学习12用C++语言写一个简单的发布者和订阅者.docx
- 文档编号:3567658
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:11
- 大小:21.84KB
机器人操作系统ROS Indigo 入门学习12用C++语言写一个简单的发布者和订阅者.docx
《机器人操作系统ROS Indigo 入门学习12用C++语言写一个简单的发布者和订阅者.docx》由会员分享,可在线阅读,更多相关《机器人操作系统ROS Indigo 入门学习12用C++语言写一个简单的发布者和订阅者.docx(11页珍藏版)》请在冰豆网上搜索。
机器人操作系统ROSIndigo入门学习12用C++语言写一个简单的发布者和订阅者
这个教程将会包含怎样用C++去写一个发布者和订阅者.
1.1写一个发布者Node
“Node”是连接在ROS网络中一个可执行单元的术语.这里我们创建一个会不断广播messages的发布者(“talker”)node.
改变目录到你之前创建的工作空间的beginner_tutorialspackage中:
cd~/catkin_ws/src/beginner_tutorials
1.1.1代码
在beginner_tutorialspackag目录中创建一个srv目录:
mkdir-p~/catkin_ws/src/beginner_tutorials/src
这个目录会包含所有beginner_tutorialspackage中的源文件.
在beginner_tutorialspackage中创建一个src/talker.cpp文件.并且把下面的代码粘贴上去":
27#include"ros/ros.h"
28#include"std_msgs/String.h"
29
30#include
31
32/**
33*ThistutorialdemonstratessimplesendingofmessagesovertheROSsystem.
34*/
35intmain(intargc,char**argv)
36{
37/**
38*Theros:
:
init()functionneedstoseeargcandargvsothatitcanperform
39*anyROSargumentsandnameremappingthatwereprovidedatthecommandline.Forprogrammatic
40*remappingsyoucanuseadifferentversionofinit()whichtakesremappings
41*directly,butformostcommand-lineprograms,passingargcandargvistheeasiest
42*waytodoit.Thethirdargumenttoinit()isthenameofthenode.
43*
44*Youmustcalloneoftheversionsofros:
:
init()beforeusinganyother
45*partoftheROSsystem.
46*/
47ros:
:
init(argc,argv,"talker");
48
49/**
50*NodeHandleisthemainaccesspointtocommunicationswiththeROSsystem.
51*ThefirstNodeHandleconstructedwillfullyinitializethisnode,andthelast
52*NodeHandledestructedwillclosedownthenode.
53*/
54ros:
:
NodeHandlen;
55
56/**
57*Theadvertise()functionishowyoutellROSthatyouwantto
58*publishonagiventopicname.ThisinvokesacalltotheROS
59*masternode,whichkeepsaregistryofwhoispublishingandwho
60*issubscribing.Afterthisadvertise()callismade,themaster
61*nodewillnotifyanyonewhoistryingtosubscribetothistopicname,
62*andtheywillinturnnegotiateapeer-to-peerconnectionwiththis
63*node.advertise()returnsaPublisherobjectwhichallowsyouto
64*publishmessagesonthattopicthroughacalltopublish().Once
65*allcopiesofthereturnedPublisherobjectaredestroyed,thetopic
66*willbeautomaticallyunadvertised.
67*
68*Thesecondparametertoadvertise()isthesizeofthemessagequeue
69*usedforpublishingmessages.Ifmessagesarepublishedmorequickly
70*thanwecansendthem,thenumberherespecifieshowmanymessagesto
71*bufferupbeforethrowingsomeaway.
72*/
73ros:
:
Publisherchatter_pub=n.advertise : String>("chatter",1000); 74 75ros: : Rateloop_rate(10); 76 77/** 78*Acountofhowmanymessageswehavesent.Thisisusedtocreate 79*auniquestringforeachmessage. 80*/ 81intcount=0; 82while(ros: : ok()) 83{ 84/** 85*Thisisamessageobject.Youstuffitwithdata,andthenpublishit. 86*/ 87std_msgs: : Stringmsg; 88 89std: : stringstreamss; 90ss<<"helloworld"< 91msg.data=ss.str(); 92 93ROS_INFO("%s",msg.data.c_str()); 94 95/** 96*Thepublish()functionishowyousendmessages.Theparameter 97*isthemessageobject.Thetypeofthisobjectmustagreewiththetype 98*givenasatemplateparametertotheadvertise<>()call,aswasdone 99*intheconstructorabove. 100*/ 101chatter_pub.publish(msg); 102 103ros: : spinOnce(); 104 105loop_rate.sleep(); 106++count; 107} 108 109 110return0; 111} 1.1.2代码解释 现在我们分解代码. #include“ros/ros.h” ros/ros.h是一个非常方便的头文件它包含了最常用的ROS系统部分所必须的一些头文件. #include“std_msgs/String.h” 这里包含了std_msgspackage中的std_msgs/Stringmessage.这个头文件自动的从String.msg.file中产生.更多关于message的信息,请查看msgpage. Ros: : init(argc,argv,”talker”); 初始化ROS.这个允许ROS通过命令行--(现在不重要)重新映射名字.同样可以用来制定node的名字.在系统中Nodes的名字必须是唯一的. 名字必须是一个基础的名字,比如,不能有/在里面. Ros: : NodesHandlen; 为这个node创建一个handle.创建的第一个NodeHandle用来初始化node,最后一个销毁的会清除所有node占有的资源. ros: : Publisherchatter_pub=n.advertise : String>("chatter",1000); 告诉master我们将要在chattertopic中要发布一个std_ksgs/String类型的message,这就会让master告诉nodes听取chatter,在这个tpoic上在我们将要发布数据.第二个参数是发布队列的大小.这样的话如果我们发布的太快,在开始丢弃之前的message前,它会最大缓冲是1000个messages. NodeHandle: : advertise()返回一个ros: : Publisher的对象,它有两个作用: (1)它包含一个允许你发布message到它创建的topic上的publish()方法(2)当它程序跑飞时,会自动避开危险. ros: : Rateloop_rate(10); ros: : Rate对象会指定一个你想循环的频率.它会跟踪距离上次调用Rate: : sleep(),有多长时间了,并且休眠正确长度的时间. 这里我们设置为10hz: intcount=0; while(ros: : ok()) {} 默认roscpp会安装一个SIGINT信号处理函数提供对ctrl+c的处理,ctrl+c会导致ros: : ok()返回错误. Ros: : ok()会返回错误如果: 接受到SIGINT(ctrl+c) 我们通过用另一个有同样名字的node网络。 ros: : shutdown()被应用的另一部分调用。 所有的ros: : NodeHandles都被摧毁了。 一旦ros: : ok()返回错误,所有的ROS调用都会失败. 87std_msgs: : Stringmsg; 88 89std: : stringstreamss; 90ss<<"helloworld"< 91msg.data=ss.str(); 我们使用适应message的类在ROS上广播了一个message,通常从一个msg文件产生出来。 其他复杂的数据类型也是是可以的,但是现在我们准备用标准的Stringmessage,它有一个成员: ”data”。 chatter_pub.publish(msg); 现在实际上我们在向任何一个连接上的人广播这个message. ROS_INFO("%s",msg.data.c_str()); ROS_INFO和它的友元类都是用来替代printf/cout的。 更多信息请看rosconsoledocumentation ros: : spinOnce(); 对于这个程序调用ros: : splinOnce()不是必要的,因为我们不会接受到任何回叫信号。 然而,如果你打算为这个应用添加一个订阅,并且没有调用ros: : splinOnce(),你绝不会得到回叫信号,所以还是添加的好。 loop_rate.sleep(); 现在使用ros: : Rate对象去空耗掉剩下的时间以满足10hz的发布速度。 这里是步骤的简要描叙: 初始化ROS系统 广告给master我们将要发布std_msgs/Stringmessage到chattertopic上 在发布message的时候循环以满足10次每秒钟 1.2写一个订阅者Node 1.2.1代码 在beginner_tutorialspackage中src目录下创建listener.cpp文件,并且把下面的代码粘贴进去: 28#include"ros/ros.h" 29#include"std_msgs/String.h" 30 31/** 32*ThistutorialdemonstratessimplereceiptofmessagesovertheROSsystem. 33*/ 34voidchatterCallback(conststd_msgs: : String: : ConstPtr&msg) 35{ 36ROS_INFO("Iheard: [%s]",msg->data.c_str()); 37} 38 39intmain(intargc,char**argv) 40{ 41/** 42*Theros: : init()functionneedstoseeargcandargvsothatitcanperform 43*anyROSargumentsandnameremappingthatwereprovidedatthecommandline.Forprogrammatic 44*remappingsyoucanuseadifferentversionofinit()whichtakesremappings 45*directly,butformostcommand-lineprograms,passingargcandargvistheeasiest 46*waytodoit.Thethirdargumenttoinit()isthenameofthenode. 47* 48*Youmustcalloneoftheversionsofros: : init()beforeusinganyother 49*partoftheROSsystem. 50*/ 51ros: : init(argc,argv,"listener"); 52 53/** 54*NodeHandleisthemainaccesspointtocommunicationswiththeROSsystem. 55*ThefirstNodeHandleconstructedwillfullyinitializethisnode,andthelast 56*NodeHandledestructedwillclosedownthenode. 57*/ 58ros: : NodeHandlen; 59 60/** 61*Thesubscribe()callishowyoutellROSthatyouwanttoreceivemessages 62*onagiventopic.ThisinvokesacalltotheROS 63*masternode,whichkeepsaregistryofwhoispublishingandwho 64*issubscribing.Messagesarepassedtoacallbackfunction,here 65*calledchatterCallback.subscribe()returnsaSubscriberobjectthatyou 66*mustholdontountilyouwanttounsubscribe.WhenallcopiesoftheSubscriber 67*objectgooutofscope,thiscallbackwillautomaticallybeunsubscribedfrom 68*thistopic. 69* 70*Thesecondparametertothesubscribe()functionisthesizeofthemessage 71*queue.Ifmessagesarearrivingfasterthantheyarebeingprocessed,this 72*isthenumberofmessagesthatwillbebufferedupbeforebeginningtothrow 73*awaytheoldestones. 74*/ 75ros: : Subscribersub=n.subscribe("chatter",1000,chatterCallback); 76 77/** 78*ros: : spin()willenteraloop,pumpingcallbacks.Withthisversion,all 79*callbackswillbecalledfromwithinthisthread(themainone).ros: : spin() 80*willexitwhenCtrl-Cispressed,orthenodeisshutdownbythemaster. 81*/ 82ros: : spin(); 83 84return0; 85} 1.2.2代码解释 现在,我们把代码打断成一段段的,忽略上面已经分析过的部分 34voidchatterCallback(conststd_msgs: : String: : ConstPtr&msg) 35{ 36ROS_INFO("Iheard: [%s]",msg->data.c_str()); 37} 当一个新的message抵达chattertopic时这个回调函数会被调用.这个message以boostshared_ptr,的形式传递,这意味着你可以储存它,而不用担心它会在被删除,并且无需拷贝底层的数据. ros: : Subscribersub=n.subscribe("chatter",1000,chatterCallback); 在master启动的前提下订阅chattertopic,ROS会调用chatterCallback()函数只要一个新的message到达时.第二个参数是队列的大小,假设我们没有足够的能力去使发送message足够的快.这样的话,如果队列达到1000个messages,随着新的message的到来,我们会开始丢掉旧的message. NodeHandle: : subscribe()会返回一个ros: : Subscriber对象,你必须坚持直到你想取消订阅.当订阅对象被摧毁时,它会自动取消订阅chattertopic. 这里有不同版本的NodeHandle: : subscribe()函数允许你指定一个类的成员函数,或者甚至任何被BoostFunction对象调用的东西,roscppoverview包含更多的信息. ros: : spin(); ros: : spin()进入了一个循环,调用message回调尽可能的快.即使这样,但不用担心,如果没有什么要做就不会占用许多CPU资源,ros: : spin()会退出一旦ros: : ok()返回错误,这意味着ros: : shutdown()被调用了,不是被默认的Ctrl+c处理函数,然后master告诉我们去关机,就是被手动调用. 还有其他调用回调函数的方法,但是这里我们不关心它.roscpp_tutorialspackage中有一些关于这个的应用演示。 roscppoverview 也包含更多的信息. 这里再一次简要的概括以上内容: 初始化ROS系统 订阅chattertopic Spin,等待message到来 当一个message到来时,chatterCallback()函数被调用 1.3编译代码 在之前的教程中你用catkin_create_pkg去创建一个package.xml和一个CMakeLists.txt文件. 产生的这个CMakeLists.txt文件看起来应该像这样(保留了在CreatingMsgsandSrvs中的修改和除去没有用的注释和例子): 1cmake_minimum_required(VERSION2.8.3) 2project(beginner_tutorials) 3 4##Findcatkinandanycatkinpackages 5find_package(catkinREQUIREDCOMPONENTSroscpprospystd_msgsgenmsg) 6 7##DeclareROSmessagesandservices 8add_message_files(DIRECTORYmsgFILESNum.msg) 9add_service_files(DIRECTORYsrvFILESAddTwoInts.srv) 10 11##Generateaddedmessagesandservices 12generate_messages(DEPENDENCIESstd_msgs) 13 14##Declareacatkinpackage 15catkin_package() 不要担心修改被注释掉的例子,只需要添加下面几行到你的CMakeLists.txt文件就好了: include_directories(include${catkin_INCLUDE_DIRS}) add_executable(talkersrc/talker.cpp) target_link_libraries(talker${ca
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 机器人操作系统ROS Indigo 入门学习12用C+语言写一个简单的发布者和订阅者 机器人 操作系统 ROS 入门 学习 12 C+ 语言 一个 简单 发布者 订阅