☰
ROS Melodic 离线安装方案:Ubuntu 18.04 下 rosdep 本地化与依赖处理
2026/10/17 1:04:12 网站建设 项目流程

1. 为什么这个安装方案值得单独拿出来讲

ROS Melodic 是 ROS1 生态里相当特殊的一个版本,它官方绑定的系统就是 Ubuntu 18.04,两者之间的依赖关系咬得很死。很多人第一次装 ROS,卡住的地方根本不是编译报错,而是rosdep update这一步反复超时、反复重试、最后直接放弃。我自己前前后后在不同机器上装过不下十次 Melodic,踩过的坑基本都集中在网络环节,所以这套“先把压缩包拉到本地,再离线喂给 rosdep”的思路,是我目前最推荐给新手的做法。

先说清楚这套方案适合谁。如果你手上是一台刚装好的 Ubuntu 18.04,网络环境不太理想,或者你希望整个安装过程可控、可复现、不依赖实时网络,那这套流程就是为你准备的。它解决的核心问题有三个:一是apt安装阶段因为源的问题卡住,二是rosdep init和rosdep update因为访问外部资源失败而中断,三是整个安装过程不可重复,换台机器就得重新赌一次网络。

需要提前说明的是,本文讲的“网络原因”指的是访问软件源和依赖索引时的连通性问题,处理思路是提前把需要的资源下载到本地,再让安装程序从本地读取。这是纯粹的工程做法,和任何特定网络工具无关,你只需要有一台能正常下载文件的机器即可。

整套流程我拆成四块:环境确认与源配置、核心包安装、rosdep 离线处理、验证与收尾。每一块我都会把“为什么这么做”讲透,因为只照着命令敲,遇到变体情况你还是会懵。

2. 装之前必须确认的几件事

2.1 系统版本和架构别搞错

ROS Melodic 只认 Ubuntu 18.04,代号 bionic。你可以在终端里跑一句确认:

lsb_release -a

输出里Release必须是18.04,Codename必须是bionic。我见过有人拿 20.04 硬装 Melodic,apt阶段就开始报一堆依赖冲突,最后装出来的东西半死不活。架构方面,Melodic 官方支持 amd64 和 arm64,用uname -m看一眼,x86_64对应 amd64,aarch64对应 arm64。这个信息后面配源的时候要用到。

还有一点容易被忽略:确认你的系统是全新安装还是已经装过别的 ROS 版本。如果之前装过 Noetic 或者别的版本,/opt/ros目录下可能已经有残留,apt源列表里也可能有旧条目。我的建议是,装 Melodic 之前先把旧的 ROS 相关源清理干净,避免版本串味。

2.2 磁盘空间和权限

ROS Melodic 的桌面完整版装下来大概要占 2 到 3 GB,加上你后面要放的离线压缩包,建议预留至少 10 GB 空闲空间。用df -h看一下根分区。权限方面,全程需要 sudo,确认你的账号在 sudoers 里,这个一般没问题。

2.3 先把系统自带源理顺

这一步是很多人跳过、但后面会反复回来补的。Ubuntu 18.04 默认的软件源在国内访问速度参差不齐,装 ROS 之前先把系统源换成响应快的镜像,能省掉大量等待时间。具体换哪个镜像,你根据自己实际能访问的来选,这里不指定具体地址,只讲方法:编辑/etc/apt/sources.list,把archive.ubuntu.com和security.ubuntu.com替换成你手头可用的镜像域名,然后:

sudo apt update sudo apt upgrade -y

upgrade这一步别省,把系统补丁打齐,后面装 ROS 依赖时能少一堆版本冲突。我实测下来,系统本身没更新干净,是后面apt install报依赖错误的常见原因之一。

提示:换源之后如果apt update报 GPG 签名错误,说明镜像的公钥没导入,先解决签名问题再往下走,不要带着报错硬装。

3. 配置 ROS 软件源的正确姿势

3.1 添加源和密钥

ROS 的软件源和系统源是分开的。官方文档给的命令是往/etc/apt/sources.list.d/ros-latest.list里写一条源地址,然后导入密钥。这里的关键在于,源地址里的packages.ros.org如果访问不畅,apt update就会卡住。处理办法是提前把这条源也指向你能访问的镜像。

添加源的命令长这样:

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu bionic main" > /etc/apt/sources.list.d/ros-latest.list'

如果你要用镜像,把packages.ros.org/ros/ubuntu换成镜像对应的路径即可。密钥导入用:

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

密钥服务器如果连不上,可以换一个 keyserver 地址,或者提前把密钥文件下载到本地再用apt-key add导入。这一步失败的话,后面apt update会直接报NO_PUBKEY,装不了任何 ROS 包。

3.2 更新索引并确认源生效

sudo apt update

更新完之后,用下面这条命令确认 ROS 源已经被识别:

apt-cache policy ros-melodic-desktop-full

如果能看到候选版本号,说明源配好了。看不到的话,回头检查源文件路径和密钥,别急着往下装。

3.3 为什么建议先下载压缩包到本地

标题里特别强调了“先将所需压缩包下载到本地”,这个思路的价值在于把不可控的实时网络访问,变成可控的本地文件操作。具体来说,有两类东西适合提前下载:

第一类是 ROS 的核心 deb 包。如果你担心apt install过程中断,可以用apt-get install --download-only先把包下到/var/cache/apt/archives/,再离线安装。命令是:

sudo apt-get install --download-only ros-melodic-desktop-full

这样包会先落到本地缓存,网络断了也不影响已经下好的部分,重试时只补缺的。

第二类就是 rosdep 需要的索引文件,这个放到下一节重点讲。把这两类资源都本地化之后,整个安装过程就变成“本地文件搬运”,稳定性完全不一样。

4. 核心包安装与依赖处理

4.1 安装桌面完整版

sudo apt install ros-melodic-desktop-full

这一步会拉一大堆依赖,包括 Gazebo、RViz、各种感知和仿真库。如果前面源配好了,这一步通常能顺利跑完。中途如果报某个依赖找不到,大概率是系统源和 ROS 源没同步好,先apt update再重试。

装完之后,环境变量要配一下:

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

这一步别偷懒用setup.sh之外的写法,Melodic 的setup.bash是标准入口。配好之后新开终端会自动加载,echo $ROS_DISTRO应该输出melodic。

4.2 安装构建工具和依赖

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

这几个包是后面编译工作空间和跑 rosdep 的基础。python-rosdep尤其关键,它就是接下来离线处理的主角。装的时候如果提示某个包已经是最新版,正常,跳过即可。

4.3 初始化 rosdep 的坑点

sudo rosdep init

这条命令做的事情是从网上拉一个20-default.list文件放到/etc/ros/rosdep/sources.list.d/。问题就出在这里,它访问的地址经常连不上,报错通常是ERROR: cannot download default sources list from...。

处理办法有两个方向。方向一是换一个能访问的镜像地址,把rosdep init实际访问的 URL 替换掉。方向二是干脆手动创建这个文件,把内容写进去,绕过init的网络请求。我一般用方向二,因为最可控:

sudo mkdir -p /etc/ros/rosdep/sources.list.d/ sudo tee /etc/ros/rosdep/sources.list.d/20-default.list << 'EOF' # os-specific listings first yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/osx-homebrew.yaml osx # generic yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/base.yaml yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/python.yaml yaml https://raw.githubusercontent.com/ros/rosdistro/master/rosdep/ruby.yaml gbpdistro https://raw.githubusercontent.com/ros/rosdistro/master/releases/fuerte.yaml fuerte EOF

注意,这里写进去的 URL 是 rosdep 后续update时要访问的。如果你网络访问这些地址不畅,就要在下一步做本地化替换。

5. rosdep update 离线化处理全流程

5.1 理解 rosdep update 到底在干什么

rosdep update的本质是把一堆 YAML 索引文件下载到本地~/.ros/rosdep/sources.cache/目录下,然后建立缓存。它要下载的文件包括base.yaml、python.yaml、ruby.yaml以及各个 rosdistro 的distribution.yaml。这些文件加起来体积不大,但数量多,逐个下载时任何一个超时都会导致整个 update 失败。

所以离线化的思路很直接:在一台能正常访问的机器上,把这些文件全部下载下来,打包拷到目标机器,然后让 rosdep 从本地读取。这里有两种实现路径,我都讲一下。

5.2 路径一:手动下载并替换缓存

先在一台网络正常的机器上,把 rosdep 需要的文件结构完整拉下来。最省事的办法是在那台机器上正常跑一次rosdep update,然后把~/.ros/rosdep/sources.cache/整个目录打包。这个目录的结构大致是:

sources.cache/ ├── index └── ...(各个 yaml 文件按 hash 命名)

把打包好的sources.cache拷到目标机器的~/.ros/rosdep/下,覆盖同名目录。然后关键一步,修改/etc/ros/rosdep/sources.list.d/20-default.list,把里面的 URL 全部改成file://开头的本地路径,指向你放好的文件。比如:

yaml file:///home/yourname/rosdep_local/base.yaml

这样rosdep update就只读本地文件,不再发起网络请求。实测下来,这种方式最稳,因为完全绕开了网络。

5.3 路径二:用本地 HTTP 服务模拟源

如果你不想改20-default.list里的 URL 结构,可以在本地起一个简单的 HTTP 服务,把下载好的文件目录暴露出去,然后把20-default.list里的域名换成127.0.0.1加端口。比如用 Python 自带的:

cd /path/to/rosdep_files python -m SimpleHTTPServer 8000

然后把源地址改成http://127.0.0.1:8000/...。这种方式的好处是 URL 结构不用大改,rosdep 以为自己在访问网络,实际走的是本地回环。缺点是每次 update 前都要先把服务起起来。

5.4 两种路径的对比

对比项手动替换缓存本地 HTTP 服务
网络依赖完全无仅本地回环
操作复杂度中,需改配置文件低,改域名即可
可重复性高,一次配好长期用中,每次要起服务
适合场景长期固定机器临时调试

我个人更推荐路径一,配好之后一劳永逸。路径二适合你只是想快速验证一下,不想动配置文件的情况。

5.5 执行 update 并验证

配置好之后执行:

rosdep update

如果一切正常,你会看到它逐个读取本地文件并建立缓存,最后输出updated cache in ...。这时候可以跑一句验证:

rosdep resolve roscpp

能正常输出依赖解析结果,就说明 rosdep 已经可用了。

注意:rosdep update默认会检查文件的时间戳和 hash,如果你手动替换的缓存和20-default.list里声明的对不上,它会重新尝试下载。所以替换缓存和改 URL 这两步要配套做,不能只做一半。

6. 常见问题与排查速查

6.1 apt 阶段典型报错

报错信息原因处理办法
NO_PUBKEYROS 源密钥没导入重新导入密钥,或换 keyserver
404 Not Found源地址路径写错核对 bionic 和 main 是否拼对
依赖冲突系统源没更新或混入旧 ROS 源清理旧源,apt update后重试
下载中断网络不稳用--download-only先下到本地

6.2 rosdep 阶段典型报错

报错信息原因处理办法
cannot download default sources listinit 访问网络失败手动创建 20-default.list
ERROR: unable to process source某个 yaml 下载失败本地化该文件并改 URL
update timeout逐个下载超时整体替换 sources.cache
no rosdep cache缓存目录权限不对检查 ~/.ros 属主

6.3 几个我踩过的坑

第一个坑是rosdep init和rosdep update用的不是同一个用户。init是 sudo 跑的,写的是/etc/ros/;update是普通用户跑的,写的是~/.ros/。如果你用 sudo 跑update,缓存会写到 root 的 home 下,普通用户读不到。这个错误很隐蔽,表现是 update 显示成功,但编译时 rosdep 又说没缓存。

第二个坑是手动替换缓存后忘了改文件权限。~/.ros/rosdep/sources.cache/如果属主是 root,普通用户 update 时会报权限错误。用chown -R $USER:$USER ~/.ros修一下。

第三个坑是20-default.list里的 URL 改了,但缓存里的 index 文件还指向旧地址,导致 update 时又去访问网络。解决办法是改完 URL 后把sources.cache整个删掉,重新 update 一次让它重建。

7. 安装后的验证与工作空间初始化

7.1 基础验证

装完之后跑几个命令确认环境正常:

roscore

新开一个终端:

rosrun turtlesim turtlesim_node

再开一个:

rosrun turtlesim turtle_teleop_key

能看到小乌龟窗口并且键盘能控制它动,说明核心环境没问题。这一步别跳过,它是判断整个安装是否成功的黄金标准。

7.2 初始化工作空间

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

catkin_make第一次跑会编译一堆东西,如果 rosdep 配好了,依赖解析会很快。编译完成后:

source devel/setup.bash echo $ROS_PACKAGE_PATH

能看到~/catkin_ws/src在路径里,就说明工作空间配好了。

7.3 用 rosdep 装依赖的实战

在工作空间里,如果你 clone 了一个需要额外依赖的包,标准做法是:

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

这条命令会扫描src下所有包的package.xml,解析出缺失依赖并安装。如果前面 rosdep 离线化做得好,这一步会非常顺。我实测下来,离线化之后这条命令的失败率从大概三成降到了接近零。

8. 一些让流程更顺的补充经验

8.1 把整个流程脚本化

这套步骤我建议写成一个 shell 脚本,把源配置、密钥导入、包安装、rosdep 本地化串起来。这样换机器时直接跑脚本,不用回忆每一步。脚本里对每个可能失败的点加判断,比如密钥导入失败就提示手动处理,而不是直接往下走。

8.2 离线资源的版本管理

你下载的 rosdep 索引文件是有时效性的,rosdistro 会更新。建议每隔一段时间重新拉一次最新文件,替换本地的旧版本。可以在脚本里加一个日期标记,方便你知道当前用的是哪一版。

8.3 关于镜像选择

镜像的选择没有绝对最优,取决于你实际能访问哪个。我的做法是准备两三个候选,哪个快用哪个。配源的时候把候选都写进注释,切换时改一行就行。

8.4 编译大型包时的内存问题

Melodic 上编译一些大型包,比如带大量模板的 C++ 项目,可能会因为内存不足被 OOM killer 干掉。表现是编译到一半突然中断,日志里没有明显错误。处理办法是加 swap,或者用catkin_make -j2限制并行编译数。这个坑我在小内存机器上遇到过好几次,一开始还以为是代码问题。

8.5 环境变量的加载顺序

如果你同时装了多个 ROS 版本,~/.bashrc里 source 的顺序很重要。后 source 的会覆盖前面的。确认echo $ROS_DISTRO输出的是你当前想用的版本。这个细节在多版本共存时特别容易出问题。

整套流程走下来,核心就一句话:把不可控的网络访问,变成可控的本地文件操作。apt 阶段用--download-only预下载,rosdep 阶段用本地缓存加 file URL 替换,两步做完,Melodic 的安装就从“看运气”变成了“按步骤执行”。我在几台网络条件各异的机器上都用这套方法装过,成功率很稳定。如果你在替换缓存那一步遇到 index 对不上的问题,把sources.cache删干净重新 update 一次,基本都能解决。

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

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

立即咨询