我们做机器人开发的人,对ROS1的感情是很复杂的。一方面它确实有各种老态龙钟的毛病,另一方面,你打开任何一个开源机器人项目,从SLAM建图到机械臂运动规划,底层跑的还是它。就算ROS2已经出了好几年,ROS1的生态存量太大了,尤其是科研教学和工业落地场景,Noetic版本的使用率依然高得吓人。这篇文章不聊虚的,直接把我装ROS1、配环境、建工作空间、和ROS2共存这几件事的完整流程和踩坑记录写出来,给正在折腾环境的朋友们一个能直接照着操作的参考。
我默认你是想在自己的电脑上搭一个能跑仿真、能接真机、能编译源码的环境,而不是只想装个demo看一眼。所以我花了不少篇幅讲清楚为什么要这么装、每一步在做什么,以及出了问题怎么排查。内容会有点长,但每一条都是实测过的,照着做基本不会翻车。
1. 装ROS1前必须想清楚的三件事
1.1 版本与系统的对应关系,选错就是灾难
ROS1的正式版本发布是跟Ubuntu系统强绑定的。这不是软件商店里那种“支持全平台”的软件,而是一套依赖系统底层库的框架。目前市面上你还能装到的ROS1版本主要就两个:
| 版本代号 | 对应Ubuntu系统 | 支持状态 |
|---|---|---|
| Melodic | Ubuntu 18.04 | 已停止维护 |
| Noetic | Ubuntu 20.04 | 最后版本,官方支持至2025年 |
所以如果你问我推荐用什么系统装ROS1,我只有一句:老老实实用Ubuntu 20.04,装Noetic。第18.04已经停止维护了,软件源里的很多包都开始报错,折腾起来纯粹浪费时间。而最新的Ubuntu 22.04和24.04根本没有官方ROS1版本,你非要装的话只能走Docker或者源码编译的路子,复杂度直接上一个台阶,完全不建议新手碰。
很多人会问,那我的电脑是Windows/Mac怎么办?两个方案:
- 装虚拟机,用VirtualBox或者VMware装Ubuntu 20.04
- 用WSL2,也就是Windows Subsystem for Linux 2
我自己的主力开发环境就是WSL2,因为内存占用比虚拟机小,启动快,和Windows文件系统互通也方便。不过需要注意,WSL2不支持USB直连,你要是想接雷达、电机驱动板这类USB设备,还是得用真Ubuntu系统或虚拟机,这个坑后面细说。
1.2 ROS1和ROS2能共存吗,能,但别天真
搜索词里高频出现“ROS1和ROS2可以共存吗”这个问题,我直接给结论:可以共存,在同一个Ubuntu系统上同时安装不会冲突,因为它们默认安装路径不同,环境加载也独立。
但这不代表你可以同时运行两个版本的程序。主机侧的ROS1节点和ROS2节点之间默认是互相发现不了的,因为通信中间件完全不一样。如果想让两者互通,在当前生态里基本就三条路:
- 装ros1_bridge这个官方桥接包,在中间做一个转发
- 用Docker分别跑两个版本的独立环境
- 在主机上通过source不同setup.bash来切换当前终端环境
我自己的习惯是主机装ROS1,ROS2丢到Docker里隔离跑,这样互不干扰。如果你需要跑一些ROS2独有功能的项目,再单独开容器。这样最干净,也最不容易把环境搞乱。
1.3 新手和老手的安装策略差异
如果你是第一次接触ROS1,我强烈建议你先把整条链路跑通,也就是“装好→启动roscore→写一个最简单的发布订阅节点→跑通”,再去研究深层的原理。别一上来就搞复杂的图形化界面工具、Gazebo仿真、MoveIt这些。
原因很简单,ROS的学习曲线比较陡峭,但好在它是一个非常成熟的框架,只要把最基本的概念理解了,后面的进阶内容都是叠加式的增量学习。安装部分只要你按步骤走,通常一次就能成功。
2. Ubuntu 20.04安装ROS1 Noetic完整实操
2.1 准备软件源和系统依赖
安装ROS1前,先把系统更新到最新状态,避免因为系统包版本过旧导致后续编译出错。命令就三板斧:
sudo apt update sudo apt upgrade -y然后安装一些基础工具,比如curl和git,后面会用得到:
sudo apt install -y curl git vim这一步有个小细节:如果你的网络环境访问Ubuntu官方源比较慢,可以提前换国内镜像源。具体改法在/etc/apt/sources.list里把archive.ubuntu.com替换为mirrors.aliyun.com或者mirrors.tuna.tsinghua.edu.cn。改完记得再跑一次sudo apt update让索引生效。
我实测下来,国内源对ROS安装的成功率和速度影响非常大。ROS的软件包很多,一个完整的桌面版安装下来要下载好几个GB,如果网速上不来,装到一半中断的情况非常常见。
2.2 添加ROS软件源和密钥
ROS1 Noetic的二进制包托管在packages.ros.org,需要先把源地址写进系统的软件源列表。这里建议直接用国内镜像,速度会快很多,我以清华源为例:
sudo sh -c 'echo "deb https://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros1-latest.list'接下来添加ROS官方的公钥,用来验证软件包签名:
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654如果这一步报keyserver连不上的错,可以用美国主机密钥服务器再试一次:
sudo apt-key adv --keyserver 'hkp://pgp.mit.edu:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654密钥加成功后会显示OK,然后刷新一下软件源:
sudo apt update刷新的时候如果你发现源里已经能看到ros-noetic相关的包名,那就说明这一步成功了。可以用apt-cache search ros-noetic | wc -l看一眼数量,正常应该能搜索到上千个包。
2.3 安装方式选择:Desktop-Full版最省心
ROS1安装方式分好几种,我直接给你一个选择策略:
| 安装方式 | 包含内容 | 适用场景 |
|---|---|---|
| ros-noetic-ros-base | 仅核心通信库 | 嵌入式设备/极简环境 |
| ros-noetic-desktop | 核心+可视化工具 | 日常开发够用 |
| ros-noetic-desktop-full | 全部+仿真器+导航等 | 强烈推荐新手和常规项目 |
我在实际开发中从来都是直接装desktop-full版本。它除了包括ROS本身,还带上了Gazebo仿真器、RViz可视化、MoveIt运动规划库、导航栈等一整套东西。单独一个功能包就要配半天依赖,装完整版本能省掉大量时间:
sudo apt install -y ros-noetic-desktop-full这个安装过程会比较长,耐心等。在安装过程中系统会自动配置依赖,个别包可能会有冲突,通常按照提示apt --fix-broken install就能解决。
装完以后最核心的验证动作是初始化rosdep:
sudo rosdep init rosdep updaterosdep的作用是解决源码编译时的依赖关系,这个后面建工作空间编译功能包的时候会用到。国内网络跑rosdep init偶尔会卡住,如果报错提示连不上raw.githubusercontent.com,可以考虑给rosdep配置代理,或者在/etc/hosts里手动解析一下对应域名的IP。这一步是源码编译绕不开的环节,建议提前搞定。
2.4 配置环境变量
ROS1每次使用前都需要加载环境变量。它用的是什么?就是source命令。把配置写进~/.bashrc以后,每次打开终端都会自动加载,不用手动执行:
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc source ~/.bashrc注意一点:/opt/ros/noetic/setup.bash这个文件是安装核心包的时候自动生成的,如果你只装了ros-base,这个文件也存在,不需要担心。
验证是否安装成功可以执行:
roscore如果看到类似于started core service [/rosout]的输出,就说明ROS1已经能正常运行了。Ctrl+C停掉它,我们继续。
3. 用WSL2搭建ROS1开发环境的完整方案
3.1 WSL2的优势和踩坑点
我看到“wsl下载ros1”这个热搜词出现频率很高,确实现在Windows用户最方便的办法就是WSL2。让我先用一段话讲清楚WSL2到底是个啥:它本质上是一个轻量虚拟机,微软官方直接集成在Win10/11系统里。你不需要装VirtualBox,也不用装VMware,一条命令就能启用,启动速度比传统虚拟机快一个量级。
WSL2装ROS1的流程跟原生Ubuntu几乎一样,因为WSL2跑的就是一个完整的Ubuntu内核。但也有几个坑:
- USB设备不支持:WSL2默认不支持USB直通。你要接STM32、雷达、IMU、舵机控制板这样的设备,需要配合usbipd-win这个第三方工具实现USB转发,或者干脆回归虚拟机。
- 图形界面显示:WSL2没有原生显示服务器,跑RViz需要配X Server。Windows端装VcXsrv或者WSLg,搭配好DISPLAY环境变量才能弹出窗口。
- 性能损耗:WSL2的IO性能在某些场景下比原生Linux低,尤其是ROS编译大量源码的时候,IO会成为瓶颈。
如果你只是做纯软件的仿真,比如跑TurtleBot3、Gazebo仿真环境,WSL2完全够用。但一旦要接真实硬件,我建议还是老老实实装一个原生的Ubuntu系统(双系统也好,虚拟机也好)。
3.2 WSL2安装ROS1实操指南
先在Windows PowerShell(管理员)里启用WSL功能:
wsl --install默认会安装最新的Ubuntu LTS版本,但目前WSL商店里默认的Ubuntu版本可能是22.04或24.04,这就有个问题:它们没有官方ROS1包。你需要手动安装Ubuntu 20.04版本:
wsl --install Ubuntu-20.04或者更稳妥的办法,先查看可用发行版列表:
wsl --list --online然后指定安装:
wsl --install -d Ubuntu-20.04装完之后第一次启动会让你设置用户名和密码,这时候就进入了一个完整的Ubuntu 20.04环境。后面的ROS1安装步骤,跟虚拟机和真机完全一样,按照第2部分的命令直接操作就行。
3.3 WSL2显示RViz窗口的配置
很多人卡在WSL2下RViz窗口弹不出这个问题上,其实原理很简单。WSL2跑的是Linux环境,但Windows和Linux之间的GUI显示协议需要打通。Windows 11的用户直接用WSLg就好,Window 10用户需要装一个VcXsrv。
Windows 10下的具体配置流程:
- 从sourceforge下载VcXsrv并安装
- 启动XLaunch,Display number填写0,勾选Disable access control
- 在WSL2的
~/.bashrc里加上:
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0 export LIBGL_ALWAYS_INDIRECT=1然后执行:
source ~/.bashrc再运行rviz,基本就能弹出窗口了。如果你用的是Windows 11,系统内置了WSLg,直接忽略上面这些,RViz窗口会自动弹出。
4. 创建ROS1工作空间从零开始
4.1 工作空间结构核心概念
创建ROS1工作空间是走进ROS开发的第一步,不管你是写节点还是引用第三方包,都得在一个工作空间里进行。ROS1的空间结构其实就三层:
src/:源代码目录,源代码和功能包都放在这里build/:编译中间文件目录,由编译器自动生成,不需要手动管devel/:编译产物和环境变量目录,生成的脚本和可执行文件在这里
我把这个结构讲清楚,是因为很多新手不理解为什么每次都要source devel/setup.bash。那是因为ROS1通过这个文件把工作空间里的包路径注入到系统环境中,这样rosrun和roslaunch才能找到你编译出来的可执行文件。
4.2 一步步创建你的第一个工作空间
打开终端,创建一个叫catkin_ws的工作空间:
mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src注意,catkin_ws这个名字不是强制要求的,你可以随意命名,但尽量用简单英文,别用中文或者带空格。我见过太多因为目录名字特殊导致编译失败的案例。
然后初始化工作空间:
cd ~/catkin_ws catkin_make执行完以后,你的catkin_ws下会多出build和devel两个目录。接下来加载环境变量:
source devel/setup.bash为了以后一打开终端就自动加载,把它写进~/.bashrc:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc注意一个细节:如果系统里同时存在ROS1和ROS2的环境变量,顺序很重要。必须确保ROS1的setup.bash在最外层,ROS2的也会自动加载,这两者之间如果你操作不当,会导致rosrun命令都找不到了。
4.3 创建功能包并写一个最小可运行节点
工作空间本身是空的,它不能跑任何东西。你需要先创建功能包(package),功能包是ROS1代码组织的基本单位。
cd ~/catkin_ws/src catkin_create_pkg hello_ros roscpp rospy std_msgs这条命令创建了一个名为hello_ros的功能包,并声明依赖roscpp和rospy——这是ROS1的C++和Python客户端库,以及std_msgs标准消息包。
进入功能包目录,创建一个最简单的发布者节点talker.py:
#!/usr/bin/env python3 import rospy from std_msgs.msg import String def talker(): rospy.init_node('talker', anonymous=True) pub = rospy.Publisher('chatter', String, queue_size=10) rate = rospy.Rate(1) while not rospy.is_shutdown(): hello_str = "hello world %s" % rospy.get_time() rospy.loginfo(hello_str) pub.publish(hello_str) rate.sleep() if __name__ == '__main__': try: talker() except rospy.ROSInterruptException: pass然后修改CMakeLists.txt,找到这几行取消注释:
catkin_install_python(PROGRAMS scripts/talker.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )回到工作空间根目录编译:
cd ~/catkin_ws catkin_make source devel/setup.bash开三个终端分别执行:
roscorerosrun hello_ros talker.pyrostopic echo /chatter如果能看到不断刷新的hello world消息,恭喜你,你的ROS1开发闭环已经完全跑通了。
4.4 用catkin tools替代catkin_make
catkin_make是ROS1最传统的编译工具,简单直接,但在大型项目中会有两个问题:一是多包增量编译比较慢,二是编译过程不好控制。所以我推荐你装一下catkin_tools:
sudo apt install -y python3-catkin-tools用法几乎一样:
cd ~/catkin_ws catkin build它的优势在于彩色输出、增量编译、支持并发编译。而且catkin build编译后同样生成devel/setup.bash,环境变量加载方式不变。后面如果你要管理大型工作空间,建议直接用这个。
5. Ubuntu 22.04和24.04上跑ROS1的替代方案
5.1 为什么不建议在20.04以上系统硬装ROS1
搜索词“ubuntu22.04安装ros1”热度很高,说明很多人的电脑出厂就是22.04,不太想为了ROS1重装系统。我理解这种心情,但必须说清楚:官方不支持就是官方不支持。ROS1的Noetic是20.04专属,没有提供22.04的二进制包。你要么别在意,要么就换系统。
在22.04上硬装ROS1的方法网上确实有人分享过,本质上是把Noetic的软件源强制指过去,通过apt暴力安装。但Nosetic的依赖比如Python2相关的库,在22.04上已经不再提供包了,强行装会破坏系统依赖。这条路我试过,编译经常碰到莫名其妙的头文件缺失问题,最后你会发现省下来的时间全花在调依赖上了。
5.2 Docker方案最优雅
如果你不想换系统,又想用ROS1,Docker是我目前用过最舒服的方案。原理很简单:用容器打包一个完整的Ubuntu 20.04环境,在里面装ROS1,宿主系统完全不受影响。
先装Docker Engine,然后拉取镜像:
docker pull ros:noetic-desktop-full启动一个容器并映射显示:
docker run -it --name ros1_noetic \ --env="DISPLAY=$DISPLAY" \ --env="QT_X11_NO_MITSHM=1" \ --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ ros:noetic-desktop-full进入容器后,所有的ROS1命令都能直接用了:
source /opt/ros/noetic/setup.bash roscoreDocker容器的问题在于:文件持久化需要挂载数据卷,GPU加速配置复杂,而且如果打算长期开发,每次启动容器都要重新source环境变量,会有点烦。但对临时评估和验证项目来说,Docker是最干净快捷的路线。
5.3 虚拟机方案适合接硬件的场景
对于需要插USB设备、真实传感器的场景,我还是推荐用VMware Workstation或VirtualBox装一个完整的Ubuntu 20.04虚拟机。虚拟机对USB直通的支持比WSL2要好很多,VirtualBox只需要安装扩展包,就能把Windows的USB设备转发到虚拟机里。
虚拟机的性能损耗比WSL2大,但胜在隔离性好,装坏了不伤主系统。我自己的做法是:日常分析代码在Windows原生环境做,跑编译和仿真就在虚拟机或者WSL2里做,两边文件通过共享目录互通,体验相当流畅。
6. 环境配置、共存与日常使用进阶
6.1 ROS1和ROS2共存时的环境隔离与切换
前面提到过共存是可行的,这里把具体操作讲透。Ubuntu 20.04既能装ROS1 Noetic,也能装ROS2 Foxy(同样基于20.04)。两个环境默认装在不同目录,通过bashrc里的source顺序来决定当前终端默认加载哪一套。
如果你希望大多数时候用ROS1,少数时候切到ROS2,建议这样配置~/.bashrc:
# ROS1 source /opt/ros/noetic/setup.bash # ROS2 (注释掉,需要时手动开) # source /opt/ros/foxy/setup.bash需要切到ROS2的时候,打开一个新终端手动执行:
source /opt/ros/foxy/setup.bash有个容易踩的坑:ROS1和ROS2的环境变量是相互覆盖的,source的顺序决定了最后谁生效。同时加载两个环境会导致rosrun指令失效,因为两个版本的rosrun可执行文件在不同的路径下,系统无法识别你调用的到底是哪个。我的建议是,不要在同一个终端里频繁来回切换,建立两个预设终端模板最省心。
6.2 环境变量常用命令与常见配置技巧
ROS1的环境变量虽然有不少,但日常使用你只要关注几个核心的:
| 命令/变量 | 作用 |
|---|---|
echo $ROS_DISTRO | 查看当前ROS版本 |
echo $ROS_PACKAGE_PATH | 查看功能包搜索路径 |
| `printenv | grep ROS` |
rospack find 包名 | 找到某个包的实际路径 |
关于~/.bashrc里source的配置,我再分享一个我自己觉得很舒服的组合:
source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash这样每次打开终端,工作空间的包也自动加载了。不过如果你catkin_make之后又新建了新的功能包,要重新source一次devel/setup.bash才能识别到,这个习惯要养成。
6.3 网络环境与下载慢的应对
在安装ROS1的过程中,90%的人都会被网络问题卡住。除了换国内镜像源,还有几个小技巧:
rosdep update比较慢时,可以用sudo c_rehash /etc/ssl/certs修复证书问题- GitHub源码下载慢时,可以给git设置代理
wget下载慢时,先把链接拿下来丢到浏览器或者迅雷里下载,再手动解压
记住一个原则:ROS安装包的下载失败、校验失败、依赖解析失败,绝大多数都是网络原因。先检查网络,再检查配置,不要一上来就重装系统。
6.4 一个实用的小习惯:给工作空间写脚本
每次操作前都要source环境变量,时间久了容易觉得繁琐。我习惯在~/catkin_ws里放一个init.sh脚本:
#!/bin/bash source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash export ROS_MASTER_URI=http://localhost:11311 export ROS_HOSTNAME=localhost exec "$@"这样每次打开终端直接:
./init.sh roscore或者直接运行你自己的节点脚本,减少输入和出错概率。这也是干这行时间长了总结出来的经验:凡是重复两次以上的操作,就值得写个脚本。
7. 使用过程中最常见的五个问题与排查方法
7.1 rosdep update卡死或报错
rosdep update报错主要是网络问题。如果提示ERROR: unable to process source,可以试试下面的方法:
在/etc/hosts里手动加上GitHub相关域名的解析(具体IP可以查DNS),然后重新执行sudo rosdep init和rosdep update。如果还是不行,检查是否开启了代理,如果代理没配对,反而更慢。
还有一种情况是安装完desktop-full后,rosdep没装全。可以检查:
sudo apt install -y python3-rosdep rosdep --version正常情况下会输出版本号,如果提示找不到命令,就是没装rosdep。
7.2 命令找不到:rosrun、roslaunch
百分之八十的情况是你的环境变量没有加载。先检查:
echo $ROS_PACKAGE_PATH如果输出为空,就是setup.bash没有生效。执行:
source /opt/ros/noetic/setup.bash再看是否正常。如果这个能解决,那就把source写进~/.bashrc,一步到位。
7.3 编译时找不到头文件或依赖包
报错类似于fatal error: xxx.h: No such file or directory。这基本说明你的功能包依赖没有写全。比如你用到了geometry_msgs,但CMakeLists.txt里忘了加find_package(catkin REQUIRED COMPONENTS geometry_msgs),就会找不到头文件。
解决方法是:在src/下找到对应包,编辑package.xml和CMakeLists.txt,把用到的消息包都加进去,重新编译。
7.4 Python脚本无法运行或打印乱码
如果你用的是Ubuntu 20.04,默认Python3是3.8,和ROS1 Noetic的Python3支持没问题。但如果你的代码里用了print而不是rospy.loginfo,在终端里输出会非常乱。建议规范写法:
rospy.loginfo("this is a log message")同时talker.py第一行要写#!/usr/bin/env python3,否则终端可能默认用Python2执行,直接语法报错。权限也要给到:
chmod +x scripts/talker.py7.5 roscore启动失败:端口被占用
启动roscore时如果报错提示11311端口被占用,用下面的命令查看:
lsof -i :11311找到占用进程的PID,然后kill -9 PID杀死进程,再重新启动roscore。还有一种可能,是多台机器之间的ROS_MASTER_URI设置冲突,单机使用就统一设成localhost即可。
8. 一个完整体验ROS1的最小项目流程
我觉得光讲理论不够,最后分享一个我每次搭好环境后用来做自检的小项目流程。它能一次性检验你的安装、编译、通信、可视化全链路是否正常。
第一步,在catkin_ws/src下创建一个新包,包含发布者和订阅者两个节点。发布者周期发布一个std_msgs/String消息,订阅者接收到消息后打印到终端。
第二步,在工作空间根目录执行catkin_make,编译通过后source devel/setup.bash。
第三步,三个终端分别运行roscore、发布者节点、订阅者节点。如果你能看到发布者的日志和订阅者的接收日志同时滚动,说明通信链路正常。
第四步,运行rqt_graph查看节点和话题的实时关系图。如果能看到deliver节点通过chatter话题连接receiver节点,整个可视化工具箱也确认没问题了。
第五步,运行rosbag record -a录一段数据,再rosbag play回放,验证数据记录和回放功能。
这套流程走完,基本就说明你的ROS1环境和核心工具链都是健康可用的。后面再深入接触具体机器人平台或者仿真环境,都是在这个基础上做加法。
我自己一直在用这套自检流程,不管是新装的机器还是换的新电脑,跑一遍心里就有底了。总比拿着一个教程装完就说“我会ROS1了”强,这东西核心还是得动手跑通一遍,眼睛看会的不算数。
ROS1的学习曲线不算陡,但依赖环境坑多,容易让人在安装阶段就泄气。这篇文章的目的就是替你把这些坑趟平了,后面进入真正的机器人开发时,能少浪费点精力和耐心在环境问题上。