前言
成功编写第一个程序无疑是一个学习者最激动的时刻。接下来会以最简单的Hello ROS!程序为例,详细地讲解一下如何编译ROS程序。
一、创建工作区和功能包
1.创建工作区
我们所创建的包,应该全部放到一个叫做工作区的目录中 。可以用任何你喜欢的名字命名你的工作区,并且把目录存储在你账号中的任何位置。
1.使用标准的mkdir命令行去创建一个目录,我们将把这个新的目录称作你的工作区目录。 2.在工作区目录中创建一个叫做 src 的子目录,这个子目录将用于存放功能包的源代码
2.创建功能包
创建一个新ROS功能包的命令应该在你工作区中的src目录下运行,
catkin_create_pkg package-name
OK了
ROS 包的命名遵循一个命名规范,只允许使用小写字母、数字和下划线,而且首字符必须是一个小写字母。一些 ROS工具,包括 catkin,不支持那些不遵循此命名规范的包。
二、编写程序
1.编写C++程序
在你的功能包目录中创建 src 目录来存放 C ++源文件, hello.cpp 的源文件也存放在 功能包的src下(别弄混了src)
代码如下(示例):
2
3
4
5 #include <ros / ros.h>
6
7 int main ( int argc , char ** argv ) {
8
9 ros::init ( argc , argv , " hello _ros " ) ;
10
11
12 ros::NodeHandle nh ;
13
14
15 ROS_INFO_STREAM( " Hello , ? ROS! " ) ;
16 }
ros::init函数初始化ROS客户端库。在你程序的起始处调用一次该函数 。函数最后的参数是一个包含节点默认名的字符串。(这个默认名可以通过启动文件或者通过rosrun 命令行参数覆盖。)
**ros::NodeHandle(节点句柄)**对象是你的程序用于和ROS系统交互的主要机制 。创建此对象会将你的程序注册为ROS节点管理器的节点。最简单的方法就是在整个程序中只创建一个NodeHandle对象。
(在内部,NodeHandle 类维护一个引用计数,仅仅在第一个NodeHandle 对象创建时才会在节点管理器注册新的节点。同样,只有当所有的 NodeHandle 对象都销毁后,节点才会 注销。这一细节有两个影响:首先,如果愿意,你可以为一个节点创建很多 NodeHandle 对象。这样做只有在一些特殊的应用中才有意义。其次,这意味着,在一个程序中使用标准的 roscpp 接口来运行多个节点是不可能的。)
ROS_INFO_STREAM 宏将生成一条消息,且这一消息被发送到不同的位置,包括控制台窗口。
2.编译 Hello 程序
(1)声明依赖库
声明依赖库 首先,我们需要声明程序所依赖的其他功能包。对于 c++程序而言,此步骤是必要的,以确保 catkin 能够向 c++编译器提供合适的标记来定位编译功能包所需的头文件和链接库。 为了给出依赖库,编辑包目录下的 CMakeLists.txt 文件。该文件的默认版本含有如下行: find_package(catkin REQUIRED) 所依赖的其他 catkin 包可以添加到这一行的 COMPONENTS 关键字后面,如下所示:
find_package(catkin REQUIRED COMPONENTS package-names)
我们同样需要在包的package.xml 文件中列出依赖库,通过使用build_depend (编译依赖)和 run_depend(运行依赖)两个关键字实现: <build_depend>package-name</build_depend> <run_depend>package-name</run_depend>
对于 hello 例程,我们需要添加名为 roscpp 的依赖库,它提供了 ROS 的 C++客户端库。并且hello 程序在编译时和运行时都需要 roscpp 库,因此,修改后的 find_package 行如下所示: find_package(catkin REQUIRED COMPONENTS roscpp) 清单文件需要包括: <build_depend>roscpp</build_depend> <run_depend>roscpp</run_depend>
然而,在清单文件中声明的依赖库并没有在编译过程中用到;如果你在此处忽略它们,你可能不会看到任何错误消息,直到发布你的包给其他人,他们可能在没有安装所需包的情况下编译你发布的包而导致报错。
(2)声明可执行文件
接下来,我们需要在 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})
(3)编译工作区
使用下面的命令来编译所有包中的所有可执行文件:
catkin_make
因为被设计成编译你的工作区中的所有包,这个命令必须从你的工作区目录运行。它将会完成一些配置步骤(尤其是你第一次运行此命令时),并且在你的工作区中创建 devel 和 build 两个 子目录。这两个新目录用于存放和编译相关的文件,例如自动生成的编译脚本、目标代码和可执行文件。
(4)Sourcing setup.bash
最后一步是是执行名为 setup.bash 的脚本文件,它是 catkin_make 在你工作区的 devel 子目录下生成的。
source devel/setup.bash
这个自动生成的脚本文件设置了若干环境变量,从而使 ROS 能够找到你创建的功能包和新生成的可执行文件。它类似于全局 setup.bash,但是是专门为你的工作区量身定做的。
三. 执行 hello 程序
rosrun agitr hello
rosrun package-name executable-name rosrun 命令有两个参数,其中第一个参数是功能包的名称,;第二个参数是该软件包中的可执行文件的名称。 (别忘了roscore!)
这个 rosrun 命令,可能会产生如下所示的错误: [rospack] Error: stack/package package-name not found 此错误的两个可能的原因是: (1)错误地拼写了功能包名; (2)没有成功运行你的工作区中的 setup.bash。
总结
到这就成功了,继续探索神奇的ROS吧! 参考书籍:《a gentle introduction to ROS》
|