最近不少朋友跟我聊起同一个话题:刚把主力机升到 Ubuntu 24.04,兴冲冲准备装 ROS1 Noetic,结果照着网上的教程折腾半天,不是卡在 Python 依赖上,就是 roscore 起不来,最后灰头土脸地回来问“是不是 24.04 根本装不了 Noetic”。其实能装,但前提是你得先搞清楚 24.04 和 Noetic 之间的“代沟”到底在哪,然后选对安装路线。这篇文章我就把这段时间实测过的几种方案、踩过的坑、绕过的弯,一次性整理给你。
1. 为什么 24.04 装 Noetic 这么“别扭”:兼容性问题的根源
很多人一上来就搜“ubuntu 24.04 安装 ros1 noetic”,然后找一篇教程照着敲命令,失败了再换下一篇。这种做法效率极低,因为你没搞明白 Noetic 和 24.04 之间的根本矛盾。先把这层窗户纸捅破,后面所有步骤你都能自己判断对错了。
1.1 官方支持矩阵与 Python 版本断层
ROS1 Noetic 官方支持的操作系统是 Ubuntu 20.04(Focal Fossa),没错,首选就是 20.04。ROS1 的发行版和 Ubuntu 版本是强绑定的,Noetic 对应的就是 20.04,官方二进制源里也只有 focal 的包。到了 Ubuntu 22.04 想装 Noetic,已经是靠第三方维护的 jammy 源硬顶上去的,民间方案居多。到了 24.04,情况就更麻烦了。
最关键的问题出在 Python 上:20.04 自带的是 Python 3.8,而 24.04 自带的是Python 3.12。Noetic 的 rospy、catkin 这些核心工具,从开发到测试都是基于 Python 3.8 的。Python 3.12 里不少第三方库的 API 变了、底层 C 扩展的 ABI 也变了,Noetic 的代码压根没跟上这个节奏。所以你装好系统后,光一个rosdep或者catkin_make就可能因为 Python 版本报一堆莫名其妙的错误。
1.2 系统库版本漂移带来的连锁反应
除了 Python,24.04 里其他系统库的版本也全面升级了,这同样是个大坑:
- OpenCV:24.04 自带 OpenCV 4.10,而 Noetic 官方是搭配 OpenCV 4.2 开发的。
cv_bridge这种依赖图像库的 ROS 包,编译时经常会因为 OpenCV 接口变化直接挂掉。 - Boost:Boost 版本更新后,一些旧接口(比如
boost::bind相关的写法)被标记为弃用甚至移除,编译老包时错误信息能把人看晕。 - CMake:24.04 自带 CMake 3.28,而旧版本的 ROS 包是用老 CMake 写的,新版本对某些写法更严格,策略(Policy)不一致就会报
CMake Error。
也就是说,你面临的不是“装一个 ROS 包”,而是“让一整套 2020 年时候的生态,硬跑在 2024 年的系统底座上”。
1.3 “能装上”和“能用好”是两码事
网上有些教程说“24.04 能装 Noetic,亲测成功”,你得看他成功到什么程度。有的只是把roscore跑起来了,有的甚至没跑起来,只装了个 ros-comm 就说成功。但 Noetic 不是为了跑一个空壳 roscore 用的。你后面要编译自己的工作空间,要跑 rviz、Gazebo,要装各种乱七八糟的第三方依赖包,每个都可能踩到版本兼容的雷。
所以我在这篇文章开头就把话说清楚:如果你的目标是长期做 ROS1 开发,24.04 原生装 Noetic 不是最优解,最优解是后面要讲的容器方案。如果你有特殊原因必须原生装,那也得做好“自己动手修依赖”的心理准备。下面我把主流方案都摊开对比一下,你自己选。
2. 四条安装路线横向对比:选错路等于浪费时间
在 24.04 上跑 Noetic,目前圈子里比较常见的做法有四条路线。我都试过,各有各的适用场景,先把它们摆在一张表里看个大概。
| 方案 | 安装难度 | 稳定性 | 适用场景 | 缺点 |
|---|---|---|---|---|
| Ubuntu 20.04 官方二进制解包 | 中高 | 差 | 硬要在宿主环境用 apt 管理 ROS 包 | 依赖冲突多,解包后缺一堆东西,不推荐 |
| Docker 容器跑 Noetic | 低 | 高 | 绝大多数开发者日常使用 | 对容器概念陌生的人有学习成本 |
| conda/RoboStack 环境 | 中 | 中高 | 偏好 conda 管理环境、不愿用 Docker 的人 | 部分旧包需要自己编译,conda 源偶尔抽风 |
| 源码编译核心包 | 高 | 中 | 想深入理解 ROS 构建、特殊定制需求 | 费时费力,报错全靠自己修 |
2.1 路线A:Ubuntu 20.04 官方源二进制包直接解包
这条思路是:既然 Noetic 官方源只认 focal,那把 20.04 的 .deb 包下载下来,直接dpkg -i解包安装到 24.04 上行不行?理论上可以,但实际操作会碰到一个很尴尬的问题:.deb包声明了一堆依赖(libpython3.8、特定版本的 boost、OpenCV 等等),而 24.04 系统里装的是更新的版本。用dpkg强装,要么强制忽略依赖,要么手动把依赖链上的老库一个个拉下来。就算全部塞进去,也很容易把系统里已有的新版库搞乱。更别提后续你要用apt安装其他软件时,依赖关系可能直接崩掉。
这条路线我只建议一种人尝试:你只是想要一个roscore能跑起来的 Noetic,并且非常清楚自己在做什么,愿意花一整天处理依赖地狱。否则,别碰。
2.2 路线B:Docker 容器跑 Noetic(推荐)
这是我最推荐的方案,也是我现在的主力开发方式。原理很简单:既然 Noetic 官方只支持 20.04,那我们就用 Docker 拉起一个 Ubuntu 20.04 的容器,在容器里面用官方源装 Noetic。这样一来,系统库、Python 版本全部和官方一致,完美绕开 24.04 的所有兼容性问题。宿主机上的 Ubuntu 24.04 只是个“壳”,负责跑 Docker 和显示图形界面。
有人可能担心容器里跑不了 GUI、用不了串口摄像头,其实都有成熟的解决方案,后面实操部分我会详细讲怎么透传。
2.3 路线C:conda/RoboStack 环境隔离方案
RoboStack 是 conda-forge 社区维护的一套 ROS 发行版安装方案。它把 ROS 的二进制包打包成 conda 包,安装在独立的 conda 环境里,不依赖系统 Python 和系统库。你只需要在 Ubuntu 24.04 上装个 Miniforge 或 Mambaforge,然后通过mamba创建环境,把ros-noetic-desktop之类的包拉进来。
这条路线的优势是:环境隔离,不太会污染系统;包管理器是 conda,安装和卸载都很干净。缺点是:conda 里的 ROS 包版本更新节奏和官方源不完全同步,某些小众包可能没有打包,需要你手动源码编译。另外,RoboStack 目前的 Python 适配版本一般是 3.10/3.11,虽然比系统自带的 3.12 安全,但和官方 3.8 仍然有差异,偶尔会遇到小问题。
2.4 路线D:源码编译核心包(最后的顽固派方案)
如果你既不想用 Docker,又不想用 conda,就非得在宿主环境的 24.04 里原生跑 Noetic,那只能走源码编译这条路。把 ROS 的核心包(catkin、genmsg、roscpp、rospy、ros_comm 等)从 GitHub 拉下来,自己编译装到系统里。
这条路能走通,也能满足“原生安装”的执念,但工程量不小,而且后面每装一个 ROS 功能包,都可能要处理一次兼容问题。适合有时间、有精力、想深入理解 ROS 构建系统的人。我把关键步骤放在后面单独一章,方便你按图索骥。
3. Docker 方案实操:十分钟跑起可用的 Noetic 环境
如果你决定先用 Docker 方案,这章可以直接照着抄。我的环境是 Ubuntu 24.04 宿主机 + Docker Engine(也可以换成 Windows 上的 WSL2 + Docker Desktop,原理一样),容器里是 Ubuntu 20.04 + Noetic。
3.1 安装 Docker 与 Dockerfile 编写
Docker 的安装就不展开了,直接给命令。Ubuntu 24.04 上推荐用官方源装:
sudo apt update sudo apt install -y docker.io docker-compose-v2 sudo systemctl enable --now docker sudo usermod -aG docker $USER装完记得重新登录一下用户组,不然每次都要sudo docker。然后新建一个目录,写一个 Dockerfile:
FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive # 国内用户建议换清华或中科大源 RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list \ && apt-get update \ && apt-get install -y lsb-release gnupg curl wget git vim \ && sh -c 'echo "deb http://packages.ros.org/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros1-latest.list' \ && curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add - \ && apt-get update \ && apt-get install -y ros-noetic-desktop-full \ && echo "source /opt/ros/noetic/setup.bash" >> /root/.bashrc构建镜像:
docker build -t ros1_noetic:20.04 .镜像比较大,desktop-full 接近 3GB,第一次构建要有耐心。如果网络条件不好,注意先把 apt 源和 ROS 源都换成国内镜像,不然容易下载失败。
3.2 挂载工作空间与 GUI 透传
镜像构建好以后,真正用起来的关键是挂载宿主机的 ROS 工作空间。这样你在 Ubuntu 24.04 里写的代码,直接同步到容器里编译运行,非常方便。
先创建好宿主机工作空间:
mkdir -p ~/catkin_ws/src然后启动容器,把宿主机工作空间挂载进去:
xhost +local:docker docker run -it --rm \ --name ros1_noetic \ --network=host \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -v ~/catkin_ws:/root/catkin_ws \ ros1_noetic:20.04 \ /bin/bash解释一下关键参数:
--network=host:直接用宿主机网络,方便跑多机 ROS 通信,也省去端口映射的麻烦。-e DISPLAY=$DISPLAY:把显示环境变量传给容器。-v /tmp/.X11-unix:/tmp/.X11-unix:X11 图形透传的“管道”,这样容器里的 rviz、rqt 才能显示窗口。-v ~/catkin_ws:/root/catkin_ws:工作空间共享。
如果你在 WSL2 里用 Docker Desktop,图形显示更简单,WSLg 会自动处理 GUI,DISPLAY 变量一般也不用额外设置。容器起来后,你先验证一下 roscore:
source /opt/ros/noetic/setup.bash roscore看到started core service [/rosout]就说明环境没问题。再开一个终端进容器跑rviz,能弹出来图形界面,就说明 GUI 透传成功。
3.3 设备透传(串口/摄像头)与其他坑
开发机器人离不开串口和摄像头。串口透传的办法是启动容器时加上:
--device=/dev/ttyUSB0如果不知道设备挂在哪个节点,可以先用ls /dev/ttyUSB*或ls /dev/ttyACM*查一下。摄像头的话,USB 摄像头一般也是/dev/video0,同样用--device=/dev/video0透传。如果你有多个设备、懒得一个个加,可以用:
-v /dev:/dev --privileged注意这行命令等于把整个设备的访问权都给了容器,安全性差一点,自己权衡。
这一路上我遇到的坑主要有两个,给你提前打预防针:
第一个是--network=host在 Docker Desktop for Windows 上支持得不好,实测 WSL2 里要改用-p 11311:11311做端口映射,或者使用docker run --network=bridge。第二个是容器是临时的,加了--rm后退出即删,如果你有多次启停的需求,建议用一个持久化的容器名称,并且把工作空间数据都放在挂载目录里,别存在容器内部。不然某天手一抖把容器删了,里面辛辛苦苦编译的东西全没了。
4. 源码编译方案的关键步骤与依赖顺序
如果你已经决定走“源码编译”这条硬核路线,那我默认你是有一定 Linux 和编译基础的。这章我按我成功编译的顺序来写,尽量把关键点提炼出来,避免你走弯路。
4.1 构建依赖清单:比官方文档多装的东西
在 24.04 上编译 Noetic 核心包,你不能只装 ROS 官方文档列的那些依赖。我实际用的依赖安装命令如下:
sudo apt update sudo apt install -y \ build-essential cmake git python3-pip \ python3-empy python3-catkin-pkg python3-rospkg \ libboost-all-dev libeigen3-dev libopencv-dev \ libpcl-dev libyaml-cpp-dev libtinyxml2-dev \ libconsole-bridge-dev liblz4-dev libbz2-dev \ libcurl4-openssl-dev liblog4cxx-dev \ libgtest-dev libgflags-dev libgoogle-glog-dev \ libpoco-dev liburdfdom-dev libassimp-dev \ python3-defusedxml python3-netifaces注意几个点:python3-empy一定不能缺,catkin_pkg和rospkg如果 apt 版本不对,后面rosdep和catkin_make都会报错。另外我额外装了不少图形、点云相关的系统库,是因为 Noetic 很多核心包在编译时会去查找这些库。漏一个,编译到那个包时就给你一个红色CMake Error,再回头补装又得等半天。
4.2 构建顺序与 CMake 参数
我踩过最深的坑是:一开始图省事,把 ROS 核心仓库全部 clone 下来,用catkin_make一次性编译,结果各种依赖报错,根本理不清头绪。后来我换成按顺序、分批次编译,一次只编一组,就顺多了。
建议构建顺序:
- catkin(构建系统本身)
- genmsg / gencpp / genpy(消息生成工具)
- roscpp_core(cpp_common, roscpp_serialization, roscpp_traits, rostime)
- std_msgs(基础消息类型)
- ros_comm(roscpp, rospy, roslaunch, rosmaster 等核心通信组件)
- rosconsole / roslib / roscpp_traits(依赖项,常被前一步自动拉起来)
每个包单独建 build 目录编译安装:
git clone https://github.com/ros/catkin.git cd catkin mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 make -j$(nproc) sudo make install-DPYTHON_EXECUTABLE这个参数很重要,它告诉 CMake 用哪个 Python 解释器。在 24.04 上如果不显式指定,CMake 可能去找系统里其他 Python 版本,然后给你编出一堆链接不上的库。
4.3 Python 3.12 兼容层处理
源码编译中最折磨人的其实不是 C++ 编译,而是 Python 脚本在 3.12 下跑不了。我在编译时遇到的几个典型报错和处理方式:
ModuleNotFoundError: No module named 'defusedxml'解决:
pip3 install --user defusedxml还有:
ImportError: No module named 'empy'Noetic 需要的是 empy 3.x 版本,直接:
pip3 install --user empy==3.3.4注意千万别装 empy 4.x,那家伙 API 变了,catkin 会直接罢工。另外catkin_pkg和rospkg如果 apt 版本太老,建议用 pip 重装到用户目录:
pip3 install --user --upgrade catkin_pkg rospkg还有一个 24.04 特有的问题:默认没有python这个命令(只有python3),而 ROS 很多脚本里写的#!/usr/bin/env python。处理办法是装个兼容包:
sudo apt install -y python-is-python3这个包会建立软链接,让python指向python3,能省掉很多脚本的麻烦。
4.4 常见编译错误的判断思路
源码编译最怕的是“硬编不过去”,报错信息一长串,看着就头大。我的经验是分三步定位:
第一步,看报错类型。fatal error: xxx.h: No such file or directory是缺头文件,去装对应的 dev 库;undefined reference to xxx是链接库缺失,检查CMakeLists.txt里的target_link_libraries;No module named xxx是 Python 模块缺失,用 pip 补。
第二步,查具体包名。报错里通常会提到某个 ROS 包,比如Could not find a package configuration file provided by "roscpp",基本说明roscpp还没安装或者 CMake 找不到它的路径。源码编译时,安装完一个包后要把它的share路径加进CMAKE_PREFIX_PATH:
export CMAKE_PREFIX_PATH=/usr/local:$CMAKE_PREFIX_PATH第三步,搜索引擎定位。把报错原文粘贴到搜索引擎,基本能找到前人的解决方案。但注意,关键词一定要带着noetic和24.04或者Python 3.12,这样过滤掉大部分无关结果。
5. 安装完成后的环境配置与工作空间创建
不管你是用 Docker 方案还是源码编译方案,装好之后总要面对“怎么创建第一个工作空间”“怎么管理环境变量”这些日常操作。这章我讲一些跟 24.04 场景强相关的配置经验。
5.1 创建 catkin 工作空间并验证
没装 ROS 之前,你可能已经在 24.04 上建过各种目录,但 catkin 工作空间建议单独建。因为编译产生的 build 和 devel 目录很大,如果跟你自己的项目混在一起,后面清理起来很麻烦。
mkdir -p ~/catkin_ws/src cd ~/catkin_ws catkin_make第一次catkin_make会生成build和devel目录,同时在devel/下生成setup.bash。验证一下:
source devel/setup.bash echo $ROS_PACKAGE_PATH如果你能看到类似/home/你的用户名/catkin_ws/src:/opt/ros/noetic/share这样的路径,说明环境已经认到你的工作空间了。这时候你在src下新建一个功能包试试:
cd ~/catkin_ws/src catkin_create_pkg test_pkg roscpp rospy std_msgs cd ~/catkin_ws catkin_make能编过就说明整套环境跑通了。
5.2 环境变量与 .bashrc 管理
环境变量这东西,最怕的是重复 source。比如你把/opt/ros/noetic/setup.bash写在.bashrc里,又把工作空间的devel/setup.bash也写在.bashrc里,然后每次打开终端都重复 source 一遍,短期内没事,但时间长了 ROS 包路径会越来越乱,甚至出现“明明装了包却找不到”的情况。
我的做法是,在.bashrc里只写一次,并且做两个判断:
if [ -f /opt/ros/noetic/setup.bash ]; then source /opt/ros/noetic/setup.bash fi if [ -f "$HOME/catkin_ws/devel/setup.bash" ]; then source "$HOME/catkin_ws/devel/setup.bash" fiDocker 用户注意,容器里的.bashrc和宿主机是隔离的,建议在 Dockerfile 里只写source /opt/ros/noetic/setup.bash,工作空间环境等容器起进来以后手动 source,避免每次进容器都要面对重复路径。
5.3 与 ROS2 共存的切换方案
很多人的需求是在同一台 24.04 上同时用 ROS1 和 ROS2,毕竟 ROS2 的新包也越来越多。ROS1 和 ROS2 确实能共存,关键就是环境变量切换。ROS1 用的是/opt/ros/noetic,ROS2(比如 Humble 或 Jazzy)用的是/opt/ros/humble或/opt/ros/jazzy。两个版本的setup.bash都写到.bashrc里,后 source 的会覆盖前面的环境变量,导致命令紊乱。
我现在的做法是,在.bashrc里用一个函数来切换:
function set_ros1() { source /opt/ros/noetic/setup.bash export ROS_MASTER_URI=http://localhost:11311 } function set_ros2() { source /opt/ros/humble/setup.bash }然后每次打开终端手动敲一下要用的版本。如果你嫌麻烦,可以直接开两个终端,一个专门跑 ROS1,一个专门跑 ROS2,谁也不影响谁。ROS1 和 ROS2 通信要用ros1_bridge,先把两套环境都 source 好,再单独编译运行 bridge,这个属于进阶操作了,你先把底层环境分开,后面再研究不迟。
5.4 国内镜像源和包管理加速
24.04 用户装软件,第一件事建议换国内 apt 源,不然下载速度感人。ROS 的 apt 源也一样,官方源packages.ros.org在国内连接很不稳定。Docker 方案里,我推荐把 ROS 源换成清华或中科大:
sudo sh -c 'echo "deb https://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros1-latest.list'源码编译的国内用户,记得在 clone 时用--depth=1减少下载量,或者干脆用 gitee 上的镜像仓库,能快不少。
6. 高频连环坑:WSL、显卡、字体和版本污染
最后一章,我把在 24.04 上装 Noetic 时最容易碰到的那些“非 ROS 本身的坑”集中说一下。这些坑单独拎出来都不大,但凑一起能把人折磨疯。
6.1 WSL 场景下的特殊问题
在 WSL2 里装 Noetic(比如配合 Docker),跟我上面介绍的宿主机方案有些差异。WSL2 的网络模型和宿主机不同,--network=host在 Docker Desktop 里经常不生效。我之前踩过:在 WSL2 里启动容器后,宿主机访问不到容器里的 roscore,折腾半天发现是网络模式的问题。解决办法是:
- 用桥接模式 + 端口映射,比如
docker run -p 11311:11311; - 或者在 WSL2 里关闭 Docker Desktop 的“基于 WSL2 的引擎”里某些网络优化选项,但这属于 Docker Desktop 的配置细节,不同版本界面不一样,不展开。
另外 WSL2 里挂载 USB 设备默认是不行的,需要 usbipd 之类的工具或者用serial-over-USB方案。如果你主要是进行纯算法开发,影响不大;但如果你要接实车调试,建议还是老老实实用双系统,别在 WSL2 里折腾设备透传了。
6.2 rviz OpenGL 和显卡驱动问题
24.04 比较新的系统上,跑 rviz 或者 Gazebo 时经常会弹libGL error: failed to load driver: swrast。这个问题本质上是 OpenGL 库和显卡驱动的匹配问题。在虚拟机上尤其常见,因为虚拟显卡提供的 GL 支持有限。
简单的处理办法是用软件渲染:
export LIBGL_ALWAYS_SOFTWARE=1然后再启动 rviz。性能上会差一点,但至少窗口能弹出来,做简单的可视化没问题。如果你用的是 NVIDIA 独显,建议装好官方驱动后再跑一下glxinfo | grep "OpenGL renderer"确认渲染器是不是 NVIDIA 的,确认之前别骂 ROS 不好用。
6.3 千万别乱动系统 Python
24.04 系统的很多工具依赖 Python 3.12,比如apt、gnome-shell等。有些人为了满足 Noetic 的 Python 依赖,直接去改系统默认 python 版本,或者 pip install 一些会覆盖系统包的库。这是我在新手教程里最担心出现的操作,一旦搞坏,轻则桌面进不去,重则系统起不来。
正确做法是:给 ROS 用的 Python 依赖,一律用pip3 install --user装在用户目录,或者用虚拟环境(venv)和 conda 环境隔离。千万不要sudo pip3 install xxx,也千万不要去改/usr/bin/python3的软链接。系统 Python 一旦动过,你现在可能没事,下次系统更新时就是灾难。
6.4 字体和终端体验
这不是 ROS 的必须项,但很多人习惯把开发环境弄得舒服一点。24.04 默认终端里跑 ROS 的roslaunch日志,彩色输出和字体渲染效果确实一般。我自己一直用的是 macOS 风格的等宽字体,在 WSL 和 Ubuntu 桌面下都能保持接近 Mac 的体验。具体做法很简单:下载一个喜欢的等宽字体(比如 JetBrains Mono 或 SF Mono 的开源替代版)放进~/.local/share/fonts/,然后在终端偏好设置里选一下就行。
这里多啰嗦一句,开发 ROS 项目时终端字号别调太小,因为roslaunch的输出信息量很大,字号太小看久了眼睛特别累,尤其是跑多机通信、看日志定位问题时,容易漏看关键错误信息。
最后再说几句实在话。我在 24.04 上最终的组合是:宿主机环境里用 Docker 跑 Noetic 做日常开发,另外留了一个源码编译的“实验室环境”用来研究 ROS 底层构建逻辑。如果你的目标是“赶紧把项目跑起来”,直接克隆我给出的 Docker 方案,不要犹豫;如果你是非要在 24.04 上原生装 Noetic 不可,也请把源码编译那章的依赖和坑都过一遍再动手。还有一个建议:如果你手头正好有 Ubuntu 20.04 或 22.04 的装机盘,只是想安安稳稳做 ROS1 开发,那真的不用跟自己过不去,装个老版本系统,Noetic 官方源直接一把梭,省下来的时间拿去买杯咖啡不香吗?