尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

ROS2 colcon完全指南:从安装到排错,一文搞定

发布时间:2026/9/24 23:30:52

资讯中心
01
ARTICLE

ROS2 colcon完全指南:从安装到排错,一文搞定

ROS2 colcon完全指南:从安装到排错,一文搞定
很多人从ROS1转过来或者刚接触ROS2第一个卡住的地方往往不是消息通信不是tf树反而是最不起眼的编译工具。catkin_make用顺手了到了ROS2里突然变成colcon build命令不一样输出目录不一样报错也不太一样一堆人就在这一步折腾半天。今天这篇就把colcon这件事讲透从安装到常用参数从并行编译到疑难排查全是实操里真正用得到的东西。1. 为什么ROS2选择了colcon它到底解决了什么问题1.1 colcon的出身和定位colcon全称是Collective Construction直译过来是集体构建。它不是ROS2刚发明的新东西而是从ament_tools、catkin这些工具一路迭代出来的。它的核心职责只有一个按照依赖关系把工作空间里的多个软件包有序地编译成可用的库、可执行文件和Python模块。如果你用过ROS1一定对catkin_make、catkin build这些命令有印象。catkin_make是把所有包放在一个大的CMake工程里统一编译缺点是某个包出了问题整个编译就跟着崩。colcon把每个包当成独立单元按拓扑顺序逐个编译某个包失败不会拖垮全部而且天然支持增量编译——你只改了其中一个包重新build时不会把整个空间都重编一遍。这里多说一句ROS2官方之所以选colcon还有一个重要原因是它同时支持C和Python两种包的混合编译。ROS1时代C包用catkinPython包往往直接扔进src里靠setup.py处理经常出现编译过了但导入不进来的别扭局面。colcon对ament_cmake和ament_python两类包统一管理编译完都输出到install目录source一下就能用这个体验比ROS1清爽太多。1.2 colcon工作空间的基本结构用colcon之前你得先理解ROS2工作空间的布局。一个典型的工作空间长这样your_ws/ ├── src/ # 存放所有源码包 ├── build/ # 编译中间产物每个包一个子目录 ├── install/ # 安装结果可执行文件、库、Python模块都在这 └── log/ # 编译日志排查问题很有用这个结构和ROS1的catkin workspace很像但有个关键区别ROS1的catkin_make把产物放在devel目录ROS2的colcon默认放在install目录。很多人刚上手时习惯性地source devel/setup.bash结果发现找不到包其实就是目录搞错了。另外要注意src下的每个包可以是用Python写的ROS2包内部是setup.py、setup.cfg、package.xml也可以是C包内部是CMakeLists.txt、package.xml甚至可以在一个src目录里混合放置。colcon不会因为你放了一堆乱七八糟的文件夹就罢工它通过package.xml来识别哪些是ROS2包这也是为什么包目录里必须有这个文件。1.3 colcon的安装方式装colcon非常简单两种方式任选其一。第一种是apt安装推荐给绝大多数人省心sudo apt install python3-colcon-common-extensions这个包会带上colcon以及常用扩展插件比如测试、清理、Graph相关功能。第二种是pip安装适合想用最新版、或者apt源里版本老化的情况pip install colcon-common-extensions我个人的建议是能用apt就用apt因为apt会帮你处理掉一部分系统依赖比如colcon需要用到的python3-pkg-resources等。有些人在纯净的Ubuntu上直接pip装后面会遇到import Anaconda的Python还是系统Python之类的坑这个后面排查部分再细说。装完之后别忘了把ROS2环境加载进来一般是在~/.bashrc里加上source /opt/ros/humble/setup.bash版本不同路径不一样Foxy、Rolling、Jazzy等版本的对应路径大家应该能举一反三。配置好之后新开终端在任意位置输入colcon --help验证一下colcon --help如果输出了帮助信息说明colcon已经就位。出现command not found的话检查两个地方一是colcon是否真的装了二是ROS2环境是否真的source了。注意即使装了colcon如果你的bashrc里没有source ROS2的setup.bash终端里也只有部分命令可用这个坑我见过好多回。2. colcon常用命令和关键参数详解2.1 最基础的colcon build在你的工作空间根目录下执行cd ~/your_ws colcon build它会自动扫描src目录解析所有包的依赖关系然后按顺序编译。默认行为包含这几个要点自动创建build、install、log三个目录不用手动建。编译结果输出到install目录每个包生成一个子文件夹。默认是Debug模式后面讲参数时会提到怎么改成Release。默认使用所有CPU核心并行编译如果机器比较老可能会卡顿。编译完成后终端会输出每个包的结果绿色的FINISHED就是成功红色的FAILED就是失败中间会有Running和Finished的统计信息。这里有个小细节colcon build的退出码也是有用的如果你在写CI脚本可以靠它判断整个工作空间是否编译成功。编译完之后要source install目录里的setup.bashsource install/setup.bash不source的话ros2 run找不到你编译出的节点。这个步骤和ROS1的source devel/setup.bash是同一个道理只是路径不一样。如果你发现每次开新终端都要手动source可以在bashrc里加一行但要注意路径别写错不然整个终端环境都乱了。2.2 指定编译目标只编一个包或者排除某些包工作空间里包多的时候全量编译很浪费时间。colcon给了你精准控制的手段# 只编译某个包及其依赖 colcon build --packages-select my_package # 只编译某个包不编译它的依赖前提是依赖已在install中 colcon build --packages-select my_package --packages-skip-build-finished # 排除某些包编译其他所有包 colcon build --packages-ignore unwanted_package--packages-select是我平时用得最频繁的参数。比如我改了my_package里的代码跑一下这个命令几秒钟就完事不用等整个工作空间重新编。这里要注意一个细节如果你改的这个包被其他包依赖那么只编它还不够依赖它的包也需要同步编译因为接口可能变了。colcon不会自动帮你递推编译它只编你指定的包和它依赖的包不会去编依赖它的包。想要连依赖它的包一起编可以加上--packages-up-to my_package但方向是反的——它编的是my_package依赖的所有包而不是依赖my_package的包这个仔细品一下。还有一个--packages-skip-build-finished参数我刚开始没搞懂它和纯粹用--packages-select的区别。实际操作中这个参数适合你已经编译过一次第二次想快速只编指定包、忽略那些没改过的包的情况。它会在扫描阶段把已经标记为build finished的包跳过进一步节省时间。2.3 符号链接模式Python开发者的最爱colcon build --symlink-install这个参数我必须重点讲。ROS2的Python包本质上是把源码文件复制到install目录然后生成一个可导入的模块。默认情况下每次修改Python源码都要重新build才能生效非常麻烦。而加了这个参数后install目录里不再生成副本而是创建指向src目录源码的符号链接。你改了源码保存之后立刻就能通过ros2 run运行新代码连bash都省了。C包就没这么幸福了因为C需要编译成二进制改了源码必须重新编译。不过对C来说--symlink-install也有点作用——至少头文件的链接是符号链接改头文件时能少踩一点缓存冲突的坑但用到头文件的其他包仍然需要重编。如果你工作空间里Python包占多数这个参数建议直接写进日常用的编译命令里甚至可以设置成默认值后面会说怎么配置。2.4 并行编译线程数的控制colcon build默认会使用机器的全部CPU核心来并行编译这对高配机器来说效率很高但在内存较小的机器上容易爆内存。而且并行编译时终端输出是交错的某个包报错了信息会被冲掉你很难看清问题出在哪。这时候可以限制并行数# 使用4个线程并行编译 colcon build --parallel-workers 4 # 串行编译一个包一个包地编 colcon build --executor sequential我自己的经验是如果你的CPU是8核16线程这种主流配置--parallel-workers 4到8之间比较舒服。设成$(nproc)会尽量拉满但对内存小的机器不友好。另外真正卡住编译的往往不是CPU而是内存。每个编译进程都是独立的内存占用者如果你的内存只有8GB而工作空间里有大型C库比如PCL、OpenCV依赖的包并行数还是保守一点好。如果你想知道当前系统有多少核可以用nproc返回的数字可以直接用来设置线程数。也可以直接在命令里组合colcon build --parallel-workers $(nproc)但在服务器上我一般不建议这么做因为你的编译任务会抢占别人在用的CPU资源。2.5 传给CMake的参数--cmake-argsC包的编译底层还是CMake很多配置必须通过CMake参数传进去。colcon提供了一个透传参数colcon build --cmake-args -DCMAKE_BUILD_TYPERelease这个是最常见的用法。默认情况下colcon构建的是Debug版本Debug版本没有做优化运行时速度明显偏慢而且二进制文件更大。如果做实际机器人部署或者跑SLAM建图这种计算密集型的节点建议用Release模式。还可以传多个参数colcon build --packages-select my_pkg --cmake-args -DCMAKE_BUILD_TYPERelease -DBUILD_TESTINGOFF注意--cmake-args后面的参数会应用到本次编译的所有C包上如果你只想针对某个包传参一个比较绕的办法是先用--packages-select选中目标包再加--cmake-args这样参数就只对这个包生效。因为colcon只会把参数传给本次参与编译的CMake包。还有一个--ament-cmake-args参数专门传给ament_cmake的平时用得不那么多但如果你的包用了ament_cmake的高级特性可以留意一下。2.6 测试相关的colcon命令ROS2的包测试也是通过colcon管理的。写完单元测试后可以这样执行colcon test colcon test-result --verbosecolcon test会执行所有包里的测试test-result --verbose会把失败详细信息打出来。这两个命令一定要连着用因为colcon test本身只显示测试有没有跑不显示具体哪个断言失败了。如果你在写CI或者Makefile希望测试失败时返回非零退出码可以这样colcon test --return-code-on-test-failure这个参数在做自动化流水线时很有用一键判断测试是否通过。许多人不知道colcon test也可以像build一样用--packages-select来只跑指定包的测试不传的话会跑全部。2.7 别的常用命令除了build和test还有几个命令虽然不常用但关键时候很顶用。# 列出工作空间中所有的包 colcon list # 查看包的依赖关系 colcon list --dependencies # 清理编译产物 colcon clean workspacecolcon list非常直观它会扫描src目录把每个包的名称、路径、类型列出来。--dependencies选项还可以查看依赖树用来排查循环依赖或者缺失依赖非常方便。colcon clean workspace会把build和install目录清空相当于从头来过。如果你不确定哪个包缓存出了问题直接clean一下再重新build往往能解决问题。这个命令还可以更精细# 只清理build目录 colcon clean build # 只清理install目录 colcon clean install3. 实操实录从零编译一个混合工作空间3.1 场景设定假设我们要创建一个工作空间里面有一个C写的talker节点和一个Python写的listener节点用来模拟最经典的发布订阅通信。这个场景很小但足以把colcon的完整流程走一遍顺便验证C和Python包的混合编译。先建目录结构mkdir -p ~/colcon_demo/src cd ~/colcon_demo然后用ros2 pkg命令创建两个包cd ~/colcon_demo/src ros2 pkg create cpp_talker --build-type ament_cmake --dependencies rclcpp std_msgs ros2 pkg create py_listener --build-type ament_python --dependencies rclpy std_msgs这里--build-type参数指定了包的构建类型--dependencies会自动帮你把依赖写进package.xml和CMakeLists.txt里。如果少了这一步后面编译时find_package会报错大家在创建包时务必养成显式声明依赖的习惯。3.2 C节点的编译过程先用一个最简的发布节点替换cpp_talker/src/cpp_talker.cpp里的模板代码。简单来说就是创建一个节点用Timer周期性发布Hello World字符串。我不展开写完整代码重点看编译行为。回到工作空间根目录cd ~/colcon_demo colcon build --packages-select cpp_talker执行后终端会显示Starting cpp_talker Finished cpp_talker Summary: 1 package finished这时install目录下会生成cpp_talker的产物。如果你用--symlink-installC包的头文件会以符号链接的形式存在但可执行文件仍然是实实在在编译出来的。source之后运行source install/setup.bash ros2 run cpp_talker cpp_talker终端会不断输出Publishing: Hello World说明C节点编译运行成功。3.3 Python节点的编译过程和ros2 runPython包就不用编译C那样编了colcon做的是把源码安装到install目录。比如py_listener的目录结构默认是py_listener/ ├── package.xml ├── setup.py ├── setup.cfg └── py_listener/ └── __init__.py你把自己的listener逻辑写进py_listener/py_listener.py然后cd ~/colcon_demo colcon build --packages-select py_listener --symlink-install这里的--symlink-install就是Python开发的灵魂。不加这个参数每次改代码都要重新build加了之后直接改src下的py文件再ros2 run就是新代码。source之后验证source install/setup.bash ros2 run py_listener listener可以看到它订阅到了talker发布的消息。3.4 全量编译和source顺序的坑如果你两个包都要编可以一次全量构建cd ~/colcon_demo colcon build --symlink-install --parallel-workers 4输出会显示两个包各自的状态。这里有个实际工作中常见的问题如果你在多个工作空间之间切换比如又要用ros2官方例程又要用自己的工作空间一定要小心source的顺序。后source的会覆盖先source的所以原则上应该把底层依赖的工作空间放后面或者说把更上层的应用工作空间放在最后source。很多人遇到ros2 run找不到自己包的问题八成是source环境写得有毛病。3.5 如何让重复编译更顺手每次敲一长串build命令确实烦人。我个人的做法是在~/.bashrc里加几个常用函数的别名alias cbcolcon build --symlink-install --parallel-workers 4 alias cbscolcon build --symlink-install --packages-select alias cbtcolcon test colcon test-result --verbose这样日常操作变成cb # 全量编译 cbs my_pkg # 只编某个包还可以设置环境变量COLCON_OPTIONS让所有colcon命令自动带上默认参数export COLCON_OPTIONS--symlink-install设置之后你直接输入colcon build等效于colcon build --symlink-install。这个环境变量是我后来才发现的一用就离不开了。不过要注意它会对所有colcon子命令生效如果某个命令不支持这个参数可能报错但build这个场景完全没问题。4. 常见问题与排查技巧实录4.1 colcon: command not found这是一个高频报错但原因有好几种我一个个说。第一你压根没装colcon。解决sudo apt install python3-colcon-common-extensions。第二你装了但终端里找不到。这种情况多发生在pip安装时Python版本和系统PATH不匹配。比如你系统里有两个Pythonpip把colcon装到了某个不在PATH的Scripts目录下。在Ubuntu上我推荐一律用apt安装不折腾。第三你的bashrc没有source ROS2环境。colcon本体只要能运行就和ROS2环境关系不大但如果你是从某个特定路径调用的还是建议先确认环境变量AMENT_PREFIX_PATH是否正常。4.2 build时报错找不到依赖包典型报错长这样CMake Error: The following variables are used in this project, but they are set to NOTFOUND.或者Package xxx not found这种问题90%的原因是这个依赖包要么没装要么装了但不在当前环境中。ROS2官方包的安装可以通过apt完成比如sudo apt install ros-humble-turtlebot3-gazebo对于一些还没被apt收录的包你就得先把依赖包源码编译出来。这里有个排查思路先用ros2 pkg prefix看看某个包在不在环境里ros2 pkg prefix slam_toolbox如果输出一个路径说明这个包在当前环境里可用如果没输出说明环境里没有这个包。还有一个经常被忽视的点src之外的工作空间如果先编译过在install里生成了某些包再全量编译时如果没有source install/setup.bash新的编译进程是感知不到这些已装好的依赖的。所以每次编译前最好确保当前终端source了ROS2版本环境必要时还要source之前编译过的install/setup.bash。如果你在bashrc里已经source了install/setup.bash但install目录不存在或者路径错了也会导致找不到包这种问题很隐蔽。4.3 编译失败后没有输出有用的错误信息colcon并行编译有好处坏处就是多个进程的输出会交错在一起一个包的报错信息可能被淹没。解决这个问题我的习惯是单独重编失败的那个包加--packages-select再加低并行度colcon build --packages-select bad_package --parallel-workers 1 --event-handlers console_direct--event-handlers console_direct的作用是把日志直接打印在终端而不是缓冲到log目录。加上这个参数后你会看到更完整、更有顺序的编译输出。这个参数平时不必常开但排查错误时很有用。4.4 增量编译不生效改动代码后运行还是旧版本这个坑在Python包里最常见。如果你是默认方式编译的Python包没有加--symlink-install那么源码被拷贝到了install目录你改了src里的文件install里的还是旧文件运行起来自然是旧版本。解决方案就是加--symlink-install参数或者每次改完都重新build。另外还有一种情况是C包你改了某个头文件但只build当前包没有重编依赖这个头文件的其他包导致其他包运行时还是旧的内联实现或者旧接口。这种问题在大型项目里很难排查。我的建议是如果改动涉及公共接口保险起见把依赖它的包也一起build一遍。colcon本身提供了--packages-up-to参数它的语义是编译指定包及其所有依赖包注意是依赖它不是它依赖的所以不适合用来重编依赖方。想重编所有依赖方目前没有一条命令直接搞定只能手工--packages-select列出那些包或者干脆全量编译。4.5 Python包build成功但import失败build成功但运行时看不到模块通常是包的安装路径没被加入Python搜索路径。在ROS2里这个路径是由AMENT_PREFIX_PATH和Python的site-packages机制共同决定的。排查时可以手动检查install目录下是否有对应的Python包目录。如果发现install下没有生成py_listener的目录说明包没被正确处理。可能原因包括package.xml里的exec_depend缺了rclpy、setup.py入口点写得不对等。另外要特别提醒不要在Build目录下直接运行Python脚本因为那里缺少安装后的布局。要用ros2 run它内部会处理好环境变量。4.6 log目录爆炸式增长colcon每次build都会在log目录下生成新的日志文件如果长期不清理工作空间会越来越大。我的习惯是定期清理colcon log clean或者直接删除log目录它只是日志不影响编译。4.7 如何在多终端下共享编译产物我自己做机器人调试时经常开好几个终端一个终端编译另一个终端要在编译完后立刻运行新节点。只要你在两个终端里都source了同一个install/setup.bash就都能访问编译产物不需要每个终端都重新build。这一点大家应该没疑问但要注意如果你在一个终端里编译后另一个终端没有刷新环境变量某些已安装包的环境变化比如新增了可执行文件可能感知不到。这时候重开终端或者重新source一下install/setup.bash即可。4.8 常见错误速查表现象可能原因解决方法colcon: command not found未安装或未source环境sudo apt install python3-colcon-common-extensionssource /opt/ros/humble/setup.bashCMake Error: Notfound缺少依赖包用ros2 pkg prefix确认apt安装或先编译依赖包Python模块找不到未加--symlink-install或install未source加--symlink-install重新source install/setup.bash编译输出杂乱无重点并行编译日志交错使用--packages-select单独编加console_direct包没编但Summary显示通过增量编译误判colcon clean workspace后全量重编内存不足导致编译卡死并行数太高减小--parallel-workers5. 实际开发中我建议把这些colcon用法刻进肌肉记忆上面这些内容基本覆盖了ROS2开发中colcon的绝大部分场景。最后分享一点个人的体会。我刚开始从ROS1切到ROS2时最不适应的不是改名后的命令而是编译完还要source install/setup.bash这件事。ROS1的catkin_make虽然也会生成setup.bash但很多老手习惯在bashrc里写死导致新工作空间的包总是找不到。到了ROS2这个机制更规范了每个工作空间都明确要求先source再运行。我在实际项目里的习惯是一个工作空间一个终端配置文件启动终端时自动source对应工作空间的install/setup.bash。比如在~/robot_ws下我会在bashrc末尾加source ~/robot_ws/install/setup.bash但这样会有一个副作用如果我同时开了多个工作空间后source的会覆盖先source的导致另一个工作空间的包不可见。所以对多工作空间并存的用户来说用--merge-install可以缓解这个问题。这个参数会把所有包安装到同一个install目录而不是每个包一个子目录减少了环境变量冲突。但它也有自己的坑比如不同包同名文件会互相覆盖所以一般不建议新手用知道有这个东西就行。踩过几次坑之后我的工作流固定成代码改动小就用cbs只编对应包加--symlink-install改动大就全量cb不确定的时候先colcon list看看工作空间里到底有哪些包再决定怎么编。记住一句话colcon本身不复杂它只是把CMake、setup.py、ament这些底层工具统一到一个入口里。你把它的参数吃透了再把动态库覆盖、环境变量覆盖这些常见的坑都踩一遍后面的ROS2开发流程会顺很多。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。