资讯动态

ROS2入门实战:用turtlesim和Gazebo玩转机器人开发

发布时间:2026/9/7 21:21:08 来源:尧图企业网站定制
昨天营地里最安静的时刻是每个人都在跟自己的 Ubuntu 24.04 较劲。安装 ROS2 Jazzy、加载环境变量、第一次敲出ros2 run demo_nodes_cpp talker看到终端里一行行刷出字符串那场面确实像看到烟花。但说实话Day 1 结束时的兴奋基本停留在装好了三个字上真正理解 ROS2是从 Day 2 开始的——我们要让小海龟跑起来让每个学生亲眼看见节点话题消息这些抽象概念到底长什么样。这篇内容适合三类人看带少年创客营、学校社团、或者在家里折腾机器人的老师和家长正在带初中生做机器人项目、却经常被节点为什么连不上卡住的技术志愿者当然还有自学 ROS2 卡在第一个周末的爱好者。网上搜ros2 菜鸟教程能搜出一堆命令但多数教程默认你已经知道为什么要敲这些命令而 Day 2 要补的恰恰是这个为什么。这一天的目标不多跑一只乌龟、看懂一张数据流图、认识一组坐标系、打开一个仿真世界。全部跑通之后学生就有资格说自己从零到一接触过真正的 ROS2 了。1. 从装好了到让它动起来Day 2 必须先完成的验收入门Day 1 最容易踩的坑是我明明装了为什么ros2命令找不到。说穿了就是环境变量的问题。ROS2 安装完成后所有命令、库、工具的路径都写在/opt/ros/jazzy/setup.bash里不在每个终端 source 一次shell 就根本不知道ros2在哪里。所以我的 Day 2 第一课不是新知识是让学生打开终端先敲三行source /opt/ros/jazzy/setup.bash echo source /opt/ros/jazzy/setup.bash ~/.bashrc ros2 --version第一行让当前终端生效第二行让以后每次打开终端自动生效第三行验证安装结果。这一步不能省尤其在教室里二十多台电脑有的学生加过.bashrc有的没加后面几十条指令会全面翻车。另外如果有人同时装了 Humble 和 Jazzy 两个版本终端里重复 source 会导致环境变量互相覆盖后加载的版本会盖掉前面的。排查方法也简单which ros2和ros2 --version对一下看实际生效的是哪一套。那 Day 2 的验收标准怎么定我不写能启动 turtlebot3这种模糊目标而是给学生三条可以自检的标准能用自己的话说清楚节点、话题、消息、服务是什么能让两个节点通过话题通信并在 rqt_graph 里画出连线能在 rviz2 里看到坐标系在 gazebo 里看到一台机器人模型。这三条恰好覆盖从能装到能用的中间地带。后面几节课就是围绕这三条标准逐项展开。这里我想多说一句给少年营讲课最忌讳的就是把 Day 2 变成命令行背诵课。学生照着 PPT 敲二十行命令敲完不知道发生了什么第二天全忘。所以接下来所有内容我都设计成先预测再运行再解释的节奏让他们在动手之前先想一步。2. 小海龟不是玩具用一只龟装下节点、话题、消息这三个核心概念如果只能选一个程序向初学者介绍 ROS2我一定会选 turtlesim。它足够简单简单到只有一个画布和一只乌龟又足够典型因为它的背后完整地展示了 ROS2 最核心的通信模型。打开第一个终端启动海龟窗口ros2 run turtlesim turtlesim_node再开第二个终端启动键盘控制ros2 run turtlesim turtle_teleop_key按住方向键小乌龟开始移动。此时整个系统里发生了这样一件事turtle_teleop_key节点把键盘的方向键转换成速度指令发布到/turtle1/cmd_vel这个话题上turtlesim_node节点订阅了这个话题读到了速度数据然后刷新画布让乌龟移动。这就是 ROS2 最基础的计算图节点通过话题收发消息。为了让学生彻底理解我会让他们逐个运行这几条命令并观察输出ros2 node list ros2 topic list ros2 topic info /turtle1/cmd_vel ros2 topic echo /turtle1/cmd_vel ros2 topic hz /turtle1/cmd_velnode list能看到当前在线的节点topic list能看到所有话题topic info能查看话题的类型和发布/订阅者topic echo则把话题上流动的数据实时打印出来。最让人兴奋的是最后一条按住方向键的同时终端里冒出一串linear.x: 2.0、angular.z: 1.5之类的数据。那一刻学生才真正明白所谓的机器人控制在底层其实就是这样的数字流在节点之间飞来飞去。这就要说到消息类型了。/turtle1/cmd_vel的数据类型是geometry_msgs/msg/Twist。Twist 从英语直译是扭转在机器人领域里它表示速度指令由两部分组成linear线速度单位 m/s只关注 x、y、z 三个方向angular角速度单位 rad/s表示绕 x、y、z 三轴旋转的速度。对小海龟来说linear.x控制前进后退angular.z控制左右转向。键盘上上/下对应修改linear.x左/右对应修改angular.z。这个把按键映射成期望速度的套路在真实机器人里也一样遥控器控制底盘、手柄控制机械臂本质上都是把人手动作转换成速度指令再发布出去。顺带提一个后续经常用到的消息类型sensor_msgs/msg/Imu。IMU 是惯性测量单元它输出的是角速度angular_velocity和线加速度linear_acceleration有的还带姿态四元数orientation数据里还包含各自的协方差矩阵用来告诉下游这个数据我有多大把握。初学者常把 Twist 和 Imu 搞混其实记一句话就够Twist 是我希望它怎么动的控制指令Imu 是它实际上感受到了怎样的运动的测量反馈。控制指令告诉你该往哪走测量反馈告诉系统现在到底在哪。如果只停留在用键盘控制学生很快就会问能不能不让乌龟听按键指挥让它自己画个圈这就是 Day 2 的第一个动手小项目。我用一个最简单的 Python 脚本先绕开 ROS2 包管理的复杂性直接用rclpy写一个发布者import rclpy from rclpy.node import Node from geometry_msgs.msg import Twist class DrawCircle(Node): def __init__(self): super().__init__(draw_circle) self.pub self.create_publisher(Twist, /turtle1/cmd_vel, 10) self.timer self.create_timer(0.1, self.timer_callback) def timer_callback(self): msg Twist() msg.linear.x 2.0 msg.angular.z 2.0 self.pub.publish(msg) def main(argsNone): rclpy.init(argsargs) node DrawCircle() rclpy.spin(node) node.destroy_node() rclpy.shutdown() if __name__ __main__: main()运行方式很简单只要环境变量加载好直接python3 draw_circle.py乌龟就会自动画圆。为什么要单独给个定时器而不用一个 while 循环因为rclpy.spin()是 ROS2 的事件循环定时器回调才是 rclpy 推荐的消息发布方式这样的节点能被 CtrlC 干净地退出不会产生僵尸进程。这个例子虽然小但完整覆盖了创建节点、创建 Publisher、构造消息、按周期发布这四步后面的传感器发布、导航指令发布全是这个模板的变体。需要说明的是正式项目里我们会把这个脚本放进一个 ROS2 包里去 build但 Day 2 先跑通最重要建包的工作可以放到 Day 3。3. rviz2 装好只是第一步真正难的是搞清楚 TF 坐标系小海龟跑起来之后学生通常热情高涨这时候我顺势把 rviz2 摆上台面。rviz2 是 ROS2 的通用可视化工具机器人模型、传感器点云、激光数据、路径规划结果、坐标变换关系都能在一个三维场景里显示出来。安装命令很简单sudo apt install ros-jazzy-rviz2启动更简单ros2 run rviz2 rviz2但几乎每个第一次打开 rviz2 的人都会懵一个灰色网格什么都没有。绝大多数人这时候以为软件坏了其实不是。rviz2 默认不加任何显示内容你需要手动 Add 一个 Display。常用的包括 Grid、TF、RobotModel、LaserScan、Map 等。所谓 Display就是告诉 rviz2你想看什么数据、用什么方式画出来。这里真正的难点不是 rviz2 的操作而是它背后那个叫 TF 的东西。TF 是 ROS 里维护坐标变换关系的框架。简单说机器人身上有无数个坐标系底盘中心、激光雷达安装位置、摄像头中心、机械臂末端每一个部件都有自己的原点。TF 就是记录这些坐标系之间相对位置和姿态的树状结构。我给学生的类比是这样的TF 树就像一家人在小区里的位置关系。map是城市地图坐标系它管的是整个小区的全局位置odom是你从出门开始用手机计步器累计出来的我大概走了多远的坐标系它从起点一点一点累积所以会有漂移base_link是机器人自己的身体坐标系以它自己的中心为原点激光雷达装在左前还是右后就看它相对base_link平移了多少。这三个坐标系在后续导航里反复出现现在先让学生记住map负责全局地图odom负责短时的里程估算base_link负责机器人的身体姿态。为了直观感受 TF可以做一个最简单的实验。在 rviz2 里把 Fixed Frame 设成map然后打开一个终端发布一个静态坐标变换ros2 run tf2_ros static_transform_publisher 0 0 0 0 0 0 map base_link然后到 rviz2 左侧 Display 里点 Add选择 TF场景里会出现一个显示坐标系的小箭头。这个命令的意思是base_link相对于map没有平移、没有旋转固定在同一个位置。虽然实际机器人里这些坐标变换通常由robot_state_publisher或者里程计节点发布但手动发布一次静态 TF能让学生很快理解坐标系是发布出来的、可以被订阅显示的这个本质。rviz2 显示不出来九成是下面几个原因终端没有 source 环境rviz2 版本不对Fixed Frame 选了一个当前 TF 树里不存在的坐标系发布 TF 的节点根本没启动或者static_transform_publisher的坐标参数顺序写错机器人模型文件路径不对robot_description参数里没有内容。其中最容易忽略的是第二个。很多小车启动后节点实际发布的是base_link和odom但 rviz2 默认 Fixed Frame 是map于是一打开就报红显示Frame [map] does not exist。解决办法很简单把顶部 Fixed Frame 改成base_link或者odom就好。这个细节如果不提前讲几十个学生同时举手问为什么是红色那场面会很酸爽。4. 从键盘控制到自主导航先看懂我在哪、去哪、怎么走当学生已经习惯了用键盘控制机器人几乎百分之百会问同一个问题能不能让它自己走这个问题就是机器人导航。这时候千万别急着给他们上 Nav2 安装教程而是先把导航拆开让他们理解自己走这件事到底包含哪几个子问题我在哪——定位问题我要去哪——目标点问题怎么走——路径规划问题路上遇到障碍怎么办——局部避障与速度控制问题。用日常场景解释就是从家走到学校你得先知道自己站在小区哪个门的门口这是定位打开手机地图选学校和校门这是全局路径规划走到半路发现前面修路临时绕道这是局部避障每一步迈多大、往哪偏这是底层的速度控制。对应的 ROS2 导航栈是一堆互相配合的节点map_server加载地图AMCL负责在地图上定位planner_server做全局路径规划controller_server做局部路径跟踪与避障。它们之间同样通过话题和服务通信。这样讲学生能理解导航不是一个程序而是一个由很多节点组成的团队。这个心智模型一旦建立后面学什么模块都不会慌。热词里有八叉树地图导航这里简单解释一句常见的 2D 导航地图是一张黑白栅格图黑的是障碍物、白的是自由空间适合地面小车但在三维环境里比如无人机、带机械臂的机器人在室内穿行就需要表达哪个位置有东西、哪个位置是空的八叉树地图OctoMap就是把三维空间不断切成八个小块、最终用体素记录占据状态的建模方式。它的好处是内存占用随环境复杂度变化不会简单地空间越大越吃内存这对资源有限的机器人平台尤其友好。说到资源受限机器人创客营里很常见的就是树莓派小车、RK3588 开发板、甚至 ESP32 加简易底盘的组合。我给带队老师的建议是不要指望这类板子直接跑完整的 Nav2 全家桶。Nav2 对 CPU 和内存的要求不低在树莓派 4B 上硬跑通常会很卡。更务实的路线是让小车只负责采集传感器数据里程计、IMU、激光把计算放在电脑上先用 Gazebo 仿真跑通导航逻辑再降级到真机如果坚持用板载计算就要尽量避免同时开 rviz2 做可视化把可视化放到远程电脑。这个取舍思路其实就是工程里常说的计算卸载。在少年营阶段把这个思维教给学生比多跑通一个 demo 更有价值。另外如果学生手头是 bittle 这类四足机器人它也支持 ROS2但这类平台的躯干姿态更复杂需要额外理解关节反馈和 IMU 的融合建议放到后面的进阶课再说。5. 为什么我建议创客营第一站选 Gazebo而不是那些更炫的仿真器真机机器人对少年营来说有几个天然难题贵、娇气、容易撞坏、充电麻烦。所以第一台机器人用仿真器来当再合适不过。但市面上的仿真器不少有的看起来特别炫酷集成却让人头疼。先放一张对比表仿真器开源免费资源占用ROS2 集成青少年上手难度适合场景Gazebo是中等非常成熟中等多数 ROS2 教学项目、机器人算法验证Webots是较低较成熟较低教学过程、机器人比赛Isaac Sim免费但需账号很高强高具身智能研究、大规模渲染我的结论非常明确入门阶段用 Gazebo。理由有三。第一它的 ROS2 集成经过多年打磨ros_gz桥接工具能直接让仿真里的传感器数据通过 ROS2 话题发布出来学生切换真机和仿真时代码几乎不用改。第二社区资料庞大随便一个常见机型都能找到现成的模型。第三它对硬件要求不苛刻集成显卡也能跑简单的场景而 Isaac Sim 这类工具对显卡的要求会让一半学生的电脑当场阵亡。在 Ubuntu 24.04 ROS2 Jazzy 的环境下安装流程比网上很多教程写的要简单。当前 ROS2 Jazzy 默认配套的 Gazebo 版本是 Harmonic直接安装桥接包即可sudo apt update sudo apt install ros-jazzy-ros-gz装完以后可以先用一个空世界验证ros2 launch ros_gz_sim gazebo.launch.py如果能看到 Gazebo 窗口打开说明桥接层没问题。很多学生卡在这一步常见原因主要有三个一是 Ubuntu 版本和 ROS2 发行版不匹配比如在 22.04 上硬装 Jazzy 的包导致依赖冲突二是 Gazebo 模型文件下载速度慢界面卡在Downloading model三是显卡驱动有问题渲染窗口黑屏或闪退。模型下载的问题可以通过提前把常用模型库放到本地并设置GZ_SIM_RESOURCE_PATH环境变量来解决渲染卡顿可以先试试关闭 GUI 只用 headless 模式跑等确认流程没问题再开窗口。空世界进去以后再上真实一点的场景。我常用 TurtleBot3 的 Gazebo 环境来做第一次机器人上路体验sudo apt install ros-jazzy-turtlebot3-gazebo ros-jazzy-turtlebot3-teleop export TURTLEBOT3_MODELburger ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py不出意外会看到一个仿真小屋里有一台两轮小车。另一个终端里启动键盘遥控export TURTLEBOT3_MODELburger ros2 run turtlebot3_teleop teleop_keyboard然后让学生在终端里按方向键Gazebo 里的小车开始移动。这也是他们第一次在没有物理硬件的情况下看到键盘速度指令 → 仿真物理引擎 → 机器人模型位移的完整链路。这里的TURTLEBOT3_MODEL环境变量特别容易漏launch 文件读取模型类型全靠它不 export 会直接报模型未找到。由于 Shell 环境变量是终端级的所以 launch 和 teleop 必须在各自终端里分别设置。这一步跑通之后每个学生都拥有了一台怎么摔都不心疼的机器人。后面无论是测试激光数据、跑 SLAM、测导航算法都可以在仿真里大胆折腾。6. 少年创客营 Day 2 课堂实录三个最容易翻车的环节和我的处理方式最后这部分写给带队老师。Day 2 内容不算多但实际操作时总有让人哭笑不得的状况。我踩过三轮课才总结出下面三个高频翻车点提前说透能省一半时间。第一个是终端混乱。学生照着教程开七八个终端每个终端都在跑不同节点很快分不清哪个对应哪个。我现在的规矩是一个终端只跑一个节点开新终端之前先在标题栏写上节点名。在 GNOME 终端里可以右键选择Profile Preferences改标题或者在命令里加上--ros-args --remap __node:my_name给节点重命名。另外强烈建议把ros2 node list和ros2 topic list作为必查命令教给学生一旦分不清谁在做什么就敲这两条救场。第二个是 teleop 键盘没反应。排查思路很固定先确认turtlesim_node还活着再确认 teleop 窗口有焦点最后用ros2 topic hz /turtle1/cmd_vel检查话题上到底有没有数据在流动。多数情况下是学生把终端焦点点到了别的地方按下方向键全被其他地方吃掉了。如果话题上有数据但乌龟不动那就换成检查turtlesim_node是不是订阅了同一个话题名。这套排查链路不只是在乌龟demo里能用到了真实底盘上也一样。第三个是教室局域网里的互相干扰。一个教室二十台电脑共用同一个 WiFi所有学生的 ROS2 节点都在同一个网络域里默认的ROS_DOMAIN_ID都是 0就会出现我控制不了我的乌龟隔壁同学却把我的乌龟开走了的灵异事件。解决办法很简单在每台电脑的~/.bashrc里设置一个互不重复的编号echo export ROS_DOMAIN_ID5 ~/.bashrc source ~/.bashrcROS_DOMAIN_ID是 ROS2 的 DDS 域隔离机制可以把同一个物理网络里的不同选手隔开。这个参数只影响 DDS 的域参与者不影响使用体验但对多人教学来说几乎是必须配置的。如果不做这步演示导航的时候你会发现全班机器人的轨迹全都纠缠在一起。下面是一张 Day 2 课堂检查清单带队老师可以直接当验收表用阶段检查命令通过标准环境验收ros2 --version显示 Jazzy 版本号节点通信ros2 node list能看到turtlesim和teleop节点话题数据ros2 topic echo /turtle1/cmd_vel按键时出现 Twist 数据发布频率ros2 topic hz /turtle1/cmd_vel频率 10Hz 左右节点关系rqt_graph能看到两个节点通过话题连线坐标可视化rviz2 中添加 TF能看到map到base_link的坐标系仿真运行turtlebot3_world.launch.py小车在 Gazebo 中可被键盘控制时间分配上如果只有 3 小时的半天营我建议30 分钟环境验收50 分钟 turtlesim40 分钟 rviz2 和 TF50 分钟 Gazebo 小车最后 10 分钟学生互相展示。如果有 5 小时就加入自己写画圆节点、以及让 TurtleBot3 在 rviz2 里显示激光数据这两个拓展内容。Day 2 不要塞太多内容贪多学生反而容易混。最后说一个小技巧每完成一个环节让学生先猜一猜下一条命令会输出什么再运行验证。我之前并不认为这个习惯有多神奇但真正在课堂里试过之后才发现学生看到预测键盘按下时 topic echo 会打印linear.x: 2.0变成现实的那一刻比他们机械敲完一百条命令记住的还要多。Day 2 的课就到这里下一节可以试试让机器人自己完成导航任务那又是一个全新的世界。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价