一.前言
最近在树莓派4B上面编译机械臂运动的功能包一直卡住,但是在虚拟机上验证是可以迅速编译通过的,而且树莓派的swap空间和运行内存监控的时候也没有被占满
经过一番探索和尝试,终于找到了解决方案,将编译时间从几小时卡住缩短到6分钟完成。本文将详细记录问题排查过程和解决方案,希望能帮助到遇到类似问题的开发者。
二.作者的遇到问题的现象
这是笔者当时编译了3个小时还是卡在这里的画面(当然笔者不只是编译了这一次就回头了,笔者不信邪连续编译了大概有三四天,都是这种情况,且每次通过xshell传输后从新编译的进程都不一样)。
然后总结一下:
我的系统状态的话是树莓派4B 4G,4Gswap空间,未完全使用,系统界面运行流畅,无卡顿,编译的进程好长时间无进展,笔者是ros2 humble版本的,系统是Ubuntu22.04
三.问题分析
1.定位卡住环节
通过查看编译日志,发现卡住发生在链接阶段,特别是与MoveIt2库相关的链接过程。MoveIt2是ROS2中用于机械臂控制的强大框架,但也是一个相当复杂的库,包含大量模板和依赖关系。
查看具体编译日志的命令 ps:其实只需要colcon build 加上最后一句话就行,按我格式写也非常好
colcon build --packages-select 包名 --cmake-args -DCMAKE_BUILD_TYPE=Release --event-handlers console_direct+2.资源瓶颈分析
树莓派4B虽然性能不错,但在处理大型C++项目时仍面临限制:
- 内存限制 :4GB内存对于大型C++项目的编译可能不足
- ARM架构特殊性 :某些库在ARM架构上的编译效率可能低于x86
- 链接器效率 :默认链接器在处理复杂依赖时可能效率低下
四.我的解决方案
1.进程管理和清理
首先终止卡住的编译进程,清理之前的构建文件:
以我的wheeltec_arm_pick为例 ps:::前四个命令可以不执行,但是需要中断掉当前的编译进程
# 终止卡住的编译进程 sudo pkill -9 11099 # 替换为实际的进程ID sudo pkill -9 colcon sudo pkill -9 cmake sudo pkill -9 gmake # 清理之前的构建文件 cd ~/ws_arm_my rm -rf build/wheeltec_arm_pick install/wheeltec_arm_pick2.安装并配置Gold链接器
Gold链接器是GNU binutils的一个替代链接器,对于大型C++项目链接效率更高:
# 安装gold链接器 sudo apt update sudo apt install binutils-gold -y # 设置环境变量使用gold链接器 export LD=ld.gold3.优化CMakeLists.txt配置
对CMakeLists.txt进行针对性优化,重点是减少内存使用和提高编译效率:
# ROS2 Humble强制要求CMake≥3.16.3 cmake_minimum_required(VERSION 3.16.3) project(wheeltec_arm_pick) # 树莓派4B专用配置 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # 使用最保守的编译选项,避免过度优化导致卡死 set(CMAKE_CXX_FLAGS_RELEASE "-O0 -DNDEBUG") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") # 链接器优化 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-Wl,--no-keep-memory -Wl,--reduce-memory-overheads -Wl,--as-needed") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-Wl,--no-keep-memory -Wl,--reduce-memory-overheads -Wl,--as-needed") # 减少编译警告,降低处理负载 add_compile_options(-Wall -Wno-unused-parameter -Wno-unused-result -Wno-deprecated-declarations) # 禁用tracetools(解决兼容性问题) set(AMENT_ENABLE_TRACETOOLS OFF CACHE BOOL "Enable tracetools") set(AMENT_CMAKE_ENABLE_TRACETOOLS OFF CACHE BOOL "Enable tracetools") # 保留所有MoveIt2依赖和功能...4.环境变量优化
设置保守的编译选项,减少资源消耗: ps:笔者这里用的是"-j3",一共四核,用的三线程,这样会更快
# 设置保守的编译选项 export CXXFLAGS="-O0" export CFLAGS="-O0" export MAKEFLAGS="-j1" # 单线程编译,减少内存压力5.临时增加交换空间(swap空间足够的忽略就可以)
为编译过程提供额外的内存缓冲:
# 创建临时交换文件 sudo fallocate -l 4G /swapfile1 sudo chmod 600 /swapfile1 sudo mkswap /swapfile1 sudo swapon /swapfile16.少一点线程编译
为避免内存峰值过高,我用的是双线程编译
# 使用双线程编译减少内存压力 colcon build --packages-select wheeltec_arm_pick --parallel-workers 2五.最终效果
可以看到最终是编译成功的
六.总结
在嵌入式设备如树莓派上编译大型ROS2项目时,资源管理是关键。本文介绍的方法不仅解决了功能包的编译问题,也为类似情况提供了参考思路:
1. 分析瓶颈 :确定是内存问题而非CPU或存储问题
2. 针对性优化 :从编译选项、链接器选择、内存管理多方面入手
3. 保持功能 :优化过程中确保不牺牲核心功能
4. 环境适配 :考虑ARM架构的特殊性进行针对性调整
这种方法论可以应用到其他在资源受限环境下编译大型C++项目的场景中。
注:这种方法在笔者的设备上得到了解决,但是问题千千万,这种方法不一定是唯一,作者的方法可能也有一些冗余或错误的地方,还望大佬们多多包涵指正!