ROS2工作空间与colcon编译——开发流程的第一步

面试的时候被问:"你ROS2项目怎么组织的?怎么编译?"我说"用colcon build"。面试官说:"colcon和catkin有什么区别?overlay workspace了解吗?"

我当时的表情大概是这样的:啊?

ROS2的工作空间管理和ROS1的catkin有很大不同。搞清楚这些概念,是你从"能跑demo"到"能开发项目"的关键一步。

工作空间的基本结构

ROS2的工作空间(workspace)就是一个项目目录,标准结构是这样的:

my_robot_ws/ ├── src/ # 源代码放这里 │ ├── my_pkg1/ │ ├── my_pkg2/ │ └── ... ├── build/ # 编译中间产物(每个包一个子目录) ├── install/ # 编译输出(每个包一个子目录) └── log/ # 编译日志

你只需要关心src目录,其他三个都是colcon自动生成的。

创建工作空间:

mkdir -p ~/robot_ws/src cd ~/robot_ws

然后把你的包放到src下面。一个workspace可以包含多个包,每个包独立编译。

colcon:ROS2的编译工具

ROS1用catkin_make或者catkin build,ROS2换成了colcon。colcon不只能编译ROS项目,它是一个通用的Python/C++项目构建工具,ROS2只是它的一个使用场景。

最基本的编译命令:

cd ~/robot_ws colcon build

这会编译src下的所有包。编译完成后,install目录下会生成每个包的安装文件。要使用这些包,需要source环境:

source install/setup.bash

常用的编译选项:

colcon build --packages-select my_pkg # 只编译指定的包 colcon build --packages-up-to my_pkg # 编译某个包及其所有依赖 colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release # 指定编译类型 colcon build --symlink-install # 用符号链接代替拷贝(Python开发神器)

--symlink-install这个选项在开发Python包时特别有用。它让install目录下的Python文件指向src目录的符号链接,这样你改了源码不用重新编译,直接生效。能省下大量时间。

overlay workspace:叠加工作空间

这是ROS2的一个重要概念,也是和ROS1区别最大的地方之一。

假设你在做一个项目,需要用到社区的navigation包,但你想修改其中一部分代码。你不需要fork整个仓库,而是可以用overlay的方式:

/opt/ros/humble/ # 底层workspace(系统安装的ROS2) ~/nav_overlay_ws/src/ # 你的叠加workspace └── navigation/ # 只放你要修改的包

编译overlay workspace时,它会"覆盖"底层workspace中同名的包。其他没修改的包还是用底层的版本。

cd ~/nav_overlay_ws colcon build source install/setup.bash # 这个setup.bash包含了overlay和底层的路径

overlay的好处是:你只维护自己修改的部分,其他依赖都用系统版本。升级ROS2的时候,你的修改不会受影响。

C++包和Python包的区别

ROS2支持两种类型的包:ament_cmake(C++)和ament_python(Python)。

C++包用CMakeLists.txt管理编译,适合性能要求高的模块:

cmake_minimum_required(VERSION 3.8) project(my_cpp_pkg) find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) add_executable(my_node src/my_node.cpp) ament_target_dependencies(my_node rclcpp) install(TARGETS my_node DESTINATION lib/${PROJECT_NAME}) ament_package()

Python包用setup.py管理,适合快速开发和原型验证:

from setuptools import setup package_name = 'my_py_pkg' setup( name=package_name, version='0.1.0', packages=[package_name], install_requires=['setuptools'], entry_points={ 'console_scripts': [ 'my_node = my_py_pkg.my_node:main', ], }, )

一个项目里可以同时有C++包和Python包。colcon会自动识别每个包的类型,分别用对应的工具编译。

依赖管理

ROS2的依赖分两种:系统依赖和包依赖。

系统依赖用rosdep管理:

rosdep install --from-paths src --ignore-src -r -y

这会根据每个包的package.xml自动安装所需的系统包。

包依赖在package.xml里声明:

<depend>rclcpp</depend> <depend>std_msgs</depend> <buildtool_depend>ament_cmake</buildtool_depend>

<depend>表示编译和运行都需要,<build_depend>只在编译时需要,<exec_depend>只在运行时需要。

面试中怎么聊

面试官问工作空间管理,你可以说:"我们用overlay workspace的方式组织项目。底层是系统安装的ROS2,上面叠加项目自己的包。这样升级ROS2版本的时候,我们的代码不受影响。编译用colcon,开发Python包时用--symlink-install加速迭代。CI里用--packages-up-to只编译改动的包及其依赖,节省编译时间。"

常见编译错误排查

colcon编译最常遇到的错误有几种。第一种是"ament_cmake not found",通常是没source ROS2的setup.bash。第二种是"找不到头文件",检查CMakeLists.txt里的find_package和include_directories是否正确。第三种是"链接错误undefined reference",说明库没有正确链接,检查package.xml的依赖声明和CMakeLists.txt的ament_target_dependencies。

一个排查技巧:用colcon build --event-handlers console_direct+可以看到每个包的详细编译输出,比默认的错误信息详细得多。遇到疑难编译问题,这个参数能帮你快速定位。

colcon构建的进阶技巧

colcon除了基本的build命令,还有很多实用功能。--packages-select可以只编译指定的包,在大型workspace中节省大量时间;--cmake-args可以切换编译模式;--event-handlers可以实时显示编译输出方便排查错误。另外colcon test和colcon test-result可以运行和查看测试结果,是保证代码质量的重要工具。

给你的建议

一开始不要纠结workspace的组织方式。先建一个简单的workspace,放一两个包,跑通编译和运行的流程。等项目变复杂了,再考虑overlay和分包策略。

一定要学会--packages-select。项目大了之后,每次全量编译太慢,只编译你改的包能省很多时间。

还有,source install/setup.bash这一步别忘了。很多人编译完了直接跑,报"package not found",就是因为没source环境。建议把这行加到~/.bashrc里,省得每次手动source。


上一篇:第110篇 DDS通信原理——ROS2底层是怎么传数据的

下一篇预告:第112篇 ROS2 Node节点——机器人系统中的最小执行单元