适用于产品: 幻尔科技 ROS2 机型(JetRover三合一ROS智能车 / JetAuto麦轮式机器人 / JetAcker阿克曼ROS机器人 / ROSOrin智能小车 / LanderPi三合一ROS2智能车 / MentorPi智能视觉小车 / TurboPi智能视觉小车 等,凡官方镜像自带 ros2_ws 的机型)
涉及模块: colcon 工作空间 / overlay 环境链 / install 目录 / 第三方预编译库
核心标签: 通用 ros2 #colcon #编译 #环境 #共享库
先记住一句:出厂镜像里的程序已经编译好并且整机验证过,开机直接能跑,不需要你再编译一次。在官方工作空间里敲 colcon build,不是"更新一下",而是把整套已经验证过的程序替换成一份现场编出来的、没验证过的版本。
一、先看症状对不对得上
如果出现下面任意一种,先怀疑是"在出厂环境里编译过",而不是先怀疑硬件:
| 症状 | 客户通常的描述 |
|---|---|
| 编译前正常,编译后某个功能报错 | “我就重新编译了一下” |
| 报错关键字是共享库找不到 | error while loading shared libraries、cannot open shared object file、undefined symbol |
| 编译过程中途失败 | 编到某个包报错退出,之后连原来能用的功能也不能用了 |
| 只改了一个包,坏的功能却不止一个 | “我明明只动了 A” |
反过来,如果编译前后行为完全一样、报错和库无关,那就不是这条原因,别往这个方向查。
二、为什么在出厂环境里编译会把功能编坏
四层原因,单独一层就够毁掉环境:
(1)overlay 把官方版本盖掉了
ROS2 的工作空间一旦被 source,它的 install 目录就排在系统已装包的前面,同名的功能包以工作空间里的为准。你在官方工作空间里重新 colcon build,等于把那些原本能正常跑的包,逐个替换成现场刚编出来的版本。
(2)编译产物的依赖关系会重新对一遍
编出来的程序要去系统里找动态库。官方镜像是"程序加依赖"一起验证过的固定组合,你在现场重编时如果某个依赖缺了、版本不同,就会在启动时报找不到共享库或未定义符号。而且这个过程是先编完、再跑到那一步才报错,看起来就像"原先好的功能被编坏了"。
(3)编到一半失败,install 里留下的是不完整结果
这类机器内存有限,并行编译很容易中途失败。只要有一个包没编完,install 里留下就是一个残缺的工作空间,整套功能会同时不可用。这时候再重新编一次也不一定能恢复,因为上一次留下的中间产物会干扰。
(4)有些东西本来就不在 src 里
三维建图用的 rtabmap、深度相机 SDK、部分第三方视觉库,是镜像里预编译装好的,源码根本不在你的工作是空间的 src 目录。你在官方工作空间里重编,只能编到 src 里那部分,结果就是"一部分是旧的预编译、一部分是新编的",两边版本对不上,一调用就报错。这是最常见的"编译完反而坏了"的真相。
三、建议做法:另建独立工作空间叠加
要改代码、加自己的功能,就在官方环境之上叠一个独立工作空间,改坏了删掉就恢复,官方环境一点不受影响。
第一步,建目录,把要改的包源码放进去。注意只放你要动的那几个包,不要把官方 src 整棵拷过来:
mkdir -p /home/ubuntu/my_ws/src
cd /home/ubuntu/my_ws && colcon build --symlink-install
第二步,每次开终端按这个顺序 source,官方在前,自己的在后。容器里默认是 zsh,把 setup.bash 换成 setup.zsh 即可:
source /opt/ros/humble/setup.bash
source /home/ubuntu/ros2_ws/install/setup.bash
source /home/ubuntu/my_ws/install/setup.bash
第三步,验证叠加是否生效:
ros2 pkg prefix controller
ros2 pkg prefix 你改的包名
判定标准很简单:没改过的包,prefix 必须还指向官方目录;只有你改过的那几个包才指向 my_ws。如果连没改的包也跑到 my_ws 去了,说明你把官方源码整棵拷进去了,这就是第四层原因,撤掉重来。
建议在动手前先备份一张卡镜像。Jetson 机型备份 NVMe 或 SD 卡,树莓派机型直接备份 SD 卡。编译翻车时换回备份卡是最快的恢复手段,比排查快得多。
四、已经编坏了怎么恢复
先说结论:不要手动去修。缺哪个库补哪个库、编坏哪个包重编哪个包,这种做法拼不回出厂那套验证过的组合,通常是把问题从一个功能扩散到更多功能。
按可靠程度从高到低:
(1)有备份卡镜像,直接换回来
这是最快的,也是唯一能做到"和出厂完全一致"的方式。
(2)没有备份,重置镜像
按 GEN-016 重置镜像与备份流程重新烧录,恢复出厂状态。刷机前先把你的代码拷出来,卡要整个重写,里面不会留东西。
(3)容器型机型:重启容器通常没用
容器可写层已经被写脏了,重启只是重新进同一个脏环境。只有重置整机镜像才能恢复。
重置镜像前必须做的一件事:把你的源码、训练好的模型、标定文件拷到 U 盘或另一台电脑。刷完机这些都不在卡上了。
五、容器机型还有两条额外红线
(1)不要执行 sudo apt autoremove
容器里的 ROS 包在镜像构建时被标记成自动安装,apt 会把它们当成孤儿包删掉,一次就能把 400 多个 ROS 包清空,整个 ROS2 环境报废。
(2)不要执行 sudo apt upgrade
容器基础是 Ubuntu 22.04,但部分镜像的 apt 源被配成了更新的发行版源。upgrade 会用新版本的包覆盖系统,直接编坏。这类镜像里 apt install 报 404 也是同一个原因,不是网络问题。
真的需要装包时,先把 apt 源改回与系统版本一致的四行(main / updates / backports / security),再 apt-get update。