ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Jetson TX2装ROS Melodic避坑指南:从aarch64架构到软件源配置

Jetson TX2装ROS Melodic避坑指南:从aarch64架构到软件源配置

ROS学习03:在Jetson TX2上装ROS Melodic,我是怎么把坑一个个填平的

手头有一块Jetson TX2开发板的人,早晚都会遇到同一个问题:怎么在它上面把ROS跑起来。我拿到板子之后,第一件事就是装ROS melodic,原本以为照着官方wiki敲几行命令就能结束,结果从换软件源到rosdep update,几乎每一步都出状况。这篇文章就是我在TX2上完整安装ROS Melodic的实录,所有报错、定位思路和修复命令都写在里面,目标是让你顺着走一遍、一步坑都不踩。

需要这份教程的人,大概是三类:刚接触ROS的嵌入式方向学生,想在这块板子上做机器人或视觉项目的开发者,以及被网上各种新旧教程搞混、装到一半系统坏掉的倒霉蛋。如果你是这三类中的任意一类,这篇内容应该能帮你省下至少一个晚上的折腾时间。

1. 为什么在TX2上装ROS,不能直接照搬PC教程

1.1 架构差异:aarch64不是小问题

普通PC上的Ubuntu几乎都是x86_64架构,而Jetson TX2的CPU是ARM架构,系统层面看到的是aarch64。这个差异会实打实地影响apt软件源、预编译包和依赖解析。

apt在添加软件源和安装包时,会根据系统架构自动选择对应的版本。如果sources.list里写的是面向PC的普通Ubuntu源路径,在TX2上执行apt update时,经常会出现404错误或者索引缺失。你可以先执行uname -m看一下,输出aarch64才是对的,如果是x86_64,说明你系统本身就不是TX2的原生环境。

这也是为什么很多教程在TX2上不能直接照抄。ROS官方apt源本身是支持arm64架构的,但那些面向普通PC写的教程,源路径虽然是官方地址,实际调试时遇到的问题和排错方向完全不同。

1.2 JetPack系统不是"纯净Ubuntu"

TX2通常是用JetPack刷机工具安装系统,这个系统基于Ubuntu 18.04,但预装了大量英伟达定制组件:CUDA、cuDNN、TensorRT、OpenCV,还改了内核和设备树。它比标准Ubuntu多出很多"自带环境",这听起来是好事,但会让apt依赖解析变得复杂。

举个例子,JetPack预装的OpenCV版本未必匹配ROS的cv_bridge依赖要求。安装ROS核心包时不一定立刻冲突,但后续编译视觉相关功能包时就会暴露。还有,JetPack自带的Python版本、编译工具链和标准Ubuntu略有不同,你在某个PC教程里看到的包版本号,在这块板子上可能就是另一套。

我的建议是:把TX2的系统看成"特制版Ubuntu",而不是"标准Ubuntu 18.04"。遇到依赖问题时,先从JetPack角度排查,再考虑ROS本身的配置对不对。

1.3 网上教程多,但环境假设差很远

Jetson系列里资料最多的是Nano和AGX,树莓派的ROS教程也是一抓一大把。这些板子虽然都是ARM架构,但系统版本、JetPack版本、内存和存储空间都不一样。很多命令看起来相同,实际上的源地址、依赖关系和坑点各不相同。

我试过照着一个树莓派的教程走,前面几步没问题,到公钥导入和rosdep初始化那一步就开始报奇怪的错误。后来才意识到,对方用的系统源、ROS发行版、甚至网络环境都和我不同。所以在TX2上装ROS,心里要有一个坐标系:arm64 + Ubuntu 18.04 + ROS Melodic + JetPack环境。凡是教程和这个组合对不上的,都得多留个心眼。

2. 安装前两件事:确认系统状态和换对软件源

2.1 安装前必须确认的三项信息

很多人在装ROS之前根本没确认过自己的系统状态,结果装到一半发现系统版本不对、架构不对、空间不够,只能回头重来。建议动手前先花两分钟跑几条命令:

lsb_release -a # 查看Ubuntu版本,18.04对应bionic uname -m # 查看架构,必须是aarch64 cat /etc/nv_tegra_release # 查看JetPack/L4T版本 free -h # 查看内存,TX2一般是8GB df -h # 查看根分区可用空间

这几条命令每条都有自己的用途。lsb_release -a确认系统代号是不是bionic,因为ROS melodic对应的就是bionic;如果是其他代号,后面添加ROS源时用$(lsb_release -sc)自动展开会产生错误。uname -m确认架构,防止你把PC教程里的amd64源抄进来。cat /etc/nv_tegra_release则是看L4T版本,比如R32系列对应JetPack 4.x,这个版本信息在后续排查驱动相关依赖时很有用。内存和磁盘就更不用说了,装desktop-full之前如果根分区剩余空间不足5GB,建议先清理或挂载外部存储,不然后面会很难受。

2.2 换Ubuntu软件源:ARM平台用的是ubuntu-ports

这一步是TX2装机最容易翻车的地方。标准PC的Ubuntu源路径通常是archive.ubuntu.com/ubuntu,但ARM架构的Ubuntu源路径不一样,是ubuntu-ports。

如果不换源,直接用官方源也能装,但在某些网络条件下速度会比较慢。如果换源时写错了路径,比如把bionic写成bionic,或者用的是没有-ports的普通路径,apt update时会直接报404。

我自己的做法是先把原始文件备份,再写入镜像站配置:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

然后编辑/etc/apt/sources.list,把内容替换成下面的结构:

deb http://YOUR_MIRROR/ubuntu-ports/ bionic-ports main restricted universe multiverse deb http://YOUR_MIRROR/ubuntu-ports/ bionic-ports-updates main restricted universe multiverse deb http://YOUR_MIRROR/ubuntu-ports/ bionic-ports-security main restricted universe multiverse deb http://YOUR_MIRROR/ubuntu-ports/ bionic-ports-backports main restricted universe multiverse

注意YOUR_MIRROR要替换成你实际使用的镜像站地址,关键是后面的路径必须包含ubuntu-ports。这一步为什么重要?因为arm64架构的Ubuntu软件包在官方仓库里都放在ubuntu-ports这个路径下面,普通PC源里根本没有对应的arm64包索引。你用的镜像站只要同步了ubuntu-ports目录就可以,具体选哪个可以从自己实际网络延迟来判断,适合自己就好。

替换完成后执行:

sudo apt update

这时如果能看到正常读取索引、没有404,说明源没问题。接下来可以顺手装几个基础工具:

sudo apt install curl wget git net-tools ssh

这些工具后面都用得上,尤其是curl,导入ROS公钥的时候必须用。

这里有个小忠告:apt upgrade不要急着一上来就执行。TX2的内核和驱动是JetPack定制的,盲目升级系统内核可能导致硬件加速相关的组件失效。如果没有明确需要,装ROS之前先保持内核版本不动,等系统稳定后再考虑选择性升级。

2.3 为什么这里不推荐动Python环境

Jetson平台上有不少用户是为了跑深度学习才买的,所以很多人已经装了Anaconda或者手动改了Python环境。这点在装ROS之前要特别小心:ROS Melodic是基于Python 2的,而JetPack系统默认的python命令指向Python 2.7,这是ROS工具链能正常运行的前提。

如果你为了深度学习把默认python改成了python3,或者装了conda之后改了PATH优先级,后面执行rosdep、roslaunch时就会出现各种ModuleNotFoundError或者python2/3语法报错。我的建议是:系统默认的python别动,python3的使用通过虚拟环境或者conda环境来隔离,千万不要直接改/usr/bin/python这个符号链接。

3. 安装流程实录:从ROS源到环境变量

3.1 添加ROS软件源与公钥

源的问题解决后,开始加ROS自己的apt源。ROS官方源地址是packages.ros.org,它和系统源是分开的两个独立配置。

echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/ros-latest.list

在TX2上执行时,$(lsb_release -sc)会自动展开为bionic,正好对应Ubuntu 18.04和ROS melodic。这一步需要解释一下:为什么不能用其他ROS发行版的源?因为Ubuntu 18.04官方支持的ROS发行版就是melodic。kinetic对应16.04,noetic对应20.04,如果你把noetic源写到18.04的系统里,apt会提示版本不匹配。

接下来导入公钥,两种方式任选一种。

方式一,从rosdistro仓库直接下载密钥并导入:

curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -

方式二,通过密钥服务器导入:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

两种方式我都用过。第一种比较快,但如果网络环境不好,连接raw.githubusercontent.com不稳定时会失败。第二种走的是keyserver,稳定性通常好一些,但也不是百分之百。如果你两种都试了还是导入失败,先别继续,先解决网络问题,因为公钥导不进去,后面apt update一定会报NO_PUBKEY错误。

导入公钥后执行sudo apt update,这时应当能看到packages.ros.org的索引被正常读取。如果这一步出现了"GPG error"或"NO_PUBKEY",就先排查公钥环节,不要急着安装。

3.2 安装ROS Melodic核心套件

索引更新成功后,安装命令其实很简单:

sudo apt install ros-melodic-desktop-full

desktop-full包含ROS核心、机器人通用功能包、可视化工具rqt和RViz、仿真工具Gazebo等。大部分人装这个准没错。但它体积不小,TX2板载存储紧张的话要提前看剩余空间。

如果你的eMMC或SD卡剩余空间比较小,可以先装基础版:

sudo apt install ros-melodic-ros-base

然后按项目需要逐个安装功能包,比如:

sudo apt install ros-melodic-slam-gmapping ros-melodic-navigation ros-melodic-teleop-twist-keyboard

我自己的做法是,第一次装就选desktop-full,后续开发省事很多。如果空间确实不够,就清理apt缓存,或者把根目录下不必要的大文件挪走。注意不要在安装过程中强行中断,apt操作跑到一半被Ctrl+C打断,很容易留下dpkg锁,下次安装任何包都会报"could not get lock"。

3.3 rosdep init与update:依赖管理的关键一环

ROS的源码包在工作空间编译时,经常需要解析系统依赖,rosdep就是做这件事的工具。装完ROS本体后,还需要单独安装rosdep相关工具链:

sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential

然后执行:

sudo rosdep init rosdep update

rosdep init只执行一次,作用是把rosdep的默认源列表写入/etc/ros/rosdep/sources.list.d/。rosdep update则是更新具体的依赖索引。这一步在网络环境不稳定的情况下非常容易卡住,后面我会专门讲它的坑。

3.4 配置环境变量

安装完成后,需要让每个终端都能自动加载ROS环境。把setup.bash写入到~/.bashrc:

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

然后检查一下:

echo $ROS_DISTRO

如果输出melodic,说明环境变量已经生效。这个环节容易被忽略的是,如果你用的是zsh而不是bash,必须写到~/.zshrc里,否则换个终端就找不到roscore命令。还有,如果你在TX2上经常用sudo执行命令,注意sudo环境不会自动加载用户的.bashrc,所以没事别用sudo跑roscore。

到这里,ROS melodic的主体已经装完了。但真正让人头疼的是各种细节问题,下面这部分是我觉得整个安装过程中最值得看的内容。

4. 我实际踩过的六个高频坑:报错、定位与修复

4.1 apt update出现404或找不到Package索引

我在第一次安装时就栽在这里。当时的报错大概长这样:

Err:6 http://archive.ubuntu.com/ubuntu bionic Release 404 Not Found

第一反应是网络问题,但重试了几次都一样。后来才意识到,问题出在软件源路径:我在sources.list里用了普通PC路径,而TX2是ARM架构,应该用ubuntu-ports路径。

修复方法:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo nano /etc/apt/sources.list

把里面所有指向普通路径的地址改成ubuntu-ports格式,然后apt update。这里要额外注意,有些教程会让你利用lsb_release -sc自动生成路径,这在源路径不标准时反而会掩盖问题。我建议直接把源写成静态的bionic-ports,清清楚楚不会错。

4.2 公钥导入失败,apt update报NO_PUBKEY

报错样式:

W: GPG error: http://packages.ros.org/ros/ubuntu bionic InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F42ED6FBAB17C654

意思是系统不认识packages.ros.org的密钥。原因通常是第一步导入公钥时网络失败,或者根本没有执行导入命令。很多教程会把公钥导入放在添加源之后,如果你跳过了那一步,就会遇到这个报错。

修复思路分两种情况。如果ros.asc方式导入失败,就换密钥服务器方式:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

如果还是失败,可以用下面的方式手动下载密钥文件再导入:

curl -s -o /tmp/ros.key https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc sudo apt-key add /tmp/ros.key

再次执行apt update,确认没有GPG相关报错再继续。

4.3 rosdep update一直卡住或超时

这是TX2上安装ROS时最常见的拦路虎。现象是sudo rosdep init没反应,或者rosdep update卡在某个URL下载上很久不动,甚至直接报:

ERROR: cannot download default sources list from https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/sources.list.d/20-default.list Website may be down.

我遇到这个问题时试了好几次都没成功。根本原因在于rosdep默认从raw.githubusercontent.com拉取配置文件,而这个域名在部分网络环境下访问不稳定。

处理方法可以分两步。第一步,先看init有没有成功创建配置文件:

ls /etc/ros/rosdep/sources.list.d/

如果20-default.list已经存在,说明init其实已经完成,直接跑rosdep update即可。如果文件不存在,可以手动创建目录和文件:

sudo mkdir -p /etc/ros/rosdep/sources.list.d/ sudo nano /etc/ros/rosdep/sources.list.d/20-default.list

然后把rosdep默认的源列表写入。内容大致是几个yaml文件的地址,分别对应osx、base、python、ruby,以及各ROS发行版的release索引。写完保存后执行:

sudo rosdep update

之后的rosdep update仍然需要从那些URL拉取数据,所以如果网络还是很差,我的策略是多重试几次,或者换一个网络环境再执行。只要update最后能读到数据,哪怕慢一点,就算成功了。rosdep是后续源码编译时的重要依赖管理工具,这一步别跳过去。

4.4 依赖错误与半安装状态

安装过程中如果网络中断,或者你手痒按了Ctrl+C,apt可能留下半安装的包。之后执行任何apt命令,都会出现类似:

E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a'

处理方法就是按提示执行:

sudo dpkg --configure -a sudo apt --fix-broken install

如果提示"could not get lock /var/lib/dpkg/lock",说明有另一个apt进程还在跑,或者旧的锁没释放。可以查看进程,确认是哪个apt进程占用的,等它结束就好。尽量不要直接删锁文件,除非你非常确定没有apt进程在运行。

4.5 默认Python版本冲突

我在TX2上装过深度学习环境,当时把默认python指到了3.6,结果rosdep命令直接报:

ModuleNotFoundError: No module named 'rosdep2'

原因是rosdep、roslaunch这些ROS工具链默认使用python2,而系统python指向python3后,python3环境里根本没有安装rosdep2这个包。

修复方法是把系统默认python指回Python 2.7:

sudo rm /usr/bin/python sudo ln -s /usr/bin/python2.7 /usr/bin/python

但这其实是一个永久的教训:在TX2这种既要跑ROS又要跑深度学习的板子上,python2和python3的并存是常态,正确做法是保持系统默认python是2.7,而深度学习框架通过conda或其他虚拟环境来隔离。动手改系统级别的python符号链接,后患无穷。

4.6 安装过程卡顿甚至无响应

ROS melodic的desktop-full包数量多,TX2的CPU处理大量依赖时负载很高。如果你开着图形桌面、浏览器、多个终端,内存很容易吃紧。轻则apt变慢,重则安装进程被系统杀掉。

安装前建议先关闭不需要的图形界面程序,或者直接加swap。TX2自带的8GB内存在裸系统下够用,但开了桌面环境后就会紧张。可以用一个swapfile缓解:

sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

需要永久生效的话,在/etc/fstab里加一行对应swapfile的挂载条目。这个操作对TX2这种存储介质是SD或SSD的开发板来说比较实用,能防止安装大软件时触发OOM。

5. 安装完成后的验证与TX2日常使用建议

5.1 用最小demo验证ROS环境

安装完成之后,不要急着开始写代码,先用最基础的方式验证环境是否真的可用。

第一个终端执行:

roscore

看到类似"started core service"的输出,说明ROS核心节点正常启动。

新开一个终端执行:

rosrun turtlesim turtlesim_node

如果弹出一个小海龟窗口,说明节点运行正常。再开一个终端执行:

rosrun turtlesim turtle_teleop_key

然后你就能用方向键控制小海龟移动了。这一步通过,说明ROS Melodic在TX2上的通信、节点管理和图形显示都正常。

想进一步确认可视化工具是否可用,可以跑:

rosrun rqt_graph rqt_graph

看到节点之间的连线图,就说明rqt工具链也装好了。

5.2 存储空间的维护

ROS melodic的desktop-full安装后,/opt/ros/melodic目录通常会占用2GB以上,加上依赖包,整体空间占用还是比较明显的。TX2板载存储一般是16GB起步,如果你用的是SD卡或NVMe SSD,情况会好一些。

日常可以定期执行:

sudo apt clean sudo apt autoremove

apt clean会清掉/var/cache/apt/archives里的deb安装包,这些文件在安装完成后就没用了。apt autoremove会移除不再被依赖的孤立包,但要留意输出内容,不要把想保留的库误删。

如果你装了desktop-full之后几乎不用Gazebo,也可以考虑卸载一部分不用的仿真组件来释放空间。但ROS功能包之间依赖关系复杂,我的建议是空间实在紧再去动这些组件,否则老老实实保持完整安装更省心。

5.3 工作空间编译的建议

ROS开发通常要先建一个catkin工作空间:

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

在TX2上编译时,一个常见错误是使用默认的并行线程数导致内存吃满。TX2虽然有8GB内存,但catkin_make默认并行度可能让它瞬间耗尽。建议编译时手动限制并发:

catkin_make -j2

如果你有大量源码包要编译,-j2肯定会慢一些,但稳定。等你确定系统负载扛得住,再逐步调到-j4。编译过程中如果遇到内存不足报错,优先限线程次数,不要硬扛。

另外,编译时不要用sudo。普通用户编译出来的build和devel目录权限都在用户自己名下,后续增量编译才顺畅。如果用了sudo,后面每次编译都要sudo,非常别扭。

5.4 装好ROS后,先做一次系统镜像备份

这一点算是我踩了好几次坑之后最深切的体会。TX2系统一旦被依赖搞乱,或者你在测试某些功能包时把驱动搞坏,恢复成本很高。重刷JetPack、再装一次ROS,整个过程又要几个小时。

我的习惯是,在ROS装好、环境验证通过之后,立刻把SD卡或eMMC里的系统做成镜像备份。这样后面无论怎么折腾,随时可以恢复到当前这个干净状态。TX2开发板的使用者完全可以把这个备份文件当成自己的"后悔药",比反复重装系统省事得多。

结尾的一点体会

在TX2上前后折腾了不止一遍,最后稳定记录下来的流程就是上面这套。我的最大感受是:环境配置出错,九成问题出在架构和软件源上,剩下的则是网络不稳定和JetPack定制环境的叠加效应。遇到报错时,先别急着复制搜索到的片段,先问自己三个问题——板子是什么架构?系统是什么版本?源地址里的路径和架构对不对得上?这三个问题捋清楚了,大部分坑都能绕过去。

最后再分享一个小技巧:把关键步骤的报错信息养成截图或者记录到文本文件的习惯。特别是像公钥指纹、rosdep源列表这种看起来繁琐的东西,一旦遇到问题翻看记录,比重新上网搜索快得多。ROS只是机器人开发的起点,环境稳定了,后面编译和调试才不会被破事打断。

RELATED READING

延伸阅读

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