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.04Codename必须是bionic。我见过有人拿 20.04 硬装 Melodicapt阶段就开始报一堆依赖冲突最后装出来的东西半死不活。架构方面Melodic 官方支持 amd64 和 arm64用uname -m看一眼x86_64对应 amd64aarch64对应 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 -yupgrade这一步别省把系统补丁打齐后面装 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 源密钥没导入重新导入密钥或换 keyserver404 Not Found源地址路径写错核对 bionic 和 main 是否拼对依赖冲突系统源没更新或混入旧 ROS 源清理旧源apt update后重试下载中断网络不稳用--download-only先下到本地6.2 rosdep 阶段典型报错报错信息原因处理办法cannot download default sources listinit 访问网络失败手动创建 20-default.listERROR: unable to process source某个 yaml 下载失败本地化该文件并改 URLupdate timeout逐个下载超时整体替换 sources.cacheno 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_makecatkin_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 一次基本都能解决。