ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

树莓派4B ROS Melodic完整版镜像:预装环境与避坑指南

树莓派4B ROS Melodic完整版镜像:预装环境与避坑指南

1. 为什么我要做这个树莓派4B的ROS Melodic完整版镜像

树莓派4B跑ROS这件事,看起来简单,实际上手才知道坑有多深。我从树莓派3B时代就开始折腾ROS,那时候内存只有1GB,跑个roscore再开个rviz基本就卡死了。到了4B,内存有2G、4G、8G可选,CPU也升级到了Cortex-A72四核,理论上跑ROS Melodic应该很轻松,但现实是——官方根本没有现成的完整版镜像。

你可能要问,不是有Ubuntu MATE的镜像吗?确实有,但那个是桌面版,预装了一堆用不上的软件,镜像体积大得离谱,烧录到SD卡后启动慢、占用资源多。而且ROS Melodic在ARM架构上的安装,跟x86平台完全不是一回事,很多包需要从源码编译,apt源里根本没有现成的二进制包。我试过在树莓派4B上从零开始装ROS Melodic,光是解决依赖问题就花了两天,中间遇到各种编译错误、Python版本冲突、OpenCV链接失败等等问题。

这个完整版镜像v1.0,就是把我踩过的所有坑都填平之后,打包出来的一个可以直接烧录使用的系统镜像。它基于Ubuntu 18.04 Server版构建,预装了ROS Melodic的完整桌面版组件,包括rviz、rqt工具集、Gazebo仿真环境(虽然树莓派上跑Gazebo有点吃力,但至少能启动),以及常用的导航、建图、视觉相关的功能包。镜像大小控制在4GB以内,烧录到16GB以上的SD卡就能用,启动后直接source一下环境变量就能开始跑ROS节点。

适合谁来用这个镜像?如果你是做移动机器人、无人机、智能小车这类项目的开发者,手头正好有树莓派4B,不想在环境配置上浪费时间,那这个镜像就是给你准备的。哪怕你之前没接触过ROS,只要会用基本的Linux命令,烧录完开机就能跟着教程跑起来。当然,如果你是想在树莓派上做深度学习推理,这个镜像里也预装了TensorFlow Lite和PyTorch的ARM版本,可以直接调用。

2. 镜像的整体设计与核心思路拆解

2.1 为什么选择Ubuntu 18.04 Server而不是桌面版

ROS Melodic的官方支持平台就是Ubuntu 18.04,这个没得选。但Ubuntu 18.04有Desktop和Server两个版本,我最终选了Server版作为基础,原因有三个。

第一,资源占用。Desktop版预装了GNOME桌面环境,开机后内存占用就在500MB以上,而Server版只有100MB左右。树莓派4B虽然性能不错,但内存毕竟有限,省下来的400MB可以多跑好几个ROS节点。如果你确实需要图形界面,可以后续手动安装轻量级的LXDE或者Xfce,比GNOME省资源得多。

第二,软件包冲突。Desktop版自带了很多多媒体、办公相关的软件包,其中一些会跟ROS的依赖产生冲突。比如Desktop版预装的Python库版本可能跟ROS需要的版本不一致,导致pip安装时出现依赖地狱。Server版干净得多,从零开始装ROS,所有依赖都是可控的。

第三,镜像体积。Desktop版的基础镜像就有2GB多,加上ROS完整版之后轻松超过6GB。Server版基础镜像不到1GB,加上ROS之后控制在4GB以内,烧录和备份都方便很多。

注意:Server版没有图形界面,所有操作都要通过SSH或者串口终端完成。如果你不熟悉命令行操作,建议先花点时间学习基本的Linux命令,或者后续自己装个轻量桌面。

2.2 ROS Melodic完整版到底包含哪些组件

很多人说“完整版”,但每个人的定义不一样。我这个镜像里的“完整版”是指ROS Melodic Desktop-Full安装选项所包含的所有内容,具体包括:

  • 核心通信层:roscore、rosmaster、参数服务器、消息传递机制,这是ROS运行的基础。
  • 基础工具集:roslaunch、rosrun、rostopic、rosservice、rosbag、rosnode等命令行工具,日常调试离不开。
  • 可视化工具:rviz(3D可视化)、rqt(Qt工具箱,包含rqt_graph、rqt_plot、rqt_console等)、rqt_image_view。
  • 仿真环境:Gazebo 9(虽然树莓派上性能有限,但跑简单的仿真场景没问题)、robot_state_publisher、joint_state_publisher。
  • 导航与建图:navigation包(包含amcl、move_base、costmap_2d等)、slam_gmapping、hector_slam、cartographer(这个是我额外编译进去的,官方源里没有ARM版本)。
  • 视觉与感知:cv_bridge、image_transport、usb_cam、realsense2_camera(支持Intel RealSense深度相机)、opencv3(ROS自带的版本)。
  • 机械臂与运动规划:moveit(这个包很大,但考虑到很多人用树莓派做机械臂控制,我还是放进去了)、ros_control。
  • Python与C++开发环境:python3、catkin、rosdep、rosinstall、以及常用的编译工具链(gcc、g++、cmake、make)。

除此之外,我还预装了一些常用的第三方包,比如teleop_twist_keyboard(键盘控制)、joy(手柄控制)、web_video_server(网页查看摄像头画面)等。这些包虽然不在Desktop-Full的默认列表里,但实际项目中经常用到,提前装好省得后面再折腾。

2.3 镜像构建的底层逻辑与工具链选择

构建这个镜像,我用的工具是pi-gen,这是树莓派官方用来构建Raspbian镜像的脚本工具。虽然我要构建的是Ubuntu系统,但pi-gen的框架可以复用,只需要替换底层的rootfs和内核即可。

整个构建流程分为三个阶段:

  1. 基础系统构建:从Ubuntu 18.04 Server的ARM64根文件系统开始,配置网络、SSH、用户账户、时区等基础设置。
  2. ROS安装与配置:通过chroot进入根文件系统,添加ROS的apt源,安装ros-melodic-desktop-full,然后从源码编译那些没有ARM二进制包的组件(比如cartographer、moveit的部分依赖)。
  3. 系统优化与清理:删除不必要的文档、缓存、临时文件,压缩镜像体积。配置开机自启动项,确保ROS环境变量在登录时自动source。

这里有个关键点:树莓派4B是ARM64架构(aarch64),但Ubuntu 18.04的ARM64镜像默认内核可能不支持树莓派4B的所有硬件。所以我用了树莓派官方维护的内核分支,确保WiFi、蓝牙、USB、HDMI这些外设都能正常工作。具体来说,我参考了Ubuntu官方为树莓派提供的预装镜像,提取了其中的内核和设备树文件,集成到我的构建流程里。

实操心得:构建ARM镜像最耗时的环节是源码编译。像cartographer这种包,在树莓派4B上编译一次要将近两个小时。我的建议是,如果只需要基本功能,可以跳过这些大型包的编译,直接用apt安装预编译版本。但如果你确实需要这些功能,建议在x86机器上用交叉编译工具链编译好再拷贝过去,能省不少时间。

3. 镜像安装与首次启动的完整实操

3.1 烧录镜像前的准备工作

拿到镜像文件之后,别急着往SD卡里写。先确认几件事:

SD卡选择:推荐用Class 10以上的32GB microSD卡,最好是A1或A2等级的。我实测过,用普通卡跑ROS,rosbag录制的时候写入速度跟不上,会丢帧。32GB是底线,因为镜像本身接近4GB,烧录后系统分区会自动扩展到整张卡,但ROS的日志和bag文件很占空间,16GB的卡用不了多久就满了。

烧录工具:Windows下用balenaEtcher或者Raspberry Pi Imager,macOS下用dd命令或者Etcher,Linux下直接用dd。我个人习惯用dd,命令如下:

sudo dd if=ros_melodic_rpi4_v1.0.img of=/dev/sdX bs=4M status=progress sync

注意把/dev/sdX替换成你实际的SD卡设备名,千万别写错了,否则可能把电脑硬盘给格了。

烧录后的验证:烧录完成后,把SD卡插回电脑,应该能看到一个名为boot的分区。打开里面的config.txt文件,确认以下几行没有被注释掉:

arm_64bit=1 gpu_mem=128 dtoverlay=vc4-kms-v3d

这几行分别控制64位模式、GPU内存分配和显示驱动。如果arm_64bit=1被注释了,系统会以32位模式启动,ROS的很多包会跑不起来。

3.2 首次启动与网络配置

把SD卡插入树莓派4B,接上电源和网线(第一次启动建议用有线网络,比WiFi稳定),等待系统启动。首次启动会进行分区扩展和初始化,大概需要2-3分钟,期间HDMI可能没有输出,这是正常的。

启动完成后,通过路由器管理界面找到树莓派的IP地址,或者用arp -a命令扫描局域网。然后用SSH登录:

ssh ubuntu@<树莓派IP>

默认用户名是ubuntu,密码是ubuntu。首次登录会强制要求修改密码,按提示操作即可。

登录后第一件事是配置WiFi(如果你打算用无线的话):

sudo nano /etc/netplan/50-cloud-init.yaml

修改成类似这样的内容:

network: version: 2 ethernets: eth0: dhcp4: true wifis: wlan0: dhcp4: true access-points: "你的WiFi名称": password: "你的WiFi密码"

保存后执行sudo netplan apply生效。然后用ip a查看wlan0是否获取到了IP地址。

注意:树莓派4B的WiFi模块在Ubuntu 18.04下需要额外的固件文件才能正常工作。我的镜像里已经预装了这些固件,但如果你自己从零构建,记得把brcmfmac43455-sdio.bin和brcmfmac43455-sdio.txt放到/lib/firmware/brcm/目录下。

3.3 ROS环境的初始化与验证

SSH登录后,ROS环境变量不会自动加载,需要手动source:

source /opt/ros/melodic/setup.bash

为了避免每次登录都要手动source,把这行加到~/.bashrc末尾:

echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc source ~/.bashrc

然后验证ROS是否安装成功:

roscore &

如果看到类似这样的输出,说明ROS核心已经跑起来了:

... logging to /home/ubuntu/.ros/log/... started core service [/rosout]

再开一个终端,运行:

rostopic list

应该能看到/rosout和/rosout_agg两个话题。这就说明ROS通信层工作正常。

接下来测试rviz能不能启动:

rviz

如果你是通过SSH登录的,没有图形界面,rviz会报错“cannot connect to X server”。这是正常的,rviz需要图形界面才能运行。你可以通过VNC或者直接在树莓派上接显示器来使用rviz。

3.4 关键参数配置与性能调优

树莓派4B跑ROS,默认配置下性能一般,需要做一些调优。

CPU频率调节:默认情况下,树莓派的CPU会根据负载动态调频,最高1.5GHz。但ROS的某些节点对延迟敏感,动态调频可能导致响应不及时。可以把CPU调成性能模式:

sudo apt install cpufrequtils sudo cpufreq-set -g performance

交换分区调整:树莓派默认的交换分区只有100MB,编译大型ROS包的时候很容易爆内存。建议调到2GB:

sudo nano /etc/dphys-swapfile

把CONF_SWAPSIZE改成2048,然后重启交换服务:

sudo systemctl restart dphys-swapfile

ROS网络配置:如果你有多台机器需要跟树莓派通信,需要设置ROS_MASTER_URI和ROS_IP:

export ROS_MASTER_URI=http://<树莓派IP>:11311 export ROS_IP=<树莓派IP>

这两行也建议加到~/.bashrc里。

实操心得:树莓派4B的USB3.0接口对WiFi模块有干扰,如果你用USB3.0设备(比如外接硬盘),WiFi信号会明显变差。解决办法是用USB延长线把设备远离树莓派本体,或者干脆用有线网络。

4. 常见问题排查与避坑指南

4.1 启动阶段的高频问题

问题一:系统启动后HDMI没有输出

这个最常见。树莓派4B的HDMI输出在Ubuntu下需要正确的显示驱动配置。检查/boot/config.txt里是否有dtoverlay=vc4-kms-v3d这一行,如果没有就加上。另外,如果你的显示器分辨率比较特殊,可能需要手动指定:

hdmi_group=2 hdmi_mode=82

hdmi_mode=82对应1920x1080 60Hz,其他分辨率可以查树莓派官方文档的表格。

问题二:WiFi无法连接

先确认/lib/firmware/brcm/目录下有brcmfmac43455-sdio.bin和brcmfmac43455-sdio.txt这两个文件。如果没有,从树莓派官方的Raspbian镜像里拷贝过来。然后检查/etc/netplan/下的配置文件格式是否正确,YAML对缩进非常敏感,多一个空格少一个空格都会导致解析失败。

问题三:roscore启动时报错“Cannot bind to port 11311”

这说明11311端口被占用了。用sudo lsof -i:11311查看是哪个进程占用的,杀掉即可。如果每次启动都这样,可能是之前的roscore没有正常退出,检查~/.ros/log/下的日志文件。

4.2 ROS运行时的典型故障

故障一:rviz启动后闪退

树莓派4B的GPU内存默认只有64MB,rviz需要至少128MB才能正常渲染。修改/boot/config.txt里的gpu_mem=128,重启后生效。如果还是闪退,可能是OpenGL驱动的问题,试试安装mesa-utils并运行glxinfo检查OpenGL是否正常。

故障二:rosbag录制时丢帧

这通常是SD卡写入速度不够导致的。用dd命令测试SD卡的写入速度:

dd if=/dev/zero of=~/testfile bs=1M count=1024 conv=fdatasync

如果写入速度低于20MB/s,建议换一张更快的卡。另外,录制bag的时候可以用--buffsize参数增大缓冲区:

rosbag record --buffsize=256000000 /topic1 /topic2

故障三:编译ROS包时内存不足

树莓派4B的4GB版本编译大型包时也可能爆内存。除了增大交换分区,还可以限制编译时的并行任务数:

catkin_make -j2

-j2表示只用两个核心编译,虽然慢一点,但内存占用会少很多。

4.3 问题速查表

问题现象可能原因解决方法
系统启动后无HDMI输出显示驱动未配置检查/boot/config.txt中的dtoverlay和hdmi_mode
WiFi无法连接固件缺失或配置错误确认/lib/firmware/brcm/下有固件文件,检查netplan配置
roscore端口被占用之前的进程未退出sudo lsof -i:11311找到并杀掉进程
rviz闪退GPU内存不足修改gpu_mem=128并重启
rosbag丢帧SD卡写入速度慢换高速卡,增大--buffsize
编译时内存不足交换分区太小增大交换分区到2GB,用-j2限制并行任务
SSH连接超时网络配置问题检查IP地址,确认SSH服务已启动

避坑技巧:每次修改/boot/config.txt之前,先备份一份。我有一次改错了参数,系统直接起不来,只能把SD卡拔下来插到电脑上恢复。备份命令很简单:sudo cp /boot/config.txt /boot/config.txt.bak。

5. 镜像的扩展与二次开发建议

5.1 如何添加自己的ROS包

镜像里预装了catkin工具链,你可以直接在工作空间里编译自己的包。标准流程如下:

mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace cd ~/catkin_ws catkin_make

编译完成后,source一下工作空间的setup.bash:

source ~/catkin_ws/devel/setup.bash

然后就可以把自己的包放进去编译了。如果你要从GitHub克隆别人的包,注意检查package.xml里的依赖项,用rosdep安装:

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

5.2 镜像的备份与克隆

调教好的系统一定要及时备份。最直接的方法是用dd把整张SD卡克隆成镜像文件:

sudo dd if=/dev/sdX of=~/ros_melodic_backup.img bs=4M status=progress

但这样备份出来的镜像跟SD卡容量一样大,哪怕实际只用了4GB,32GB的卡备份出来就是32GB。更好的方法是先用gparted缩小分区,或者用pi-gen的export-image脚本只导出已使用的部分。

如果你有多台树莓派需要部署同样的环境,可以用clonezilla做网络克隆,或者直接把备份好的镜像烧录到多张SD卡上。

5.3 后续版本规划

v1.0版本是基于ROS Melodic的,但Melodic的官方支持到2023年就结束了。后续我计划做两个分支:一个是升级到ROS Noetic(基于Ubuntu 20.04),另一个是适配ROS 2的Foxy或Humble版本。ROS 2在树莓派上的性能比ROS 1好很多,尤其是DDS通信层对多核CPU的利用率更高。

另外,我还想加入一些针对特定应用场景的预配置,比如:

  • SLAM建图专用版:预装cartographer和slam_toolbox,配置好激光雷达和IMU的驱动。
  • 视觉识别专用版:预装OpenCV 4.x、TensorFlow Lite、PyTorch,以及常用的目标检测模型。
  • 机械臂控制专用版:预装MoveIt和ros_control,配置好常见的舵机驱动。

这些版本会根据实际需求逐步推出,如果你有特别想要的功能,也可以自己在这个镜像的基础上扩展。

最后分享一个小技巧:如果你觉得镜像体积太大,可以用apt clean和rm -rf /var/lib/apt/lists/*清理apt缓存,再用dd的conv=sparse选项压缩空白块,能把镜像体积再缩小10%左右。但注意,清理apt缓存后,后续安装新包需要重新apt update。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进