
装好 ROS 2 之后很多初学者都会对着终端愣半天环境变量配好了、ros2命令也能用了然后呢我见过不少同学卡在这一步——教材翻到第一章第三节“运行你的第一个机器人”却不知道这个“机器人”到底在哪、怎么运行、运行完能看到什么。这篇文章就把这件事彻底讲透基于 Ubuntu 22.04 ROS 2 Humble用官方自带的小海龟仿真器 turtlesim把第一个“机器人”真正跑起来同时通过这个简单的例子把 ROS 2 最核心的“节点、话题、服务”三个概念一次性理清。这篇内容适合三类人刚装完 ROS 2 但不知道下一步该干什么的新手已经能用ros2 run跑通 demo、但对内部机制还是一团浆糊的同学以及想快速判断“ROS 2 到底适不适合我的项目”的开发者。读完你会得到一套完整可复现的实操流程以及几个只在真实环境里踩过坑才会知道的排查技巧。1. 为什么第一个程序从 turtlesim 开始1.1 麻雀虽小五脏俱全的仿真平台很多教程一上来就让新手装 Gazebo、跑 MoveIt、控制真实机械臂我其实不太推荐。原因很简单你连“节点之间怎么通信”都没建立体感直接上重型工具只会被海量参数淹没最后变成了“照着抄但不知道在抄什么”。而 turtlesim 这个官方自带的小海龟仿真器恰好是 ROS 2 世界里最轻量、最完整的教学平台。它模拟了一个会接收速度指令、会报告自身位置和姿态的“机器人”。你给它发布线速度和角速度它就在窗口里移动它移动的同时不断把自己的坐标、朝向、速度发布出来。这套“输入指令—执行运动—反馈状态”的闭环和真实机器人完全一致。唯一的区别是turtlesim 不需要买硬件、不需要处理传感器噪声、更不用担心撞坏东西你可以在它身上随便试错。我第一次带新人跑这个例子时最喜欢说一句话你在 turtlesim 里理解的每个概念搬到差速小车、机械臂、无人机的 ROS 2 代码里几乎一个字母都不用改。话题还是那个话题、节点还是那个节点变的只是消息内容和执行机构。这就是为什么我坚持让所有新同学从这个小海龟开始。1.2 把“节点—话题—服务”跑在看得见的地方ROS 2 的通信模型有三根支柱节点、话题、服务。教科书定义背下来不难但真正理解需要看到它们“活”起来。turtlesim 是干这件事最好的载体节点在这个例子里turtlesim_node海龟服务端节点负责窗口显示、物理模拟、坐标计算turtle_teleop_key键盘遥控节点负责读键盘输入、转换成速度指令。它们是两个完全独立的进程互相不认识。话题turtle_teleop_key把速度指令发布到名为/turtle1/cmd_vel的话题上turtlesim_node订阅这个话题拿到指令就移动。这就好比一个广播电台和一个听众电台不知道有多少人在听听众也不知道是谁在播。服务当你用/spawn服务生成一只新海龟时客户端发一个请求“帮我在坐标 (x, y) 生成一只新海龟”服务端处理完返回“生成成功名字是 turtle2”。这是“一问一答”的通信方式和话题的“发布—订阅”模式有本质区别。这三个概念如果只看文档很容易记混。但在 turtlesim 里你能用一条命令ros2 topic list直接看到话题列表用ros2 node info看到每个节点的发布订阅关系用rqt_graph看到整个通信关系的图形化展示。眼睛看到了脑子就记住了。2. 从零开始的环境准备装一个能跑的 ROS 22.1 版本选择装 Humble 而不是更“新”的版本ROS 2 的发行版迭代速度不慢目前主流的 LTS长期支持版本是 Humble Hawksbill官方支持周期到 2027 年 5 月。为什么我反复推荐新手装 Humble而不是追最新版三个原因资料最多绝大多数教程、开源项目、问答帖子都是基于 Humble 写的你踩到坑时搜到的解决方案成功率最高。兼容性最稳Humble 对应 Ubuntu 22.04而 22.04 又是目前服务器和桌面端占有率极高的系统版本软件源里的二进制包都是直接编译好的安装即用。社区验证充分Humble 发布至今已经过了足够长的时间各种已知问题基本都有明确的解决路径。如果你用的是 Ubuntu 20.04那对应版本是 FoxyUbuntu 24.04 对应的是 Jazzy。这里要特别强调一句版本之间的命令和配置有差异别拿 Humble 的教程硬套别的发行版。我见过不少新人拿 Ubuntu 24.04 强行装 Humble 的二进制包结果依赖冲突一堆最后全盘重来。2.2 安装步骤源、软件包、环境变量安装本身不复杂核心就三步。首先确认你的 Ubuntu 版本和系统源能正常更新cat /etc/os-release sudo apt update然后添加 ROS 2 官方软件源并安装桌面版sudo apt install software-properties-common curl sudo add-apt-repository universe sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release echo $UBUNTU_CODENAME) main | sudo tee /etc/apt/sources.list.d/ros2.list /dev/null sudo apt update sudo apt install ros-humble-desktop这里我多说两句装包选择的细节。ros-humble-desktop是完整桌面版包含 ROS 2 核心、可视化工具rqt、RViz、模拟器turtlesim、Gazebo和大量示例包。如果你只打算跑一些基础节点可以装ros-humble-ros-base体积会小很多。但我建议新手直接上 desktop因为后面学 TF、学可视化、学导航时都会用到这些工具省得以后再补装。装完并不是结束还有一个非常关键的步骤让系统每次打开终端都能自动找到 ROS 2 命令。echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc这行命令把 ROS 2 的环境变量注入当前 shell。不执行这步你输入ros2一定会收到command not found。关于这个问题的排查细节我在后面第 4 节还会展开讲。2.3 ros2 命令找不到根源都在环境变量很多新手装完 ROS 2第一反应是打开终端输入ros2 --help然后看到一个冰冷的bash: ros2: command not found第一反应是“没装成功”。其实大概率是环境变量没生效。source /opt/ros/humble/setup.bash的作用是告诉系统ROS 2 的可执行文件在/opt/ros/humble/bin这个目录下。如果你每次打开新终端都要手动执行一次这个命令很容易忘。正确的做法就是 2.2 里写的那样把这行追加到~/.bashrc里让每个新终端自动加载。但这里也有个坑如果你同时装了 ROS 1 和 ROS 2或者装了多个 ROS 2 发行版~/.bashrc里可能会写多行 source后面写的会覆盖前面写的导致命令串版本。我建议只保留一行也就是你当前在用的那个发行版。另外~/.bashrc里的环境变量只对当前用户生效如果你用sudo或切换到其他用户需要重新配置。2.4 安装后的健康检查环境配好之后先别急着跑第一个机器人花 30 秒做一个快速体检ros2 --help ros2 pkg list | grep turtlesim第一行验证命令行工具是否可用第二行确认 turtlesim 这个仿真包已经装进来了。如果ros2 pkg list输出的内容里有turtlesim恭喜你的环境完全没问题可以直接进入实战环节。如果这里就报错直接跳到第 4 节对照排查。3. 第一次启动“机器人”完整实操记录3.1 启动你的第一个机器人必备的两个终端好的最激动人心的时刻到了。打开两个终端窗口并且确保两个窗口都已经 source 过环境变量如果你按 2.2 配了~/.bashrc新开的终端会自动生效。第一个终端启动海龟仿真器ros2 run turtlesim turtlesim_node你会看到弹出一个蓝色窗口窗口中央有一只小海龟。别小看这一刻——在 ROS 2 的世界里这只海龟就是你的第一个“机器人”它已经作为一个节点运行在系统里了。第二个终端启动键盘遥控节点ros2 run turtlesim turtle_teleop_key按提示用键盘上的上下左右方向键控制海龟移动。按一下F可以让海龟快速转圈按G可以画一个漂亮的正弦轨迹。玩一会儿你就会发现两个终端里跑着两个独立的程序它们通过 ROS 2 的话题机制互相通信一个人负责想“往哪走”另一个人负责执行“怎么走”。这里必须解释一下ros2 run这条命令的语法因为往后你会用它启动成千上万个节点ros2 run package_name executable_namepackage_name是功能包名executable_name是包内可执行程序的名字。在这个例子里turtlesim是功能包名turtlesim_node和turtle_teleop_key是这个包里预先编译好的两个可执行程序。能跑通这条命令说明你的包管理、环境变量、运行链路都已经正常了。3.2 键盘控制直观感受“速度指令”的含义当你按下方向键上键盘节点会发布一条 Twist 类型的速度消息核心字段是线速度linear.x和角速度angular.z。你按“上”linear.x变成正值海龟直行按“左”angular.z变成正值海龟原地左转。这里推荐一个小实验能帮你彻底理解速度指令按一下“上”看着海龟往前走然后立即松开按键。你会观察到海龟停在了原地而不是滑行一段距离。这说明键盘节点在松开按键后发了一条全零速度指令海龟执行“停”。真实机器人也是这样如果你不给它发指令它就停在那不动。同样值得做的是先按“上”让海龟往前走再按“右”让海龟转弯感受一下直角转弯需要的操作组合。你会意识到“从 A 点走到 B 点”这件事在机器人世界里其实就是一系列速度指令的组合直行、转向、再直行、再转向。这也是后期你写运动控制算法的基本思维框架。3.3 打开上帝视角用命令行“透视”整个系统玩完键盘这时候 ROS 2 系统里有至少两个节点在运行。打开第三个终端我们来用命令行“透视”刚才那些操作背后到底发生了什么。先看当前系统里有几个节点ros2 node list正常情况下会输出/turtlesim /teleop_turtle/turtlesim是海龟仿真器节点/teleop_turtle是键盘遥控节点。注意这些带斜杠的是节点的全限定名在真实系统里节点名可以任意起只要保证在一个 ROS 2 域内不重名。再看系统里有哪些话题在流动ros2 topic list这里能看到/turtle1/cmd_vel速度指令话题、/turtle1/color_sensor颜色传感器话题、/turtle1/pose位置姿态话题等等。其中/turtle1/pose特别有意思它是海龟不断向外界广播“我在哪”的通道。想看某个话题上正在流动的数据实时监听位置话题ros2 topic echo /turtle1/pose然后去键盘控制的终端按几下方向键你会看到坐标x、y和朝向theta在实时变化。theta的单位是弧度这也是后面所有角度计算的基础单位不是角度制这里很多人会犯迷糊。想看某个节点的详细信息包括它发布什么话题、订阅什么话题、提供什么服务ros2 node info /teleop_turtle这个命令会列出这个节点所有的发布者、订阅者、服务客户端和服务端。把这个输出和/turtlesim的对比一下你能立刻明白“谁在说话、谁在听”。如果嫌命令行不够直观再说一个图形化工具rqt_graph会弹出一个窗口里面用箭头清晰画出节点之间的通信关系。你会看到/teleop_turtle指向/turtlesim的一条箭头边上标注着/turtle1/cmd_vel这就是一次完整的话题通信。很多同学在这一刻会突然顿悟原来 ROS 2 的“分布式通信”就是这个感觉——节点彼此独立只靠话题交换数据。3.4 手动发布话题不用键盘也能让海龟走圆形看完了“上帝视角”如果把键盘节点关掉在第二个终端按CtrlC海龟会停在原地不动。这时你可以亲自扮演“遥控者”用命令行直接向话题发指令完全绕过键盘节点。让海龟走一个圆形轨迹ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist {linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {z: 1.8}}这条命令的语法拆开看--once表示只发布一次/turtle1/cmd_vel是话题名geometry_msgs/msg/Twist是消息类型后面花括号里是具体数值。线性速度 2.0 米每秒仿真中的单位角速度 1.8 弧度每秒两者叠加海龟就会边前进边转弯画出一个圆弧。想让海龟走更规则的运动可以加一个--rate 10参数以 10Hz 的频率持续发布指令ros2 topic pub --rate 10 /turtle1/cmd_vel geometry_msgs/msg/Twist {linear: {x: 1.0, y: 0.0, z: 0.0}, angular: {z: 0.0}}这条命令会一直发海龟就匀速直线前进。用完记得CtrlC停掉不然它会一路走到墙边然后报错退出。手动发布话题这个操作在后续调试中会大量用到尤其是在测试某个驱动节点时你会经常用这种方式手工注入一个话题数据验证执行端是否正常工作。3.5 写一个自己的节点让海龟自己跑正方形到了这一步你已经会“用” ROS 2 了但离“开发”还差一步亲手写一个节点。我们来写一个 Python 节点让海龟自动走一个正方形不需要人工干预。新建一个文件夹比如~/turtle_square在里面创建square.pyimport rclpy from rclpy.node import Node from geometry_msgs.msg import Twist class SquareMover(Node): def __init__(self): super().__init__(square_mover) self.publisher self.create_publisher(Twist, /turtle1/cmd_vel, 10) self.timer self.create_timer(2.0, self.timer_callback) self.state 0 self.corners 0 def timer_callback(self): msg Twist() if self.state 0: # 直行阶段 msg.linear.x 1.0 msg.angular.z 0.0 self.state 1 else: # 左转90度 msg.linear.x 0.0 msg.angular.z 1.57 self.state 0 self.corners 1 if self.corners 4: self.timer.cancel() self.publisher.publish(msg) def main(argsNone): rclpy.init(argsargs) node SquareMover() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ __main__: main()然后在终端运行cd ~/turtle_square source /opt/ros/humble/setup.bash python3 square.py强烈建议你先让海龟回到窗口中央可以重启一下turtlesim_node然后再运行这个脚本观察海龟自动走一个正方形。代码逻辑很简单一个 2 秒触发一次的回调先直行、再左转循环四次后自动结束。这段代码展示了一个 ROS 2 节点的完整骨架也是后续所有节点开发的基础rclpy.init()初始化 ROS 2 客户端库Node(square_mover)创建一个节点名字叫square_movercreate_publisher(...)创建一个发布者绑定到/turtle1/cmd_vel话题create_timer(...)创建一个定时器每 2 秒触发一次回调rclpy.spin(node)让节点持续运行不断处理回调如果你能自己把这段代码从无到有敲出来并且理解每一行的作用恭喜ROS 2 开发的大门已经向你打开了。后续学再复杂的包本质上也还是这套骨架的变体。4. 新手最容易卡住的问题排查4.1 软件包找不到E: Unable to locate package这个问题几乎每天都会在社区里被问一次。现象是执行sudo apt install ros-humble-desktop时apt 报错E: Unable to locate package ros-humble-desktop。原因几乎永远是同一个ROS 2 的软件源没有正确配置。排查顺序如下第一确认你的系统是 Ubuntu 22.04Humble 不支持其他版本的系统直接用二进制包安装第二确认ros.list文件确实存在内容指向packages.ros.org第三确认你已经执行过sudo apt update而不是配完源就直接 install。如果这三步都做了还是不行用下面这句强制刷新一次缓存sudo apt update sudo apt upgrade顺便提一句网络原因导致的源下载失败偶尔也会出现换一下镜像源比如把packages.ros.org替换为国内镜像地址通常能解决但这属于环境问题这里就不展开了。4.2 命令找不到bash: ros2: command not found输入ros2提示找不到命令有两种可能ROS 2 没装成功或者环境变量没加载。判断方法很简单先看看安装目录是否存在ls /opt/ros/如果能看到humble这个目录说明 ROS 2 本身装好了问题出在环境变量上。手动执行一次source /opt/ros/humble/setup.bash然后再试ros2 --help。如果这次能用了说明就是~/.bashrc里的 source 没生效。检查一下.bashrc文件末尾有没有那行source /opt/ros/humble/setup.bash没有就补上有就检查是不是被注释掉了。这里有个小技巧修改完.bashrc后不需要重启终端直接执行source ~/.bashrc就能让当前终端生效。4.3 图形界面出不来ros2 run turtlesim turtlesim_node之后终端没有任何报错但海龟窗口就是没弹出来。这大概率不是 ROS 2 的问题而是显示环境的问题。这种情况在虚拟机、WSL、远程 SSH 环境下特别常见。首先确认当前会话有没有显示权限echo $DISPLAY如果输出为空说明图形环境没传给这个终端。在真实 Ubuntu 桌面环境里一般不会出现这个问题如果是 WSL2需要额外安装并配置 X Server比如 VcXsrv、MobaXterm 等。配置好之后把 DISPLAY 变量设置成 Windows 主机的 IP 地址然后再试图启动。如果你是在无图形界面的服务器上做开发可以考虑用xvfb这类虚拟显示工具跑无头仿真但那就属于进阶用法了新手阶段更建议在本地桌面环境操作省去一堆麻烦。4.4 海龟窗口能开但键盘没反应这种情况也很常见turtlesim 窗口正常键盘遥控节点也启动了按方向键海龟就是不动。第一个要检查的是当前焦点在哪个窗口。键盘节点的输入监听需要你先把焦点切到终端窗口而不是海龟窗口否则按键被其他窗口吃掉了。第二个要检查的是话题连接是否正常。终端里运行ros2 topic info /turtle1/cmd_vel看看输出里的订阅者数量是不是 1 个如果显示 0说明turtlesim_node没有订阅到这个话题可能是版本冲突或命名空间问题。第三个要检查的是 ROS_DOMAIN_ID。这个概念在第 2 节提过但这里必须再次强调如果你启动两个节点的终端环境里ROS_DOMAIN_ID设置不一致或者一个有一个没有它们就处于不同的“通信域”谁也找不到谁。解决办法是让两个终端保持相同的环境变量最简单的方式是都通过~/.bashrc设置成同一个固定值比如 0。4.5 海龟撞墙“消失”了很多新手第一次看到这种情况会吓一跳海龟走到窗口边缘然后整个进程报错退出窗口关闭。这其实是 turtlesim 有意设计的“越界保护”机制海龟一旦超出边界仿真器节点会直接终止。现实中这对应着机器人的安全逻辑——永远不应该让机器人无限制地冲出去。解决办法很简单重启仿真器节点让海龟回到初始位置。但这件事给我们的启示比现象本身更重要真实机器人系统中运动控制必须考虑边界条件和安全机制。你现在写的是小海龟以后写的是价值不菲的移动平台防碰撞、限位、急停这些逻辑从第一天开始就要养成习惯。4.6 问题排查速查表现象大概率原因排查命令 / 操作apt 找不到软件包ROS 2 源未配置或未 update重配源执行sudo apt updateros2命令不存在环境变量未加载source /opt/ros/humble/setup.bash并写入.bashrc窗口弹不出来显示环境问题echo $DISPLAY配置 X Server键盘控制无效焦点不在终端 / 话题没连上 / 域 ID 不一致切换焦点ros2 topic info /turtle1/cmd_vel海龟越界退出超出仿真边界重启turtlesim_node注意控制移动范围5. 从仿真到实物下一站在哪5.1 把 turtlesim 的思维迁移到真实机器人turtlesim 跑通之后很多人会问一句这和真实机器人有什么关系答案是你在 turtlesim 里搭建的“节点—话题”通信模型在真实机器人上完全复用。举个例子真实差速小车的底盘驱动节点本质就是一个“订阅/cmd_vel输出 PWM 或电机电流”的进程这和turtlesim_node订阅/turtle1/cmd_vel的结构一模一样。唯一的区别是执行器的实现细节——小海龟在屏幕上画线真实小车在物理世界转动轮子。所以当你开始做真实项目时可以先在仿真里验证你的控制逻辑再替换掉底层的执行节点。很多团队的实际开发流程就是这样先用 turtlesim 或 Gazebo 把上层逻辑比如导航、路径规划调通再接到真实硬件上。这样做有两大好处一是调试效率高不用每次改代码都下地跑车二是安全算法没验证之前不会直接控制真机。5.2 当目标变成 ESP32 这类单片机micro-ROS 的衔接如果你后续想把 ROS 2 跑到 ESP32、STM32 这类资源受限的单片机上会接触到 micro-ROS。它相当于 ROS 2 的一个瘦身版客户端层让单片机用非常小的内存开销接入 ROS 2 网络。在 micro-ROS 的世界里话题、节点、服务的概念和你在 turtlesim 里学的一模一样只是底层传输方式变成了串口、WiFi 或无线串口消息格式也要考虑带宽。我建议学习的路线是先彻底吃透本篇的 turtlesim 内容再用虚拟机构建多机通信场景最后再用 micro-ROS 连物理开发板。每一步都在加深“分布式通信”这个核心心智模型。基础打牢之后再上硬件你会发现自己不是在那对着报错乱试而是能清晰地指出问题出在哪个环节——是话题没通、是时序不对、还是执行端故障。我在实际带新人时一直强调一个观点不要因为 turtlesim 只是个“玩具”就轻视它。你现在在这个玩具上建立的每个概念、踩过的每个坑都是后面真实机器人开发中最宝贵的判断力来源。把这一节彻底吃透比你囫囵吞枣跑十个 demo 都有用。