☰
Jetson Orin系统降级实战:从Ubuntu 22.04回退到20.04并搭建ROS Noetic环境
2026/10/3 9:26:09 网站建设 项目流程

1. 为什么要把 Jetson Orin 从 Ubuntu 22.04 回退到 20.04:需求拆解与最核心的动机

拿到 Jetson AGX Orin 或者 Orin NX 开发板,很多人第一件事就是升级系统,默认装上 Ubuntu 22.04 总觉得“版本越新越安心”。但真到了跑机器人方案的时候,你很快会发现一个尴尬的事实:ROS Noetic 官方只支持 Ubuntu 20.04,哪怕是源码编译也很难在 22.04 上完整体验。我最早在 Orin 上装了 JetPack 6.0(对应 Ubuntu 22.04),满怀信心开始搭建 ROS 环境,结果一路踩坑——依赖冲突、Python 版本不匹配、二进制包缺失,最后老老实实刷回 Ubuntu 20.04。这篇文章就把整个“回退”过程和 ROS-noetic 适配方案完整写出来,所有命令都是我在 Arm64 平台上实测过的。

先说清楚,Jetson Orin 的 CPU 架构是 Arm64,和我们电脑上常见的 x86_64 完全不一样。Arm64 的软件生态比 x86_64 干净不少,但也意味着你不能无脑套用网上搜到的 x86 环境搭建教程。Ubuntu 20.04 对应 JetPack 5.x,L4T(Linux for Tegra)版本是 R35.x;Ubuntu 22.04 对应的是 JetPack 6.x,L4T 版本在 R36 以上。从 22.04 回退到 20.04,本质上就是一次完整的系统刷写,不是简单的 apt 降级。因为 L4T 内核、驱动、固件和用户态系统是绑定的,不能只换个软件源就“退回去”。

这个问题的适用人群非常明确:想在 Jetson Orin 上稳定运行 ROS Noetic、需要兼容大量旧机器人代码、或者依赖某些在 20.04 上才正常工作的驱动库的开发者。如果你只是做纯深度学习推理,其实 22.04 完全可以继续用,没必要折腾。但如果你和我一样做机器人相关项目,回退到 20.04 并从硬件驱动层就保持和主流机器人社区一致,能省掉大量不必要的兼容性排查时间。

说实话,我之前也试图用容器方案解决:在 Ubuntu 22.04 上跑一个 Ubuntu 20.04 的 Docker,里面装 ROS Noetic。这个方法能用,但有两个很致命的痛点。第一,如果要用到 Jetson 上的 CSI 摄像头、GPIO、CAN 总线,容器里需要额外映射设备节点,还要处理用户组权限,非常麻烦;第二,很多 ROS 功能包涉及 CUDA 加速,容器里调用宿主机 CUDA 库版本容易出现 ABI 不兼容。所以最终我还是选择了物理层面回退系统,一劳永逸。下面我会从方案选型开始,一步步带你完成这次降级。

2. 降级前的完整准备:方案选型、硬件检查与数据备份

2.1 两种降级路径:全盘刷机与软件层面的“伪降级”

很多人听到“回退”两个字,第一反应是能不能通过 apt 直接降级,比如修改 sources.list 里的版本代号,然后 apt dist-upgrade。这里我直接说结论:Jetson Orin 上不要尝试这种操作。因为 Ubuntu 22.04(JetPack 6.x)和 Ubuntu 20.04(JetPack 5.x)之间不只是用户态软件包的差异,它们的内核版本、设备树、Bootloader 都是不同的。你如果真的强行改源降级,大概率会在重启时卡在 U-Boot 引导阶段,或者出现内核模块加载失败、显示器无信号、USB 控制器不识别等问题。

真正可行的降级路径只有两类。第一类是通过 NVIDIA 官方的 SDK Manager 进行完整系统刷写,这是最推荐的方式。SDK Manager 会先擦除整个 EMMC 或 NVMe 上的数据,然后烧录 L4T R35.4.1 或 R35.5.0,再带上对应的 Ubuntu 20.04 rootfs,整个过程相当于给机器重新做一个干净的系统。第二类是用命令行刷机脚本,也就是 L4T 驱动包自带的 flash.sh 脚本,这种方案更适合没有桌面 Linux 主机的用户,或者需要自定义 rootfs 的高级玩家。

我实际测试下来,如果你手头有一台 x86 的 Linux 主机,SDK Manager 的图形界面最省心,它还会帮你自动安装 JetPack 组件(CUDA、cuDNN、TensorRT)。如果你只有 Windows 主机,情况稍微复杂,推荐在 Windows 上用虚拟机跑一个 Ubuntu 20.04 或者 22.04 的 Linux 环境,然后通过 USB 连接 Orin 进入 Recovery 模式刷机。注意虚拟机的 USB 直通必须开启,否则无法识别 Jetson 的 Recovery 设备。

2.2 Jetson Orin Arm64 平台的特殊性:为什么不能照搬树莓派的降级流程

在树莓派上刷系统,烧录一张 SD 卡就结束了;在 Jetson Orin 上就没这么简单。Orin 的存储分为两种:一种是板载 EMMC(AGX Orin 部分型号有,Orin NX 模组通常搭配外部存储),另一种是 NVMe SSD。刷机时不仅要写 rootfs,还要写 Bootloader、内核、设备树等分区。这些分区的位置和大小在 L4T 的 partition 配置里定义,不同模组、不同存储组合的配置都会有差异。

另一个关键点是,Jetson Orin 的驱动包(L4T)是专门为 Arm64 编译的,内核源码和预编译 .deb 包都只面向 arm64 架构。回退到 Ubuntu 20.04 之后,软件源里的普通软件包是 arm64 版本,而 NVIDIA 提供的驱动、CUDA 等组件则来自 NVIDIA 自己的源,这两套源缺一不可。不少人在刷机成功但装不上 ROS 时候才发现问题:CUDA 装好了,但 ROS 依赖的某些系统库版本不对。所以这里提前说清楚,回退系统只是第一步,真正的“适配工作”其实是从系统刷完开始的。

如果你买的是 Jetson Orin NX 模组,还需要特别留意模组本身有没有预装过老版本系统。NVIDIA 在 R35 之后的刷机脚本中要求模组处于 Recovery 模式,并且有时需要先进入强制恢复模式再连接主机。这个细节我后面会专门展开讲。

2.3 刷机前需要准备的东西:硬件、主机环境与数据备份清单

刷机前准备得越充分,实际操作越不容易翻车。我没有开玩笑,这个环节很多人忽略,最后卡在“主机识别不到设备”或者“刷机刷到一半 USB 断开”的时候,才回头来补功课,浪费大量时间。按照下面这张清单核对一次,省心很多。

首先硬件方面,你需要一台可以正常运行的 Jetson Orin 设备,一块配套的电源适配器(AGX Orin 通常是 60W 或更高功率,Orin NX 开发套件自带电源),一根数据线。这里的数据线不是普通 USB 充电线,必须是支持数据传输的 USB Type-C 线。建议多准备一根,因为线材质量不好会导致刷机过程中断。主机方面,最好有一台 Ubuntu 20.04 或 22.04 的 x86 电脑,如果只有 Windows,在虚拟机里装一个 Ubuntu 22.04 也行,但要注意 USB 直通是否正常。

软件方面,需要从 NVIDIA 官网下载 SDK Manager(如果是图形界面方案),或者下载 L4T 驱动包 BSP(如果走命令行方案)。BSP 的命名一般是“Jetson_Linux_R35.x.x_aarch64.tbz2”和对应的 Root 文件系统包“Tegra_Linux_Sample-Root-Filesystem_R35.x.x_aarch64.tbz2”。建议下载 R35.4.1 或 R35.5.0 版本,这两个版本我实测都支持 ROS Noetic 的依赖,而且稳定性不错。

数据备份是必须做的。回退系统会清空整个磁盘,包括你之前装在 EMMC 或 NVMe 上的所有文件。建议先备份这几个目录: /home 下的工作代码、/etc 下自己改过的配置文件、/var/lib/docker 里如果有容器镜像也需要备份(不过把镜像重新导出来比较省事)。如果项目代码已经推到 Git 仓库,那就更简单,直接从本地拉取即可。总之备份策略不要偷懒,宁可多拷一份,也不要刷机之后才想起某个重要的代码文件躺在旧的系统盘里。

3. 完整刷机实操:从 Ubuntu 22.04 到 Ubuntu 20.04 的全过程记录

3.1 进入 Recovery 模式:这一步是整个刷机流程的地基

刷机的第一步是把 Jetson Orin 切换到 Recovery(强制恢复)模式。不同型号进入方式略有差异,但核心逻辑一致:按住 Recovery 键再按 Reset 键,或者在断电状态下按住 Recovery 键再上电。以 Jetson AGX Orin 开发套件为例,操作步骤如下:

  1. 拔掉电源适配器,让设备完全断电。
  2. 找到设备上的 Recovery 按钮(通常在 Type-C 接口旁边)和 Reset 按钮。
  3. 按住 Recovery 键不要松开,然后插上电源适配器。
  4. 继续保持按住 Recovery 键约 2 秒,松开即可。
  5. 用 USB Type-C 线连接 Jetson Orin 的 Type-C 口和 Linux 主机的 USB 口。

连接之后,在主机上执行 lsusb,你应该能看到一个 NVIDIA 设备,设备 ID 大概是 “0955:7023” 或者类似。只要 lsusb 里出现了 NVIDIA 相关的条目,说明设备已经被识别。如果 lsusb 没有任何反应,优先检查线材是不是能传数据的线,再检查 VMware 或者 VirtualBox 的 USB 直通设置。

我实际操作中最容易犯的错误是:忘记了板载的 Type-C 口不止一个,有的口是数据口,有的口可能只支持电源供电。比如 AGX Orin 开发套件上有两个 USB Type-C 口,一个是 USB 3.2 数据口,另一个是 DP 视频输出口。必须把数据线接到支持 USB 数据功能的 Type-C 口上,否则主机永远无法识别设备。这个在 NVIDIA 的官方文档里有说明,但很多教程不会特意强调。

3.2 使用 SDK Manager 刷写 Ubuntu 20.04(JetPack 5.x)

进入 Recovery 模式并确认设备被识别后,接下来就是刷写环节。如果你选择了 SDK Manager 路线,先在主机上安装 SDK Manager。安装包下载完成后,通过 dpkg -i 安装,如果有依赖问题就执行 apt --fix-broken install。打开 SDK Manager 后,它会自动识别连上的 Jetson 设备。

在 SDK Manager 的登录界面需要使用 NVIDIA 开发者账号。登录后选择设备和目标操作系统版本。这里要特别注意:默认情况下 SDK Manager 可能显示最新的 JetPack 6.x(对应 Ubuntu 22.04),但我们要回退到 Ubuntu 20.04,所以必须手动选择 JetPack 5.1.x 或者 5.0.x 的版本。不同版本的列表在界面上会标注对应的 Ubuntu 版本代号,选择 L4T R35.x 对应的那个即可。

接下来 SDK Manager 会显示两个步骤:

  • Step 1:下载并安装 JetPack 组件到主机(这一步会下载一个较大的镜像文件)。
  • Step 2:将系统烧录到 Jetson 设备。

建议先勾选“Download now, install later”把镜像整体下载下来,再执行烧录。这样可以避免网络不稳定导致的失败。烧录过程中,SDK Manager 会先向设备写入 Bootloader,再写入内核分区,然后是 rootfs。整个过程大约需要 10~20 分钟,具体取决于网络和存储速度。期间千万不要拔掉 USB 线,也不要给设备断电。

烧录完成后,SDK Manager 会提示你设置用户账户(用户名、密码、主机名等)。设置完成后 Jetson 会自动重启进入 Ubuntu 20.04 桌面。到这里系统层面的回退已经完成。

3.3 使用命令行 flash.sh 刷写(没有 SDK Manager 环境时的备用方案)

SDK Manager 虽然方便,但如果你用的是 Windows 虚拟机,或者遇到显卡驱动、Java 运行环境等 SDK Manager 本身的兼容性问题,更推荐用命令行方案。L4T 驱动包提供了完整的刷机脚本,只要主机是 Linux,就能完成同样的事情。

命令行刷机的步骤如下:

  1. 解压 L4T 驱动包:
mkdir jetson-l4t && cd jetson-l4t tar xf Jetson_Linux_R35.5.0_aarch64.tbz2
  1. 解压 Root 文件系统包,并放置到 Linux_for_Tegra/rootfs 目录下:
cd Linux_for_Tegra sudo tar xpf ../../Tegra_Linux_Sample-Root-Filesystem_R35.5.0_aarch64.tbz2
  1. 执行根文件系统配置脚本,生成可用的 Ubuntu 20.04 rootfs:
sudo ./apply_binaries.sh
  1. 确认 Jetson 设备处于 Recovery 模式并被主机识别(lsusb 能看到 NVIDIA 设备),然后执行烧录:
sudo ./flash.sh jetson-agx-orin-devkit nvme0n1p1

注意 flash.sh 后面的参数并不是固定不变的。即使你的是 AGX Orin 开发套件,但如果有不同的存储配置,参数也可能不同。这里 nvme0n1p1 表示把系统烧录到 NVMe 固态硬盘的第一个分区。如果你的系统是烧到 EMMC,就不需要这个参数,直接 sudo ./flash.sh jetson-agx-orin-devkit 即可。不同模组的设备名称可以在官方文档里查,Orin NX 开发套件对应的是 jetson-orin-nx-devkit。

命令行方式的一个好处是,可以自定义 rootfs。比如你可以预先在 rootfs 里加入 ROS Noetic 的安装脚本,或者替换默认的软件源。这些操作在 SDK Manager 的图形界面里很难做。缺点是脚本一旦开始执行,中途如果 USB 断开会直接失败,而且失败后可能处于一种“半砖”状态,需要重新进入 Recovery 模式再来一次。所以还是那句话,线材稳定性非常重要。

3.4 刷机后首次启动:确认 Ubuntu 20.04 和 Arm64 平台状态

刷机完成并重启之后,首先要确认系统确实是 Ubuntu 20.04,且运行在 arm64 架构上。打开终端执行:

cat /etc/os-release uname -m

cat /etc/os-release 会显示 VERSION_ID="20.04",uname -m 会输出 aarch64。这两项确认了系统版本和架构都没问题。

接下来还要检查几个关键硬件是否正常。第一,GPU 驱动是否正常工作。执行:

nvidia-smi

在 Jetson 上,nvidia-smi 的输出和桌面显卡略有不同,但应该能看到 NVIDIA 驱动的版本信息。第二,CUDA 是否可用。执行:

nvcc --version

如果输出了 CUDA 版本,说明 JetPack 自带的 CUDA 已经配置在 PATH 里。第三,检查存储分区和磁盘空间。执行:

df -h

确保 rootfs 所在分区(通常是 /)有足够的剩余空间,因为后面安装 ROS 和一些功能包会占用几个 GB 的空间。如果你的系统是烧到 NVMe,检查挂载点是否正常。

我踩过一个典型的坑:刷完了 Ubuntu 20.04,但用户空间里没有安装 JetPack 的 NVIDIA 软件包,导致 ROS 的 SDK 包无法找到 CUDA 版本。原因是在 SDK Manager 默认勾选 JetPack 组件时,它会在刷完系统后自动安装 CUDA 等组件。但如果用命令行 flash.sh 刷机,默认不会安装这些组件,必须手动安装。所以用 flash.sh 的朋友,刷完之后还要继续执行 SDK Manager 的 components 安装步骤,或者下载 JetPack 的 Debian 包手动安装。这个细节很容易被忽略,我在这里多说一句:用命令行刷机 ≠ 完整的 JetPack 环境,只有 rootfs 和内核,CUDA 库是另一回事。

4. ROS Noetic 适配方案:在 Ubuntu 20.04 Arm64 上搭建完整机器人开发环境

4.1 安装 ROS Noetic:官方源与镜像源的选择

系统回到 Ubuntu 20.04 之后,安装 ROS Noetic 就是顺理成章的事了。虽然网上有很多一键安装脚本,但我建议逐步操作,这样后续排错时可以清楚知道哪一步出了问题。ROS Noetic 官方支持的平台是 Ubuntu 20.04,架构可以支持 amd64 和 arm64,所以我们在 Jetson Orin 上可以直接用二进制包安装,不需要源码编译整个 ROS,省了不少事。

先添加 ROS 软件源并更新:

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros-latest.list' sudo apt install curl curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - sudo apt update

由于国内访问 packages.ros.org 可能较慢,建议把源替换为国内镜像。中科大、清华、上交的 ROS 源都有现成的配置。比如用中科大源:

sudo sh -c 'echo "deb https://mirrors.ustc.edu.cn/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros-latest.list'

然后将密钥文件也换成镜像站提供的版本,避免 gpg 错误。如果 apt update 时提示“The following signatures couldn't be verified”,说明密钥没有正确导入,可以手动下载密钥到 /usr/share/keyrings:

curl -s https://mirrors.ustc.edu.cn/ros/ubuntu/pool/main/r/ros-rosdistro/ros.asc | sudo tee /usr/share/keyrings/ros-archive-keyring.gpg >/dev/null

然后修改 sources.list 里的 deb 行,加上 signed-by 参数:

echo "deb [signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] https://mirrors.ustc.edu.cn/ros/ubuntu focal main" | sudo tee /etc/apt/sources.list.d/ros-latest.list

接着执行完整安装。如果你只想装核心的 ROS 库,执行:

sudo apt install ros-noetic-ros-base

如果你需要完整的桌面版本(包含 rviz、rviz 插件、仿真器、常用工具),执行:

sudo apt install ros-noetic-desktop-full

在 Jetson 上,ros-noetic-desktop-full 的安装包数量比较多,而且依赖 Qt、OpenGL 等图形库,建议空间足够的情况下直接装 full 版本。实测整个安装过程大约需要 5~10 分钟,空间占用 3~5 GB。安装完成之后,别忘了注册环境变量:

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

检查一下是否安装成功:

roscore

如果 roscore 正常启动,说明 ROS Noetic 在 Ubuntu 20.04 Arm64 上的基础环境已经 OK 了。

4.2 Arm64 平台上的依赖适配:Python、OpenCV、Eigen 和 PCL

ROS 装好之后并不意味着所有功能包都能直接用,Arm64 平台上经常遇到的坑主要集中在几个底层依赖上。我自己踩得最深的一个是 OpenCV 版本冲突。Jetson 的 JetPack 自带 OpenCV 通常是 4.x,但 ROS Noetic 的 vision_opencv 系列包会依赖系统里的 OpenCV 版本。有时候你 apt 安装 ros-noetic-cv-bridge,它会自动把系统自带的 OpenCV 替换成另一个版本,导致 ROS 节点加载时出现符号错误。

这里分享一套比较稳妥的适配思路:在 Ubuntu 20.04 的 Arm64 上,尽量不要用 apt 单独安装 OpenCV,而是优先使用 JetPack 自带的 OpenCV。安装 cv-bridge 这类包时,如果遇到依赖冲突,考虑使用 Rosdep 和源码编译的方式,将 cv-bridge 单独放到一个工作空间里编译。命令大概是:

mkdir -p ~/ros_cv_ws/src cd ~/ros_cv_ws/src git clone -b noetic https://github.com/ros-perception/vision_opencv.git cd ~/ros_cv_ws rosdep install --from-paths src --ignore-src -r -y catkin_make -DCMAKE_BUILD_TYPE=Release

编译前需要确保 cmake 能找到 JetPack 自带的 OpenCV。如果没有自动找到,可以在 catkin_make 时手动指定:

catkin_make -DOpenCV_DIR=/usr/lib/aarch64-linux-gnu/cmake/opencv4

Eigen 和 PCL 在 ROS 里也很常见。Eigen 3.3 在 Ubuntu 20.04 里默认版本就能满足大多数包的要求,但有些包要求 Eigen 3.4,那就需要源码编译。编译 Eigen 非常简单,解压后 cmake,最后把生成的 Eigen 目录拷贝到 /usr/include/eigen3 即可。PCL 方面,Ubuntu 20.04 仓库自带 PCL 1.10,配合 ROS Noetic 的 pcl_ros 是正常的,通常直接 apt install ros-noetic-pcl-ros 就行。

如果你做视觉导航、点云处理相关的工作,建议提前验证一下这几个核心库是否都能正常 include 和链接。最简单的办法是创建一个测试包,里面分别 include OpenCV、Eigen、PCL 的头文件,然后 catkin_make,如果编译通过,说明依赖没有问题。别等到大项目编译到最后才报出头晕的模板错误,那时候很难定位是库版本问题还是代码问题。

4.3 在 Jetson Orin 上对 ROS Noetic 做硬件加速适配:CUDA、TensorRT 与 CSI 相机

机器人项目里经常需要跑视觉算法,纯 CPU 跑在 Jetson Orin 上有点浪费算力。Orin 的 GPU 性能很强,配合 CUDA 和 TensorRT,很多推理任务可以做到实时。但在 ROS Noetic 环境里用上 GPU 加速,需要做一些额外适配。

首先是确认 CUDA 环境变量。JetPack 5.x 安装的 CUDA 位于 /usr/local/cuda 目录,正常情况下 nvcc --version 已经能工作。如果找不到,可以在 .bashrc 里手动加:

export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

然后是一些依赖 CUDA 的 ROS 包。比如你想要跑基于 TensorRT 的目标检测节点,通常需要下载原型库的预处理模型并用 trtexec 转换成 TensorRT 引擎。这种节点的编译依赖 Jetson 上的 TensorRT 版本,建议直接从 JetPack 源里安装:

sudo apt install nvidia-tensorrt

不过 JetPack 里 TensorRT 的 Python 接口是通过 pip 提供的,在 ROS 节点里一般用 C++ API 调用。需要注意 TensorRT 的 .so 库路径,如果你编译时提示找不到 libnvinfer.so,就在 CMakeLists.txt 里指定:

find_library(NVINFER_LIB nvinfer HINTS /usr/lib/aarch64-linux-gnu)

CSI 相机是机器人和自动驾驶项目里最常用的传感器之一。在 Ubuntu 20.04 + ROS Noetic 的 Jetson 上,常用的驱动是 gstreamer 和 v4l2。JetPack 5.x 提供了 libargus 底层接口,但 ROS 生态里更建议使用 usb_cam(对 USB 相机)或 gscam(对 CSI 相机)。装 gscam 时需要确认 gstreamer 的版本,Ubuntu 20.04 自带 gstreamer 1.16,JetPack 里也有对应的插件。一个比较实用的测试命令:

gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM),width=1280,height=720,framerate=30/1' ! nvvidconv ! xvimagesink

如果这条命令能弹出相机画面,说明 CSI 相机在系统层面没问题,ROS 节点只需要调用 gstreamer pipeline 就行。gscam 的配置逻辑就是把上面这条 pipeline 写进 launch 文件,然后在 ROS 里订阅图像话题。

我自己在适配过程中发现,Orin 上 CSI 相机的图像格式是 NVMM 内存,v4l2 不一定直接支持,必须走 gstreamer 的 nvarguscamerasrc 插件。所以如果有人直接装 v4l2 驱动层的 CSI 节点发现没图像,大概率是内存格式不匹配的原因。

4.4 工作空间组织与 Catkin 编译调优:在 Arm64 上提升编译效率

机器人项目通常会用到一个或多个 catkin 工作空间。在 Jetson Orin 上编译代码时,如果只是按照默认方式 cmake / make,效率其实一般。Orin 的核心数很多(AGX Orin 是 12 核),不把 -j 参数用满就很亏。但是 -j 参数设置得过大会导致内存不足、编译中途 OOM。根据我的实践经验,AGX Orin 32GB 版本可以用 -j4 到 -j8,如果是 64GB 版本可以大胆 -j8 到 -j12。Orin NX 8GB 建议 -j4 以下。

catkin_make 指定编译并行度:

catkin_make -j8 -l8

如果你用 catkin build(catkin_tools),可以这样:

catkin build -j8 -l8

需要提醒的是,有些包本身对编译并行不友好,比如依赖 openmp 或者生成 protobuf 的包,并行编译偶尔会出现“段错误”。遇到这种情况,把 -j 降到 2 甚至 1 重新编译那个包再试即可。这不是 Jetson 特有的问题,Arm64 平台也一样,但内存紧张时更容易触发。

另外,强烈建议在 Ubuntu 20.04 上安装 ccache,缓存编译结果可以明显加速重复编译。Jetson 上的 GCC 版本是 9.x,ccache 对它的支持很好。装好 ccache 之后,在 .bashrc 里导出:

export PATH=/usr/lib/ccache:$PATH

这样 cmake 编译时就会自动调用 ccache。或者更直接一点,在 catkin 的配置里指定:

catkin_make -DCMAKE_CXX_COMPILER_LAUNCHER=ccache

我实测过,一个包含十几个功能包的项目,第一次全量编译大约需要 30 分钟,配合 ccache 后第二次增量编译基本能缩短到 5 分钟以内。这个优化在调试阶段非常值。

还有一个容易被忽略的点是 swap 设置。如果编译大包时内存不足,建议创建一个 swapfile。Ubuntu 20.04 使用 systemd 管理 swapfile 很方便:

sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

这个操作在编译大型库(比如 moveit、gazebo 的一些插件)时能救命。我之前在 Orin NX 8GB 上编译过 Cartographer,不开 swap 基本必挂。

5. 常见问题与排查技巧实录:刷机、依赖和编译的全流程避坑

5.1 刷机失败:USB 断开、Recovery 模式无法识别、烧录中途报错

刷机失败是最让人头疼的,我见过很多排查了半天最后发现是线材问题。这里列一个快速排查表,按顺序检查能节省大量时间。

症状|可能原因|解决方案主机 lsusb 没有 NVIDIA 设备 | USB 线不支持数据传输 / 入了错误的 Type-C 口 | 更换数据线,插到数据口而不是 DP 口,重新进入 Recovery 模式 lsusb 能看到设备但 flutter 后提示“no such device” | USB 连接不稳定,或者驱动未加载 | 重新拔插 USB,确认主机执行了 sudo 权限的刷机命令 烧录过程中途报错“failed to write partition” | 设备存储接口异常,或者刷机参数不对 | 检查 flash.sh 参数是否正确,nvme0n1p1 是否匹配实际存储 烧录完成但开机黑屏 | rootfs 损坏,或者烧录时选了错误的分区布局 | 重新执行一次完整刷写,不要跳过格式化步骤

关于 Recovery 模式,还有一个常见误区:部分 Orin 开发套件在断电状态下长按 Recovery 键再插电,等待 2 秒后松开,但主机的 lsusb 仍然没识别。这种情况可以试试先插 USB 线再上电,或者按住 Recovery 键的同时短按 Reset 键。不同批次的开发板时序要求略有差异,多试几种组合总没错。

如果你用 SDK Manager 时遇到“Target component not installed”之类的错误,大概率是之前刷过一半,SDK Manager 的状态数据库有残留。建议清理 ~/.nvsdkm 或者重装 SDK Manager 再试。

5.2 ROS 安装和编译时常见错误:Python 版本、cv_bridge、CMake 找不到依赖

ROS Noetic 默认使用 Python 3.8,Ubuntu 20.04 自带 3.8,这个组合在 Arm64 上是正常的。但如果你之前装过 conda,并且设置了 base 环境,那么 ROS 的命令可能会自动使用 conda 的 Python,从而出现 import rospy 报错或者找不到 catkin 之类的问题。解决方法是:在编译和运行 ROS 节点前,先 conda deactivate,或者把 /opt/ros/noetic/bin 加到 PATH 的最前面。

cv_bridge 的问题是重灾区。这里再补充一个很常见的报错:编译 cv_bridge 时提示 OpenCV 版本冲突,比如你用了 JetPack 自带 OpenCV 4.5.4,但系统里 apt 也装了一个 4.2.0。解决方法是在 CMakeLists.txt 中明确指定 OpenCV 路径,或者在编译前卸载系统自带的 libopencv-dev:

sudo apt remove libopencv-dev

还有一类编译失败是因为 ROS 功能包依赖某个没有安装或版本过低的系统库。比如编译 moveit 时需要 boost、console_bridge、yaml-cpp 等库。排查思路是这样的:先报错信息里的关键词搜,然后 rosdep install --from-paths src --ignore-src -r -y 把所有依赖装上。如果 rosdep 无法识别某个依赖,就看报错缺少哪个头文件,再 apt search 那个头文件对应的包。

在 Arm64 上,很多有 x86 预编译二进制的 ROS 包只能用源码编译,所以尽量保证 CMake 工具链完整。安装基础的编译工具:

sudo apt install build-essential cmake git python3-pip

另外,pip 安装 Python 包时,在 Ubuntu 20.04 上默认是 Python 3.8。很多新版本的 Python 包(比如 numpy 2.x)已经不再支持 Python 3.8,强行安装可能会失败或者编译报错。ROS Noetic 生态里的很多包也依赖老版本 numpy。所以建议不要贸然升级系统 Python 里的 numpy,除非你有充分的理由。如果某个包非要 numpy 新版本,建议用 virtualenv 或者 conda 单独创建环境,不要污染系统 Python。

5.3 JetPack 组件与 ROS 的版本兼容性:CUDA、cuDNN、TensorRT 一定要配套

最后再强调一个很容易被忽略的问题:Jetson 上的 JetPack 组件版本必须和 L4T 版本、Ubuntu 版本严格匹配。比如你在 Ubuntu 20.04(JetPack 5.x)下安装了深度学习相关包,那么这些包依赖的 CUDA、cuDNN、TensorRT 都是从 JetPack 的 apt 源里装的,版本是绑定 L4T R35 的。如果你手动去 NVIDIA 官网下载 CUDA 12.x 的安装包,强行装上去很大概率会导致系统里的 libcuda.so 和你编译的程序不兼容。

我自己有一段时间在 Orin 上跑 detectron2 时,torch 的 CUDA 版本要求比较高,和 JetPack 自带的 CUDA 11.4 冲突,最后直接放弃在物理环境里折腾,改用了 NVIDIA 官方提供的 PyTorch 容器镜像。这个容器方案不涉及系统层驱动冲突,而且性能几乎没有损失。如果你在 ROS 里做深度学习推理,推荐思路是:ROS 节点负责数据输入输出和逻辑控制,深度学习推理使用独立的 Python 环境或者容器,两者通过 socket 或共享内存通信。这样既保持了 ROS 环境的纯净,又能自由选择最新的深度学习框架版本。

TensorRT 版本的问题也类似。JetPack 5.x 自带的 TensorRT 是 8.5 或 8.6,如果你有一个用 TensorRT 8.4 导出的引擎文件,可能会因为版本不兼容而报错。这种问题是“低版本引擎可以在高版本运行,但高版本引擎不一定能降级”的典型情况,所以工作流里最好统一 TensorRT 版本。

6. 最后的实操心得,以及一点关于“要不要回退”的建议

整个流程走下来,我的感受是:Jetson Orin 从 Ubuntu 22.04 回退到 Ubuntu 20.04 这件事本身不复杂,真正的复杂度在于后续你有没有耐心把 ROS Noetic 的周边生态全部理顺。刷机只花了一个小时左右,但我在 OpenCV 冲突、TensorRT 版本、CSI 相机 pipeline 上花了两天。这两天的排查经历也让我养成了一个习惯:每次在 Jetson 上装新包之前,先检查版本矩阵,尽量不要让系统陷入多个版本混战的局面。

如果你是机器人行业从业者,我的建议很明确:直接回退到 Ubuntu 20.04 + ROS Noetic,这是目前社区支持最成熟的组合。虽然 Ubuntu 22.04 已经发布很久,但 ROS 社区的主力还在 Noetic,很多成熟的算法包和蓝本代码没有完全迁移到 ROS 2 或者 Ubuntu 22.04。与其在系统边缘反复折腾,不如用回退换来稳定运行。回退完顺手把 JetPack 5.x 的 CUDA、TensorRT 也部署好,整个 Orin 就会变成一个非常适合做边缘机器人开发的平台。

最后分享一个小技巧:无论你是用 SDK Manager 还是 flash.sh 刷机,刷完以后别急着装一堆东西。先把系统原样启动一遍,确认基础驱动正常,再做一次镜像备份。Jetson 上可以用它自带的 backup 工具,或者直接把 rootfs 打包。这样以后如果再折腾坏,恢复系统只需要 5 分钟,而不是从头再来一遍长流程。我就是吃完一次大亏之后才学乖的,现在手上有两个干净的系统镜像,分别对应“纯 Ubuntu 20.04 刷机后状态”和“安装完 ROS Noetic 基础环境后状态”,想折腾新环境时直接恢复镜像,省心到了极点。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询