转载:中国大学MOOC———《机器人操作系统入门》
https://legacy.gitbook.com/book/sychaichangkun/ros-tutorial-icourse163/details
对于源代码包,我们只有编译才能在系统上运行。而Linux下的编译器有gcc、g++,随着源文件的增加,直接用gcc/g++命令的方式显得效率低下,人们开始用Makefile来进行编译。然而随着工程体量的增大,Makefile也不能满足需求,于是便出现了Cmake工具。CMake是对make工具的生成器,是更高层的工具,它简化了编译构建过程,能够管理大型项目,具有良好的扩展性。对于ROS这样大体量的平台来说,就采用的是CMake,并且ROS对CMake进行了扩展,于是便有了Catkin编译系统。
早期的ROS编译系统是rosbuild,但随着ROS的不断发展,rosbuild逐渐暴露出许多缺点,不能很好满足系统需要。在Groovy版本面世后,Catkin作为rosbuild的替代品被正式投入使用。Catkin操作更加简化且工作效率更高,可移植性更好,而且支持交叉编译和更加合理的功能包分配。目前的ROS同时支持着rosbuild和Catkin两种编译系统,但ROS的核心软件包也已经全部转换为Catkin。rosbuild已经被逐步淘汰,所以建议初学者直接上手Catkin。
本节我们主要来介绍catkin的编译系统。
Catkin是基于CMake的编译构建系统,具有以下特点:
find_package()
基础结构,pkg-config
find_package()
代码,pkg-config
文件一个Catkin的软件包(package)必须要包括两个文件:
package.xml: 包括了package的描述信息
CMakeLists.txt: 构建package所需的CMake文件
package.xml
catkin编译的工作流程如下:
catkin_ws/src/
下递归的查找其中每一个ROS的package。package.xml
和CMakeLists.txt
文件,Catkin(CMake)编译系统依据CMakeLists.txt
文件,从而生成makefiles
(放在catkin_ws/build/
)。make
刚刚生成的makefiles
等文件,编译链接生成可执行文件(放在catkin_ws/devel
)。也就是说,Catkin就是将cmake
与make
指令做了一个封装从而完成整个编译过程的工具。catkin有比较突出的优点,主要是:
catkin_make
进行编译要用catkin编译一个工程或软件包,只需要用catkin_make
指令。一般当我们写完代码,执行一次catkin_make
进行编译,调用系统自动完成编译和链接过程,构建生成目标文件。编译的一般性流程如下,在1.5节我们编译ROS-Academy-for-Beginners教学包就是这样的流程。
$ mkdir -p ~/catkin_ws/src #创建工作空间
$ cd ~/catkin_ws #回到工作空间,catkin_make必须在工作空间下执行
$ catkin_make #开始编译
$ source devel/setup.bashh #刷新坏境,建议没一个新终端都执行一次
注意:catkin编译之前需要回到工作空间目录,catkin_make
在其他路径下编译不会成功。编译完成后,如果有新的目标文件产生(原来没有),那么一般紧跟着要source刷新环境,使得系统能够找到刚才编译生成的ROS可执行文件。这个细节比较容易遗漏,致使后面出现可执行文件无法打开等错误。
catkin_make
命令也有一些可选参数,例如:
catkin_make [args]
-h, --help 帮助信息
-C DIRECTORY, --directory DIRECTORY
工作空间的路径 (默认为 '.')
--source SOURCE src的路径 (默认为'workspace_base/src')
--build BUILD build的路径 (默认为'workspace_base/build')
--use-ninja 用ninja取代make
--use-nmake 用nmake取'make
--force-cmake 强制cmake,即使已经cmake过
--no-color 禁止彩色输出(只对catkin_make和CMake生效)
--pkg PKG [PKG ...] 只对某个PKG进行make
--only-pkg-with-deps ONLY_PKG_WITH_DEPS [ONLY_PKG_WITH_DEPS ...]
将指定的package列入白名单CATKIN_WHITELIST_PACKAGES,
之编译白名单里的package。该环境变量存在于CMakeCache.txt。
--cmake-args [CMAKE_ARGS [CMAKE_ARGS ...]]
传给CMake的参数
--make-args [MAKE_ARGS [MAKE_ARGS ...]]
传给Make的参数
--override-build-tool-check
用来覆盖由于不同编译工具产生的错误
Catkin工作空间是创建、修改、编译catkin软件包的目录。catkin的工作空间,直观的形容就是一个仓库,里面装载着ROS的各种项目工程,便于系统组织管理调用。在可视化图形界面里是一个文件夹。我们自己写的ROS代码通常就放在工作空间中,本节就来介绍catkin工作空间的结构。
介绍完catkin编译系统,我们来建立一个catkin的工作空间。首先我们要在计算机上创建一个初始的catkin_ws/
路径,这也是catkin工作空间结构的最高层级。输入下列指令,完成初始创建。
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/
$ catkin_make #初始化工作空间
第一行代码直接创建了第二层级的文件夹src,这也是我们放ROS软件包的地方。第二行代码使得进程进入工作空间,然后再是catkin_make。
注意:1. catkin_make命令必须在工作空间这个路径上执行 2.原先的初始化命令catkin_init_workspace仍然保留
catkin的结构十分清晰,具体的catkin工作空间结构图如下。初看起来catkin工作空间看起来极其复杂,其实不然,catkin工作空间的结构其实非常清晰。
在工作空间下用tree命令,显示文件结构。
$ cd ~/catkin_ws
$ sudo apt install tree
$ tree
结果为:
─ build
│ ├── catkin
│ │ └── catkin_generated
│ │ └── version
│ │ └── package.cmake
│ ├──
......
│ ├── catkin_make.cache
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├──
......
├── devel
│ ├── env.sh
│ ├── lib
│ ├── setup.bash
│ ├── setup.sh
│ ├── _setup_util.py
│ └── setup.zsh
└── src
└── CMakeLists.txt -> /opt/ros/kinetic/share/catkin/cmake/toplevel.cmake
通过tree命令可以看到catkin工作空间的结构,它包括了src
、build
、devel
三个路径,在有些编译选项下也可能包括其他。但这三个文件夹是catkin编译系统默认的。它们的具体作用如下:
在编译过程中,它们的工作流程如图:
后两个路径由catkin系统自动生成、管理,我们日常的开发一般不会去涉及,而主要用到的是src文件夹,我们写的ROS程序、网上下载的ROS源代码包都存放在这里。
在编译时,catkin编译系统会递归的查找和编译src/
下的每一个源代码包。因此你也可以把几个源代码包放到同一个文件夹下,如下图所示:
catkin工作空间基本就是以上的结构,package是catkin工作空间的基本单元,我们在ROS开发时,写好代码,然后catkin_make,系统就会完成所有编译构建的工作。至于更详细的package内容,我们将在下面继续介绍。
在1.6节我们曾对package软件包进行了分类,分别介绍了二进制包和源代码包。而ROS中的package的定义更加具体,它不仅是Linux上的软件包,更是catkin编译的基本单元,我们调用catkin_make
编译的对象就是一个个ROS的package,也就是说任何ROS程序只有组织成package才能编译。所以package也是ROS源代码存放的地方,任何ROS的代码无论是C++还是Python都要放到package中,这样才能正常的编译和运行。
一个package可以编译出来多个目标文件(ROS可执行程序、动态静态库、头文件等等)。
一个package下常见的文件、路径有:
├── CMakeLists.txt #package的编译规则(必须)
├── package.xml #package的描述信息(必须)
├── src/ #源代码文件
├── include/ #C++头文件
├── scripts/ #可执行脚本
├── msg/ #自定义消息
├── srv/ #自定义服务
├── models/ #3D模型文件
├── urdf/ #urdf文件
├── launch/ #launch文件
其中定义package的是CMakeLists.txt
和package.xml
,这两个文件是package中必不可少的。catkin编译系统在编译前,首先就要解析这两个文件。这两个文件就定义了一个package。
通常ROS文件组织都是按照以上的形式,这是约定俗成的命名习惯,建议遵守。以上路径中,只有CMakeLists.txt
和package.xml
是必须的,其余路径根据软件包是否需要来决定。
创建一个package需要在catkin_ws/src
下,用到catkin_create_pkg
命令,用法是:catkin_create_pkg package depends
其中package是包名,depends是依赖的包名,可以依赖多个软件包。
例如,新建一个package叫做test_pkg
,依赖roscpp、rospy、std_msgs(常用依赖)。
$ catkin_create_pkg test_pkg roscpp rospy std_msgs
这样就会在当前路径下新建test_pkg
软件包,包括:
├── CMakeLists.txt
├── include
│ └── test_pkg
├── package.xml
└── src
catkin_create_pkg
帮你完成了软件包的初始化,填充好了CMakeLists.txt
和package.xml
,并且将依赖项填进了这两个文件中。
rospack是对package管理的工具,命令的用法如下:
rostopic命令 | 作用 |
---|---|
rospack help |
显示rospack的用法 |
rospack list |
列出本机所有package |
rospack depends [package] |
显示package的依赖包 |
rospack find [package] |
定位某个package |
rospack profile |
刷新所有package的位置记录 |
以上命令如果package缺省,则默认为当前目录(如果当前目录包含package.xml)
roscd
命令类似与Linux系统的cd
,改进之处在于roscd
可以直接cd
到ROS的软件包。
rostopic命令 | 作用 |
---|---|
roscd [pacakge] |
cd到ROS package所在路径 |
rosls
也可以视为Linux指令ls
的改进版,可以直接ls
ROS软件包的内容。
rosls命令 | 作用 |
---|---|
rosls [pacakge] |
列出pacakge下的文件 |
rosdep
是用于管理ROS package依赖项的命令行工具,用法如下:
rosdep命令 | 作用 |
---|---|
rosdep check [pacakge] |
检查package的依赖是否满足 |
rosdep install [pacakge] |
安装pacakge的依赖 |
rosdep db |
生成和显示依赖数据库 |
rosdep init |
初始化/etc/ros/rosdep中的源 |
rosdep keys |
检查package的依赖是否满足 |
rosdep update |
更新本地的rosdep数据库 |
一个较常使用的命令是用于安装工作空间中src
路径下所有package的依赖项(由pacakge.xml文件指定)。
rosdep install --from-paths src --ignore-src --rosdistro=kinetic -y