ros_tutorials 源码详细分析
工作区路径:/home/cp/work2/ros2Learn/ros2_humble/src/ros/ros_tutorials
仓库:github.com/ros/ros_tutorials
ros_tutorials 是 ROS 官方入门教程集合,包含经典 turtlesim 仿真器及 ROS 1 时代的 C++/Python 教程。在 ROS 2 Humble 工作区中,只有 turtlesim 是 ament 包、会被实际编译;roscpp_tutorials 与 rospy_tutorials 仍为 catkin/ROS 1 遗留代码,供参考,不参与 ROS 2 构建。
1. 仓库结构总览
1 | ros_tutorials/ |
| 包 | 构建系统 | ROS 2 可编译 | 版本 | 作用 |
|---|---|---|---|---|
turtlesim |
ament_cmake | ✅ | 1.4.3 | 交互式小乌龟仿真,ROS 2 官方教程标配 |
roscpp_tutorials |
catkin | ❌ | 0.9.1 | roscpp API 分步示例 |
rospy_tutorials |
catkin | ❌ | 0.9.1 | rospy API 分步示例 |
ros_tutorials |
catkin metapackage | ❌ | 0.9.1 | 聚合上述三包 |
2. 在 ROS 2 生态中的角色
flowchart LR
subgraph tutorials [ros_tutorials]
TS[turtlesim_node\nQt GUI]
TELEOP[turtle_teleop_key]
DRAW[draw_square]
MIMIC[mimic]
end
subgraph concepts [演示的 ROS 2 概念]
TOPIC[Topic 发布/订阅]
SRV[Service 请求/响应]
ACT[Action 长时间任务]
PARAM[Parameter 动态配置]
end
subgraph users [典型使用者]
DOC[官方文档教程]
LEARN[初学者实验]
TEST[多节点/多命名空间测试]
end
TS --> TOPIC & SRV & ACT & PARAM
TELEOP --> TOPIC & ACT
DRAW --> TOPIC & SRV
MIMIC --> TOPIC
tutorials --> usersturtlesim 是 ROS 2 “Hello World” 级演示平台:比 demo_nodes_cpp 更直观,覆盖 topic、service、action、parameter 四类通信原语。
3. turtlesim — 架构设计
3.1 类层次
1 | TurtleApp (QApplication + rclcpp::init) |
| 类 | 文件 | 职责 |
|---|---|---|
TurtleApp |
turtlesim.cpp |
初始化 rclcpp + Qt 事件循环 |
TurtleFrame |
turtle_frame.cpp/h |
画布、定时器、乌龟生命周期管理 |
Turtle |
turtle.cpp/h |
单龟 ROS 接口、运动积分、绘制 |
3.2 Qt + rclcpp 融合模式
核心在 TurtleFrame::onUpdate():
1 | void TurtleFrame::onUpdate() |
- QTimer 16ms(约 60Hz)驱动 GUI 刷新
- 每帧调用
rclcpp::spin_some处理回调,避免阻塞 Qt 主线程 - 这是 GUI 节点中 rclcpp 与 Qt 集成的经典模式
3.3 坐标系
- 内部仿真:
pos_以米为单位,Y 轴向下(屏幕坐标) - 对外
Pose.msg:Y 轴向上(y = canvas_height - pos_.y()) - 角度
theta:弧度,逆时针为正
4. ROS 2 接口一览
4.1 节点级服务(/turtlesim 节点)
| 服务 | 类型 | 功能 |
|---|---|---|
/spawn |
turtlesim/srv/Spawn |
创建新乌龟 |
/kill |
turtlesim/srv/Kill |
删除指定乌龟 |
/clear |
std_srvs/Empty |
清除轨迹 |
/reset |
std_srvs/Empty |
重置为单龟初始状态 |
4.2 每只乌龟的接口(以 turtle1 为例)
| 类型 | 名称 | 消息/服务类型 |
|---|---|---|
| 订阅 | /turtle1/cmd_vel |
geometry_msgs/Twist |
| 发布 | /turtle1/pose |
turtlesim/Pose |
| 发布 | /turtle1/color_sensor |
turtlesim/Color |
| 服务 | /turtle1/set_pen |
turtlesim/SetPen |
| 服务 | /turtle1/teleport_relative |
turtlesim/TeleportRelative |
| 服务 | /turtle1/teleport_absolute |
turtlesim/TeleportAbsolute |
| Action | /turtle1/rotate_absolute |
turtlesim/RotateAbsolute |
4.3 自定义消息/服务/Action
Pose.msg — 位姿 + 速度反馈:
1 | float32 x, y, theta |
RotateAbsolute.action — ROS 2 Action 教程示例:
1 | # Goal |
Spawn.srv — 可选名称,空则自动生成 turtle2、turtle3…
5. Turtle 类核心逻辑
5.1 构造:注册 ROS 接口
1 | Turtle::Turtle(...) |
5.2 运动学更新(update)
每帧 dt ≈ 0.016s 执行:
- Teleport 请求(相对/绝对瞬移,可画线)
- Action 旋转:向目标角
theta以 ±1.0 rad/s 旋转,发布 feedback/result - 速度超时:超过 1 秒无
cmd_vel则速度归零 - 积分运动:
1 | orient_ = orient_ + ang_vel_ * dt; |
- 边界 clamp — 撞墙警告并限制在画布内
- 发布 pose 和 color_sensor(读取轨迹图像像素 RGB)
5.3 Action 与 cmd_vel 互斥
收到 cmd_vel 时会 abort 正在执行的 rotate_absolute goal;收到新 rotation goal 也会 abort 前一个。体现 Action 与连续控制的分工。
6. TurtleFrame 管理逻辑
6.1 启动
- 声明参数
background_r/g/b(0–255,默认蓝紫色#4556ff) - 从
share/turtlesim/images/加载 9 种乌龟皮肤(ardent, foxy, humble 等发行版命名) - 默认 spawn 一只
turtle1在画布中心 - 订阅
/parameter_events以响应背景色变更
6.2 乌龟命名
1 | if (real_name.empty()) |
空名称自动生成;重名 spawn 返回失败。
7. 教程可执行文件
CMakeLists 构建 4 个目标:
| 可执行文件 | 源码 | 演示内容 |
|---|---|---|
turtlesim_node |
src/*.cpp |
主仿真器 |
turtle_teleop_key |
teleop_turtle_key.cpp |
键盘控制 + Action 客户端 |
draw_square |
draw_square.cpp |
状态机画正方形 |
mimic |
mimic.cpp |
订阅 pose 转发 cmd_vel |
7.1 turtle_teleop_key
- 原始终端模式读键盘(Unix
termios/ WindowsReadConsoleInput) - 方向键 → 发布
Twist到turtle1/cmd_vel - G/B/V/C/D/E/R/T → 发送
RotateAbsoluteaction goal - 独立线程
rclcpp::spin处理 action 回调
7.2 draw_square
有限状态机:FORWARD → STOP_FORWARD → TURN → STOP_TURN → ...
- 订阅
turtle1/pose获取反馈 - 发布
turtle1/cmd_vel控制运动 - 启动时调用
/reset服务 - 典型 闭环控制 入门示例
7.3 mimic
1 | twist_pub_ = this->create_publisher<geometry_msgs::msg::Twist>("output/cmd_vel", 1); |
配合 remapping 可实现「一只龟模仿另一只」:
1 | ros2 run turtlesim mimic --ros-args \ |
8. 多实例与 Launch
1 | return LaunchDescription([ |
命名空间隔离后,话题变为 /turtlesim1/turtle1/cmd_vel 与 /turtlesim2/turtle1/cmd_vel,演示 namespace 机制。
9. 依赖关系
1 | turtlesim |
10. roscpp_tutorials(ROS 1 遗留)
构建系统:catkin + roscpp + rosconsole
按子目录组织的 C++ 教程,覆盖 ROS 1 API:
| 目录 | 主题 |
|---|---|
talker/ / listener/ |
最基本 pub/sub |
add_two_ints_* |
Service 客户端/服务端 |
parameters/ |
参数服务器 |
timers/ |
Timer 回调 |
listener_*_spin |
多种 spin 模式 |
notify_connect/ |
连接/订阅通知 |
node_handle_namespaces/ |
命名空间 |
time_api/sleep/ |
时间 API |
代码使用 #include "ros/ros.h",带 %Tag(...)% 标记供文档系统自动抽取。ROS 2 等价教程在 ros2/examples 和官方文档中,不在此包。
11. rospy_tutorials(ROS 1 遗留)
构建系统:catkin + rospy
按编号组织的 Python 教程:
| 目录 | 主题 |
|---|---|
001_talker_listener/ |
pub/sub 基础 |
002_headers/ |
消息 header |
003_listener_with_user_data/ |
回调 userdata |
004_listener_subscribe_notify/ |
订阅通知 |
005_add_two_ints/ |
Service |
006_parameters/ |
参数 |
007_connection_header/ |
连接头 |
008_on_shutdown/ |
关闭钩子 |
009_advanced_publish/ |
高级发布 |
含与 roscpp_tutorials 交叉测试的 launch 文件(C++ ↔ Python 互通)。同样未移植到 rclpy。
12. 典型使用流程
1 | # 终端 1:启动仿真 |
常用 CLI 实验:
1 | ros2 service call /spawn turtlesim/srv/Spawn "{x: 2.0, y: 2.0, theta: 0.0, name: ''}" |
13. 设计特点与局限
| 特点 | 说明 |
|---|---|
| 教学优先 | API 覆盖全面,代码可读性高 |
| Qt 集成 | spin_some + QTimer 经典 GUI 模式 |
| 多龟支持 | spawn/kill 动态管理 |
| ROS 2 Action | RotateAbsolute 是官方 action 教程载体 |
| 发行版彩蛋 | 乌龟皮肤命名对应 ROS 发行版 |
| 局限 | 说明 |
|---|---|
| 无物理仿真 | 简单运动学积分,非 Gazebo |
| 2D 平面 | 仅 x/y/theta |
| ROS 1 教程未移植 | roscpp/rospy tutorials 在 Humble 中不编译 |
| 单线程 spin_some | 不适合高并发重计算 |
| 无 TF | 不发布坐标变换(与真实机器人栈不同) |
14. 推荐阅读顺序
- 快速体验:运行
turtlesim_node+turtle_teleop_key - 主程序:
turtlesim.cpp→turtle_frame.cpp→turtle.cpp - 接口定义:
msg/、srv/、action/ - 教程节点:
draw_square.cpp(闭环)→mimic.cpp(remapping)→teleop_turtle_key.cpp(action) - 对比 ROS 1 教程:
roscpp_tutorials/talker/talker.cpp与 ROS 2demo_nodes_cpp的差异 - Launch:
multisim.launch.py理解 namespace
15. 小结
ros_tutorials 仓库是 ROS 官方教程的历史集合:在 ROS 2 Humble 中,实际可用的是 turtlesim——一个 Qt + rclcpp 的小乌龟仿真器,完整演示 Topic、Service、Action、Parameter 四大通信机制,并附带键盘遥控、画正方形、mimic 等示例节点。roscpp_tutorials 与 rospy_tutorials 保留 ROS 1 catkin 代码,供 API 对比参考,但不参与 ROS 2 构建。
如果你希望,我可以把本文写入 ros2doc/ros/ros_tutorials 源码详细分析.md,或继续分析 draw_square 状态机与 pose 闭环控制的数学细节。
正在加载留言…