学习10:消息发布器和订阅器(C++)
来源:互联网 发布:翻拍小说的网络电视剧 编辑:程序博客网 时间:2024/06/08 10:20
因为我不会python,所以只能用C++了 - -#
1 节点
ROS中把可执行文件叫做【节点】。
去刚才的beginner_tutorial(眼花了,单词打没打错?……)目录下,新建src文件夹,里面写一个
talker.cpp
里面代码如下
/* * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */// %Tag(FULLTEXT)%// %Tag(ROS_HEADER)%#include "ros/ros.h"// %EndTag(ROS_HEADER)%// %Tag(MSG_HEADER)%#include "std_msgs/String.h"// %EndTag(MSG_HEADER)%#include <sstream>/** * This tutorial demonstrates simple sending of messages over the ROS system. */int main(int argc, char **argv){ /** * The ros::init() function needs to see argc and argv so that it can perform * any ROS arguments and name remapping that were provided at the command line. For programmatic * remappings you can use a different version of init() which takes remappings * directly, but for most command-line programs, passing argc and argv is the easiest * way to do it. The third argument to init() is the name of the node. * * You must call one of the versions of ros::init() before using any other * part of the ROS system. */// %Tag(INIT)% ros::init(argc, argv, "talker");// %EndTag(INIT)% /** * NodeHandle is the main access point to communications with the ROS system. * The first NodeHandle constructed will fully initialize this node, and the last * NodeHandle destructed will close down the node. */// %Tag(NODEHANDLE)% ros::NodeHandle n;// %EndTag(NODEHANDLE)% /** * The advertise() function is how you tell ROS that you want to * publish on a given topic name. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. After this advertise() call is made, the master * node will notify anyone who is trying to subscribe to this topic name, * and they will in turn negotiate a peer-to-peer connection with this * node. advertise() returns a Publisher object which allows you to * publish messages on that topic through a call to publish(). Once * all copies of the returned Publisher object are destroyed, the topic * will be automatically unadvertised. * * The second parameter to advertise() is the size of the message queue * used for publishing messages. If messages are published more quickly * than we can send them, the number here specifies how many messages to * buffer up before throwing some away. */// %Tag(PUBLISHER)% ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);// %EndTag(PUBLISHER)%// %Tag(LOOP_RATE)% ros::Rate loop_rate(10);// %EndTag(LOOP_RATE)% /** * A count of how many messages we have sent. This is used to create * a unique string for each message. */// %Tag(ROS_OK)% int count = 0; while (ros::ok()) {// %EndTag(ROS_OK)% /** * This is a message object. You stuff it with data, and then publish it. */// %Tag(FILL_MESSAGE)% std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str();// %EndTag(FILL_MESSAGE)%// %Tag(ROSCONSOLE)% ROS_INFO("%s", msg.data.c_str());// %EndTag(ROSCONSOLE)% /** * The publish() function is how you send messages. The parameter * is the message object. The type of this object must agree with the type * given as a template parameter to the advertise<>() call, as was done * in the constructor above. */// %Tag(PUBLISH)% chatter_pub.publish(msg);// %EndTag(PUBLISH)%// %Tag(SPINONCE)% ros::spinOnce();// %EndTag(SPINONCE)%// %Tag(RATE_SLEEP)% loop_rate.sleep();// %EndTag(RATE_SLEEP)% ++count; } return 0;}// %EndTag(FULLTEXT)%
/* * Copyright (C) 2008, Morgan Quigley and Willow Garage, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */// %Tag(FULLTEXT)%#include "ros/ros.h"#include "std_msgs/String.h"/** * This tutorial demonstrates simple receipt of messages over the ROS system. */// %Tag(CALLBACK)%void chatterCallback(const std_msgs::String::ConstPtr& msg){ ROS_INFO("I heard: [%s]", msg->data.c_str());}// %EndTag(CALLBACK)%int main(int argc, char **argv){ /** * The ros::init() function needs to see argc and argv so that it can perform * any ROS arguments and name remapping that were provided at the command line. For programmatic * remappings you can use a different version of init() which takes remappings * directly, but for most command-line programs, passing argc and argv is the easiest * way to do it. The third argument to init() is the name of the node. * * You must call one of the versions of ros::init() before using any other * part of the ROS system. */ ros::init(argc, argv, "listener"); /** * NodeHandle is the main access point to communications with the ROS system. * The first NodeHandle constructed will fully initialize this node, and the last * NodeHandle destructed will close down the node. */ ros::NodeHandle n; /** * The subscribe() call is how you tell ROS that you want to receive messages * on a given topic. This invokes a call to the ROS * master node, which keeps a registry of who is publishing and who * is subscribing. Messages are passed to a callback function, here * called chatterCallback. subscribe() returns a Subscriber object that you * must hold on to until you want to unsubscribe. When all copies of the Subscriber * object go out of scope, this callback will automatically be unsubscribed from * this topic. * * The second parameter to the subscribe() function is the size of the message * queue. If messages are arriving faster than they are being processed, this * is the number of messages that will be buffered up before beginning to throw * away the oldest ones. */// %Tag(SUBSCRIBER)% ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);// %EndTag(SUBSCRIBER)% /** * ros::spin() will enter a loop, pumping callbacks. With this version, all * callbacks will be called from within this thread (the main one). ros::spin() * will exit when Ctrl-C is pressed, or the node is shutdown by the master. */// %Tag(SPIN)% ros::spin();// %EndTag(SPIN)% return 0;}// %EndTag(FULLTEXT)%
2 编译节点
写好了代码自然要编译把- -#
再CMakeList.txt加入
include_directories(include ${catkin_INCLUDE_DIRS})add_executable(talker src/talker.cpp)target_link_libraries(talker ${catkin_LIBRARIES})add_executable(listener src/listener.cpp)target_link_libraries(listener ${catkin_LIBRARIES})
这会生成2个可执行文件talker和listener。并且存储cakin_ws/devel/lib/<package name>里。
还需要一行
add_dependencies(talker beginner_tutorials_generate_messages_cpp)
回到最高的工作空间,执行catkin_make。
生成了一堆东西,编译成功!
3. 执行节点
3.1 启动roscore
这个显然的。。先启动了先。
直接执行roscore,这个前文说过多次了
3.2 启动订阅器(listener)和发送器(talker)
首先确认source过那个我们刚在玩的工作空间下的setup,bash文件啊!!
直接
$ rosrun beginner_tutorials listener (C++)
$ rosrun beginner_tutorials talker字面就可以猜出来2个代码的意思~
(别忘了每个终端都需要source一次啊!!!)
4 解读代码
4.1 解读发布器代码
具体细节见代码,中文注释
#include "ros/ros.h"//貌似是核心的ros头文件,先引用了先。#include "std_msgs/String.h"//黑人问号.jpg#include <sstream>int main(int argc, char **argv){ /** * ros::init()函数需要argc和argv,这样可以实现我们之前也做过的,重定向节点名称。 * 重定向节点名称,我们再前面小乌龟模仿移动的章节玩过了。 * 第三个参数,比如下main的"talker"貌似是默认的节点名,且不能包含奇怪字符比如/ */// %Tag(INIT)% ros::init(argc, argv, "talker");// %EndTag(INIT)% /** * NodeHandle 是一个重要的节点类型,我们后续操作要用到这个东西。 * 貌似定义的时候,有很好的初始化函数。析构函数也写的很棒? */// %Tag(NODEHANDLE)% ros::NodeHandle n;// %EndTag(NODEHANDLE)% /** * advertise返回一个Publisher对象,第一个参数,"chatter"是话题名,1000是缓冲队列大小。 * (最多保存)的消息的数量。同时这个advertise还有2个功能,消息类型不对他会拒绝发布, * 他有一个publish成员,可以用来发布消息。(后面会出现介绍)。至于。。std_msg::String * 是干嘛的?难道指的是,发布的消息类型是std_msg::String类型的嘛?(看了源代码,貌似是这个意思)。 */// %Tag(PUBLISHER)% ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);// %EndTag(PUBLISHER)%// %Tag(LOOP_RATE)% ros::Rate loop_rate(10); //程序下面有一个ros::ok(),这个大致就是10Hz的频率执行ros::ok()// %EndTag(LOOP_RATE)%// %Tag(ROS_OK)%/** * ros::ok()为false的条件: * 1:键盘按了ctrl+c * 2:同样名字的节点被运行了 * 3:ros::shutdown() 被调用 * 4:节点中所有的 NodeHandle被销毁。 */ int count = 0; while (ros::ok()) {// %EndTag(ROS_OK)% /** * This is a message object. You stuff it with data, and then publish it. */// %Tag(FILL_MESSAGE)% std_msgs::String msg; std::stringstream ss; ss << "hello world " << count; msg.data = ss.str();// %EndTag(FILL_MESSAGE)%// %Tag(ROSCONSOLE)% ROS_INFO("%s", msg.data.c_str()); //目测,是向终端输出字符串。// %EndTag(ROSCONSOLE)%// %Tag(PUBLISH)% chatter_pub.publish(msg);//发布msg这个消息,msg类型正好也是之前再advertise里定义的std_msg::String类型,类型统一// %EndTag(PUBLISH)%// %Tag(SPINONCE)% ros::spinOnce();//貌似不写这句话,回调函数就没用了// %EndTag(SPINONCE)%// %Tag(RATE_SLEEP)% loop_rate.sleep();//上面定义了10Hz,这里就会休眠0.1s的样子。// %EndTag(RATE_SLEEP)% ++count; } return 0;}// %EndTag(FULLTEXT)%
4.2 解读代码接收器
一样的,直接看代码,和代码中文注释
#include "ros/ros.h"#include "std_msgs/String.h"/** * 下面是一个回调函数。再定义接收器的时候会用到。 * 看起来接收器实现的代码内部,会自动让这个函数绑定一个 * 消息的指针。比如这里,接受的消息类型是std_msgs::String类型,和前面定义 * 的发布器发布的消息类型一样。这里抓到消息,就用ROS_INFO命令,输出到 * 终端,让我们看到。*/// %Tag(CALLBACK)%void chatterCallback(const std_msgs::String::ConstPtr& msg){ ROS_INFO("I heard: [%s]", msg->data.c_str());}// %EndTag(CALLBACK)%int main(int argc, char **argv){ ros::init(argc, argv, "listener"); ros::NodeHandle n; /** * 这个订阅器的代码和之前的发布其很类似,参数分别为节点名、缓存大小。 * 第三个参数和前面的回调函数应该说过了。 * 很好的析构函数保证了,对象被销毁的时候,就不会再继续订阅了。 */// %Tag(SUBSCRIBER)% ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);// %EndTag(SUBSCRIBER)% /** * spin()函数会进入一个循环,软件实现中断程序~?中断级别之类的他怎么实现呢- -# * 当然了,还是会接受ctrl+c之类的退出。 */// %Tag(SPIN)% ros::spin();// %EndTag(SPIN)% return 0;}// %EndTag(FULLTEXT)%
阅读全文
0 0
- 学习10:消息发布器和订阅器(C++)
- ROS:消息发布器和订阅器(c++)
- ROS学习笔记--消息发布器和订阅器
- ROS入门_1.14 编写及测试简单的消息发布器和订阅器 (C++)
- 编写测试简单的消息发布器和订阅器 (C++)(十)
- 编写简单的消息发布器和订阅器
- ROS学习(基于Ubuntu 15.04 和ROS Jade)第三章 ROS核心教程 之 11 编写简单的消息发布器和订阅器 (C++)
- redis 消息订阅和发布
- ActiveMQ发布消息和订阅消息
- Redis学习10——消息订阅与发布
- rabbitMQ学习笔记(四) 发布/订阅消息
- rabbitMQ学习笔记(四) 发布/订阅消息
- ROS学习(-)基本概念+发布&订阅消息
- ROS 编写消息发布器(publisher)和订阅器(subscriber)-精简
- ROS 自定义消息发布器和订阅器测试 +代码详解(入门级)
- ROS-python实现简单的消息发布器和订阅器
- ROS教程(十一):编写简单的消息发布器和订阅器
- ROS教程(十二):测试消息发布器和订阅器
- mongodb的分组查询和处理
- 机器学习模型应用以及模型优化的一些思路
- Ngrok内网穿透配合msf木马
- git---基本操作、新建分支,合并分支branch到主干master ,git pull ,git push
- mongodb如何修改字段名称,删除字段
- 学习10:消息发布器和订阅器(C++)
- JavaScript在HTML中的使用
- 51 Nod1416DFS
- LTE实战技巧之下载速率提升
- 零基础Objective-C 第三章--------------面向对象编程的基础知识(1)
- 考研之中科大软院
- 暗时间(读书笔记)
- PHP分页函数
- html制作列表