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. opencv的x64库的版本和vs的版本的对应关系

    1 关于vs的版本 visual studio是一个集成开发环境,而vc++是一个c++的compiler,vc++有一个版本和一个版本号,vs也有一个版本,它们的对应关系如下: MSVC++ 4.x ...

  2. vs2013 solution文件解析

    1 定义一个project Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "render", &quo ...

  3. sed相关

    1 global flag sed 's/xxx/xxx/' inputfile,如果没有带global flag g的话,匹配替换的只是inputfile中的每一行的第一个匹配项.如果带了g的话,才 ...

  4. php xmlrpc使用示例

    xmlrpc 远程过程调用, 使用xml文本方式传输数据. soap协议比xmlrpc复杂并强大. 1.修改 php.ini,开启 xmlrpc 扩展 2.rpc_client.php <?ph ...

  5. Golang 环境变量及工作区概念

    GOROOT go的安装路径 GOPATH 可以有多个目录,每个目录就是一个工作区,放置源码文件,以及安装后的归档文件和可执行文件: 第一个工作区比较重要,go get会自动从一些主流公用代码仓库下载 ...

  6. PHP生成图片太慢了。。有些都不出来、

    现在为了使用不同宽高的图片,做了个动态生成的程序.每次根据图片传入的宽高来输出图片,然后 html 页面里用 <img src="xxx.com/img?src=c8d997dae15 ...

  7. REST、DRF(View源码解读、APIView源码解读)

    一 . REST            前言 1 . 编程 : 数据结构和算法的结合 .小程序如简单的计算器,我们输入初始数据,经过计算,得到最终的数据,这个过程中,初始数据和结果数据都是数据,而计算 ...

  8. uboot移植添加nfs支持

    手头6410开发板uboot(基于2011.06)其他功能包括ping和tftp都执行正常,唯独缺少nfs. 只需要在其配置文件(每个开发板文件通常名称不同,include/configs/*6410 ...

  9. 51Nod XOR key —— 区间最大异或值 可持久化字典树

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1295 1295 XOR key  题目来源: HackerRa ...

  10. 分享知识-快乐自己:Struts2(动态方法、动态结果、通配符、方法内部跳转、action跳转、OGNL 的使用及注意事项)

    这里主要以案例演示:涵盖以下知识点 1.动态方法调用:使用关键 符号 ! 进行操作   例如:/命名空间 ! 方法名 2.动态结果集:就是说,通过后台返回的结果 ${} 获取,重定向到符合预期的页面. ...