1、订阅者程序

我们继续使用 turtlesim 作为测试平台,订阅 turtlesim_node发布的/turtle1/pose 话题。 这一话题的消息描述了海龟的位姿 (位置和朝向) 。尽管目前你已经对这一程序的某些部分感到熟悉了,但这里还是有三个新的知识点。

编写回调函数      发布和订阅消息的一个重要的区别是订阅者节点无法知道消息什么时候到达。为了应对这一事实,我们必须把响应收到消息事件的代码放到回调函数里,ROS 每接收到一个新的消息将调用一次这个函数。订阅者的回调函数类似于:

void function_name(const package_name::type_name &msg)
{
. . .
}

其中参数 package_name 和 type_name 和发布消息时的相同,它们指明了我们想订阅的话题的消息类。回调函数的主体有权限访问接收到消息的所有域,并以它认为合适的方式存储、使用或丢弃接收到的数据。 与往常一样, 我们必须包含定义该类的头文件。

本例程中,回调函数接收类型为 turtlesim::Pose 的消息,所以我们需要的头文件是 turtlesim/Pose.h。(我们可以使用 ros-topic
info 命令来确定这是正确的消息类型) 。这个回调函数仅仅是通过 ROS_INFO_STREAM 在终端打印消息数据,包括 x、y 和 theta 数据成员。 (我们可以使用 rosmsg 来查看这个消息类型拥有哪些数据域) 。与这里不同,一个真正的程序当然会使用消息来做一些有意义的事情。

注意订阅者的回调函数的返回值类型为 void。其实这样安排是合理的, 因为调用此函数是 ROS 的工作, 返回值也要交给 ROS,所以我们的程序无法获得返回值, 当然非 void 的返回值类型也就没有意义了。

创建订阅者对象      为了订阅一个话题,我们需要创建一个ros::Subscriber对象:

ros::Subscriber sub = node_handle.subscribe (topic_name,queue_size, pointer_to_callback_function);

这个构造函数有三个形参,其中大部分与 ros::Publisher 声明中的类似:

---node_handle 与我们之前多次见到的节点句柄对象是相同的。

---topic_name 是我们想要订阅的话题的名称,以字符串的形式表示。本例程中是"turtle1/pose"。再次强调,我们忽略了前斜线使其成为相对名称。

---queue_size 是本订阅者接收消息的队列大小,是一个整数。通常,你可以使用一个较大的整数,例如 1000,而不用太多关心队列处理过程。

---最后一个参数是指向回调函数的指针,当有消息到达时要通过这个指针找到回调函数。在 C++中,你可以通过对函数名使用符号运算符(&,“取址”)来获得函数的指针。在我们的实例中,其方法如下: &poseMessageReceived

你可能注意到了,创建 ros::Subscriber 对象时,我们没有在任何地方显式地提到消息类型。C++编译器会根据我们提供的函数指针中的数据类型判断出正确的消息类型。

给ROS控制权       最后的复杂之处在于只有当我们明确给ROS许可时,它才会执行我们的回调函数。实际上有两个略微不同的方式来做到这一点,其中一个版本如下所示:

ros::spinOnce();
这个代码要求 ROS 去执行所有挂起的回调函数,然后将控制权限返回给我们。

另一个方法如下所示:
ros::spin();

这个方法要求 ROS 等待并且执行回调函数,直到这个节点关机。

换句话说,ros::spin()大体等于这样一个循环:
while(ros::ok( )) 
{
ros::spinOnce();
}

使用 ros::spinOnce()还是使用 ros::spin()的建议如下:你的程序除了响应回调函数,还有其他重复性工作要做吗?如果答案是“否”,那么使用 ros::spin();否则,合理的选择是写一个循环,做其他需要做的事情, 并且周期性地调用 ros::spinOnce()来处理回调。本程序使用 ros::spin(),因为程序唯一的工作就是接收和打印接收到的位姿消息。

2、编译并运行subpose

编译和运行这个例程的步骤与我们之前看到的两个例程相同。

不要忘记确认为你的包添加了 turtlesim 依赖库,因为我们使用了 turtlesim/Pose 消息类型。

当 turtlesim_node 和 pubvel 两个程序同时运行时, 程序的输出如表 3.6 所示。

程序代码:

代码要同时运行上一节的发布程序 rosrun pub_vel pubvel,以及rosrun turtlesim turtlesim_node,再结合本节的程序 rosrun sub_vel subpose

package.xml文件添加的内容

对于CMakeLists.txt文件添加的内容

第3章 编写ROS程序-3的更多相关文章

  1. 第3章 编写ROS程序-1

    1.创建工作区和功能包 在我们写任何程序之前,第一步是创建一个容纳我们的功能包的工作区,然后再创建功能包本身. 创建工作区  使用标准的mkdir命令行去创建一个目录,我们将把这个新的目录称作工作区目 ...

  2. 第3章 编写ROS程序-2

    1.发布者程序 在本节中,我们将看到如何发送随机生成的速度指令到一个turtlesim海龟,使它漫无目的地巡游.这个程序的源文件称为pubvel,这个程序展示了从代码中发布消息涉及的所有要素. 其代码 ...

  3. C#入门到精通系列课程——第2章编写C#程序

    ◆本章内容 (1)熟悉Visual Studio 2017开发环境 (2)编写第一个C#程序 (3)C#程序结构预览 (4)程序编写规范 (5)难点解答 ◆本章简述 要学习C#编程,必然要熟悉C#程序 ...

  4. 编写ROS程序--HelloROS

    <机器人操作系统浅析>ch3学习记录 A Gentle Introduction to ROS 3.1 创建工作区(工作空间)和功能包 创建工作空间 ~/ros 我们称之为工作区目录 在工 ...

  5. SLAM+语音机器人DIY系列:(二)ROS入门——4.如何编写ROS的第一个程序hello_world

    摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...

  6. 第 3 章 编写 PAM 应用程序和服务

    Solaris 开发者安全性指南 Previous: 第 2 章 开发特权应用程序 Next: 第 4 章 编写使用 GSS-API 的应用程序 第 3 章 编写 PAM 应用程序和服务 可插拔验证模 ...

  7. ROS Learning-013 beginner_Tutorials (编程) 编写ROS服务版的Hello World程序(Python版)

    ROS Indigo beginner_Tutorials-12 编写ROS服务版的Hello World程序(Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的 ...

  8. ROS Learning-011 beginner_Tutorials (编程) 编写 ROS 话题版的 Hello World 程序(Python版)

    ROS Indigo beginner_Tutorials-10 编写 ROS 话题版的 Hello World 程序(Python版) 我使用的虚拟机软件:VMware Workstation 11 ...

  9. [Hadoop in Action] 第4章 编写MapReduce基础程序

    基于hadoop的专利数据处理示例 MapReduce程序框架 用于计数统计的MapReduce基础程序 支持用脚本语言编写MapReduce程序的hadoop流式API 用于提升性能的Combine ...

随机推荐

  1. meaven环境变量配置

    首先,先到官网去下载maven.这里是官网的地址:http://maven.apache.org/download.cgi  请选择最新的版本下载,这里咱们下载的是apache-maven-3.1.1 ...

  2. 2017-2018-1 20179209《Linux内核原理与分析》第四周作业

    本周学习内容为<跟踪分析MenuOS简单linux系统的启动过程>和教材中的进程调度及内核数据结构. 一.跟踪分析Linux内核的启动过程 这个实验我是在实验楼环境中完成的,最初想在自己的 ...

  3. jforum二次开发教程

    环境准备: 一.Tomcat服务器     首先需要在本地搭建tomcat.tomcat搭建过程本人博客中有,不再重复纪录.因为开始没有搭建成功,浪费了一定时间.   二.Mysql服务器     在 ...

  4. GEO(地理信息定位)

    核心知识点: 1.GEO是利用zset来存储地理位置信息,可以用来计算地理位置之间的距离,也可以做统计: 2.命令:geoadd geopos geodist geohash georadius/ge ...

  5. BZOJ 3037 创世纪

    题解: 首先从基环树上的环上选两个点x,y 断开x,y之间的边,然后做树形DP. 设f[x]为选x的情况下的最大值,g[x]为不选x的情况下的最大值. 分两种情况讨论, 1.选x,则y一开始就处于被支 ...

  6. CodeForces - 540C Ice Cave —— BFS

    题目链接:https://vjudge.net/contest/226823#problem/C You play a computer game. Your character stands on ...

  7. Codeforces - 828C String Reconstruction —— 并查集find()函数

    题目链接:http://codeforces.com/contest/828/problem/C C. String Reconstruction time limit per test 2 seco ...

  8. POJ1113 Wall —— 凸包

    题目链接:https://vjudge.net/problem/POJ-1113 Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submis ...

  9. block implicitly retains self to indicate this is 警告消除

    Build Settings 输入CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF 设置为No

  10. html5--2.7新的布局元素(4)-time

    html5--2.7新的布局元素(4)-time 学习要点 了解微格式的概念 掌握time元素的用法 微格式的概念 HTML5中的微格式,是一种利用HTML5中的新标签对网页添加附加信息的方法,附加信 ...