ROS—工作空间和功能包的创建
% 博主是机器人方向,计算机相关不是很专业,本篇只是作为学习ROS系统过程中,一些概念的简单挖掘,如有错误,欢迎大家批评指正!
首先理解高级语言程序执行的一个简单过程
1. 源程序(Source Code):
源程序是一系列人类可读的计算机语言指令, 即由所谓的“高级语言”或者“汇编语言”编写的程序代码。源程序只是给人看的,不能直接在计算机上执行,需要用“编译程序”将源程序编译为二进制形式的代码。像C语言源程序的扩展名为“.c”。
2. 目标程序 (Object Code):
源程序经过“编译器”编译之后生成的机器代码,即“目标程序”,也叫“二进制代码”。目标程序的扩展名为“.obj”。存放目标程序的文件叫“目标文件”或“二进制文件”,其中存放着机器代码和代码运行中使用的数据。但是,目标程序还是不能被计算机正常执行,因为其没有解决函数之间调用的的问题,需要将各个目标程序与库函数连接,这时候就用到了“链接器”。
3. 可执行程序 (Executable Program):
“链接器”将二进制目标程序与库函数(Library, 库不是独立的程序,其为向其他程序提供服务的程序)连接起来,形成的完整的、可在操作系统下独立执行的程序称为“可执行程序”。
构建系统 ( Build System )
https://segmentfault.com/a/1190000015367674
粗显地理解构建系统
现在我们知道,从“源码”到“可执行文件”需要编译、链接,其实此外还有其他诸多繁复的工作,比如复制、处理头文件等,较大的工程甚至都要处理数以百万计的任务,而且任务之间又有复杂的依赖关系。
当然,这些复杂的东西是不需要手动去做的,操作系统有一整套的系统来自动完成软件构建过程中这些复杂工作,这就是我们要提到的“构建系统”。
上一节中提到的编译器、链接器以及代码生成器、文件生成器都属于编译工具,是构建系统的组件之一。构建系统还有一个重要组件:“构建工具”,它是一种位于编译工具级别之上的程序,其调用必要的编译工具来产生最终的构建输出。它对源文件和目标文件之间的关系具有足够的了解,以使它足以编排整个构建过程。此外,构建系统还包括用来“发布打包和目标”的机器,它生成可以实际安装在用户机器上的东西。
构建过程:即构建工具调用每个编译工具来完成工作。
配置信息:要想构建目标,构建系统就得需要以下一些信息:工具链组件(例如,C++编译器,应该就是一些编译工具)的位置、源代码的位置、代码依赖关系、外部依赖、依赖所在的位置、应构建的目标项、构建目标要存储的位置、以及安装位置。这些配置信息一般存储在一个配置文件中,这个文件可由构建系统读取。在CMake(一个常见的构建系统)中,它就是通常存储在一个称为“CMakeList.txt”的文件中;对于GNU Make,则一般存储在“Makefile”中。指定了这些配置信息,构建系统就能利用这些信息以适当的顺序来处理和构建源代码以生成目标。
形象地类比一下构建系统:将构建系统理解为一个**“汽车加工厂”**,设计师(程序员)向加工厂(构建系统)提供了图纸(源代码,高级语言)以及其他一些加工(编译)和装配(打包、输出)要求(相关配置),然后加工厂按照图纸和要求完成汽车成品的“构建”,最后将一个能开的合格汽车(可执行文件)交付客户,用户开上就能走(终端安装上软件就能直接使用)。
ROS的构建系统:Rosbuild or Catkin ?
ROS最初的构建系统采用的是Rosbuild, 但是Rosbuild 最大的问题就是,可移植性比较差,因为其混合使用了Bash脚本、GUN Make和CMake来进行构建,使用rosbuild时,当调用构建系统时,必须先调用rosbuild提供的自定义脚本,例如rosmake,这是一个Bash脚本,这个脚本会调用make,make再调用CMake,CMake又会生成另一个makefile,并最终再次调用make。
后来ROS官方的构建系统采用了更为灵活的 Catkin 系统,Catkin 实际上是基于 CMake 的。只需调用CMake就可调用Catkin。Catkin加上一些Python代码一起实现自定义的CMake宏。所以,任何系统只要支持Python和CMake,那catkin就可以轻松移植到该系统上。当然,相比rosbuild,Catkin还有诸多优势,不一一列举了,详情可见Catkin from ROS.org
Catkin Workspaces
Catkin 工作空间实际上就是一个工作路径文件夹,来存放工程开发相关文件的文件夹。在这个工作空间中可以修改、构建和安装catkin功能包。较为典型的Catkin 工作空间格局如下:
workspace_folder/ -- WORKSPACE
src/ -- SOURCE SPACE
CMakeLists.txt -- The 'toplevel' CMake file
package_1/
CMakeLists.txt
package.xml
...
package_n/
CATKIN_IGNORE -- Optional empty file to exclude package_n from being processed
CMakeLists.txt
package.xml
...
build/ -- BUILD SPACE
CATKIN_IGNORE -- Keeps catkin from walking this directory
devel/ -- DEVELOPMENT SPACE (set by CATKIN_DEVEL_PREFIX)
bin/
etc/
include/dd
lib/
share/
.catkin
env.bash
setup.bash
setup.sh
...
install/ -- INSTALL SPACE (set by CMAKE_INSTALL_PREFIX)
bin/
etc/
include/
lib/
share/
.catkin
env.bash
setup.bash
setup.sh
...
其主要是由四部分组成:
src/ ( Source Space )
该部分为源代码空间。该文件夹中包含移到多个的 catkin 功能包,包括功能包的源码、配置文件等。在执行配置、构建或者安装时,这个空间的东西应保持不变。在创建该工作空间时就会生成一个 CMakeLists.txt 的文件,当在工作空间中对catkin项目进行配置时,CMake就会调用这个文件。
build/ ( Build Space )
编译空间。该部分存放编译过程中产生的中间文件,在使用时是基本上不用关心的。
devel/ ( Development Space )
开发空间。回放置编译生成的一些可执行文件、库或者脚本。
install/ ( Install Space )
安装空间。功能包的安装路径。在开发是一般用不到。

创建ROS工作空间
创建 ROS 工作空间。拢共分四shuxing步:
- 创建 Catkin 工作空间:
在用户文件夹路径下创建工作空间文件夹,再创建源代码空间。注意!源代码空间存储位置的命名一定是:src.
但是,这时,这个文件夹跟一般的文件夹没什么两样,catkin为什么要到你这里面去读取源码呢?所以还需要下一步:进入到 src/文件夹,调用 "catkin_init_workspace’,对工作空间进行初始化,这时候这个文件夹才具有了ROS工作空间的“属性”。
$ mkdir -p ~/catkin_ws/src % 创建Catkin_ws/ 文件夹,并创建子文件夹 src/
$ cd ~/catkin_ws/
$ catkin_init_workspace
- 编译工作空间
然后,我们进入 catkin_ws 一级的文件夹,调用catkin_make 进行工作空间的编译。catkin_make 在工作空间中首次运行之后,它会自动在 src/文件夹中创建一个 CMakeLists.txt 的链接文件,这就是之前提到的构建系统中用来存储代码位置、依赖关系以及配置信息的文件。
另外,这时查看catkin_ws目录下增加了“build”和“devel”两个文件夹。现在,还没有install的文件夹,执行catkin_make install 就会生成install空间。
$ cd ~/catkin_ws/
$ catkin_make
- 设置环境变量
编译完工作空间之后,下面就是要让ROS_PACKAGE_PATH(ROS工作的环境变量)包含创建的工作空间目录,也就是让ROS能找得到你这个工作空间,这里使用catkin中的source命令。
在上一步编译完成之后,在“devel”文件夹下可以看到几个 *setup.sh 文件,source这些文件中的任何一个都可以将当前工作空间设置在ROS工作环境的最顶层.
$ source devel/setup.bash
- 检查环境变量
要想保证工作空间已配置正确,需确保ROS_PACKAGE_PATH 环境变量包含你的工作空间目录,采用以下命令查看。
$ echo $ROS_PACKAGE_PATH
/home/<youruser>/catkin_ws/src:/opt/ros/kinetic/share
现在,工作环境的搭建完成。
创建ROS功能包
1. 创建功能包
首先,切换到 src/ 目录下,使用 catkin_create_pkg 命令来创建一个功能包, catkin_create_pkg 的语法如下:
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
$ cd ~/catkin_ws/src
# This is an example, do not try to run this
# catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
$ catkin_create_pkg test_pkg std_msgs rospy roscpp
以上代码创建了一个名为 “test_pkg”的文件夹,后边包含了在编译时需要依赖的其他功能包:ROS的标准消息结构(int、bool等)以及C++和Python的接口。
在“test_pkg”文件夹中,系统创建了四个文件(文件夹):
src:来存放功能报的代码,比如 .cpp文件以及 .py文件;
include:存放头文件,比如C++中的 .h文件;
CMakeLists.txt
package.xml
2. 编译功能包
回到工作空间目录,调用catkin_make,并source一下,刷新环境变量,这样才能让系统找到我们的工作空间,并找到里面对应的一些功能包。
$ cd ~/catkin_ws
$ catkin_make % 启动编译;
$ source ~/catkin_ws/devel/setup.bash % 设置环境变量;
$ echo $ROS_PACKAGE_PATH % 检查环境变量;
catkin_make 编译完成之后,它发现了我们的功能包:test_pkg,并对其进行了编译(虽然里面什么都没有)。
CMakeLists.txt 和 package.xml
1. package.xml
每个功能包中都会(必须)包含一个功能包说明文件 ( Package Manifest ),在其中包含了一些功能包特征:功能包名称、版本号、开发者、维护者以及对其他功能包的依赖关系。
其实,你可以自定义package.xml。“Creating Package” from “ROS.org”
- 描述标签

可以将描述信息修改为任何你喜欢的内容,但是尽可能简短易懂。 - 维护者标签

这是要求填写的一个重要标签,其中包含维护者的名字和email,能够让其他人联系到程序包的相关人员,如果有需要可以添加多个. - 许可标签

你应该选择一种开源许可协议并将它填写到这里。一些常见的开源许可协议有BSD、MIT、Boost Software License、GPLv2、GPLv3、LGPLv2.1和LGPLv3。推荐使用BSD协议,因为 ROS 核心组件的剩余部分都已经使用了该协议。 - 依赖项标签

接下来的标签用来描述程序包的各种依赖项,这些依赖项分为build_depend、buildtool_depend、exec_depend、test_depend。
buildtool_depend是catkin中默认提供的:catkin;
build_depend存放编译时需要用到的依赖库,之前在建包时指定的std_msgs、roscpp、rospy都包含在内了;
exec_depend是在运行时需要用到的依赖;
test_depend是针对测试时所依赖的包。
这些依赖假如在创建包时没有添加完全,后续可以这个文件中手动添加。
2. CMakeLists.txt
描述功能包里的编译规则,使用CMake的语法。关于这个文件的修改,之后介绍。