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. LA 3882 And Then There Was One[约瑟夫问题的变形]

    And Then There Was One UVALive - 3882 Sample Input   Sample Output //设f[i]为(原约瑟夫问题)第i次要删除的标号 #includ ...

  2. Hadoop实战-Flume之自定义Source(十八)

    import java.nio.charset.Charset; import java.util.HashMap; import java.util.Random; import org.apach ...

  3. windows 安装 Redis

    本文安装的是 免安装版本: 1: https://github.com/MicrosoftArchive/redis/releases 下载Redis-x64-3.2.100.zip 设置密码 red ...

  4. 20170326 ABAP调用外部webservice实例

    调用外部webservice 使用Tcode: SICF SPROXSET      设置创建proxy 的权限 SE80 SOAMANAGER 一.目的:调用外部SRM系统的 webservice: ...

  5. 《高性能Javascript》 Summary(三)

    第八章.编程实践 Programming Practices 经验: 避免使用 eval_r()和Function构造器避免二次评估.此外,给setTimeout()和setInterval()函数传 ...

  6. NPM 与 Nodejs

    安装了Nodejs之后,NPM也安装好了 如何知道当前是否已经安装Nodejs和NPM了呢? node -v //查看当前nodejs的版本 npm -v //查看当前npm的版本 NPM 初始化 n ...

  7. centos7 永久修改主机名

    hostnamectl set-hostname xxx 一劳永逸,永绝后患

  8. hdmap相关单词

    交叉口(junction) 交叉口组(junctiongroup)

  9. jquery新添加元素无法删除

    $("body").on('click',".delic",function(){ $(this).parent().remove(); })

  10. CodeForces - 1005E2:Median on Segments (General Case Edition) (函数的思想)

    You are given an integer sequence a1,a2,…,ana1,a2,…,an. Find the number of pairs of indices (l,r)(l, ...