参考于:ros官网教程

实验楼:ros机器人操作系统自主学习实验

基础知识

1 一个catkin程序包由什么组成?

一个程序包要想称为catkin程序包必须符合以下要求:

该程序包必须包含catkin compliant package.xml文件

这个package.xml文件提供有关程序包的元信息。

程序包必须包含一个catkin 版本的CMakeLists.txt文件,而Catkin

metapackages中必须包含一个对CMakeList.txt文件的引用。

每个目录下只能有一个程序包。

这意味着在同一个目录下不能有嵌套的或者多个程序包存在。

最简单的程序包也许看起来就像这样:

$ my_package/
CMakeLists.txt
package.xml

2 在catkin工作空间中的程序包

开发catkin程序包的一个推荐方法是使用catkin工作空间,但是你也可以单独开发(standalone)catkin 软件包。一个简单的工作空间也许看起来像这样:

workspace_folder/        -- WORKSPACE
src/ -- 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

3 创建一个catkin程序包

首先切换到之前通过创建 catkin 工作空间教程创建的 catkin 工作空间中的

src 目录下

现在使用catkin_create_pkg命令来创建一个名为'beginner_tutorials'的新程序包,这

个程序包依赖于std_msgs、roscpp和rospy:

$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

这将会创建一个名为beginner_tutorials的文件夹,这个文件夹里面包含一个package.xml文件和一个CMakeLists.txt文件,这两个文件都已经自动包含了部分你在执行catkin_create_pkg命令时提供的信息。

catkin_create_pkg命令会要求你输入package_name,如果有需要你还可以在后面添加一些

需要依赖的其它程序包。

4 程序包依赖关系

4.1 一级依赖

之前在使用catkin_create_pkg 命令时提供了几个程序包作为依赖包,现在我们可以使用rospack命令工具来查看一级依赖包。

$ rospack depends1 beginner_tutorials

可以看见

std_msgs
rospy
roscpp

就像你看到的,rospack列出了在运行catkin_create_pkg命令时作为参数的依赖包,这些依赖包随后保存在package.xml文件中。

4.2 间接依赖

在很多情况中,一个依赖包还会有它自己的依赖包,比如,rospy还有其它依赖包(类似于C语言的函数概念:一个函数中还使用了其他的函数,这个“其他函数”就是二级依赖)。

一个程序包还可以有好几个间接的依赖包,幸运的是使用rospack可以递归检测出所有的依赖。

5 自定义你的程序包

本部分教程将剖析catkin_create_pkg命令生成的每个文件并详细描述这些文件的组成部分。

5.1 自定义 package.xml

自动生成的package.xml文件应该在你的新程序包中。现在让我们一起来看看新生成的package.xml文件以及每一个需要你注意的标签元素。

5.1.1 描述标签

首先更新描述标签: 切换行号显示

 <description>The beginner_tutorials package</description>

将描述信息修改为任何你喜欢的内容,但是按照约定第一句话应该简短一些,因为它覆盖了程序包的范围。如果用一句话难以描述完全那就需要换行了。

5.1.2 维护者标签

接下来是维护者标签:

     <!-- One maintainer tag required, multiple allowed, one person
per tag -->
     <!-- Example:  -->
     <!-- <maintainer email="[email protected]">Jane
Doe</maintainer> -->
     <maintainer email="[email protected]">user</maintainer>

这是package.xml中要求填写的一个重要标签,因为它能够让其他人联系到程序包的相关人员。至少需要填写一个维护者名称,但如果有需要的话你可以添加多个。

除了在标签里面填写维护者的名称外,还应该在标签的email属性中填写邮箱地址:

<maintainer email="[email protected]">Your Name</maintainer>

(留下你的名字,这个依赖包是我开发的,可以按照这个联系方式找到我)

(Y)

5.1.3 许可标签

再接下来是许可标签,同样的也需要:

    <!-- One license tag required, multiple allowed, one license per
tag -->
    <!-- Commonly used license strings: -->
    <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1,
LGPLv3 -->
    <license>TODO</license>

你应该选择一种许可协议并将它填写到这里。一些常见的开源许可协议有BSD、MIT、Boost Software License、GPLv2、GPLv3、LGPLv2.1和LGPLv3。你可以在Open Source Initiative中阅读其中的若干个许可协议的相关信息。对于本教程我们将使用BSD协议,因为ROS核心组件的剩余部分已经使用了该协议:

   <license>BSD</license>

5.1.4 依赖项标签

接下来的标签用来描述程序包的各种依赖项,这些依赖项分为build_depend、buildtool_depend、run_depend、test_depend。关于这些标签的更详细介绍请参考Catkin Dependencies相关的文档。在之前的操作中,因为我们将 std_msgs、 roscpp、 和 rospy作为catkin_create_pkg命令的参数,所以生成的依赖项看起来如下:

<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>genmsg</build_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>python-yaml</run_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>

除了catkin中默认提供的buildtool_depend,所有我们列出的依赖包都已经被添加到build_depend标签中。在本例中,因为在编译和运行时我们需要用到所有指定的依赖包,因此还需要将每一个依赖包分别添加到run_depend标签中:

此处官网已经更新(<run_depend>修改为<exec_depend>)。

&lt;?xml version=&quot;1.0&quot;?&gt;&lt;package format=&quot;2&quot;&gt;
&nbsp; &lt;name&gt;beginner_tutorials&lt;/name&gt;
&nbsp; &lt;version&gt;0.1.0&lt;/version&gt;
&nbsp; &lt;description&gt;The beginner_tutorials package&lt;/description&gt; &nbsp; &lt;maintainer email=&quot;[email protected]&quot;&gt;Your Name&lt;/maintainer&gt;
&nbsp; &lt;license&gt;BSD&lt;/license&gt;
&nbsp; &lt;url type=&quot;website&quot;&gt;http://wiki.ros.org/beginner_tutorials&lt;/url&gt;
&nbsp; &lt;author email=&quot;[email protected]&quot;&gt;Jane Doe&lt;/author&gt; &nbsp; &lt;buildtool_depend&gt;catkin&lt;/buildtool_depend&gt; &nbsp; &lt;build_depend&gt;roscpp&lt;/build_depend&gt;
&nbsp; &lt;build_depend&gt;rospy&lt;/build_depend&gt;
&nbsp; &lt;build_depend&gt;std_msgs&lt;/build_depend&gt; &nbsp; &lt;exec_depend&gt;roscpp&lt;/exec_depend&gt;
&nbsp; &lt;exec_depend&gt;rospy&lt;/exec_depend&gt;
&nbsp; &lt;exec_depend&gt;std_msgs&lt;/exec_depend&gt;
&lt;/package&gt;
&nbsp;&nbsp;&nbsp;&nbsp; &lt;buildtool_depend&gt;catkin&lt;/buildtool_depend&gt; &nbsp;&nbsp;&nbsp;&nbsp; &lt;build_depend&gt;roscpp&lt;/build_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp; &lt;build_depend&gt;rospy&lt;/build_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp; &lt;build_depend&gt;std_msgs&lt;/build_depend&gt; &nbsp;&nbsp;&nbsp;&nbsp; &lt;run_depend&gt;roscpp&lt;/run_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp; &lt;run_depend&gt;rospy&lt;/run_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp; &lt;run_depend&gt;std_msgs&lt;/run_depend&gt;

((σ`д′)σ  使用场景和要求)

5.1.5 最后完成的 package.xml

(上面的那一团代码看着好多啊(T_T),就不能简单点么……

其实看着多的就只有注释而已,去掉注释之后呢?)

现在看下面最后去掉了注释和未使用标签后的package.xml文件就显得更加简洁了:

&nbsp;&nbsp;&nbsp; &lt;?xml version=&quot;1.0&quot;?&gt;
&nbsp;&nbsp;&nbsp; &lt;package&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;beginner_tutorials&lt;/name&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;0.1.0&lt;/version&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;The beginner_tutorials package&lt;/description&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;maintainer email=&quot;[email protected]&quot;&gt;Your Name&lt;/maintainer&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;license&gt;BSD&lt;/license&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url type=&quot;website&quot;&gt;http://wiki.ros.org/beginner_tutorials&lt;/url&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;author email=&quot;[email protected]&quot;&gt;Jane Doe&lt;/author&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;buildtool_depend&gt;catkin&lt;/buildtool_depend&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;build_depend&gt;roscpp&lt;/build_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;build_depend&gt;rospy&lt;/build_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;build_depend&gt;std_msgs&lt;/build_depend&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;run_depend&gt;roscpp&lt;/run_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;run_depend&gt;rospy&lt;/run_depend&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;run_depend&gt;std_msgs&lt;/run_depend&gt; &nbsp;&nbsp;&nbsp; &lt;/package&gt;

6 自定义 CMakeLists.txt   ←←(超级重要的内容!!!)

到此,这个包含程序包元信息的package.xml文件已经按照需要完成了裁剪整理,现在你可以继续下面的教程了。catkin_create_pkg命令生成的CMakeLists.txt文件将在后续关于编译ROS程序代码的教程中讲述。

现在你已经创建了一个新的ROS程序包,接下来我们开始编译这个程序包。

1 编译程序包

一旦安装了所需的系统依赖项,我们就可以开始编译刚才创建的程序包了。

注意: 如果你是通过apt或者其它软件包管理工具来安装ROS的,那么系统已经默认安装好所有依赖项。

记得事先source你的环境配置(setup)文件,在Ubuntu中的操作指令如下:

&nbsp;source /opt/ros/indigo(换成你所安装的ros版本,例如咱的是kinetic)/setup.zsh

1.1 使用 catkin_make

catkin_make 是一个命令行工具,它简化了 catkin 的标准工作流程。你可以认为 catkin_make 是在 CMake 标准工作流程中依次调用了cmake 和 make。

使用方法:

在catkin工作空间下

$ catkin_make [make_targets] [-DCMAKE_VARIABLES=...]

(就像C语言里面的F5按键一样,你的程序要编译才能运行,不过这里没有F5

键,只有catkin_make)

1.2 开始编译你的程序包

对于正要马上编译自己代码的读者,请同时看一下后面的(C++)/(Python)教程,因为你可能需要修改CMakeLists.txt文件。

按照之前的创建一个ROS程序包教程,你应该已经创建好了一个catkin 工作空间和一个名为beginner_tutorials的catkin程序包。现在切换到catkin workspace并查看文件夹:

$ cd ~/catkin_ws
/$ ls src
beginner_tutorials/&nbsp; CMakeLists.txt@&nbsp;

你可以看到一个名为beginner_tutorials的文件夹,这就是你在之前的catkin_create_pkg教程里创建的。现在我们可以使用catkin_make来编译它了:

$ catkin_make

你可以看到很多cmake 和 make 输出的信息:(显示的一堆日志不用管,只看最后的信息就行了,没报错就万岁(^_−)☆

Base path: /home/user/catkin_ws
Source space: /home/user/catkin_ws/src
Build space: /home/user/catkin_ws/build
Devel space: /home/user/catkin_ws/devel
Install space: /home/user/catkin_ws/install
####
#### Running command: &quot;cmake /home/user/catkin_ws/src
-DCATKIN_DEVEL_PREFIX=/home/user/catkin_ws/devel
-DCMAKE_INSTALL_PREFIX=/home/user/catkin_ws/install&quot; in
&quot;/home/user/catkin_ws/build&quot;
####-- The C compiler identification is GNU 4.2.1-- The CXX compiler
identification is Clang 4.0.0-- Checking whether C compiler has
-isysroot-- Checking whether C compiler has -isysroot - yes--
Checking whether C compiler supports OSX deployment target flag--
Checking whether C compiler supports OSX deployment target flag -
yes-- Check for working C compiler: /usr/bin/gcc-- Check for working
C compiler: /usr/bin/gcc -- works-- Detecting C compiler ABI info--
Detecting C compiler ABI info - done-- Check for working CXX
compiler: /usr/bin/c++-- Check for working CXX compiler: /usr/bin/c++
-- works-- Detecting CXX compiler ABI info-- Detecting CXX compiler
ABI info - done-- Using CATKIN_DEVEL_PREFIX: /tmp/catkin_ws/devel--
Using CMAKE_PREFIX_PATH: /opt/ros/groovy-- This workspace overlays:
/opt/ros/groovy-- Found PythonInterp: /usr/bin/python (found version
&quot;2.7.1&quot;) -- Found PY_em: /usr/lib/python2.7/dist-packages/em.pyc--
Found gtest: gtests will be built-- catkin 0.5.51-- BUILD_SHARED_LIBS
is on-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-- ~~&nbsp;
traversing packages in topological order:-- ~~&nbsp; -
beginner_tutorials-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--
+++ add_subdirectory(beginner_tutorials)-- Configuring done--
Generating done-- Build files have been written to:
/home/user/catkin_ws/build
####
#### Running command: &quot;make -j4&quot; in &quot;/home/user/catkin_ws/build&quot;
####

(喏,这就是上面那一堆的解释)catkin_make首先输出它所使用到的每个空间所在的路径。更多关于空间的信息,请参考REP128

https://www.ros.org/reps/rep-0128.html(不过我想你也不会看……)和catkin/workspaces。

需要注意的是由于这些空间存在默认配置的原因,有几个文件夹已经在catkin工作空间自动生成了,使用ls查看:

$ ls
builddevelsrc

build 目录是build space的默认所在位置,同时cmake 和 make也是在这里被调用来配置并编译你的程序包。devel 目录是devel space的默认所在位置, 同时也是在你安装程序包之前存放可执行文件和库文件的地方。

(好了,现在你的软件已经编译好了,怎么让它运行起来呢?请看下一章节点

接下来你就看是接触ros里面第一个重要的概念了。//敲黑板)

理解 ROS 节点

概念概述

Nodes:节点,一个节点即为一个可执行文件,它可以通过ROS与其它节点进行通信。

可以看成是一个应用程序,用来完成某些功能

ros基础知识总结-LMLPHP

Messages:消息,消息是一种ROS数据类型,用于订阅或发布到一个话题。

翻译:(书面或口头的) 信息,消息,音信; 电邮(或手机)信息;

(书籍、演讲等的) 要旨,要点,教训;

就是信嘛,可以理解为各个节点之间要通信,不论传的是什么吧,都把他们塞进一个信封里,然后传出去。不管这信封里塞的是一张纸,还是一台冰箱或是一只大象什么的,统统叫做messages

Topics:话题,节点可以发布消息到话题,也可以订阅话题以接收消息。

Service:服务,服务允许节点发送请求(request) 并获得一个响应(response).

话题就像订报纸杂志,别人发什么你看什么,先看的东西不一定有.

服务就像是面对面的服务员,“哎,给我倒杯水。哎,给我上个麻辣香锅儿”然后后厨做出来了:“32号桌麻辣香锅一位~”小二然后就把菜端过来:“客官您的菜,慢用。”

Mster:节点管理器,ROS名称服务 (比如帮助节点找到彼此)。

就是中介

rosout: ROS中相当于stdout/stderr。

roscore: 主机+ rosout + 参数服务器 (参数服务器会在后面介绍)。

节点

一个节点其实只不过是ROS程序包中的一个可执行文件。ROS节点可以使用ROS客户库与其他节点通信。节点可以发布或者接收一个话题。节点也可以提供或使用某种服务。

客户端库

ROS客户端库允许使用不同编程语言编写的节点之间互相通信:

rospy = python 客户端库

roscpp = c++ 客户端库

roscore

roscore 是你在运行所有ROS程序前首先要运行的命令。

(通常被我用来测试ros环境是否正常安装hellip;hellip;)

使用rosnode

打开一个新的终端, 可以使用 rosnode 像运行 roscore 一样看看在运行什么...

注意: 当打开一个新的终端时,你的运行环境会复位,同时你的

~/.bashrc 文件会复原。如果你在运行类似于 rosnode 的指令时出现一些问题,也许你需要添加一些环境设置文件到你的

~/.bashrc 或者手动重新配置他们。

rosnode 显示当前运行的ROS节点信息。rosnode list 指令列出活跃的节点:

$ rosnode list

你会看到:

/rosout

这表示当前只有一个节点在运行: rosout 。因为这个节点用于收集和记录节点调试输出信息,所以他总是在运行的。

rosnode info 命令返回的是关于一个特定节点的信息。

$ rosnode info /rosout

这给了我们更多的一些有关于rosout的信息, 例如,事实上由它发布/rosout_agg:

------------------------------------------------------------------------Node [/rosout]
Publications:
&nbsp;* /rosout_agg [rosgraph_msgs/Log] Subscriptions:
&nbsp;* /rosout [unknown type] Services:
&nbsp;* /rosout/set_logger_level
&nbsp;* /rosout/get_loggers contacting node http://machine_name:54614/ ...
Pid: 5092

现在,让我们看看更多的节点。为此,我们将使用rosrun 弹出另一个节点。

使用 rosrun

rosrun 允许你使用包名直接运行一个包内的节点(而不需要知道这个包的路径)。

用法:

$ rosrun [package_name] [node_name]

现在我们可以运行turtlesim包中的 turtlesim_node。

然后, 在一个 新的终端:

$ rosrun turtlesim turtlesim_node

你会看到 turtlesim 窗口:

ros基础知识总结-LMLPHP

注意: 这里的 turtle 可能和你的 turtlesim 窗口不同。别担心,只是因为版本不同而已。

ROS的一个强大特性就是你可以通过命令行重新配置名称。

关闭 turtlesim 窗口停止运行节点 (或者回到rosrun turtlesim终端并使用ctrl-C)。现在让我们重新运行它,但是这一次使用Remapping Argument改变节点名称:

$ rosrun turtlesim turtlesim_node __name:=my_turtle

现在,我们退回使用 rosnode list:

$ rosnode list

你会看见类似于:

/rosout
/my_turtle(改过名字之后的)

理解ROS话题

1 开始

1.1 roscore

首先确保roscore已经运行, 打开一个新的终端:

$ roscore

如果你没有退出在上一篇教程中运行的roscore,那么你可能会看到下面的错误信息:

roscore cannot run as another roscore/master is already running.
Please kill other roscore/master processes before relaunching

这是正常的,因为只需要有一个roscore在运行就够了。

1.2 turtlesim

在本教程中我们也会使用到turtlesim,请在一个新的终端中运行:

$ rosrun turtlesim turtlesim_node

1.3 通过键盘远程控制turtle

我们也需要通过键盘来控制turtle的运动,请在一个新的终端中运行:

$ rosrun turtlesim turtle_teleop_key
[ INFO] 1254264546.878445000: Started node [/teleop_turtle], pid
[5528], bound on [aqy], xmlrpc port [43918], tcpros port [55936],
logging to [~/ros/ros/log/teleop_turtle_5528.log], using [real] time
Reading from keyboard
---------------------------
Use arrow keys to move the turtle.

现在你可以使用键盘上的方向键来控制turtle运动了。如果不能控制,请选中turtle_teleop_key所在的终端窗口以确保你的按键输入能够被捕获。

//目标:写一个tutle的键盘控制包。

2 ROS Topics

turtlesim_node 节点和 turtle_teleop_key 节点之间是通过一个 ROS 话题来互相通信的。turtle_teleop_key 在一个话题上发布按键输入消息,而 而 turtlesim 则订阅该话题以接收该消息。下面让我们使用 rqt_graph 来显示当前运行的节点和话题

2.1 使用 rqt_graph

rqt_graph能够创建一个显示当前系统运行情况的动态图形。rqt_graph是rqt程序包中的一部分。如果你没有安装,请通过以下命令来安装(如果是按照ros官网上进行的安装,并且是安装的完全版,则需要的程序包已经被安装完成,无需执行下面的命令):

$ sudo apt-get install ros-indigo-rqt
$ sudo apt-get install ros-indigo-rqt-common-plugins

在一个新终端中运行:

$ rosrun rqt_graph rqt_graph

你会看到类似下图所示的图形:

ros基础知识总结-LMLPHP

如果你将鼠标放在/turtle1/command_velocity上方,相应的ROS节点(蓝色和绿色)和话题(红色)就会高亮显示。正如你所看到的,turtlesim_node和turtle_teleop_key节点正通过一个名为/turtle1/command_velocity的话题来互相通信。

ros基础知识总结-LMLPHP

(两个人,一个人叫/teleop_turtle,是个编杂志的,另一个叫/turtlesim,是个读者,然后那个编杂志发了个杂志名字叫做/turtle1/command_velocity)

2.2 rostopic介绍

rostopic命令工具能让你获取有关ROS话题的信息。

你可以使用帮助选项查看rostopic的子命令:

$ rostopic -h

2.3 使用 rostopic echo

rostopic echo可以显示在某个话题上发布的数据。

用法:

$ rostopic echo [topic]

2.4 使用 rostopic list

rostopic list能够列出所有当前订阅和发布的话题。

让我们查看一下list子命令需要的参数,在一个新终端中运行:

$ rostopic list -h

2.3 使用 rostopic list

rostopic list能够列出所有当前订阅和发布的话题。

让我们查看一下list子命令需要的参数,在一个新终端中运行:

$ rostopic list -h
Usage: rostopic list [/topic]
Options:
&nbsp; -h, --help&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; show this help message and exit
&nbsp; -b BAGFILE, --bag=BAGFILE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list topics in .bag file
&nbsp; -v, --verbose&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list full details about each topic
&nbsp; -p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list only publishers
&nbsp; -s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list only subscribers

在rostopic list中使用verbose选项:

$ rostopic list -v

这会显示出有关所发布和订阅的话题及其类型的详细信息。

Published topics:
&nbsp;* /turtle1/color_sensor [turtlesim/Color] 1 publisher
&nbsp;* /turtle1/command_velocity [turtlesim/Velocity] 1 publisher
&nbsp;* /rosout [roslib/Log] 2 publishers
&nbsp;* /rosout_agg [roslib/Log] 1 publisher
&nbsp;* /turtle1/pose [turtlesim/Pose] 1 publisher Subscribed topics:
&nbsp;* /turtle1/command_velocity [turtlesim/Velocity] 1 subscriber
&nbsp;* /rosout [roslib/Log] 1 subscriber

3 ROS Messages

话题之间的通信是通过在节点之间发送ROS消息实现的。对于发布器(turtle_teleop_key)和订阅器(turtulesim_node)之间的通信,发布器和订阅器之间必须发送和接收相同类型的消息。这意味着话题的类型是由发布在它上面的消息类型决定的。使用rostopic type命令可以查看发布在某个话题上的消息类型。

3.1 使用 rostopic type

rostopic type 命令用来查看所发布话题的消息类型。

用法:

$ rostopic type [topic]
$ rostopic type /turtle1/cmd_vel

你应该会看到:

geometry_msgs/Twist
$ rosmsg show geometry_msgs/Twist
geometry_msgs/Vector3 linear
&nbsp; float64 x
&nbsp; float64 y
&nbsp; float64 z
geometry_msgs/Vector3 angular
&nbsp; float64 x
&nbsp; float64 y
&nbsp; float64 z

现在我们已经知道了turtlesim节点所期望的消息类型,接下来我们就可以给turtle发布命令。

4 继续学习 rostopic

现在我们已经了解了什么是ROS的消息,接下来我们开始结合消息来使用rostopic。

4.1 使用 rostopic pub

rostopic pub可以把数据发布到当前某个正在广播的话题上。

用法:

$ rostopic pub [topic] [msg_type] [args]

示例:

$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- &apos;[2.0, 0.0,
0.0]&apos; &apos;[0.0, 0.0, 1.8]&apos;

以上命令会发送一条消息给turtlesim,告诉它以2.0大小的线速度和1.8大小的角速度开始移动。

ros基础知识总结-LMLPHP

这是一个非常复杂的例子,因此让我们来详细分析一下其中的每一个参数。

rostopic pub 这条命令将会发布消息到某个给定的话题。

-1 (单个破折号)这个参数选项使rostopic发布一条消息后马上退出。

/turtle1/cmd_vel 这是消息所发布到的话题名称。

geometry_msgs/Twist 这是所发布消息的类型。

-- (双破折号)这会告诉命令选项解析器接下来的参数部分都不是命令选项。这在参数里面包含有破折号-(比如负号)时是必须要添加的。

'[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]' 正如之前提到的,在一个turtlesim/Velocity消息里面包含有两个浮点型元素:linear和angular。在本例中,2.0是linear的值,1.8是angular的值。这些参数其实是按照YAML语法格式编写的,这在YAML文档中有更多的描述。

你可能已经注意到turtle已经停止移动了。这是因为turtle需要一个稳定的频率为1Hz的命令流来保持移动状态。

$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- &apos;[2.0,
0.0, 0.0]&apos; &apos;[0.0, 0.0, 1.8]&apos;

这条命令以1Hz的频率发布速度命令到速度话题上。

我们也可以看一下rqt_graph中的情形,可以看到rostopic发布器节点(红色)正在与rostopic echo节点(绿色)进行通信:

正如你所看到的,turtle正沿着一个圆形轨迹连续运动。我们可以在一个新终端中通过rostopic echo命令来查看turtlesim所发布的数据。

ros基础知识总结-LMLPHP

4.2 使用 rostopic hz

rostopic hz命令可以用来查看数据发布的频率。

用法:

$ rostopic hz [topic]

我们看一下turtlesim_node发布/turtle/pose时有多快:

$ rostopic hz /turtle1/pose

你会看到:

subscribed to [/turtle1/pose]
average rate: 59.354
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; min: 0.005s max: 0.027s std dev: 0.00284s window: 58
average rate: 59.459
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; min: 0.005s max: 0.027s std dev: 0.00271s window: 118
average rate: 59.539
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; min: 0.004s max: 0.030s std dev: 0.00339s window: 177
average rate: 59.492
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; min: 0.004s max: 0.030s std dev: 0.00380s window: 237
average rate: 59.463
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; min: 0.004s max: 0.030s std dev: 0.00380s window: 290
$ rostopic type /turtle1/cmd_vel | rosmsg show

到此我们已经完成了通过rostopic来查看话题相关情况的过程,接下来我将使用另一个工具来查看turtlesim发布的数据。

5 使用 rqt_plot

rqt_plot命令可以实时显示一个发布到某个话题上的数据变化图形。这里我们将使用rqt_plot命令来绘制正在发布到/turtle1/pose话题上的数据变化图形。首先,在一个新终端中运行rqt_plot命令:

$ rosrun rqt_plot rqt_plot

这会弹出一个新窗口,在窗口左上角的一个文本框里面你可以添加需要绘制的话题。在里面输入/turtle1/pose/x后之前处于禁用状态的加号按钮将会被使能变亮。按一下该按钮,并对/turtle1/pose/y重复相同的过程。现在你会在图形中看到turtle的X-Y位置坐标图。

ros基础知识总结-LMLPHP

按下减号按钮会显示一组菜单让你隐藏图形中指定的话题。现在隐藏掉你刚才添加的话题并添加/turtle1/pose/theta,你会看到如下图所示的图形:

ros基础知识总结-LMLPHP

ros基础知识总结-LMLPHP

本部分教程到此为止,请使用Ctrl-C退出rostopic命令,但要保持turtlesim继续运行。

到此我们已经理解了ROS话题是如何工作的,接下来我们开始学习理解ROS服务和参数。

理解ROS服务和参数

1 ROS Services

服务(services)是节点之间通讯的另一种方式。服务允许节点发送请求(request) 并获得一个响应(response)。

(以下为整理内容,都是参数,知道并且会用就完事了)

2 使用rosservice

rosservice 可以很轻松的使用 ROS 客户端/服务器框架提供的服务。rosservice

提供了很多可以在 topic 上使用的命令,如下所示:

使用方法:

rosservice list         输出可用服务的信息

rosservice call         调用带参数的服务

rosservice type         输出服务类型

rosservice find         依据类型寻找服务find services by service

typerosservice uri          输出服务的ROSRPC uri

2.1 rosservice list

$ rosservice list

list 命令显示turtlesim节点提供了9个服务:

重置(reset), 清除(clear),

再生(spawn), 终止(kill), turtle1/set_pen,

/turtle1/teleport_absolute, /turtle1/teleport_relative,

turtlesim/get_loggers, and turtlesim/set_logger_level. 同时还有另外两个rosout节点提供的服务: /rosout/get_loggers and/rosout/set_logger_level.

/clear
/kill
/reset
/rosout/get_loggers
/rosout/set_logger_level
/spawn
/teleop_turtle/get_loggers
/teleop_turtle/set_logger_level
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/get_loggers
/turtlesim/set_logger_level

我们使用rosservice type命令更进一步查看clear服务:

2.2 rosservice type

使用方法:

rosservice type [service]

我们来看看clear服务的类型:

$ rosservice type clear
std_srvs/Empty

服务的类型为空(empty),这表明在调用这个服务是不需要参数(比如,请求不需要发送数据,响应也没有数据。)

下面我们使用rosservice call命令调用服务:

2.3 rosservice call

使用方法:

rosservice call [service] [args]

因为服务类型是空,所以进行无参数调用:

$ rosservice call clear

正如我们所期待的,服务清除了turtlesim_node的背景上的轨迹。

ros基础知识总结-LMLPHP

通过查看再生(spawn)服务的信息,我们来了解带参数的服务:

$ rosservice type spawn| rossrv show
float32 x
float32 y
float32 thetastring name
---
string name

这个服务使得我们可以在给定的位置和角度生成一只新的乌龟。名字参数是可选的,这里我们不设具体的名字,让turtlesim自动创建一个。

$ rosservice call spawn 2 2 0.2 &quot;&quot;

服务返回了新产生的乌龟的名字:

name: turtle2

现在我们的乌龟看起来应该是像这样的:

ros基础知识总结-LMLPHP

3 Using rosparam

rosparam使得我们能够存储并操作ROS 参数服务器(Parameter Server)上的数据。参数服务器能够存储整型、浮点、布尔、字符串、字典和列表等数据类型。rosparam使用YAML标记语言的语法。一般而言,YAML的表述很自然:1 是整型, 1.0 是浮点型, one是字符串, true是布尔, [1, 2, 3]是整型列表, {a: b, c: d}是字典. rosparam有很多指令可以用来操作参数.

使用方法:

rosparam set&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设置参数
rosparam get&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取参数
rosparam load&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从文件读取参数
rosparam dump&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 向文件中写入参数
rosparam delete&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 删除参数
rosparam list&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 列出参数名

我们来看看现在参数服务器上都有哪些参数:

3.1 rosparam list

$ rosparam list

我们可以看到turtlesim节点在参数服务器上有3个参数用于设定背景颜色:

/background_b/background_g/background_r/roslaunch/uris/aqy:51932/run_id

3.2 rosparam 设置 and rosparam 获取

使用:

$ rosparam set [param_name]
$ rosparam get [param_name]

现在我们修改背景颜色的红色通道:

$ rosparam set background_r 150

上述指令修改了参数的值,现在我们调用清除服务使得修改后的参数生效:

$ rosservice call clear

现在 我们的小乌龟看起来应该是像这样:

ros基础知识总结-LMLPHP

现在我们来查看参数服务器上的参数值——获取背景的绿色通道的值:

$ rosparam get background_g
86

我们可以使用rosparam get /来显示参数服务器上的所有内容:

$ rosparam get /
background_b: 255background_g: 86background_r: 150roslaunch:
&nbsp; uris: {&apos;aqy:51932&apos;: &apos;http://aqy:51932/&apos;}run_id:
e07ea71e-98df-11de-8875-001b21201aa8

你可能希望存储这些信息以备今后重新读取。这通过rosparam很容易就可以实现:

3.3 rosparam dump and rosparam load

使用方法:

$ rosparam dump [file_name]
$ rosparam load [file_name] [namespace]

现在我们将所有的参数写入params.yaml文件:

$ rosparam dump params.yaml

你甚至可以将yaml文件重载入新的命名空间,比如说copy空间:

$ rosparam load params.yaml copy
$ rosparam get copy/background_b
255

ros基础知识总结-LMLPHP

至此,我们已经了解了ROS服务和参数服务器的使用,接下来,我们一同试试使用 rqt_console 和 roslaunch。

使用 rqt_console 和 roslaunch

1 预先安装rqt和turtlesim程序包

从本节开始,为提高效率,请先下载在Github上的ros turorials功能包(同样桌面完整版有预装过,所以下面的命令可以无视)。https://github.com/ros/ros_tutorials/tree/indigo-devel 。 本教程会用到rqt 和

turtlesim这两个程序包,如果你没有安装,请先安装

$ sudo apt-get install ros-&lt;distro&gt;-rqt
ros-&lt;distro&gt;-rqt-common-plugins ros-&lt;distro&gt;-turtlesim

请使用ROS发行版名称(比如 electric、fuerte、groovy、hydro或indigo)替换掉<distro>。

注意: 你可能已经在之前的某篇教程中编译过rqt和turtlesim,如果你不确定的话重新编译一次也没事。

2 使用rqt_console和rqt_logger_level

rqt_console 属于ROS日志框架(logging framework)的一部分,用来显示节点的输出信息。 rqt_logger_level 允许我们修改节点运行时输出信息的日志等级(logger levels)(包括 DEBUG、WARN、INFO和ERROR)。现在让我们来看一下 turtlesim 在 rqt_console 中的输出信息,同时在 rqt_logger_level 中修改日志等级。在启动 turtlesim 之前先在另外两个新终端中运行 rqt_console 和 rqt_logger_level:

$ rosrun rqt_console rqt_console
$ rosrun rqt_logger_level rqt_logger_level

你会看到弹出两个窗口:

ros基础知识总结-LMLPHP

ros基础知识总结-LMLPHP

现在让我们在一个新终端中启动turtlesim:

$ rosrun turtlesim turtlesim_node

因为默认日志等级是INFO,所以你会看到turtlesim启动后输出的所有信息,如下图所示:

ros基础知识总结-LMLPHP

现在让我们刷新一下rqt_logger_level窗口并选择Warn将日志等级修改为WARN,如下图所示:

ros基础知识总结-LMLPHP

$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 0.0]'

ros基础知识总结-LMLPHP

2.1 日志等级说明

日志等级按以下优先顺序排列:

FatalErrorWarn
Info
Debug

Fatal是最高优先级,Debug 是最低优先级。通过设置日志等级你可以获取该等级及其以上优先等级的所有日志消息。比如,将日志等级设为Warn时,你会得到 Warn、Error和 Fatal 这三个等级的所有日志消息。

现在让我们按Ctrl-C退出turtlesim节点,接下来我们将使用 roslaunch 来启动多个 turtlesim 节点和一个模仿节点以让一个 turtlesim 节点来模仿另一个 turtlesim 节点。

2.2 使用roslaunch

roslaunch可以用来启动定义在launch文件中的多个节点。

用法:

$ roslaunch [package] [filename.launch]

先切换到beginner_tutorials程序包目录下:

$ roscd beginner_tutorials

如果roscd执行失败了,记得设置你当前终端下的ROS_PACKAGE_PATH环境变量。

$ roscd beginner_tutorials

如果你仍然无法找到beginner_tutorials程序包,说明该程序包还没有创建,那么请返回到ROS/Tutorials/CreatingPackage教程,并按照创建程序包的操作方法创建一beginner_tutorials程序包。

然后创建一个launch文件夹:

$ mkdir launch$ cd launch

2.3 Launch 文件

现在我们来创建一个名为 turtlemimic.launch 的 launch 文件并复制粘贴以下内容到该文件里面:


<launch> <group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group> <group ns="turtlesim2">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group> <node pkg="turtlesim" name="mimic" type="mimic">
<remap from="input" to="turtlesim1/turtle1"/>
<remap from="output" to="turtlesim2/turtle1"/>
</node> </launch>

2.4 Launch 文件解析

现在我们开始逐句解析launch xml文件。

<launch>

在这里我们以launch标签开头以表明这是一个launch文件。

<group ns="turtlesim1">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group> <group ns="turtlesim2">
<node pkg="turtlesim" name="sim" type="turtlesim_node"/>
</group>

在这里我们创建了两个节点分组并以'命名空间(namespace)'标签来区分,其中一个名为turtulesim1,另一个名为turtlesim2,两个组里面都使用相同的turtlesim节点并命名为'sim'。这样可以让我们同时启动两个turtlesim模拟器而不会产生命名冲突。

<node pkg="turtlesim" name="mimic" type="mimic">
<remap from="input" to="turtlesim1/turtle1"/>
<remap from="output" to="turtlesim2/turtle1"/>
</node>

在这里我们启动模仿节点,并将所有话题的输入和输出分别重命名为turtlesim1和turtlesim2,这样就会使turtlesim2模仿turtlesim1。

</launch>

这个是launch文件的结束标签。

2.5 使用roslaunch

现在让我们通过roslaunch命令来启动launch文件。

$ roslaunch beginner_tutorials turtlemimic.launch

现在将会有两个turtlesims被启动,然后我们在一个新终端中使用rostopic命令发送速度设定消息:

$ rostopic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/Twist -r 1
-- &apos;[2.0, 0.0, 0.0]&apos; &apos;[0.0, 0.0, -1.8]&apos;

你会看到两个turtlesims会同时开始移动,虽然发布命令只是给turtlesim1发送了速度设定消息。

我们也可以通过rqt_graph来更好的理解在launch文件中所做的事情。运行rqt并在主窗口中选择rqt_graph:

$ rqt

或者直接运行:

$ rqt_graph

ros基础知识总结-LMLPHP

ros基础知识总结-LMLPHP

到此,我们算是已经学会了 rqt_console 和 roslaunch 命令的使用,接下来我们开始学习使用rosedmdash;mdash;ROS中的编辑器。现在你可以按Ctrl-C退出所有turtlesims节点了,因为在下一篇教程中你不会再用到它们。

补充复习及提升

ros基础知识总结-LMLPHP

ros基础知识总结-LMLPHP

TIPS:

1 使用 rosed

rosed是rosbash的一部分。利用它可以直接通过package名来获取到待编辑的文件而无需指定该文件的存储路径了。

使用方法:

$ rosed [package_name] [filename]

例子:

$ rosed roscpp Logger.msg

2 使用Tab键补全文件名

使用这个方法,在不知道准确文件名的情况下,你也可以看到并选择你所要编辑的文件。

3 编辑器

rosed默认的编辑器是vim。如果想要将其他的编辑器设置成默认的,你需要修改你的 ~/.zshrc 文件,增加如下语句:

export EDITOR='emacs -nw'

这将emacs设置成为默认编辑器。注意: .zshrc文件的改变,只会在新的终端才有效。已经打开的终端不受环境变量的影响。打开一个新的终端,看看那是否定义了EDITOR:

$ echo $EDITOR
emacs -nw

注:个人觉得最好用的是gedit编辑器,但是现在VIM编辑器无疑是最为强大最为通用的编辑器,以后注定要用的

ROS消息和ROS服务的创建

1 消息(msg)和服务(srv)介绍

消息(msg): msg文件就是一个描述ROS中所使用消息类型的简单文本。它们会被用来生成不同语言的源代码。

服务(srv): 一个srv文件描述一项服务。它包含两个部分:请求和响应。 msg文件存放在package的msg目录下,srv文件则存放在srv目录下。 msg文件实际上就是每行声明一个数据类型和变量名。可以使用的数据类型如下:

int8, int16, int32, int64 (plus uint*)
float32, float64string
time, duration
other msg files
variable-length array[] and fixed-length array[C]

在ROS中有一个特殊的数据类型:Header,它含有时间戳和坐标系信息。在msg文件的第一行经常可以看到Header header的声明. 下面是一个msg文件的样例,它使用了Header,string,和其他另外两个消息类型。

&nbsp; Header header
&nbsp; string child_frame_id
&nbsp; geometry_msgs/PoseWithCovariance pose
&nbsp; geometry_msgs/TwistWithCovariance twist

srv文件分为请求和响应两部分,由'---'分隔。下面是srv的一个样例:

int64 Aint64 B
---
int64 Sum

参考如下:

/opt/ros_ws/src/ros_tutorials/roscpp_tutorials/srv/TwoInts.srv

/opt/ros_ws/src/ros_tutorials/rospy_tutorials/srv/AddTwoInts.srv

$ rossrv show rospy_tutorials/AddTwoInts

ros基础知识总结-LMLPHP

其中 A 和 B 是请求, 而Sum 是响应。下面我们就来一步一步学习如何定义消息和服务。

2 使用 msg

2.1 创建一个 msg

下面,我们将在之前创建的package里定义新的消息。

$ cd ~/catkin_ws/src/beginner_tutorials$ mkdir msg$ echo &quot;int64 num&quot;
&gt; msg/Num.msg

上面是最简单的例子——在.msg文件中只有一行数据。当然,你可以仿造上面的形式多增加几行以得到更为复杂的消息:

string first_name
string last_name
uint8 age
uint32 score

接下来,还有关键的一步:我们要确保msg文件被转换成为C++,Python和其他语言的源代码: 查看package.xml, 确保它包含以下两条语句:

  <build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>

如果没有,添加进去。 注意,在构建的时候,我们只需要"message_generation"。然而,在运行的时候,我们只需要"message_runtime"。 在你最喜爱的编辑器中打开CMakeLists.txt文件(可以参考前边的教程rosed)。 在 CMakeLists.txt文件中,利用find_packag函数,增加对message_generation的依赖,这样就可以生成消息了。 你可以直接在COMPONENTS的列表里增加message_generation,就像这样:

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs
message_generation)

有时候你会发现,即使你没有调用find_package,你也可以编译通过。这是因为catkin把你所有的package都整合在一起,因此,如果其他的package调用了find_package,你的package的依赖就会是同样的配置。但是,在你单独编译时,忘记调用find_package会很容易出错。

同样,你需要确保你设置了运行依赖:

catkin_package(
&nbsp; ...
&nbsp; CATKIN_DEPENDS message_runtime ...
&nbsp; ...)

找到如下代码块:

# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )

去掉注释符号#,用你的.msg文件替代Message*.msg,就像下边这样:

add_message_files(
&nbsp; FILES
&nbsp; Num.msg
)

手动添加.msg文件后,我们要确保CMake知道在什么时候重新配置我们的project。 确保添加了以下的代码:

generate_messages()  //位置要在正确的地方,否则编译会不通过,具体位置在.msg中会有说明

现在,你可以生成自己的消息源代码了。

2.2 使用 rosmsg

以上就是你创建消息的所有步骤。下面通过rosmsg show命令,检查ROS是否能够识消息。

首先,要先使用catkin_make编译,然后再

source/home/shiyanlou/catkin_ws/devel/setup.zsh。

使用方法:

$ rosmsg show [message type]

样例:

$ rosmsg show beginner_tutorials/Num

你将会看到:

int64 num

在上边的样例中,消息类型包含两部分:

beginner_tutorials -- 消息所在的package

Num -- 消息名Num.

如果你忘记了消息所在的package,你也可以省略掉package名。输入:

$ rosmsg show Num

你将会看到:

[beginner_tutorials/Num]:int64 num

ros基础知识总结-LMLPHP

3 使用 srv

3.1 创建一个srv

在刚刚那个package中创建一个服务:

$ roscd beginner_tutorials$ mkdir srv

这次我们不再手动创建服务,而是从其他的package中复制一个服务。 roscp是一个很实用的命令行工具,它实现了将文件从一个package复制到另外一个package的功能。

使用方法:

$ roscp [package_name] [file_to_copy_path] [copy_path]

现在我们可以从rospy_tutorials package中复制一个服务文件了:

$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv

还有很关键的一步:我们要确保srv文件被转换成C++,Python和其他语言的源代码。

现在认为,你已经如前边所介绍的,在CMakeLists.txt文件中增加了对message_generation的依赖。

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation)

同样,跟msg文件类似,你也需要在package.xml文件中做一些修改。查看上边的说明,增加额外的依赖项。

删掉#,去除对下边语句的注释:


# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )

用你自己的srv文件名替换掉那些Service*.srv文件:

add_service_files(&nbsp; FILES
&nbsp; AddTwoInts.srv)

3.2 使用 rossrv

以上就是创建一个服务所需的所有步骤。下面通过rosmsg show命令,检查ROS是否能够识该服务。

使用方法:

$ rossrv show &lt;service type&gt;

例子:

$ rossrv show beginner_tutorials/AddTwoInts

如果出错,说明配置有误,请认真检查。

你将会看到:

int64 aint64 b
---
int64 sum

跟rosmsg类似, 你也可以不指定具体的package名来查找服务文件:


$ rossrv show AddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum [rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum

4 msg和srv都需要的步骤

接下来,在CMakeLists.txt中找到如下部分:

# generate_messages(
# DEPENDENCIES
# # std_msgs # Or other packages containing msgs
# )

去掉注释并附加上所有你消息文件所依赖的那些含有.msg文件的package(这个例子是依赖std_msgs,不要添加roscpp,rospy),结果如下:


generate_messages(
DEPENDENCIES
std_msgs
)

由于增加了新的消息,所以我们需要重新编译我们的package:

$ cd ../..
$ catkin_make
$ cd -

所有在msg路径下的.msg文件都将转换为ROS所支持语言的源代码。生成的C++头文件将会放置在~/catkin_ws/devel/include/beginner_tutorials/。 Python脚本语言会在 ~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg 目录下创建。 lisp文件会出现在 ~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/ 路径下。

5 获得帮助

我们已经接触到不少的ROS工具了。有时候很难记住他们所需要的参数。还好大多数ROS工具都提供了帮助。(事实上Linux系统本身就带有这样类似的东西)

输入:

$ rosmsg -h

你可以看到一系列的rosmsg子命令:


Commands:
rosmsg show Show message description
rosmsg users Find files that use message
rosmsg md5 Display message md5sum
rosmsg package List messages in a package
rosmsg packages List packages that contain messages

同样你也可以获得子命令的帮助:

$ rosmsg show -h

这会现实rosmsg show 所需的参数:


Usage: rosmsg show [options] <message type> Options:
-h, --help show this help message and exit
-r, --raw show raw message text, including comments

6 回顾

总结一下到目前为止我们接触过的一些命令:

rospack = ros+pack(age) : provides information related to ROS packages

rosstack = ros+stack : provides information related to ROS stacks

roscd = ros+cd : changes directory to a ROS package or stack

rosls = ros+ls : lists files in a ROS package

roscp = ros+cp : copies files from/to a ROS package

rosmsg = ros+msg : provides information related to ROS message definitions

rossrv = ros+srv : provides information related to ROS service definitions

rosmake = ros+make : makes (compiles) a ROS package

简单的消息发布器和订阅器 (C++)

在 beginner_tutorials package 路径下创建一个src文件夹,用于存放源码。在 beginner_tutorials package 里创建 src/talker.cpp 文件和src/listener.cpp文件。

代码链接:

https://raw.github.com/ros/ros_tutorials/indigo-devel/roscpp_tutorials/talker/talker.cpp

https://raw.github.com/ros/ros_tutorials/indigo-devel/roscpp_tutorials/listener/listener.cpp

编译节点

在 CMakeLists.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})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

这样就可以确保自定义消息的头文件在被使用之前已经被生成。因为 catkin 所有的 package 并行的编译,所以如果你要使用其他 catkin 工作空间中其他 package 的消息,你同样也需要添加对他们各自生成的消息文件的依赖。

运行发布器和订阅器

发布器启动命令

$ roscore //运行ros
$ rosrun beginner_tutorials talker (C++) // 启动talker

启动订阅器

上一教程,我们编写了一个名为"listener"的订阅器节点。现在运行它:

$ rosrun beginner_tutorials listener     (C++)

简单的服务器和客户端 (C++)

1 编写Service节点

创建一个简单的service节点(add_two_ints_server),该节点将接收到两个整形数字,并返回它们的和。

$ cd ~/catkin_ws/src/beginner_tutorials

在 beginner_tutorials 包中创建src/add_two_ints_server.cpp文件,内容为


#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h" bool add(beginner_tutorials::AddTwoInts::Request &req,
beginner_tutorials::AddTwoInts::Response &res)
{
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
} int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server");
ros::NodeHandle n; ros::ServiceServer service = n.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two ints.");
ros::spin(); return 0;
}

2 编写Client节点

在 beginner_tutorials 包中创建src/add_two_ints_client.cpp文件,内容为:


#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
#include <cstdlib> int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_client");
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y");
return 1;
} ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
beginner_tutorials::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
} return 0;
}

3 编译节点

编辑 beginner_tutorials 里面的CMakeLists.txt,将下面的代码添加在文件末尾

源码链接:


add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp) add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)

这段代码将生成两个可执行程序add_two_ints_server和add_two_ints_client,这两个可执行程序默认被放在你的devel space 下的包目录下,默认为~/catkin_ws/devel/lib/share/<package name>。

现在运行catkin_make命令:

cd ~/catkin_ws
catkin_make

//个人认为Cmake将两个包之间的通信关系隐去了,只聚焦于实现必要功能这一问题,从而使得我们不必关心下面更复杂的内容。

测试简单的服务器和客户端

1 运行Service

从运行Service开始:


$ rosrun beginner_tutorials add_two_ints_server (C++)

你将会看到如下类似的信息:

Ready to add two ints.

2 运行Client

现在,运行Client并附带一些参数:

$ rosrun beginner_tutorials add_two_ints_client 1 3     (C++)

你将会看到如下类似的信息:


request: x=1, y=3
sending back response: [4]

Ros检查命令:roswtf

1 安装检查roswtf 可以检查你的ROS系统并尝试发现问题,:

$ roscd
$ roswtf

你应该会看到(各种详细的输出信息):


Stack: ros
================================================================================
Static checks summary: No errors or warnings
================================================================================ Cannot communicate with master, ignoring graph checks Cannot communicate with master, ignoring graph checks

检查结果说明:

Stack: ros:

roswtf根据你当前目录来确定需要做的检查,这里表示你是在rosstack中启动roswtf。

Static checks summary:

这是有关文件系统问题的检查报告.

Cannot communicate with master, ignoring graph checks(无法与master连接,忽略图(graph)的检查):

roscore没有运行,所以roswtf没有做运行时检查。

以及在有ros节点运行时的各种错误(具体错误将详细反映在报错信息和日志中。)

ros基础知识总结-LMLPHP

例如:

WARNING The following node subscriptions are unconnected:
* /rosout:
* /rosout

roswtf发出警告说rosout节点订阅了一个没有节点向其发布的话题。在本例中,这正是所期望看到的,因为除了roscore没有任何其它节点在运行,所以我们可以忽略这些警告。

(作为没接触这些问题的人,我们遇到这些问题该怎么办?简单,你不会百度么?)

ros基础知识总结-LMLPHP

05-11 22:05