年前接了一个老项目的维护工作,代码是基于 ROS Melodic 写的,但手上这台机器装的是 Ubuntu 20.04,官方对口的 ROS 版本是 Noetic。项目里有个自研功能包只适配 Melodic,迁到 Noetic 的改动量不算小,于是我把目光转向了社区里不少人验证过的一条路:在 Ubuntu 20.04 上硬装 ROS Melodic。整个过程折腾了差不多两天,踩了不少坑,也理清了很多版本适配背后的逻辑。这篇就把我的实际安装过程、每一步为什么这么做以及问题排查经验完整记录下来,给同样被版本错位困扰的朋友一个参考,尤其是那些老项目代码依赖 Melodic、又不想重装系统的场景。
顺便说一句,这是一套“非官方组合”的安装方案,官方只支持 Ubuntu 18.04 配 Melodic。能在 20.04 上装成功,靠的是把 ROS 软件源手动指向 Bionic 仓库。这种做法能解决大部分核心组件安装,但也会带来一些依赖和 Python 版本上的坑。你如果只是想跑通 roscore、rviz、rqt 和常规功能包,这套方案完全够用;如果是长期开发环境,我建议你读完这篇再决定要不要这么干。
1. 为什么要在 20.04 上装 Melodic:先搞清楚版本适配这件事
1.1 官方版本对应关系与“错位安装”的由来
ROS 1 的每个发行版都有严格对应的 Ubuntu 版本,官方只针对特定组合做测试和发布。Melodic 对应的系统是 Ubuntu 18.04(Bionic),而 Ubuntu 20.04(Focal)对应的 ROS 1 版本是 Noetic。这个对应关系不是随便定的,每个 ROS 版本编译时都链接了特定版本的系统库、Python 解释器和 Boost 库,换到另一个系统版本上,二进制包的依赖很可能对不上。
| ROS 版本 | 官方支持的 Ubuntu 版本 | 系统代号 | 首要 Python 版本 |
|---|---|---|---|
| Melodic | 18.04 | Bionic | Python 2.7 |
| Noetic | 20.04 | Focal | Python 3.8 |
所以你在 20.04 上直接执行官方 Melodic 安装教程,到添加软件源那一步就会出问题:lsb_release -sc返回的是focal,apt 会认为你想装的是 Noetic 的包,虽然也能装,但装出来的版本不对。正确做法是把软件源里的系统代号手动写死成bionic,让 apt 去 Melodic 的二进制仓库拉包。这就是整个“错位安装”的基本原理。
1.2 这种装法的风险和使用场景
我先把话说清楚:这不是官方推荐方式,能成功但有代价。最大的风险集中在两点,第一是依赖解析冲突。Melodic 的二进制包在编译时依赖 Ubuntu 18.04 的库版本,比如 Boost 1.65,而 20.04 自带的是 Boost 1.71。大部分核心包不受影响,但一些依赖特定版本库的扩展包装不上或者运行时报错。第二是 Python 版本断层。Melodic 生态大量工具基于 Python 2,而 20.04 已经默认移除 Python 2,需要额外处理。
那什么场景下值得冒这个险?我总结下来主要有三类:一是老项目代码用了 Melodic 专属功能包,迁移成本高,像我遇到的情况;二是团队统一用 Melodic 开发,新机器临时加入;三是只想跑一个基于 Melodic 的仿真或算法验证,用完了就扔。如果你是想从零开始学 ROS,完全没有历史包袱,我建议直接上 Noetic 或 ROS 2,没必要自找麻烦。
2. 装之前的环境检查与软件源配置
2.1 确认系统版本和基础环境
在动手之前,先花两分钟确认系统环境,避免装到一半发现基础条件不对。我这次是在一台全新安装的 Ubuntu 20.04.6 上操作的,之前没有装过任何 ROS 版本,这点很重要。如果机器上已经装了 Noetic 或其他 ROS 发行版,再装 Melodic 会造成环境变量和二进制包冲突,处理起来非常痛苦,不如先把旧的清干净。
cat /etc/os-release重点看VERSION_ID是不是 20.04。顺便检查一下网络能不能正常访问packages.ros.org,这一步可以用 curl 测试:
curl -I http://packages.ros.org/ros/ubuntu如果返回 200 OK,说明网络链路没问题。我在实际操作中发现,这一步多花 10 秒钟能避免后面很多莫名其妙的报错。另外,建议先把系统自带的软件源更新一遍:
sudo apt update sudo apt upgrade -y这里有个细节,系统升级后内核可能会更新,如果机器需要重启才能加载新内核,就重启一下再继续。虽然这不是安装 ROS 的必要条件,但干净、稳定的系统环境能减少变量。我遇到过在旧内核状态下编译某些功能包时出现奇怪的链接错误,重启之后就好了。
提示:如果机器之前配置过其他 ROS 源,比如 Noetic 或国内镜像,建议先检查
/etc/apt/sources.list.d/下是否有ros-latest.list之类的文件,确认没有重复源配置,否则 apt 更新时会出现源冲突警告。
2.2 修改 apt 源指向 bionic
这是整个安装流程的核心操作,也是很多人搞错的地方。ROS 官方安装教程里的命令是:
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'在 20.04 上直接跑这条命令,$(lsb_release -sc)会替换成focal,最终写入的软件源就变成了 Noetic 的源。我们要的是 Melodic,必须手动指定bionic:
echo "deb http://packages.ros.org/ros/ubuntu bionic main" | sudo tee /etc/apt/sources.list.d/ros-latest.list注意一个关键点:这里只是把 ROS 软件源指向 bionic,系统本身的 Ubuntu 软件源保持 focal 不动。也就是说,绝大多数系统库还是从 20.04 官方源安装,只有 ROS 相关包从 bionic 仓库拉取。这种混合源方案能让 apt 同时满足两边的依赖,比把整个系统源改成 bionic 要安全得多。千万不要把/etc/apt/sources.list里的系统源也改成 bionic,那会导致系统库大规模降级,甚至让桌面环境崩溃,属于自杀式操作。
2.3 安装基础依赖工具
在添加 ROS 源之前,先把后续会用到的工具装上。Ubuntu 20.04 最小安装可能缺curl、gnupg2这些基础包,apt 添加密钥时也会用到:
sudo apt update sudo apt install -y curl gnupg2 lsb-release有些教程会让你装python3-apt、python3-pip之类的包,暂时不用着急,后面处理 rosdep 时再装。另外,20.04 默认没有python命令(指向 Python 2),这个后面处理 Python 依赖时再解决,现在不用管。
3. 核心安装步骤与 python 依赖处理
3.1 添加 ROS 软件源与密钥
软件源配置好了,下一步是添加 ROS 官方仓库的 GPG 密钥,让 apt 信任这个源。ROS 官方文档给出的传统做法是:
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654这条命令会从 Ubuntu 密钥服务器拉取 ROS 的 GPG 公钥。有些网络环境下连接 keyserver 会比较慢,可以多试几次。如果实在连不上,也可以直接从 ROS 官方 GitHub 仓库下载公钥文件再导入:
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -下载如果超时,多试几次,或者手动下载ros.asc文件到本地后执行sudo apt-key add ros.asc。密钥添加成功后,执行sudo apt update,这时候 apt 会去读取 bionic 仓库的包索引。正常情况下你会看到大量ros-melodic-*的包出现在可安装列表里。如果这里报错或者列表里看不到 melodic 包,大概率是软件源地址写错了,回头检查一下 ros-latest.list 的内容。
有一个细节值得注意:apt-key这种方式在新版 apt 中被标记为弃用,但 Ubuntu 20.04 仍然支持。ROS 官方源目前还是用这个机制,没有强制切换到新的 signed-by 方式,所以按上面的命令操作即可,不用额外折腾。
3.2 选择安装版本:为什么我推荐 desktop 而不是 desktop-full
ROS 官方提供三种安装粒度,区别如下:
| 包名 | 包含内容 | 适用场景 |
|---|---|---|
| ros-melodic-ros-base | ROS 核心 + 通信基础 | 只跑 roscore 和命令行工具 |
| ros-melodic-desktop | 核心 + rqt、rviz、tf、常用消息 | 大多数开发场景,够用 |
| ros-melodic-desktop-full | desktop + gazebo、仿真相关 | 需要完整仿真环境 |
很多教程上来就让装 desktop-full,这也是一般 Ubuntu 18.04 上的标准做法。但在 20.04 上,我强烈建议只装 desktop,不要装 desktop-full。原因在于 desktop-full 包含 gazebo 仿真套件,而 gazebo 在 20.04 上的版本与 bionic 仓库里的ros-melodic-gazebo-*存在依赖冲突。我在第一次尝试时执行了:
sudo apt install ros-melodic-desktop-full结果 apt 报了一串依赖错误,核心是ros-melodic-gazebo-ros依赖的某些库在 focal 中版本对不上。当时我尝试强制安装,差点把系统的 gazebo 环境搞坏。如果你确实需要 gazebo,更稳妥的做法是装完 desktop 后单独安装自己需要的仿真功能包,遇到依赖冲突时单独处理,而不是一次性把所有包都拉进来。
所以我最终的安装命令是:
sudo apt install ros-melodic-desktop这条命令安装的包包括 roscore、rviz、rqt、tf、常见传感器消息等,个人实际使用下来,对大部分 ROS 开发场景已经完全够用。安装过程会拉取几百个依赖包,耗时取决于网络状况。装完后确认一下关键包是否就位:
dpkg -l | grep ros-melodic | head -20提示:如果 apt 在安装过程中提示某些依赖无法满足,不要加
--fix-broken或者强制安装选项硬上。正确的做法是先记下报错信息中的包名,用apt-cache policy <包名>查看可用版本,再根据具体冲突原因决定是跳过这个包还是手动处理依赖。
3.3 处理 python 2/3 依赖问题
Melodic 时代的很多 ROS 工具链是基于 Python 2 编写的,比如rosdep、rosinstall_generator、wstool这些。在 Ubuntu 18.04 上,这些工具对应的是python-rosdep、python-rosinstall这类包名。但在 20.04 上,apt 源里已经没有 Python 2 版本的这些包了,直接执行:
sudo apt install python-rosdep会提示找不到软件包。这也是 Ubuntu 20.04 装 Melodic 时最典型的坑之一。
正确的做法是安装 Python 3 版本的对应工具。ROS 官方源里其实提供了 Python 3 版本的 rosdep 等工具包:
sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool python3-catkin-tools这些包会从刚才添加的 bionic 源里安装。装完之后,rosdep命令就可以用了,只是它是以 Python 3 解释器运行的。这时候如果系统里还有残留的python命令指向 Python 2,可能会导致某些老脚本执行时报语法错误。
我实测的情况是:rosdep 初始化、更新、按依赖安装这些核心功能在 Python 3 下都能正常工作,不需要再折腾 Python 2。但如果你编译某个功能包时,它的CMakeLists.txt或 setup.py 里写死了#!/usr/bin/env python,会调用系统的 Python 2,而这个在 20.04 上是不存在的。遇到这种情况,可以临时安装python2包并手动建立软链接:
sudo apt install python2 sudo ln -s /usr/bin/python2 /usr/bin/python不过这只是权宜之计。从个人经验看,Melodic 核心功能对 Python 2 的依赖并没有想象中那么强,大部分问题在安装 Python 3 工具链后都消失了,真到某些老包必须用 Python 2 时再补也不迟。
4. rosdep 初始化与工作空间验证
4.1 rosdep 初始化、更新及常见网络问题
rosdep 是 ROS 的依赖管理工具,作用是根据功能包的 package.xml 自动安装系统依赖。安装完 Melodic 后,首先要做的是初始化和更新:
sudo rosdep init这一步会创建/etc/ros/rosdep/sources.list.d/目录,并写入默认的源列表。正常情况下应该看到如下输出:
writing /etc/ros/rosdep/sources.list.d/20-default.list done然后执行更新:
rosdep update这一步会把 rosdistro 仓库的数据拉取到本地。问题往往出在这里:rosdep 默认从 GitHub 的raw.githubusercontent.com拉取数据,在国内网络环境下经常超时,报错信息类似于:
ERROR: unable to process source [file:///home/xxx/.ros/rosdep/sources.cache] ERROR: error loading sources list: <urlopen error [Errno 110] Connection timed out>我前后试了四五次都没成功,后来换了两个思路。第一个思路是把源列表里的 URL 指向国内镜像。编辑/etc/ros/rosdep/sources.list.d/20-default.list,把里面的https://raw.githubusercontent.com/ros/rosdistro/master/...替换成可访问的镜像地址,或者干脆用本地文件。第二个思路是手动git clonerosdistro 仓库到本地,然后修改 20-default.list 指向本地路径,这样完全不依赖外网。
具体操作是:先克隆仓库:
git clone https://github.com/ros/rosdistro.git ~/rosdistro然后把 20-default.list 里的 URL 改成类似:
file:///home/你的用户名/rosdistro/rosdep/sources.list.d/20-default.list以及把yaml file:///home/你的用户名/rosdistro/rosdep/osx-homebrew.yaml osx之类的条目改成对应的本地路径。修改后重新执行sudo rosdep update就能跑通。这个方法虽然有点绕,但适合网络不稳定的场景。
需要提醒的是, rosdep update 在大多数情况下是必需的,因为后续编译功能包时要靠它解析依赖关系。如果只是运行系统自带的核心功能,不做第三方包的编译,这个环节暂时卡住也不影响 roscore 的启动,但建议还是尽早解决。
4.2 环境变量配置与第一个工作空间
rosdep 处理好之后,配置环境变量。Melodic 安装完成后,环境变量脚本在/opt/ros/melodic/setup.bash,把它写入 shell 配置,这样每次打开终端都能自动加载:
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc source ~/.bashrc这时候验证一下版本:
rosversion -d正常输出melodic。再试一下roscore,开一个终端执行:
roscore看到started core service [/rosout]之类的日志就说明核心启动成功。这里有个常见小坑:如果你刚才配置环境变量之前已经开了多个终端,那些终端不会自动加载新配置,要么source ~/.bashrc,要么重开终端。
接下来创建第一个工作空间,用来验证 catkin 编译系统是否正常:
mkdir -p ~/catkin_ws/src cd ~/catkin_ws catkin_makecatkin_make会生成build和devel目录,如果一切顺利,最后会看到类似[build] [devel]完成的提示。这个工作空间以后就是你的主要开发目录,把功能包放进src后再次执行catkin_make就能编译。
编译完成后,把工作空间的环境变量也加到.bashrc:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc4.3 catkin_make 编译验证
第一次catkin_make通常是最容易出问题的环节。我在 20.04 上遇到的最典型报错是找不到catkin_pkg模块,错误信息类似:
ImportError: "from catkin_pkg.package import parse_package" failed这是因为 catkin_make 依赖的 Python 模块没有装全。解决方法就是提前安装 Python 3 版本的 ros 构建相关依赖:
sudo apt install python3-catkin-pkg python3-rospkg python3-empy这几个包是编译功能包的核心依赖,缺了任何一个都会在编译时报错。装完之后重新执行catkin_make,一般就能顺利通过。
如果是在虚拟机上操作,catkin_make过程中 CPU 占用会比较高,属正常现象。另外,不要在/opt/ros目录下直接建工作空间,那属于系统目录,普通用户没有写权限,而且会和系统安装的 ROS 文件混在一起,清理起来很麻烦,工作空间一律建在用户目录下。
5. 实际使用中的问题排查记录
5.1 启动 roscore、rviz 的常见报错
安装完成后进入日常使用阶段,还是有几个高频问题值得提前了解。第一个是roscore启动后立刻退出,没有任何明显报错。这种情况一般发生在端口被占用,ROS 默认 master 端口是 11311,如果有其他进程占用了这个端口,roscore 起不来。排查方式:
lsof -i :11311或者换个端口试试:
roscore -p 11312看到 master 进程正常起来,说明端口冲突,后续节点的 ROS_MASTER_URI 也要同步改。
第二个高频问题是 rviz 启动时报 OpenGL 错误,尤其是在虚拟机或远程桌面环境下:
Could not initialize OpenGL这通常是图形加速环境缺失导致的。解决办法是安装 Mesa 软件渲染库:
sudo apt install mesa-utils然后在启动 rviz 前加上环境变量让 OpenGL 走软件渲染:
export LIBGL_ALWAYS_SOFTWARE=1 rviz实测这个办法在 VMware 里能稳定跑起来,但帧率会低一些。如果是实机带独立显卡,一般不存在这个问题。
第三个常见问题是启动节点时提示找不到功能包,比如Resource not found或package [xxx] not found。大部分原因是环境变量没加载,确认ROS_PACKAGE_PATH里是否包含你的工作空间和/opt/ros/melodic/share:
echo $ROS_PACKAGE_PATH如果发现缺失,重新source ~/catkin_ws/devel/setup.bash。还有一种情况是功能包没有编译,先catkin_make再试。
5.2 功能包编译时的依赖缺失
实际编译一个功能包时,最常见的问题是find_package阶段报缺失依赖。比如某个功能包依赖tf2_sensor_msgs,但你没装对应的二进制包,CMake 会提示找不到。这时的解决办法是用 rosdep 来自动检查并安装:
cd ~/catkin_ws rosdep install --from-paths src --ignore-src --rosdistro melodic -y这个命令会扫描src目录下所有功能包的依赖,并自动安装缺失的系统库。但注意一点:rosdep 数据源是基于 bionic 的,有些依赖在 focal 软件源里不存在。遇到这种情况,rosdep 会提示APT package not found。我的处理方法是先手动查看包名,然后用apt-cache search找替代包。比如 bionic 源里的某个库在 focal 中被改名或合并了,可能需要手动换成对应的 focal 版本再装。这类问题没有统一解法,只能逐个分析,但好在 20.04 上常见的 ROS 生态包大多都有替代方案。
5.3 卸载与重装注意事项
如果你在 20.04 上折腾了一阵发现不满足需求,想卸载 Melodic 换回 Noetic 或者重装,有些事情需要额外注意。卸载命令是:
sudo apt remove ros-melodic-*但光这样还不够,以下几个残留位置需要手动清理。首先是/etc/ros/rosdep/sources.list.d/下的 rosdep 配置,其次是~/.ros目录下的日志和缓存,还有就是你加在.bashrc里的source /opt/ros/melodic/setup.bash和source ~/catkin_ws/devel/setup.bash这两行,不删掉的话后续安装其他 ROS 版本会互相干扰。
如果你是在一台新机器上尝试,发现装完 rosdep 初始化始终卡住,或者 desktop 安装后频繁出现依赖问题,我的个人建议是:别硬修,直接重装系统或者换官方支持的版本组合。Ubuntu 20.04 装 Melodic 本质上是在兼容性边缘上跳舞,能用但不够优雅。我自己在这个环境里运行了一个多月,核心功能稳定,没出大问题,但每次装第三方功能包时都要额外关注依赖版本,这种隐性成本只有用的时候才体会得到。
这里额外分享一个小技巧:如果你只是需要临时跑一个基于 Melodic 的项目,又不想污染宿主机环境,可以考虑用容器方案,在容器里装 Ubuntu 18.04 和 Melodic,干净隔离,用完即弃,比在宿主机上折腾轻松得多。这个思路在团队协作时尤其好用,把容器配置提交到代码仓库,新成员拉下来直接就能跑,彻底告别环境搭建地狱。
回到标题本身。如果你已经决定在 Ubuntu 20.04 上安装 ROS Melodic,那就是一个“确认风险 + 按步骤操作 + 逐个解决依赖问题”的过程,核心是三点:软件源指向 bionic、Python 依赖用 python3 替代、rosdep 网络问题用镜像或本地方案解决。这三关过了,系统就能正常跑起来。我个人在实际安装中的体会是,整个过程最耗时间的不是安装命令本身,而是排查依赖冲突和理解版本错位的逻辑。把上文的思路理清了,大部分问题都能顺藤摸瓜解决,希望这篇记录能给你省下排查的时间。