面试的时候被问:"你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节点——机器人系统中的最小执行单元