搞机器人开发的朋友,只要开始查资料,基本都绕不开 ROS2 这个名字。不管你是刷到别人用 RViz2 显示点云、看小乌龟演示话题通信,还是招聘软件里写着“熟悉 ROS2 优先”,这个东西已经实实在在成了机器人领域的事实标准。我最早接触这套系统是在 ROS1 时代,后来切到 ROS2,中间踩过的坑、绕过的弯不在少数。这个系列第一篇,目标很明确:帮你把 ROS2 的定位、环境搭建、核心概念和第一个能跑的节点全部捋清楚,按顺序读下来,基本就能对 ROS2 有一个完整又踏实的认识。零基础的朋友可以放心看,已经从 ROS1 过来想转型的,直接跳到安装和概念对比部分也完全没问题。文章里的操作我都在 Ubuntu 22.04 + ROS2 Humble 环境里实测过,命令可以放心复制。
1. 先搞明白:为什么机器人圈都在转向ROS2
1.1 ROS1和ROS2的本质区别
很多新手上来就装 ROS2,其实并不清楚它和 ROS1 到底差在哪。ROS1 最早是斯坦福和 Willow Garage 搞出来的学术项目,设计目标是为科研提供一套好用的机器人开发框架。但它的老架构埋了不少雷:所有节点都要先连到一个叫 roscore 的中心节点,这个节点一旦挂了,整个系统就瘫痪;而且节点之间通信走的是自家协议,跨平台支持也很弱,基本只能在 Linux 上玩。
ROS2 从 2015 年开始设计,目标非常明确:要产品化、要商用、要支撑真正的机器人产品。变化最核心的一点,就是把底层的通信机制换成了 DDS(Data Distribution Service)。DDS 是 OMG 组织制定的分布式通信标准,本身就不依赖中心节点,节点之间可以直接点到点通信,单点故障问题从根上就没了。与此同时,ROS2 正式支持 Windows、macOS、嵌入式平台,后续又加入安全加密、多机通信这些能力,都是为了让它从实验室走进真实产品。
这里有一个绕不开的名词:FastDDS,对应热词里也有“fastdds ros2 封装层”。简单理解,ROS2 只是定义了一套中间件接口(RMW,ROS Middleware Interface),底层可以对接不同的 DDS 实现,FastDDS 是默认的那一个,由 eProsima 公司维护。你可以把 RMW 想象成电脑上的 USB 接口,FastDDS 就是默认插在上面的一个设备,想换也可以换,比如换成 CycloneDDS,只需要设置一个环境变量即可。这个机制带来的好处是:底层通信能力可以按场景选,比如实时性要求高的场景换 CycloneDDS,多机场景用 FastDDS 或者 RTI 的 Connext。
ROS2 还引入了 QoS 策略。这个话题往后深入讲会很复杂,但你可以先用一个比喻来理解:ROS1 的通信就像发微信,发出去就不管了,对方收没收到不知道;ROS2 的 QoS 就像寄快递,你可以选普通快递、保价快递、加急快递,每种服务的可靠性、时效性都不一样,发布者和订阅者之间谈不拢就建立不了通信。比如导航这种对实时性要求高的,就选时效优先的策略;发地图这种大数据的,可以选可靠性优先的策略。刚开始学不用死磕,知道有这么个东西可以先放着。
1.2 发行版怎么选:Humble、Foxy、Jazzy
ROS2 和 Ubuntu 一样,是有发行版概念的。目前最常见的是 Foxy、Humble、Jazzy 三个版本,其中 Foxy 已经过了支持期,新项目不建议再选。Humble 对应 Ubuntu 22.04,Jazzy 对应 Ubuntu 24.04,两者都是长期支持版(LTS),社区维护时间长,是当前入门的稳妥选择。
| 发行版 | 对应Ubuntu | 支持级别 | 适合场景 |
|---|---|---|---|
| Foxy | 20.04 | 已停止维护 | 老项目、历史课程 |
| Humble | 22.04 | LTS长期支持 | 主流教程、多数驱动支持最全 |
| Jazzy | 24.04 | LTS长期支持 | 新硬件、追求新特性 |
选版本最关键的一点,不是看谁最新,而是看你想用的教程和硬件驱动支持哪个版本。很多硬件厂商,比如 Livox 雷达,官方驱动都是先出 Humble 版本,Jazzy 的支持反而滞后。所以我个人建议:如果是自己学习,装 Humble 是最省心的,教程最多、问题搜索到的方案也最多;如果你机器上已经刷了 Ubuntu 24.04,那就直接装 Jazzy,别为了装旧版还去重做系统。热词里“ubuntu24.04安装ros2”、“install ros2 jazzy”这些都是大家在接触新版系统时遇到的需求,可以先明确一个认知:发行版不是越新越好,匹配你的系统和生态才重要。
还有朋友会问“ros1和ros2可以共存吗”,答案是肯定的。它们安装路径不同,环境变量不同,不会互相覆盖。只不过同一时间你只能 source 其中一个的环境脚本,不能在一个终端里同时用 ROS1 和 ROS2 命令。我建议日常还是分开开终端,各用各的,习惯就好。
2. 环境搭建:Ubuntu 22.04 安装ROS2 Humble 完整流程
2.1 安装前的系统准备与软件源配置
ROS2 官方主推 Ubuntu,虽然 Windows、macOS 也能装,但折腾成本高,新手就别折磨自己了。我这里以最主流的 Ubuntu 22.04 + Humble 组合为例,把完整流程走一遍。
第一步确认系统版本,确保你的系统是 22.04 而不是 20.04 或者 24.04:
lsb_release -a如果系统没问题,先配置 locale,保证终端能正常显示中文和生僻字符:
sudo apt update && sudo apt install -y locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 export LANG=en_US.UTF-8这是一步几乎不会失败的准备操作,我也遇到过跳过之后,后续在 RViz2 里出现中文乱码的情况,建议老老实实执行。
接下来是重头戏:添加 ROS2 软件源。ROS2 官方源在国内访问比较慢,实际使用中很多人会在这步卡住,然后在运行sudo apt install ros-humble-desktop的时候看到报错。我自己也踩过这个坑,后来干脆在文档里固定用镜像源。在/etc/apt/sources.list.d/ros2.list里写入镜像源地址:
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null <<EOF deb [arch=amd64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu jammy main EOF然后添加 ROS2 官方签名密钥。官方文档给的是从 raw.githubusercontent.com 下载,但国内访问很慢,我建议直接下载压缩包解压:
sudo curl -sSL https://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu/ros2-archive-keyring.asc -o /usr/share/keyrings/ros-archive-keyring.gpg如果 curl 没装,先用sudo apt install curl装一下。最后更新软件包列表:
sudo apt update更新过程中注意看结尾有没有报错,尤其是密钥相关的输出。如果提示缺少公钥,需要回头重新下载密钥文件,别急着装包。
2.2 实战排查:unable to locate package ros-humble-desktop
安装过程中出现频率最高的报错,就是热词里的这行:
E: unable to locate package ros-humble-desktop这个报错 90% 是因为软件源没配好。注意它和另一个报错本质不同:“unable to locate”通常是源里压根搜不到这个包,而“Package ros-humble-desktop is not available”则通常是源找到了但版本不匹配。
排查思路按顺序来。先确认/etc/apt/sources.list.d/ros2.list这个文件存在而且内容没写错,尤其注意 jammy 和 amd64 这两个关键参数:
cat /etc/apt/sources.list.d/ros2.list然后检查源文件末尾的 Codename 是否和系统一致:
apt-cache policy | grep -E "ros2|jammy"如果输出里面能看到 ros2 开头的源,说明源已经生效。如果输出为空或者报错,多半是源的 Codename 写错了,比如在 22.04 上写了 bookworm(Debian 的代号)。再检查 universe 组件是否开启,ROS2 安装过程中有不少依赖包来自 Ubuntu 的 universe 源,某些服务器版系统默认不带:
sudo apt install -y software-properties-common sudo add-apt-repository universe最后再刷一次源:
sudo apt update apt-cache search ros-humble-desktop这次输出如果能搜到ros-humble-desktop这个包,问题就解决了。我建议每次改完源都执行一次 apt update,再看一下输出日志,别急着装,这一步能省下大量折腾时间。
2.3 安装桌面版、初始化环境并验证小乌龟
源配好后,安装就顺理成章了。桌面版包含了机器人开发最常用的一整套工具,包括 RViz2、demo 示例、TF 库等,学习阶段装这个就行:
sudo apt install -y ros-humble-desktop这个包体积比较大,等一会是正常的。装完基础环境后,还需要装 ros-dev-tools,否则后面创建功能包的时候会提示找不到 colcon 等命令:
sudo apt install -y ros-dev-tools然后配置环境变量,把 ROS2 的 setup 脚本写进 shell 配置里,这样每次开终端自动加载:
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc source ~/.bashrc我遇到过不少朋友,明明装得很顺利,但开个新终端执行ros2却提示找不到命令,原因就是没 source。确认环境没问题:
ros2 --help能看到类似 usage 的输出,说明环境正常。这时候可以跑 ROS2 自带的示例程序体验一把,开三个终端:
第一个终端启动乌龟节点:
ros2 run turtlesim turtlesim_node第二个终端启动键盘控制节点:
ros2 run turtlesim turtle_teleop_key第三个终端监听乌龟的线速度话题:
ros2 topic echo /turtle1/cmd_vel用方向键控制乌龟移动,第三终端里能看到一条条 Twist 消息刷出来,这说明发布订阅机制已经在跑了。第一次跑通这个流程,基本就掌握了 ROS2 的最小运行套路:一个节点发布话题、一个节点订阅话题、一个终端监听验证。
3. 读懂ROS2的目录结构与核心机制
3.1 工作空间目录到底是怎么组织的
理解 ROS2 的工作空间结构,对后续开发非常关键,否则经常看到别人 clone 多个仓库后colcon build一把出结果,自己却不知道每个目录是干嘛的。ROS2 工作空间里最高频出现的四个目录是src、build、install、log,它们各有明确分工:
src:存放所有功能包源码的目录,你从 GitHub 克隆下来的包、自己写的功能包都放这里。build:编译过程中生成的临时文件,包含 CMake 缓存、中间对象等,自动生成,可以随时删除。install:编译完成后,可执行文件、库文件、配置文件会被安装到这里,是真正被运行时加载的目录。log:存放编译日志和运行日志,编译报错时可以到这里翻详细信息。
我第一次用 colcon 编译时,以为可执行文件直接在 src 下,结果折腾半天找不到。后来才明白,colcon 的产物默认都放在 install 目录,你要用的时候必须 source 下面生成的 setup.bash:
cd ~/ros2_ws colcon build source install/setup.bash而且注意,colcon build 默认是增量编译,如果你修改了某个包的代码,重新 build 的时候,它的产物会更新到 install 目录,所以改完代码记得重新 source 一下。如果你想清掉所有产物重新编译,可以删掉 build 和 install 目录再执行 colcon build。这个操作本质上等价于回到了干净的初始状态,对排查一些“我代码改了但没生效”的问题非常管用。
3.2 核心通信机制:话题、服务、动作、参数
ROS2 里节点之间通信有几种方式,刚入门容易混。我尽量用生活化的比喻解释。
话题(Topic)是使用频率最高的通信方式,属于异步发布订阅模式。发布者发完消息就离开,订阅者收不收得到,发布者不关心。就像电台广播,主播播完就走,至于多少人收听到,好像跟主播关系不大。对应到机器人的场景,传感器数据流、速度指令都是典型话题,比如刚才操作小乌龟时看到的/turtle1/cmd_vel。
服务(Service)是一问一答的同步模式,客户端发请求,服务端必须回复。就像你打电话问客服“订单到哪了”,客服必须给你一个答复。机器人里开关灯、设置参数这类操作,通常就用服务实现。在 ROS2 里可以用ros2 service list查看当前所有服务,比如 turtlesim 里有spawn服务,可以创建一只新乌龟。
动作(Action)则解决更长时间的任务,比如导航到某个目标点,可能需要几十秒,这时候动作就有优势了:它会持续反馈进度,而且随时可以取消。动作可以理解为“带进度条的服务”,实际开发中处理导航、机械臂运动这些耗时任务基本都用动作。
参数(Parameter)是节点的配置项,类似程序里的全局变量。不同节点的参数可以动态修改,不用重新编译,比如设置乌龟的背景色:
ros2 param set /turtlesim background_r 150这些概念不需要死记硬背,用多了自然就懂了。记住一句话:一次性查询用服务,持续数据流用话题,长时间任务用动作,配置变量用参数。
3.3 高频命令速查:会这几个就能应付九成场景
ROS2 命令体系设计得很规整,基本都是ros2 + 对象 + 动作的格式。我这里整理一个高频命令速查表,对应热词里的“ros2命令大全”,平时记不清的时候照着查就行。
| 命令 | 作用 | 常用场景 |
|---|---|---|
ros2 node list | 列出当前所有节点 | 查看网络里有哪些节点 |
ros2 node info /节点名 | 查看节点的详细信息 | 查节点的订阅发布话题 |
ros2 topic list | 列出所有话题 | 查看当前有哪些话题 |
ros2 topic echo /话题名 | 实时打印话题内容 | 检查数据是否在流通 |
ros2 topic hz /话题名 | 查看话题发布频率 | 检查发布是否稳定 |
ros2 topic info /话题名 | 查看话题类型和参与者 | 确认发布订阅关系 |
ros2 service list | 列出所有服务 | 查看可调用的服务 |
ros2 service call /服务名 | 调用服务 | 触发一次服务请求 |
ros2 action list | 列出所有动作 | 查看可用动作 |
ros2 param list | 列出所有参数 | 查看节点配置项 |
ros2 pkg create | 创建功能包 | 新建功能包 |
ros2 run 包名 可执行名 | 运行节点 | 启动节点 |
ros2 launch 包名 launch文件 | 启动多个节点 | 一键启动整套系统 |
小乌龟程序跑起来后,你可以挨个试这些命令。先用ros2 node list看两个节点,再用ros2 topic info /turtle1/cmd_vel查看话题类型,然后ros2 topic echo监听,整个流程跑一遍,比看书记得牢得多。
4. 从零手写第一个功能包并跑起来
4.1 创建自己的工作空间与功能包
光会跑现成的 demo 还不够,要开始写自己的代码,第一步是搭建工作空间并创建功能包。这里我演示一个最基础的 Python 功能包,因为它不需要编译 C++,对新手最友好。
mkdir -p ~/ros2_ws/src cd ~/ros2_ws/src ros2 pkg create demo_pkg --build-type ament_python --dependencies rclpy std_msgs这个命令会生成一个标准的 Python 功能包,其中需要重点关注这几个文件:
package.xml:声明包的元信息、依赖和版本setup.py:告诉系统如何安装这个包,以及哪些 Python 文件可以当作节点执行resource/demo_pkg:用于标记包内的资源位置demo_pkg/:实际存放 Python 代码的目录
创建完成后,在demo_pkg目录下新建一个talker.py文件,写一个最简单的发布者节点。
4.2 手写发布订阅节点并理解节点生命周期
我用一个发布字符串消息的节点来演示,对应热词里“ros2小乌龟”背后的这类发布订阅场景,不过这次是自己写的。
import rclpy from rclpy.node import Node from std_msgs.msg import String class Talker(Node): def __init__(self): super().__init__('talker') self.publisher = self.create_publisher(String, 'chatter', 10) self.timer = self.create_timer(1.0, self.timer_callback) self.count = 0 def timer_callback(self): msg = String() msg.data = 'hello ros2: %d' % self.count self.publisher.publish(msg) self.get_logger().info('Publishing: "%s"' % msg.data) self.count += 1 def main(args=None): rclpy.init(args=args) node = Talker() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()再建一个listener.py:
import rclpy from rclpy.node import Node from std_msgs.msg import String class Listener(Node): def __init__(self): super().__init__('listener') self.subscription = self.create_subscription(String, 'chatter', self.listener_callback, 10) def listener_callback(self, msg): self.get_logger().info('I heard: "%s"' % msg.data) def main(args=None): rclpy.init(args=args) node = Listener() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()写完之后,最关键的一步是修改setup.py,把入口函数注册成可执行命令:
entry_points={ 'console_scripts': [ 'talker = demo_pkg.talker:main', 'listener = demo_pkg.listener:main', ], },不注册这步,后面用ros2 run demo_pkg talker就会报找不到可执行文件。很多新手第一步就漏在这里,记住:ros2 run能执行的节点,必须在 setup.py 的 console_scripts 里声明过。
回到工作空间根目录编译:
cd ~/ros2_ws colcon build source install/setup.bash开三个终端,两个分别跑 talker 和 listener,另一个用ros2 topic echo /chatter验证,你会发现 talker 每发一条消息,listener 就能收到一条。到这里,你已经亲手跑通了一个最小闭环的 ROS2 应用。
4.3 用launch文件一键启动多节点
随着项目越来越大,手动开终端一个一个启动节点会累死人。ROS2 提供的 launch 机制就是来解决这个问题的,它可以用一个 launch 文件代替你手动开 N 个终端。
在demo_pkg目录下新建launch/demo.launch.py:
from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node( package='demo_pkg', executable='talker', name='talker' ), Node( package='demo_pkg', executable='listener', name='listener' ), ])然后在 setup.py 的data_files里加上 launch 文件的安装路径,这个步骤很多教程不会强调,不加的话ros2 launch找不到文件:
data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), (os.path.join('share', package_name, 'launch'), ['launch/demo.launch.py']), ],再重新编译,source 之后,一行命令就能同时启动两个节点:
ros2 launch demo_pkg demo.launch.py看到终端里同时打印出两个节点的日志,这个 launch 文件就成功了。后面你再接雷达、接相机、跑导航,所有节点都可以整理进一个 launch 文件里,一条命令启动整套机器人系统,这也是真实项目里的标准做法。
5. 继续进阶:从仿真到实战的路标
5.1 给机器人接入雷达和相机:Livox、标定与感知
基础概念和第一个节点跑通之后,很多人就想把真实传感器接进来了。目前机器人感知最常见的两类传感器是激光雷达和相机。热词里“livox avia 配置使用 ros2”、“雷达ros2”指的就是这个方向。
Livox Avia 这类激光雷达接入 ROS2 时,首先需要安装官方驱动livox_ros_driver2,装好之后它会把原始点云数据发布成 ROS2 话题,比如/livox/lidar,然后用 RViz2 添加 PointCloud2 显示,就能在三维视图里看到环境点云。这里有几个经验:第一,驱动版本要和 ROS2 发行版匹配,官方仓库会有对应分支;第二,雷达连接后先检查 USB 设备权限,赋予串口访问权限能省掉很多麻烦;第三,点云话题的 frame_id 要正确设置,不然后面的 TF 变换全是坑。
相机接入相对简单,一般用usb_cam或v4l2_camera驱动发布图像话题。但相机要参与后续的视觉定位或目标识别,就绕不开标定。ROS2 里有现成的camera_calibration功能包,配合棋盘格标定板,可以获得相机的内参矩阵和畸变系数。标定板尽量打印平整,拍摄角度覆盖多方向和距离,标定结果会更准确。
5.2 栅格地图与导航:OctoMap、Nav2、路径规划
传感器接入只是第一步,机器人的核心价值在于自主导航。ROS2 里负责导航的框架叫 Nav2,对应的热词里“ros2路径规划”“八叉树地图导航”都往这个方向指。
整套导航系统大概分成三层:第一层是建图,用激光雷达和里程计构建环境地图,常用方案有 cartographer 和 slam_toolbox;第二层是定位,让机器人在已知地图里确定自己的位置,常用 AMCL;第三层是路径规划,Nav2 会接收用户设定的目标点,通过全局规划器计算一条从当前位置到目标点的路径,再由局部规划器负责避开动态障碍。
这里特别提一下“八叉树地图”,对应热词里面的“八叉树地图导航”。传统二维栅格地图适合地面机器人,但无人机、机械臂这类需要在三维空间作业的设备,更需要三维八叉树地图。OctoMap 用八叉树数据结构来建模三维空间,每个节点记录被占据或空闲的概率,内存效率很高。ROS2 里可以用octomap_server把激光点云转换成语义化的八叉树地图,然后在 RViz2 里可视化三维占用地图。这个方向需要在基础导航跑通之后再深入,但值得提前有个概念。
5.3 嵌入式端的ROS2:micro-ROS 与 ESP32
ROS2 不只跑在电脑上,还能跑在 MCU 上。热词里“micro-ros ros2 esp32s3 vscode platformio”说的就是这个方向。
MCU 资源有限,跑不了完整的 ROS2,于是就有了 micro-ROS。它把 ROS2 的核心通信能力裁剪之后移植到 RTOS、裸机环境,让 ESP32、STM32 这类设备也能直接接入 ROS2 网络。以 ESP32-S3 为例,用 PlatformIO 在 VSCode 里创建工程时,引入 micro_ros_platformio 库,配置好 Wi-Fi 或者串口参数,就能通过 micro-ROS Agent 连接到电脑上的 ROS2 节点。这样最典型的应用是:用 ESP32 采集 IMU 或编码器数据,发布成 ROS2 话题,电脑端用 RViz2 实时可视化它的姿态。
这一段可能对纯软件背景的朋友稍显硬核,但思路很值得理解:ROS2 的生态天然覆盖从嵌入式传感器到上位机再到云端,整套链路都是相通的,学会嵌入式端接入之后,做硬件产品就有底气多了。
5.4 机械臂视觉抓取仿真与实战项目
热词里的“ros2机械臂视觉抓取仿真”也是实战性很强的方向。机械臂抓取比移动底盘复杂在多了运动规划,而这部分主要依赖 MoveIt2 框架。MoveIt2 负责机械臂的运动学解算、轨迹规划、碰撞检测,合理配置好机械臂的 URDF 模型和驱动接口,就能在 RViz2 里拖拽目标点,让机械臂规划一条无碰撞的路径运动过去。
视觉抓取仿真一般走这样的流程:先用相机模拟器生成带有物体位姿的场景,再通过目标检测或点云分割识别目标物体,计算出机械臂末端需要到达的位姿,最后交给 MoveIt2 执行抓取。如果不想一上来就上真实机械臂,可以用 Gazebo 或者 Isaac Sim 搭建仿真环境,先在仿真里跑通整套逻辑,再迁移到实体设备。不管是做毕业设计还是备赛,这类项目性强的方向,最能锻炼综合能力。
6. 高频问题排查与避坑实录
6.1 安装阶段的高频问题速查
环境问题可以说是劝退新手的第一大因素,这里把我在实操中遇到过的、以及在社区里被反复问到的问题集中整理成一张速查表。
| 报错现象 | 根本原因 | 解决方案 |
|---|---|---|
| unable to locate package ros-humble-desktop | ROS2 源没配好或未生效 | 检查 ros2.list 内容和 Codename,重新 apt update |
| Package ros-humble-desktop has no installation candidate | 源的 Codename 与系统不匹配 | 确认是 jammy 而不是 noble 或 bookworm |
| colcon: command not found | 未安装 ros-dev-tools | 安装 ros-humble-dev-tools 或 ros-dev-tools |
| bash: ros2: command not found | 环境变量未加载 | source /opt/ros/humble/setup.bash 并写入 ~/.bashrc |
| CMake 编译时报找不到 rclcpp | 缺少依赖包 | 用 rosdep 安装依赖,或直接用二进制包预装依赖 |
| 下载源码或依赖时太慢 | 网络源不通畅 | 更换国内镜像源,avoid在高峰期反复重试 |
其中“unable to locate package”是全系列最常遇到的一个坑,我在前面第 2.2 节已经详细过了一遍排查流程,这里就不重复了,直接对照着来就行。
6.2 运行阶段的高频问题速查
安装好之后,运行阶段也会遇到各种问题。尤其是涉及多机、多传感器的时候,排查起来更费劲。我把运行阶段的高频坑整理在下面。
| 现象 | 排查方向 | 建议 |
|---|---|---|
| ros2 topic list 看不到话题 | 检查发布和订阅是否在同一台机器、同一 ROS_DOMAIN_ID | 确认没有设置不同的 ROS_DOMAIN_ID |
| 两个节点的 QoS 不匹配 | 订阅者设了更大的 queue depth 但 reliability 策略不一致 | 发布订阅 QoS 要兼容,比如都设为 BEST_EFFORT 或 RELIABLE |
| rviz2 打开后黑屏/加载慢 | gazebo 和 rviz2 同时跑导致资源占用过高 | 确认显卡驱动,低配机器可以降低渲染负载 |
| source 了 .bashrc 但新终端 ros2 不可用 | 环境变量被覆盖或 shell 配置异常 | 手动 source 一下,确认 /opt/ros 路径存在 |
| 多机通信连不上 | ROS_DOMAIN_ID 不同,或处于不同网段 | 统一 ROS_DOMAIN_ID,确保在同一子网,关闭防火墙限制 |
| ros1 和 ros2 命令混用 | 同时 source 了 ROS1 和 ROS2 的环境 | 习惯分终端,避免在同一 shell 中切换 |
ROS_DOMAIN_ID 这个参数值得多说一句。ROS2 默认使用 domain ID 0,如果两台机器想协同,需要在所有节点机器上设置相同的 ROS_DOMAIN_ID:
export ROS_DOMAIN_ID=1这个 ID 会决定 DDS 通信使用的端口范围,不同 ID 的节点会直接隔离,哪怕在同一个网段也互相感知不到。
6.3 一套通用的排查思路
最后分享一个我自己在 ROS2 开发中反复使用的问题排查思路,可以当成一套标准操作流程。
先看环境,再谈应用。遇到任何"节点起不来"的问题,第一件事先执行printenv | grep -i ros确认环境变量有没有乱。我最常遇到的是用户之前装了 ROS1,环境脚本互相污染,导致 ROS2 命令行为异常。
再说看日志。ROS2 的日志信息非常详细,启动节点时会在终端给你各种警告和报错。如果日志被刷屏,可以调整日志级别,用--log-level debug启动节点就能看到更详细的调试信息。
然后做最小复现。不要一上来就启动整个系统,而是先手动启动一个节点,确认它没问题,再一个个往上加。比如雷达接入失败,就先看看雷达驱动能不能发布点云,再看 TF 树是否完整,最后再开导航。这种方法虽然慢,但每一步都稳,反而比一口气跑完整套系统再找问题快很多。
最后用ros2 doctor做一次系统巡检。ROS2 内置了这个诊断工具,可以自动检查环境变量、网络配置、共享库依赖等。我经常提醒朋友在遇到“莫名奇妙的问题”时先跑一下,它能自动定位不少配置层面的坑。
我在实际项目里体会最深的一件事是:ROS2 的学习曲线陡,但并没有陡到夸张。真正消耗耐心的不是概念本身,而是环境配置、依赖管理、版本不匹配这些“看不见的敌人”。所以建议每一步都按文档来,别跳,尤其是安装和 source 这些看起来不起眼的步骤。跳过任意一步,后面的报错可能让你多花几个小时来找原因。如果你把这一篇里的步骤都亲手跑通了,接下来的系列内容,比如 DDS 通信原理、TF 坐标变换、Nav2 导航实战,你都能在更扎实的基础上继续往下走。先别急着追求高阶功能,把基础链路打磨顺,后面的路自然就顺了。