如果你是在 VMware 虚拟机里装了 Ubuntu,然后跟着 ROS Melodic 的安装教程敲下 sudo apt install ros-melodic-desktop-full,终端却回了一句 E: Unable to locate package ros-melodic-desktop-full,这时候先别怀疑网络,也别急着重装虚拟机。这个报错的意思很直接:apt 在它当前的软件包索引里,根本找不到你让它安装的那个名字。换句话说,这不是“下载失败”,而是“仓库里没有这个候选”。
真正让人头疼的地方在于,同一个报错背后能藏好几种完全不同的原因。可能是 ROS 软件源压根没加,可能是源加了但系统版本不对,也可能是包名在 ROS Melodic 发行版里根本不存在。我见过太多人在“重新装一遍 Ubuntu”和“反复 apt update”之间浪费几个小时,结果一看源文件,ros-latest.list 里写的是 Ubuntu 20.04 的代号。这篇文章就把这个 ROS Melodic 安装过程中高频出现的 E: Unable to locate package 从原理到排查完整拆一遍,尤其是虚拟机环境下容易忽略的几个细节。
1. E: Unable to locate package 其实对应三种完全不同的问题
先把结论摆出来,后面的每一步排查都靠这个判断兜底。你在终端里看到“无法定位软件包”时,对应的真实问题通常只有三选一:ROS 源没加、ROS 源加的代号不对、包名在源里不存在。偶尔还会有第四种情况,就是密钥或缓存问题导致 apt update 没有真正把 ROS 仓库索引拉下来,但表象也是“找不到包”。
1.1 压根没把 ROS 软件源写进 apt
这是最基础但也最常见的情况。ROS Melodic 的二进制软件包并不在 Ubuntu 自带的官方源里,而是放在 packages.ros.org 这个独立软件仓库。所以如果你只是在一台刚装好的 Ubuntu 18.04 上运行 sudo apt install ros-melodic-desktop-full,apt 在自己的默认源列表里翻来找去,发现根本没有 ros-melodic-* 这种前缀的包,自然就会提示 E: Unable to locate package。
怎么判断是不是这个问题?直接看源文件:
bash复制ls -l /etc/apt/sources.list.d/
cat /etc/apt/sources.list.d/ros-latest.list
如果提示 No such file or directory,或者 ros-latest.list 文件不存在,那么 ROS 源就没配过。这是整个问题链里最容易修的一种,照着官方流程添加源、导入公钥、更新索引就能解决,后面会专门讲。
1.2 源加了,但是 Ubuntu 版本代号和 ROS 发行版对不上
软件仓库在 apt 眼里是按 Ubuntu 发行版代号分目录存放的。packages.ros.org/ros/ubuntu 下面有 dists/bionic/、dists/focal/ 这些子目录,分别对应 Ubuntu 18.04 和 Ubuntu 20.04。ROS Melodic 官方支持的是 Ubuntu 18.04 Bionic,所以 apt 只会在 bionic 这个目录里寻找 Melodic 的包。
很多安装教程会建议这样添加源:
bash复制sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
这段命令本身没问题,它会把当前系统的代号自动填进去。但如果你实际上用的是 Ubuntu 20.04,lsb_release -sc 会返回 focal,最终源文件里就写着 focal main。问题是 apt 在 focal 目录里只能找到 ROS Noetic 的二进制包,而你要装的是 Melodic,那结果就是更新索引成功,但依然什么都装不上。
ROS 1 各发行版和 Ubuntu 版本的对应关系是固定的:
| ROS 发行版 | Ubuntu 版本 | Ubuntu 代号 |
|---|---|---|
| ROS Melodic | Ubuntu 18.04 | bionic |
| ROS Noetic | Ubuntu 20.04 | focal |
| ROS Kinetic | Ubuntu 16.04 | xenial |
如果你想要的某个 ROS 发行版,和你现在系统版本对不上,添加再多的源也没有用。
1.3 包名在 Melodic 的发行索引里不存在
第三种情况稍微隐蔽一点。ROS 的软件包并不是所有版本都发布到二进制仓库,rosdistro 里记录了每个发行版实际会生成哪些 deb 包。你想装的某个功能包如果没被维护者发布到 Melodic 的二进制索引里,那么即使 ROS 源配得完全正确,apt install ros-melodic-xxx 也照样给你报 Unable to locate package。
举个例子,你在网上看到一篇文章推荐安装某个工具,文章写的是 sudo apt install ros-melodic-rtabmap,但实际包名可能是带版本限定或分了好几个子包的,比如 ros-melodic-rtabmap-ros。再比如你看到 ros-melodic-turtlebot3,但具体是需要 ros-melodic-turtlebot3-gazebo 还是 ros-melodic-turtlebot3-navigation,得先确认包名是否存在。
所以不要一看到找不到就去折腾源,先用搜索验证一下:
bash复制apt-cache search ros-melodic | grep 你想要安装的关键词
如果搜索有输出,说明源没问题,是包名写错了;如果搜索为零结果,那问题大概率还在源配置或系统版本上。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从零配好 Melodic 软件源并验证索引,这一步能解决九成问题
这一节我直接用我平时最顺手的流程写。前提是你确实用的是 Ubuntu 18.04 Bionic。如果你的系统是 Ubuntu 20.04 或 22.04,也不是完全没救,但要清楚官方二进制源里没有对应东西,后面第五节会展开。
2.1 先确认你到底在什么系统上
我在处理这类问题的时候,第一件事永远是确认系统版本。因为太多人装的虚拟机镜像并不是自己以为的那个版本,尤其是一些第三方精简镜像和 OVF 模板,打开终端显示的是定制主题,容易让人忽略真实系统版本。
bash复制cat /etc/os-release
lsb_release -a
如果 cat /etc/os-release 输出显示 VERSION_ID="18.04",lsb_release -a 输出 Codename 是 bionic,那硬件环境是满足条件的,可以继续配源。如果显示的是 20.04 或 22.04,那么直接把下面源里的代号改成 bionic 强行装 Melodic 是一个比较危险的操作,依赖关系会非常难看,我后面会再解释为什么。
2.2 先把基础工具补齐
在虚拟机里安装 Ubuntu 时,如果选的是最小安装或者服务器版,系统可能没有 curl、gnupg、lsb-release 这些包。很多人添加源时用到了 curl 下载密钥,结果提示找不到命令,然后手动装 curl 又发现自己没加 universe 源,陷入一个连环套。
建议先执行:
bash复制sudo apt update
sudo apt install -y curl gnupg2 lsb-release software-properties-common
如果这一步 apt update 本身就报各种连接错误,先解决网络或镜像源问题,再继续。lsb-release 很重要,因为 ROS Wiki 的配置命令会调用 lsb_release -sc,缺了它,命令会直接失败或生成一个不完整的源文件。
2.3 添加源并导入公钥
ROS Melodic 时代有两种常见做法。一种是早期教程里的 apt-key 方式,另一种是现在更推荐的 signed-by 方式。我建议直接用带 signed-by 的方式,因为 apt-key 在较新版本的 Ubuntu 上已经被标记为 deprecated,而且把公钥放到全局信任区,会造成不必要的安全隐患。
先创建公钥目录并下载 ROS 仓库公钥:
bash复制sudo mkdir -p /usr/share/keyrings
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
然后写入源文件。注意这里为了防止 $(lsb_release -sc) 因环境问题产生意外结果,我建议在 Ubuntu 18.04 上直接硬编码 bionic:
bash复制echo "deb [signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros/ubuntu bionic main" | sudo tee /etc/apt/sources.list.d/ros-latest.list
如果你是在其他机器上装 Noetic,就把 bionic 换成 focal。始终要记住一个原则:这里的代号必须和当前 Ubuntu 版本严格一致,不是你想装哪个 ROS 版本就写哪个代号。
添加完源之后,检查一下文件内容:
bash复制cat /etc/apt/sources.list.d/ros-latest.list
确保没有多余的空行、引号或乱码输出。文件里应该只有下面这一行:
code复制deb [signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros/ubuntu bionic main
2.4 更新索引并验证包是否可见
更新软件包索引前,先把旧的列表缓存清掉一次,避免 apt 因为缓存里的脏数据产生各种怪问题:
bash复制sudo rm -rf /var/lib/apt/lists/*
sudo apt update
如果源和公钥都正常,apt update 的输出里应该能看到类似这样的行:
code复制Get:7 http://packages.ros.org/ros/ubuntu bionic InRelease
Get:8 http://packages.ros.org/ros/ubuntu bionic/main amd64 Packages
看到 bionic InRelease 和 Packages 被正常获取,说明 ROS 源已经真正接入了。之后再验证候选包:
bash复制apt-cache policy ros-melodic-desktop-full
apt-cache search ros-melodic | head -n 20
如果 apt-cache policy 输出里显示了版本号,比如:
code复制ros-melodic-desktop-full:
Installed: (none)
Candidate: 1.4.1-0melodic.20200709.224308
那就可以放心安装:
bash复制sudo apt install ros-melodic-desktop-full
这一步如果还报 Unable to locate package,基本可以排除“ROS 源没配好”这个最常见原因了。
3. 从报错到根因:一条可以直接照着走的排查链路
遇到 E: Unable to locate package 时,我习惯按固定顺序做五步检查。这个顺序能帮我把问题压缩到最小范围,不会东改一下西试一下,最后连自己改了什么都没印象。
3.1 先把完整的报错上下文保存下来
不要只看最后一行。把终端输出完整复制下来,重定向到日志文件也行:
bash复制sudo apt install ros-melodic-desktop-full 2>&1 | tee /tmp/ros_install.log
然后看日志里的关键行是 Unable to locate package 还是别的。如果是类似 E: Unable to locate package ros-melodic-desktop-full 且前后没有出现其他错误,问题聚焦在索引缺失。但如果你看到的是 The following packages have unmet dependencies,那是另一个完全不同的故事,不能按这个思路处理。
3.2 检查源文件和 apt update 输出的具体关系
分别检查这三个地方:
bash复制ls -l /etc/apt/sources.list.d/
cat /etc/apt/sources.list.d/ros-latest.list
sudo apt update 2>&1 | tail -n 30
这时候会出现几种典型情况,我整理成了一张对照表:
| 现象 | 大概率原因 | 对应处理 |
|---|---|---|
| 源文件不存在 | 没有添加 ROS 源 | 按上一节添加 |
| 源文件里的代号是 focal | 系统版本与 Melodic 不匹配 | 换到 Ubuntu 18.04,或用 Docker |
| apt update 中有 NO_PUBKEY | 公钥未导入或已失效 | 重新下载导入 ROS 公钥 |
| apt update 出现 404 | 仓库里没有该代号目录 | 修改源文件代号 |
| apt update 正常但搜索无结果 | 包名不存在或索引损坏 | 查看 rosdistro 或清缓存 |
3.3 公钥问题为什么会被误判成“找不到包”
很多人会遇到一个迷惑现象:sudo apt update 输出一大段 W: GPG error: ... NO_PUBKEY,但最后没直接终止,apt 还能继续跑,然后 apt install 报找不到包。这是因为源更新不完整,ROS 仓库的索引没有被正常写进本地列表。apt 没有拿到索引,自然就找不到包。
解决方式是重新导入公钥,并再跑一次更新:
bash复制curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
sudo rm -rf /var/lib/apt/lists/*
sudo apt update
如果担心网络下载 ros.key 不稳定,也可以先用浏览器打开 ROS 官方文档找到当前公钥内容,手动写进文件。关键不是用什么工具,而是确保 /usr/share/keyrings/ros-archive-keyring.gpg 文件存在且非空。
3.4 确认 ROS 源是否真的被 apt 加载
只看源文件存在还不够,因为 apt 可能没把那个源列表文件识别进去。可以用这个命令查一下 apt 到底加载了哪些源:
bash复制apt-cache policy | grep -A 2 "packages.ros.org"
正常情况下会输出:
code复制 http://packages.ros.org/ros/ubuntu bionic/main amd64 Packages
release v=18.04,o=ROS,a=bionic,n=bionic,l=ROS,c=main,b=amd64
origin packages.ros.org
如果这条输出完全不存在,即使源文件存在,apt 也没有成功加载。这时候要去翻 /etc/apt/sources.list 里有没有注释符号、文件权限是否正确、或者文件后缀是不是 .list。有些教程会让人直接往 /etc/apt/sources.list 里追加内容,如果加进去的行前面不小心带了 #,等于白写。
3.5 清理本地列表缓存能解决一部分怪问题
如果源文件没问题,apt update 也显示成功,但搜索依然找不到任何 ros-melodic-* 包,我建议把 apt 的列表缓存整个清掉再重建一次:
bash复制sudo rm -rf /var/lib/apt/lists/*
sudo apt clean
sudo apt update
这个操作等价于让 apt 强制重新下载所有软件源索引。虚拟机关机后直接复制磁盘文件,或者反复挂起快照,都可能让 /var/lib/apt/lists 里的文件处于不一致状态。虽然不常见,但清一次缓存成本很低,值得优先尝试。
4. VMware 虚拟机里装 ROS Melodic 为什么更容易踩中这个坑
我在帮人远程看这个问题时,经常发现对方是在 VMware Workstation 或 VMware Fusion 里装了 Ubuntu。虚拟机本身不会让 apt 区别对待 ROS 包,但虚拟机的使用方式会给上述问题叠加很多额外的变量。
4.1 镜像版本和教程版本经常错位
最经典的场景是:网上教程写着“VMware 安装 Ubuntu 18.04”,但用户下载镜像时选成了 20.04 或 22.04,然后又照着 Melodic 的教程往下走。在虚拟机里装系统时,如果你没有刻意确认版本号,安装完成后看到桌面风格都差不多,根本不会意识到系统版本不对。
我遇到过一个特别典型的案例:某台虚拟机里运行的是 Ubuntu 20.04,用户想装 Melodic,但又没有使用自带的 Noetic,就一直卡在 Unable to locate package。最后我把源文件打开,里面写着 focal main,而用户还在问是不是要改成 bionic。这里要特别提醒一下:如果系统是 20.04,光把源文件里的 focal 改成 bionic 并不可行,因为你接下来会面临一大堆依赖版本冲突。最干净的办法是重新装 Ubuntu 18.04,或者用第五节的 Docker 方案。
4.2 最小化安装导致基础命令缺失
VMware 安装 Ubuntu 时,如果选择了最小安装,系统里可能没有 curl、gnupg、lsb-release,甚至连 vim 都没有。这会导致你执行添加源命令时出现各种“command not found”,然后又去单独安装这些工具。麻烦在于最小化安装默认只启用了 main 和 restricted 组件,某些工具软件包在 universe 组件里,所以你还得先启用:
bash复制sudo add-apt-repository universe
sudo apt update
如果 add-apt-repository 这个命令本身不存在,先装 software-properties-common。等你把基础工具装齐了,再回头做 ROS 源配置,整个过程才顺畅。
4.3 虚拟机时钟错位和网络源不可达
VMware 虚拟机关闭后,如果宿主机休眠过,虚拟机恢复后系统时间可能偏差很大。apt 使用 HTTPS 源时会对服务器证书做时间校验,如果本机时间差了几分钟到几个小时,apt update 会直接报证书验证失败或无法建立安全连接。当然,如果 ROS 源用的是 http:// 而不是 https://,时间问题可能不会立刻暴露,但 Ubuntu 自带的其他 HTTPS 源会先报错,导致整体 apt 状态不正常。
在虚拟机里碰到 apt 更新异常,可以先做两件事:
bash复制sudo apt install -y ntpdate
sudo ntpdate ntp.ubuntu.com
然后检查源是否可达:
bash复制curl -I http://packages.ros.org/ros/ubuntu/dists/bionic/Release
如果返回 HTTP/1.1 200 OK,说明源能通。如果一直卡住或超时,需要检查 VMware 虚拟机的网络适配器模式。NAT 模式通常能通外网,但有些公司内网的 VMware 环境会对 80/443 之外的流量做限制,或者 DNS 解析失败。你也可以临时把网络模式从 NAT 改成桥接模式试试,确认是不是虚拟网络导致的问题。
4.4 快照恢复容易让 apt 状态变得很脏
用 VMware 快照很方便,但也容易埋雷。比如你在某个快照里已经添加过 ROS 源,后来又回滚到一个没添加过 ROS 源的旧快照,而你自己不记得了。这时候再敲 apt install 报找不到包,就会以为是自己操作失误。
所以我的习惯是:遇到不是必现的问题时,先看当前系统状态,不要依赖记忆。检查源文件、跑一次完整更新、检查搜索结果,把“现在这台机器到底是什么状态”搞清楚,再下结论。
5. 当 Melodic 的某个包真的不存在时,能用什么兜底手段
排查到最后,你可能会发现 ROS 源没有问题,系统版本也没问题,但 apt-cache search 就是找不到你想要的包。这时候就要面对那个不讨喜的事实:这个包没有进入 Melodic 的二进制发布列表。原因可能是维护者只发布了源码包,也可能是该包在 Melodic 时代还在早期阶段,或者它根本不在 ROS 官方软件仓库里。
5.1 先确认软件包到底有没有发布到 Melodic
不要靠猜。打开 ROS 官方索引页面,或直接在命令行里查 rosdistro 数据:
bash复制curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/melodic/distribution.yaml | grep -n "package-name"
把 package-name 换成你要装的包名。如果能在 distribution.yaml 里看到这个包的记录,理论上它应该被构建成 deb 包;如果完全找不到,说明这个包压根没有进入 Melodic 的发行索引。另一种情况是包在记录里,但只存在于源码版本中,没有对应的二进制发布记录,那 apt 同样找不到。
这时候最好的验证方式其实是:
bash复制apt-cache search ros-melodic | grep 关键字
如果 ROS 源已经确认无误,而这里没有任何匹配,就说明该包在当前源里不存在,继续折腾 apt 没有意义。
5.2 Docker 方式最省心,尤其适合虚拟机环境
当宿主机系统不是 Ubuntu 18.04,或者某个包在 Melodic 二进制源里缺失时,我最推荐用 osrf/ros 官方 Docker 镜像。这个方式尤其适合 VMware 虚拟机场景,因为不需要你重装系统,也不影响宿主机现有的 ROS 环境。
先拉取镜像:
bash复制docker pull osrf/ros:melodic-desktop-full
然后进入容器:
bash复制docker run -it --rm osrf/ros:melodic-desktop-full
容器启动后,默认就是 Ubuntu 18.04 Bionic 环境,ROS Melodic 已经装好。你可以在这个容器里直接执行 apt install ros-melodic-xxx,而且因为容器内源已经提前配好,大部分包都能直接搜到。
如果需要把宿主机里的代码或数据带进去,挂载一个目录即可:
bash复制docker run -it --rm \
-v /home/yourname/catkin_ws:/catkin_ws \
osrf/ros:melodic-desktop-full
这样做还有额外的好处:不会污染宿主机系统。哪怕容器里把依赖装乱了,删掉容器重来即可,不用重装虚拟机。对于需要跑 Gazebo、RViz 这类图形程序的场景,在 VMware 里稍微配置一下 X11 转发或共享显示环境,也能让容器内窗口显示到宿主机桌面,但那是另一篇文章的量了。
5.3 源码编译始终是最后兜底
如果某个包连 Docker 镜像里都搜不到,那就只剩源码编译一条路。这种做法比较费时间,但它不受 apt 索引限制。通常流程是去该包的 GitHub 仓库,找到 Melodic 分支或对应版本的 tag,然后克隆到 catkin 工作区里编译。
理论上一个包的源码编译大概是这样:
bash复制mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone -b melodic-devel https://github.com/xxx/xxx.git
cd ~/catkin_ws
source /opt/ros/melodic/setup.bash
rosdep install --from-paths src --ignore-src -r -y
catkin_make
source devel/setup.bash
之所以把源码编译放在最后,是因为它需要处理依赖关系,而且依赖有时候也是源码包,一环扣一环,可能从早上编译到晚上。如果能在 osrf/ros:melodic 容器里直接用 apt 解决大部分依赖,再只对缺失的那一两个包做源码编译,会舒服得多。
另外,一些第三方厂商的 ROS 包不会进 ROS 官方源,而是放在自己的 apt 仓库里。比如有些相机驱动、雷达驱动,厂商只提供了自己的 apt 源,需要你额外添加他们的仓库,apt 才能找到。这种情况不是 ROS 源的问题,而是你根本没告诉 apt 该去哪里找这个包。如果你是从某个硬件厂商官网看到的安装命令,记得先看他们有没有要求添加额外的 apt 仓库。
我自己在装 ROS 环境时,已经养成了一套固定动作:先确认系统版本,再添加源,再导入公钥,然后清一次索引更新,最后用 apt-cache policy 验证候选包。整个过程不会超过五分钟。如果这样做完之后还是提示 E: Unable to locate package,我就会立刻去查 rosdistro,而不是在那个终端里一遍遍重试。能直接用二进制包就不要编译,能用容器就不要污染系统,这台机器一旦被你乱装过一堆半成品依赖,后面排查问题只会更痛苦。
