第3章 编写ROS程序-1
1、创建工作区和功能包
在我们写任何程序之前,第一步是创建一个容纳我们的功能包的工作区,然后再创建功能包本身。
创建工作区 使用标准的mkdir命令行去创建一个目录,我们将把这个新的目录称作工作区目录。
创建工作区还需要最后一步,即在工作区目录中创建一个叫做src的子目录,该子目录用于存放功能包的源代码。
创建功能包 创建一个新ROS功能包的命令应该在你工作区中的src目录下运行,如下所示:
catkin_create_pkg package-name
这个命令主要是创建了一个存放这个功能包的目录,并在那个目录下生成了两个配置文件。
第一个配置文件,叫做package.xml,它是一个清单文件。
第二个文件,叫做CMakeLists.txt,是一个Cmake的脚本文件。
所以要修改上面的包,修改如下
编辑清单文件 创建包后,你可能希望编辑其 package.xml 文件,其中包含一些描述这个包的元数据。请注意,无论是在编译时还是在运行时,其中的大部分信息 ROS 并没有使用,这些信息只有在你公开发布代码时才变得重要。本着保持文档与实际功能同步的精神,至少填写
description 和 maintainer 两部分可能是比较合理的。
2、你好,ROS!
现在已经创建好了包,可以开始编写ROS程序了。
1)一个简单的程序
新建一个名字为hello.cpp的源文件与package.xml,CMakeLists.txt同目录。
解释:
---头文件 ros/ros.h 包含了标准 ROS 类的声明,你将会在每一个你写的 ROS 程序中包含它。
---ros::init函数初始化ROS客户端库。请在你程序的起始处调用一次该函数。 函数最后的参数是一个包含节点默认名的字符串。这个默认名可以通过启动文件或者通过rosrun 命令行参数覆盖。
---ros::NodeHandle(节点句柄)对象是你的程序用于和ROS系统交互的主要机制。创建此对象会将你的程序注册为ROS节点管理器的节点。最简单的方法就是在整个程序中只创建一个NodeHandle对象。
---ROS_INFO_STREAM 宏将生成一条消息,且这一消息被发送到不同的位置,包括控制台窗口。
2)编译Hello程序
我们该如何编译和运行这个程序呢?这些交给ROS的catkin编译系统来处理。一共有四个步骤:
声明依赖库 首先,我们需要声明程序所依赖的其他功能包。对于 c++程序而言,此步骤是必要的,以确保 catkin 能够向 c++编译器提供合适的标记来定位编译功能包所需的头文件和链接库。
为了给出依赖库,编辑包目录下的 CMakeLists.txt 文件,该文件的默认版本含有如下行:
find_package(catkin REQUIRED)
所依赖的其他catkin包可以添加到这一行的COMPONENTS关键字后面,如下所示:
find_package(catkin REQUIRED COMPONENTS package-names)
对于 hello 例程,我们需要添加名为 roscpp 的依赖库,它提供了 ROS 的 C++客户端库。因此,修改后的 find_package 行如下所示:
find_package(catkin REQUIRED COMPONENTS roscpp)
以上是在CMakeLists.txt文件中进行修改,下面我们将在清单文件package.xml中进行修改:
我们同样需要在包的清单文件中列出依赖库,通过使用build_depend (编译依赖)和 run_depend(运行依赖)两个关键字实现:
<build_depend>package-name</build_depend>
<run_depend>package-name</run_depend>
在我们的例程中,hello 程序在编译时和运行时都需要 roscpp 库,因此清单文件需要包括:
<build_depend>roscpp</build_depend>
<run_depend>roscpp</run_depend>
声明可执行文件 接下来,需要在CMakeLists.txt中添加两行,来声明我们需要创建的可执行文件。其一般形式是:
add_executable(executable-name source-files)
target_link_libraries(executable-name ${catkin_LIBRARIES})
第一行声明了我们想要的可执行文件的文件名,以及生成此可执行文件所需的源文件列表。如果你有多个源文件,把它们列在此处,并用空格将其区分开。
第二行告诉 Cmake 当链接此可执行文件时需要链接哪些库(在上面的 find_package 中定义) 。如果你的包中包括多个可执行文件,为每一个可执行文件复制和修改上述两行代码。
在我们的例程中,我们需要一个名为 hello 的可执行文件,它通过名为 hello.cpp 的源文件编译而来。 所以我们需要添加如下几行代码到 CMakeLists.txt 中:
add_executable(hello hello.cpp)
target_link_libraries(hello ${catkin_LIBRARIES})
编译工作区 一旦你的CMakeLists.txt文件设置好,你就可以编译你的工作区,使用如下命令来编译所有包中的所有可执行文件:
catkin_make
因为被设计成编译你的工作区中的所有包,这个命令必须从你的工作区目录运行。它将会完成一些配置步骤(尤其是你第一次运行此命令时) ,并且在你的工作区中创建 devel 和 build 两个子目录。这两个新目录用于存放和编译相关的文件,例如自动生成的编译脚本、目标代码和可执行文件。如果你喜欢,当完成功能包的相关工作后(译者注:即完成了编写、调试、测试等一系列工作后,此时代码基本定型) ,可以放心地删除 devel 和 build两个子目录。
Sourcing setup.bash 最后的步骤是执行名为 setup.bash 的脚本文件,它是 catkin_make 在你工作区的 devel 子目录下生成的。
source devel/setup.bash
这个自动生成的脚本文件设置了若干环境变量,从而使 ROS 能够找到你创建的功能包和新生成的可执行文件。它类似于 2.2 节介绍的全局 setup.bash,但是是专门为你的工作区量身定做的。除非目录结构发生变化,否则你只需要在每个终端执行此命令一次,即使你修改了代码并且用 catkin_make 执行了重编译。
3)执行hello程序
当所有这些编译步骤完成后,新的 ROS 程序就可以使用rosrun来执行,命令是:
rosrun new_1 hello