[ROS] [笔记(1)] 一个最简单的例子:Hello Robot(消息、发布者与订阅者)

本例程包含如下内容:
1)创建编译 Package;
2)自定义消息;
3)发布者与订阅者。

0、Hello Robot 的场景:
我们想要完成这样一个场景:

1)有一系列 robot 排成一排(publisher)向管理员(subscriber)报道,每个人都发一个消息(robotID),包含 name 和 id 类似:
name=robot id=0
name=robot id=1
name=robot id=2

2)有一个管理员订阅了这个消息(robotID),然后读取消息内容并且和每个机器人打招呼:
hello robot 0
hello robot 1
hello robot 2

要完成以上的功能,我们需要创建消息(robotID)、发送消息的发送者(publisher)、接收消息的订阅者(subscriber)。他们之间的关系是这样的:
hellorobot_graph

1、创建 ros 目录:
先我们为所有的 ROS 工程创建如下路径:

以后的笔记里面,我们把这一路径称作 ROS_PATH,这一路径就是我们所有 ros 工程的基本路径。

2、创建 workspace 和 package:
一个典型的 ros 工程是在一个 workspace 下包含若干个包,每一个包应该完成一套独立的功能。它的路径通常类似于:
workspace_folder/ -- WORKSPACE
src/ -1- SOURCE SPACE
CMakeLists.txt -- 'Toplevel' CMake file, provided by catkin
package_1/
CMakeLists.txt -- CMakeLists.txt file for package_1
package.xml -- Package manifest for package_1
...
package_n/
CMakeLists.txt -- CMakeLists.txt file for package_n
package.xml -- Package manifest for package_n

我们的 workspace 命名为 hellorobot_ws,我们将所有有关这一工程的包都放在 hellorobot_ws/src 路径下,现在进入 ROS_PATH 创建这个目录:
1) 创建 workspace:

2)创建 package:
我们在该 workspace 的 src 目录下创建一个名为 hellorobot 的 package:

这里面 std_msgs rospy roscpp 是我们通常一个最基本的C++包之中需要的依赖项。后面这些依赖项均可以通过配置 package.xml 进行更改。

3)编译 package:
即使什么都不写我们已经可以编译这个包了。编译包需要在 workspace 路径下

编译成功后在 ROS_PTAH/hellorobot_ws 下就可以看到如下目录结构已经生成了:
build
devel
src

顺便说一下大家在网上下git代码,其实都是其中一个包的src的部分,相当于我们的 ROS_PTAH/hellorobot_ws/src/hellorobot/src,因此只要放入这一目录再按照此步骤运行 catkin_make 即可。

3、创建自定义消息:
1)创建 robotMsg.msg 文件:
在这里我们需要一个消息,包含 name 和 id 两个字段,其中 name 自然都是 robot。我们在 ROS_PTAH/hellorobot_ws/src/hellorobot 路径下创建 msg 文件夹,然后新建 robotMsg.msg 文件:

文件内容如下:

2)在 package.xml 添加 message 依赖:
在 package.xml 中找到如下两行代码并且取消注释:

这两行分别表示在编译和运行时的 message 依赖。

3)在 CMakeList.txt 添加编译依赖:

找到 find_package 添加 message_generation,结果如下:

找到 add_message_files ,去掉注释并添加 robotMsg.msg 消息文件:

找到 generate_messages 函数去掉注释,结果如下:

找到 catkin_package 添加如下行并启用该部分,结果如下:

顺便说下,如果你运行 catkin_make 以后,这个消息的头文件生成在:
devel/include/hellorobot/robotMsg.h
目录下。

4、创建发布者 publisher:
我们在 ROS_PTAH/hellorobot_ws/src/hellorobot/src 目录下创建 publisher.cpp 文件,代码内容如下:

其中最关键的其实只有几行:

这一行声明了我们的 Node 名字叫 “publisher”。

这一行创建了一个 Node 句柄和 Publisher,它发布的消息是 “robotID”,后面的1000是缓存消息队列长度。

后面是一个循环来不断发送消息,其中:

这一部分是我们填写的消息内容,主要的后面两行,这是我们设计的消息部分。前面 header 基本上每个消息都会填写一下。

最后我们只需要:

就把消息发送出去了。

这一行也很关键,这是为了让后面 subscriber 的 callback 能够生效。

其余部分是控制循环时间的机制,这里就不赘述了。

5、创建订阅者 subscriber:
我们在 ROS_PTAH/hellorobot_ws/src/hellorobot/src 目录下创建 subscriber.cpp 文件,代码内容如下:

其中最关键的其实只有几行:

这是我们真正的回调函数,是 subscriber 接收到订阅消息的处理函数。这里我们仅仅是打出 msg 中我们之前定义的内容,id 和 name。

这一行与之前 Publisher 类似,唯一不同的是,这里用 checkRobotCallback 指定了我们之前定义的回调函数。

这一行与之前我们使用的 spinOnce 区别是,这里会进入一个循环,不停保持对 callback 的处理,因为我们这里是需要保持一直接收消息的,所以这里用 spin。

其余地方和之前介绍的 Publisher 内容一样。

6、编译:
1)修改 CMakeList.txt 添加 Publisher 和 Subscriber 编译项:
在 CMakeList.txt 文件结尾添加如下几行:

2)运行编译命令:
在 ROS_PTAH/hellorobot_ws/ 目录下运行 catkin 编译:

如果没有问题整个工程就编译完成了。

7、运行测试:
1)首先运行 roscore:

2)其次进入 workspace 目录配置环境:

3)运行 Publisher :

将会看到类似输出:

4)新开一个 Terminal (Ctrl+Alt+T)运行 subscriber:

首先重复步骤2)配置环境。然后运行:

将会看到类似输出:

* 但实际上先打开 subscriber 再打开 publisher ,我这里会看到 subscriber 是从 3 开始的,这个还不清楚是什么原因会漏掉前3个消息。

错误提示:
1、错误:Failed to contact master
如果看到如下错误:
[ERROR] [1446531999.044935824]: [registerPublisher] Failed to contact master at [localhost:11311]. Retrying...

请检查 roscore 是否正常打开。

源码下载:
hellorobot.tar

参考文献:
[1] http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29

One Comment

Add a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注