折腾树莓派4B这件事,我前前后后重装了不下十次系统,从Raspberry Pi OS到Ubuntu 20.04再到各种精简版,最后稳定下来在用的组合就是:树莓派4B + ubuntu20.04 + VNC远程桌面 + ROS noetic。这套方案的好处很直接——不用给树莓派配显示器键盘,一台局域网里的电脑就能远程干所有活,而且ROS noetic只在Ubuntu 20.04下运行最顺,刚好和树莓派的arm64架构完美匹配。这篇文章把我踩过的坑和最终验证过的完整流程整理出来,适合刚拿到板子、想搭建一套ROS开发环境的朋友,也适合已经装了一半卡住、想找个可靠参考的人。整个流程我会按"选型→烧录→VNC→ROS→联调排错"的顺序走,每步都把为什么这么做讲清楚,方便你以后遇到类似报错能自己判断。
1. 选型定版:树莓派4B、Ubuntu 20.04 与 ROS Noetic 为什么能凑到一起
1.1 ROS版本与Ubuntu版本的强绑定关系
先说结论:ROS Noetic 只支持 Ubuntu 20.04(Focal Fossa),这是这一整套方案里最硬的约束。ROS 1 系列里,Melodic 对应 Ubuntu 18.04,Noetic 对应 Ubuntu 20.04,而且 Noetic 是 ROS 1 的最后一个版本,官方维护到 2025 年。如果你手里的教程、开源算法代码还是 ROS 1 时代的,那么 Noetic 基本就是终点站——想继续升级ROS 1的体验?没有下文了,要么留在 Noetic,要么整体迁移到 ROS 2。
这也是我现在还坚持在树莓派4B上装20.04的原因,不是20.04有多新,而是ROS生态把我钉在了这个版本上。反过来,如果你直接装Raspberry Pi OS(基于Debian),想装ROS Noetic就得自己从源码编译一大堆依赖,工程量大而且经常崩。Ubuntu 20.04 官方源里有 ROS Noetic 的 arm64 预编译二进制包,apt 直接装,省下的编译时间非常可观。
1.2 树莓派4B的硬件边界与选型建议
树莓派4B用的BCM2711芯片,四核Cortex-A72,主频1.5GHz,后来固件还解锁了1.8GHz,性能在一众ARM开发板里不算顶尖,但赢在生态完善、资料多,遇到问题一搜就有答案。内存有1GB、2GB、4GB、8GB四种版本。我的建议很直接:如果你打算在上面跑桌面 + VNC + ROS,内存至少4GB,最好8GB。
为什么这么强调内存?实测在20.04 + Xfce桌面环境里,空载内存占用大概300~400MB,这看着不多,但一旦启动 roscore 再跑上几个节点,加上开着浏览器查文档,2GB 的板子就会开始疯狂用 swap,SD卡读写一多整个系统卡到鼠标都飘。8GB 版本就从容很多,甚至可以在板子上直接编译 ORB-SLAM3 这类重工程,4GB 版本配 2GB swap 也能硬扛。顺带说一句,很多人搜树莓派4B引脚功能图,是因为后面要接传感器和电机驱动,这是另一条线,不影响本文的系统搭建,但40pin的引脚布局在Ubuntu下的操作方式和树莓派OS基本一致。
1.3 Server镜像还是Desktop镜像:先想清楚再动手
Ubuntu 官方为树莓派发布了两个 20.04.5 镜像,一个带 GNOME 桌面,一个纯 Server。带桌面的镜像装上就能看图形界面,听着方便,但 GNOME 3 在树莓派4B上体验并不好,空载内存就吃掉 900MB 往上,GPU 驱动和桌面特效也会占用 CPU。而且我们最终要用 VNC 远程,在 Server 版基础上自己装一个轻量桌面,反而比直接用官方桌面镜像更省资源、更好控制。
所以我的最终建议是:用 64 位 Server 镜像 + Xfce4 轻量桌面 + TigerVNC。这套结构既满足 VNC 远程桌面的图形操作需求,又不至于把树莓派变成一台只会发热的"慢电脑"。至于 arm64 和 armhf 的差别,一句话:ROS Noetic 官方为 arm64 提供了完整二进制包,32 位 armhf 在 20.04 的软件生态里已经明显边缘化,而且 8GB 内存板子只有 64 位系统才能完整利用,别在 32 位上纠结。
2. 镜像烧录与首次开机:四步走通“能开机、能SSH、能上网”
2.1 选镜像与烧录工具
镜像去 Ubuntu 官方发布页或国内镜像站下载:
https://cdimage.ubuntu.com/releases/20.04.5/release/选ubuntu-20.04.5-preinstalled-server-arm64+raspi.img.xz,注意文件名里必须是 arm64 和 raspi。国内从清华、阿里云等镜像站下载更快,路径大致是https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cdimage/releases/20.04.5/release/。
烧录工具我用过好几个,最稳的还是 balenaEtcher,Windows/macOS/Linux 跨平台,操作极简:选镜像、选SD卡、烧录。Linux 下也可以用 dd 直接写:
xz -dk ubuntu-20.04.5-preinstalled-server-arm64+raspi.img.xz sudo dd if=ubuntu-20.04.5-preinstalled-server-arm64+raspi.img of=/dev/sdX bs=4M status=progress conv=fsync注意 of 一定是对准 SD 卡设备,别写错盘符。不管用什么工具,烧完的 SD 卡会被分成一个 FAT32 的 system-boot 分区和一个 EXT4 的 writable 分区,FAT32 分区在 Windows、macOS 下都能直接读,后面预配置全靠它。
2.2 首次启动前的三个预配置
烧完镜像先别急着插卡开机,在 system-boot 分区里提前做好三件配置,能省掉一堆折腾。
第一,账号密码。这个镜像默认用户是ubuntu,密码是ubuntu,很多人第一次 SSH 进去会被系统强制要求立刻改密码。想跳过这个环节,就直接编辑 system-boot 里的user-data文件,找到plain_text_passwd: 'ubuntu'这项,把 ubuntu 改成你自己想用的密码,同时确认ssh_pwauth: true是开着的。保存退出即可。
第二,Wi-Fi。如果你不打算插网线,就编辑同一个分区里的network-config文件,在wifis:下面填上你的无线网络。这个文件是 cloud-init 配置,格式很严格,缩进错了整个网络起不来。下面是我实测可用的写法:
wifis: wlan0: dhcp4: true optional: true access-points: "你的SSID": password: "你的密码"第三,SSH。Ubuntu 的这个镜像默认装了 openssh-server 而且允许密码登录,如果你改过 user-data 记得把ssh_pwauth保持为 true,否则后面连不上。
这三个配置做完,保存、安全弹出 SD 卡,插到树莓派上电。第一次启动会自动做 cloud-init 初始化,给板子一两分钟时间,然后用电脑 SSH 连过去:
ssh ubuntu@树莓派IPIP 可以从路由器后台看,也可以 nmap 扫一下局域网。我建议直接把树莓派在路由器里绑定一个静态 IP,或者用 netplan 配置固定 IP,因为后面 VNC 和 ROS 都要用这个 IP,老是变会很烦。
2.3 开机之后的基础检查
登录进去后第一件事,依次执行:
sudo apt update sudo apt full-upgrade -y sudo reboot为什么要先升级?20.04.5 镜像是一个固定快照,里面的内核、固件可能落后于仓库里的修复版,尤其树莓派对 GPU、网络驱动的固件更新很敏感,不升级的话后面 VNC 可能出各种莫名其妙的显示问题。
重启后确认三个基础项:uname -m输出 aarch64 代表 64 位系统;free -h看内存;ip a看网络。如果你完全不用本地 HDMI,在/boot/firmware/config.txt里加一行gpu_mem=16能再省点内存——但注意,如果装了 Xfce 桌面并且还想用 GPU 渲染加速,不要压太低。
3. VNC远程桌面搭建:轻量桌面的选型与配置全记录
3.1 为什么我不用官方桌面镜像自带的VNC
官方 Desktop 镜像其实自带屏幕共享方案,但那是给 GNOME 登录会话用的,远程连上去体验一般,而且只支持局域网内的简单使用,想做成服务自动启动特别别扭。我更推荐 Server + Xfce4 + TigerVNC 这套组合:Xfce4 轻量、稳定,TigerVNC 是纯正的开源 VNC 服务端,支持多用户会话,手动、自动启动都方便。
3.2 安装Xfce4桌面与必要组件
回到 SSH 终端,执行:
sudo apt install -y xfce4 xfce4-goodies dbus-x11 fonts-noto-cjkdbus-x11尤其重要,少了它 VNC 连上之后很容易灰屏,因为很多桌面组件需要 D-Bus 会话总线;fonts-noto-cjk是为了显示中文不乱码——机器人如果打印中文日志,VNC 里看到的就是一排方块口,装了这个字体就正常了。这步别去装ubuntu-desktop,除非你内存大得没地方用,否则光是后台的 GNOME 相关服务就够树莓派喝一壶。
3.3 安装TigerVNC并配置用户会话
接着安装 VNC 服务端:
sudo apt install -y tigervnc-standalone-server tigervnc-common先设置 VNC 专属密码,注意这个密码不是系统登录密码,是远程连接 VNC 时用的:
vncpasswd执行后会提示要不要再设一个 view-only 密码,意思是只能看不能操作的密码,按 n 跳过就行。
然后创建用户级启动脚本:
mkdir -p ~/.vnc nano ~/.vnc/xstartup写入:
#!/bin/sh unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS export XKL_XMODMAP_DISABLE=1 [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources dbus-launch startxfce4 &保存后用chmod +x ~/.vnc/xstartup加上执行权限。这步是最容易被忽略的坑:脚本没权限,VNC 起了一个空会话,连上去就是灰屏。
启动 VNC:
vncserver -geometry 1920x1080 -depth 24 :1:1代表显示编号 1,对应端口是 5901。如果想在局域网内被其他设备访问,可以加-localhost no,避免只绑定到本机回环。
3.4 客户端连接与“激活秘钥”辟谣
Windows/Mac 电脑上装 VNC Viewer(RealVNC 出品)或者 TigerVNC Viewer 都行。很多人搜"vnc viewer 下载"和"vnc 激活秘钥",这里明确说一下:VNC Viewer 个人使用是免费的,不需要任何激活秘钥;TigerVNC Viewer 更是完全开源,连账号都不用注册。如果看到要密钥的页面,多半是下到了企业版或者奇怪来源的安装包,直接换官方渠道就好。
打开 VNC Viewer,地址栏输入树莓派IP:5901,回车,输刚才 vncpasswd 设的密码,就能看到 Xfce 桌面了。这个桌面就是树莓派上的真实用户会话,你在这个桌面上打开的终端、跑的程序,全都跑在板子上。
3.5 让VNC随系统自启:systemd服务
手动启动 VNC 适合调试,但机器人项目的常态是"树莓派上电就跑",所以我用 systemd 把它做成自启服务。新建服务文件:
sudo nano /etc/systemd/system/vncserver.service内容如下:
[Unit] Description=TigerVNC Server After=syslog.target network.target [Service] Type=forking User=ubuntu Group=ubuntu WorkingDirectory=/home/ubuntu ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill :1 > /dev/null 2>&1 || :' ExecStart=/usr/bin/vncserver -localhost no :1 -geometry 1920x1080 -depth 24 ExecStop=/usr/bin/vncserver -kill :1 [Install] WantedBy=multi-user.target注意把 User 和 Group 改成你的实际用户名。然后:
sudo systemctl daemon-reload sudo systemctl enable vncserver --now sudo systemctl status vncserver这样就算板子重启,VNC 也会自动起来。到这里,远程桌面这块就齐了。
4. ROS Noetic 安装的完整链路:换源、装包、初始化一条龙
4.1 软件源与ROS密钥的现代配置姿势
ROS Noetic 的官方 apt 源在国外,国内直连速度通常不理想,建议直接用清华大学 TUNA 镜像。先把 ROS 的仓库地址写进系统:
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros1.list'这里用了signed-by指定密钥文件的方式,比老的apt-key add更符合现在的安全习惯。接下来下载并转换 ROS 官方签名密钥:
curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo gpg --dearmor -o /usr/share/keyrings/ros-archive-keyring.gpg如果你不想用 signed-by 方式,老办法也行:
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654apt-key 在 20.04 上会打印一堆 deprecation 警告,但功能正常。两种方式选一种就行,别两个都做,不然源里会重复。
4.2 安装桌面完整版还是基础版
先更新索引:
sudo apt update然后按需选包:
sudo apt install -y ros-noetic-desktop-fullros-noetic-desktop-full包含 ROS、rqt、rviz、Gazebo 等几乎所有常用组件,是最省心的选择,但体积很大,在树莓派上下载加解压可能要三四十分钟。如果你的项目明确不需要 Gazebo 仿真,装ros-noetic-desktop就够了。如果完全走无头模式,只想让板子跑节点、通过局域网把话题数据发到电脑处理,连图形库都可以不要,装ros-noetic-ros-base最小集即可。
我个人做 SLAM 实验时,习惯在板子上装 desktop(不带 Gazebo),电脑上装完整版跑 rviz,板子上的资源留给真正干活的节点。这个取舍在树莓派上尤其重要,毕竟它总共就那几个 G 内存和 CPU。
4.3 rosdep init与update:最大概率翻车的环节
装完 ROS 本体后,官方流程是执行:
sudo rosdep init rosdep updaterosdep的作用是解析 ROS 包的依赖关系,以后从源码编译包时必须用到。这步在不少玩家手里翻车率很高,原因是rosdep init要从 raw.githubusercontent.com 拉取默认源列表,而很多网络环境下这个域名直连经常超时,报错信息通常是连接超时或者无法解析。解决方案是改用国内 Gitee 上的 rosdistro 镜像,设置环境变量后重新走:
export ROSDISTRO_INDEX_URL=https://gitee.com/ros-mirror/rosdistro/raw/master/index-v4.yaml sudo rosdep init rosdep update如果rosdep update还是慢,可以把~/.ros/下的缓存删掉重试,也可以多跑两次,这个命令本身支持增量更新。多说一句:rosdep 只在源码编译时才必须,如果后面一直用 apt 装 ROS 包,暂时卡在 rosdep 也可以先继续,但既然要搭环境,我建议还是花几分钟搞定,不然以后想拉源码包编译还得回头补课。
4.4 环境变量、catkin工作区与第一次验证
把 ROS 环境写进 bashrc,让每次新终端都能直接使用 ROS 命令:
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc source ~/.bashrc然后验证:
roscore看到started core service [/rosout]就是成功了。再开一个终端,跑一下自带的小乌龟做一次端到端验证:
rosrun turtlesim turtlesim_node如果 VNC 桌面里弹出一个蓝色背景的小乌龟窗口,说明整个链路已经全部打通:Ubuntu 系统正常、VNC 会话正常、ROS 运行正常、GUI 通过 VNC 显示正常。我第一次在这套环境跑通的时候,那种无头板子带着图形桌面跑起来的爽感还是很足的。
之后可以创建 catkin 工作区,为后续编译自己的功能包做准备:
source /opt/ros/noetic/setup.bash mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace cd ~/catkin_ws catkin_make编译大包之前记得给板子加 swap,不然 8GB 以下的板子很容易 OOM。我用的是手动 swap 文件方案:
sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab5. 组合联调与高频翻车现场:VNC掉线、灰屏、rosdep超时
5.1 一套完整的联调检查清单
环境搭好不是终点,还要能长期稳定用。我总结了一份联调检查清单,每次动过网络、改过系统服务后都会过一遍:
- 树莓派上电,等 1 分钟,SSH 能连上,说明系统正常。
- VNC Viewer 连接 5901 端口,能出桌面,说明 VNC 自启正常。
- 桌面里开终端,跑
source /opt/ros/noetic/setup.bash && roscore,说明 ROS 环境正常。 - 跑
rosrun turtlesim turtlesim_node,窗口能出来,说明 GUI 和 ROS 通道都通。 - 拔掉 HDMI、键盘、网线,只留电源,重复上面步骤,确认完全无头运行也稳定。
这五条全部通过,这个板子才算真正"毕业",可以丢进项目里用了。
下面把最常见的几类问题集中列一下,方便对照:
| 现象 | 大概率原因 | 处理办法 |
|---|---|---|
| VNC 连上灰屏 | xstartup 无执行权限 / 缺 dbus-x11 | chmod +x;安装 dbus-x11;看日志 |
| 连接一段时间自动退出 | 服务端崩溃或网络链路断开 | vncserver -list 判断;固定 IP;加 swap |
| 登录界面光标点不进密码框 | VNC 连到了图形登录管理器 | systemctl set-default multi-user.target |
| rosdep init/update 超时 | 默认源列表下载失败 | 设置 ROSDISTRO_INDEX_URL 换镜像 |
| 编译大包时系统卡死 | 内存不足触发 swap 风暴 | 添加 2G swapfile |
5.2 VNC灰屏与自动退出的根因和处理
先说灰屏。VNC 能连上但桌面一片灰,十有八九是~/.vnc/xstartup的问题:要么脚本没执行权限,要么里面少了dbus-launch,要么startxfce4命令没找到。排错顺序是:先vncserver -kill :1杀掉旧会话,然后重启 VNC,再去看~/.vnc/板子名:1.log日志,日志会直接告诉你哪一步挂了。加dbus-launch startxfce4 &这段后再重启,90% 的灰屏都能解决。
再说"VNC 连接后过一段时间自动退出"。这个问题的本质不是 VNC 服务端崩溃,就是网络链路断了。先看日志确认服务端是否还活着:vncserver -list,如果列表里:1还在,那就是网络问题,重点排查 Wi-Fi 信号弱、路由器把空闲连接踢了、IP 变动。对策我一般给三条:一是给树莓派固定 IP;二是路由器里把 DHCP 租约时间调长;三是检查有没有防火墙误杀。如果列表里:1都没了,那是服务端 OOM 被杀或崩溃,加 swap、升级内核、把自启动服务装上,基本能压住。
5.3 登录界面光标无法停留在密码框的问题
这个坑非常经典:你用 VNC 连接一个启动了图形登录管理器(LightDM/GDM)的系统,VNC 显示的是登录界面,这时鼠标和键盘焦点经常对不上,光标根本点不进密码框。
解决办法是在树莓派上关掉图形登录管理器,让系统默认进入多用户命令行模式,然后直接用用户级的 VNC 服务拉起 Xfce 会话,绕开登录界面:
sudo systemctl set-default multi-user.target sudo reboot重启后系统不会跳到本地登录界面,只有通过 VNC 连接时才会创建 Xfce 会话,自然也就不存在"光标停不进密码框"的问题。这跟联调清单第 5 条完全对应:无头运行、VNC 直接进桌面会话,而不是进登录界面。
5.4 资源优化与后续扩展思路
配置都通了以后,还有几个优化点值得做。内存上,除了前面说的gpu_mem=16,还可以把 Xfce 的窗口特效关掉,减少 CPU 负担;VNC 分辨率别盲目上 4K,1920x1080 在绝大多数场景够用,太大反而拖帧率。存储上,SD 卡建议至少用 A2 速度等级,预算允许的话直接上 USB3.0 移动固态盘启动,速度提升非常明显,ROS 日志频繁写入时尤其能感受到差别。
这套环境搭完之后,下一步自然是往里面塞真正的算法包。我自己就是用这个环境跑视觉 SLAM,照着社区里流行的做法把 ORB-SLAM3 源码拉到板子上编译,配合相机做实验。你在网上搜"orbslam3 部署 ubuntu20.04"能搜到大量方案,基本前提都是先有一套干净的 Ubuntu 20.04 + ROS Noetic 环境,而这篇文章正好帮你把这步走完了。整套流程如果你在某个环节卡住,优先去看日志文件——SSH 看系统日志,VNC 看~/.vnc下的 log,ROS 看~/.ros/log,日志从来不会骗人,比瞎猜和反复重装都靠谱。