ROS2 机器人 少年创客营:Day 6

🤖 ROS2 机器人 少年创客营:Day 6

主题:一键启动的魔法 ------ Launch 文件与动态参数

👋 欢迎回来,系统架构师!

昨天回顾 :我们掌握了 Action,让机器人能执行长任务并随时中断。现在的你,已经拥有了控制机器人的"三把利剑":Topic(广播)、Service(电话)、Action(遥控导弹)。

今天的痛点

看看你现在的桌面,为了运行一个项目,你需要打开多少个终端?

  1. ros2 run turtlesim turtlesim_node
  2. ros2 run my_turtle_bot go_to_goal
  3. ros2 run rqt_graph rqt_graph (看拓扑图)
  4. ros2 run rviz2 rviz2 (看可视化)

太麻烦了! 如果每次都要手动敲这么多命令,不仅手酸,还容易敲错。而且,如果想把海龟的背景色改成蓝色,难道要修改代码重新编译吗?

今日目标

  1. ⚡ 一键启动 :学习 Launch Files,用一行命令启动整个机器人系统。
  2. 🎛️ 动态配置 :掌握 Parameters (参数),不改代码就能调整机器人的行为(颜色、速度、目标点)。
  3. 🏗️ 工程化:将前几天的散乱脚本整合成一个专业的、可交付的 ROS 2 项目。

🗺️ 今日探险地图 (Checklist)

  • 📜 概念解锁:理解 Launch 文件的作用(导演 vs 演员)。
  • 🐍 语法入门 :编写第一个 Python 格式的 Launch 文件 (my_first_launch.py)。
  • 🎛️ 参数魔法:在代码中读取参数,并在 Launch 文件中动态赋值。
  • 🚀 实战演练:创建一个"超级启动器",同时启动仿真器、导航节点和可视化工具。
  • 🎨 创意挑战:设计一个"变色龙模式",通过命令行参数一键切换海龟颜色和背景。

📜 第一关:Launch 文件 ------ 机器人的"总导演"

如果把每个 ROS 节点(Node)比作一个演员 ,那么 Launch 文件 就是总导演

  • 演员 (Node):只负责演好自己的戏(发速度、收数据)。
  • 导演 (Launch):负责喊"Action"(启动所有节点)、安排座位(设置参数)、协调灯光(配置环境变量)。

为什么需要它?

  1. 自动化:一行命令启动几十个节点。
  2. 灵活性:可以在启动时动态修改参数(如:今天让海龟跑快点,明天跑慢点),无需重新编译代码。
  3. 复用性:把复杂的启动逻辑写死在文件里,别人只需运行一次即可。

💡 知识点 :ROS 2 推荐使用 Python 编写 Launch 文件(后缀 .launch.py),因为它比 XML 更灵活、更强大!


🎛️ 第二关:参数 (Parameters) ------ 让代码"活"起来

在写 Launch 文件之前,我们先改造一下之前的代码,让它支持外部配置

1. 改造 go_to_goal.py

打开 src/my_turtle_bot/my_turtle_bot/go_to_goal.py,我们将硬编码的目标坐标改为参数

python 复制代码
# ... 前面的 import 不变 ...

class GoToGoalNode(Node):
    def __init__(self):
        super().__init__('go_to_goal_node')
        
        # 🆕 声明参数 (带默认值)
        # 格式:self.declare_parameter(参数名, 默认值)
        self.declare_parameter('goal_x', 5.5)
        self.declare_parameter('goal_y', 5.5)
        self.declare_parameter('max_speed', 2.0)
        
        # 🆕 获取参数值
        # 如果 Launch 文件传了新值,就用新值;否则用默认值
        self.goal_x = self.get_parameter('goal_x').value
        self.goal_y = self.get_parameter('goal_y').value
        self.max_speed = self.get_parameter('max_speed').value
        
        self.reached_goal = False
        self.current_pose = None
        
        # ... 发布者和订阅者创建不变 ...
        
        # 修改日志,显示当前配置
        self.get_logger().info(f'🚀 导航启动!目标:({self.goal_x}, {self.goal_y}), 限速:{self.max_speed}')

    # ... control_loop 中的速度限制改为使用 self.max_speed ...
    # 原代码:speed = min(2.0, distance * 2.0)
    # 新代码:speed = min(self.max_speed, distance * 2.0)
    
    # ... 其余代码不变 ...

✅ 效果:现在,你可以不修改代码,直接通过命令行改变海龟的目标和速度!

bash 复制代码
# 默认运行 (去 5.5, 5.5)
ros2 run my_turtle_bot go_to_goal

# 自定义运行 (去 9.0, 1.0,且最高速度 1.0)
ros2 run my_turtle_bot go_to_goal --ros-args -p goal_x:=9.0 -p goal_y:=1.0 -p max_speed:=1.0

💻 第三关:编写 Launch 文件 (核心时刻!✨)

现在,我们要编写一个"总导演"脚本,自动启动一切。

1. 创建文件

在功能包根目录下创建一个新文件夹 launch,并在其中新建 turtle_party.launch.py

  • 路径:src/my_turtle_bot/launch/turtle_party.launch.py

2. 编写代码

python 复制代码
#!/usr/bin/env python3
# 🆕 引入 Launch 相关的库
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node

def generate_launch_description():
    """
    这是 Launch 文件的入口函数。
    它必须返回一个 LaunchDescription 对象,里面包含了所有要启动的动作。
    """
    
    # --- 1. 定义可配置的参数 (让用户能在命令行修改) ---
    # 格式:DeclareLaunchArgument('参数名', default_value='默认值', description='说明')
    goal_x_arg = DeclareLaunchArgument(
        'goal_x',
        default_value='5.5',
        description='Target X coordinate for the turtle'
    )
    
    goal_y_arg = DeclareLaunchArgument(
        'goal_y',
        default_value='5.5',
        description='Target Y coordinate for the turtle'
    )
    
    bg_color_arg = DeclareLaunchArgument(
        'bg_color',
        default_value='0x4556FF', # 默认蓝色
        description='Background color hex code (e.g., 0x000000 for black)'
    )

    # --- 2. 读取配置 ---
    # 将刚才声明的参数转换为可以在 Node 中使用的变量
    goal_x = LaunchConfiguration('goal_x')
    goal_y = LaunchConfiguration('goal_y')
    bg_color = LaunchConfiguration('bg_color')

    # --- 3. 定义要启动的节点 (Nodes) ---
    
    # 节点 A: 海龟仿真器
    turtlesim_node = Node(
        package='turtlesim',
        executable='turtlesim_node',
        name='simulator',
        parameters=[{'background_r': 69, 'background_g': 86, 'background_b': 255}] # 这里可以硬编码,也可以用参数
        # 🆕 进阶:可以通过 LaunchConfiguration 动态设置背景色,此处为简化先写死或略过复杂转换
    )

    # 节点 B: 我们的导航脚本
    navigator_node = Node(
        package='my_turtle_bot',
        executable='go_to_goal', # 对应 setup.py 里的 entry_points 名字
        name='navigator',
        output='screen', # 🌟 重要:将节点的日志输出到当前终端,方便调试
        parameters=[
            {'goal_x': goal_x}, # 🌟 关键:将 Launch 的参数传给节点
            {'goal_y': goal_y},
            {'max_speed': 1.5}
        ]
    )
    
    # 节点 C: (可选) 自动打开 rqt_graph 查看拓扑
    # rqt_node = Node(package='rqt_graph', executable='rqt_graph')

    # --- 4. 返回总导演计划 ---
    return LaunchDescription([
        goal_x_arg,
        goal_y_arg,
        bg_color_arg,
        turtlesim_node,
        navigator_node
        # rqt_node
    ])

🔧 第四关:注册与运行 (避坑指南)

⚠️ 关键步骤:修改 setup.py

为了让 ROS 2 知道我们多了一个 launch 文件夹,必须 更新 setup.py 中的 data_files
常见错误 :忘记导入 glob 模块会导致编译失败 (NameError: name 'glob' is not defined)。

✅ 正确的 setup.py 写法:
python 复制代码
from setuptools import find_packages, setup
import os
import glob  # <--- 🌟 必须添加这一行!否则编译会报错

package_name = 'my_turtle_bot'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/' + package_name, ['package.xml']),
        # 🌟 这行代码会自动查找 launch 文件夹下所有的 .launch.py 文件并安装
        ('share/' + package_name + '/launch', glob.glob(os.path.join('launch', '*.launch.py'))),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='mayf',
    maintainer_email='your_email@example.com',
    description='ROS 2 Turtle Bot Package',
    license='Apache-2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'go_to_goal = my_turtle_bot.go_to_goal:main',
            # 如果有其他脚本,继续在这里添加
            # 'start_action = my_turtle_bot.action_client_turtle:main',
        ],
    },
)

2. 编译

bash 复制代码
cd ~/ROS2
# 推荐清理旧缓存,防止旧错误干扰
rm -rf build/ install/ log/

colcon build --packages-select my_turtle_bot
source install/setup.bash

如果看到 Summary: 1 package finished,恭喜你,成功避开了 glob 陷阱!

3. 见证奇迹:一键启动!

现在,你只需要在一个终端中输入一行命令:

场景 A:默认模式

bash 复制代码
ros2 launch my_turtle_bot turtle_party.launch.py
  • 现象
    1. 海龟仿真器窗口自动弹出。
    2. 导航节点自动启动。
    3. 终端里同时显示两个节点的日志(因为加了 output='screen')。
    4. 海龟自动游向 (5.5, 5.5)。

场景 B:自定义模式 (参数魔法)

bash 复制代码
ros2 launch my_turtle_bot turtle_party.launch.py goal_x:=9.0 goal_y:=1.0
  • 现象
    1. 系统启动。
    2. 导航节点日志显示:"🚀 导航启动!目标:(9.0, 1.0)..."
    3. 海龟乖乖地游向了右下角!
    4. 全程没有修改一行代码,也没有重新编译!

🎨 第五关:创意挑战赛

现在的系统已经很像样了。来挑战更高难度的集成吧!

🌟 挑战等级

  • 🥉 青铜级:背景变色龙 🦎

    • 任务 :修改 Launch 文件,增加 red, green, blue 三个参数。
    • 逻辑 :将这三个参数传递给 turtlesim_nodebackground_r/g/b 参数。
    • 运行ros2 launch ... red:=255 green:=0 blue:=0 (让背景变成红色!)
  • 🥈 白银级:多机派对 🎉

    • 任务 :在 Launch 文件中启动两个 go_to_goal 节点。
    • 技巧 :给它们起不同的名字 (name='nav1', name='nav2'),并传入不同的目标参数。
    • 现象:一只海龟去左上,一只去右下,同时出发!
  • 🥇 黄金级:条件启动 ⚖️

    • 任务 :增加一个布尔参数 use_rviz (默认 false)。
    • 逻辑 :只有当用户输入 use_rviz:=true 时,才启动 rviz2 节点。
    • 提示 :使用 LaunchConfiguration 和 Python 的 IfCondition (需导入 from launch.conditions import IfCondition)。

🆘 常见问题急救包

问题 原因 解决方案
NameError: name 'glob' is not defined setup.py 中使用了 glob 但未导入 setup.py 顶部添加 import glob
Package not found 没编译或没 source 运行 colcon buildsource install/setup.bash
Executable not found setup.py 里的 executable 名字和 entry_points 不一致 检查 Launch 文件里的 executable='go_to_goal' 是否匹配 setup.py 中的 'go_to_goal = ...'
参数没生效 参数名拼写错误或类型不匹配 检查 declare_parameter 的名字是否和 Launch 文件里传递的名字完全一致。
日志不显示 忘记加 output='screen' Node() 定义中添加 output='screen'

📝 Day 6 总结清单

概念 关键词 作用
Launch File .launch.py, LaunchDescription 一键启动多个节点,系统集成的核心
Parameters declare_parameter, get_parameter 代码与配置分离,实现动态调整
LaunchConfiguration LaunchConfiguration('name') 在 Launch 文件中引用命令行参数
Data Files glob, data_files 将 launch 文件打包安装,使其可被 ros2 launch 发现
Output Screen output='screen' 在同一个终端查看所有节点的日志,调试神器

🔮 明日预告 (Day 7 - 结营大典)

恭喜你!你已经掌握了 ROS 2 的核心技能树:

  • 节点、话题、服务、动作 (通信)
  • 定时器、回调、闭环控制 (逻辑)
  • 工作空间、编译、Launch、参数 (工程)

最后一天,我们将举办"黑客马拉松"! 🏆

  • 任务 :综合运用所有知识,设计一个**"智能迷宫逃生""海龟足球赛"**。
  • 展示:你将拥有自己的专属仓库,向全世界展示你的代码。
  • 颁奖:颁发"ROS2 机器人 少年创客营"结业证书。

准备好迎接最终的挑战了吗?明天,让我们创造奇迹!


© 2026 ROS2 机器人 少年创客营 | 从单点突破到系统集成,你已是一名真正的机器人工程师!

相关推荐
码农三叔3 小时前
第三卷:《人形机器人的控制与运动规划》
人工智能·机器人·人形机器人
cici158745 小时前
基于RT-Thread的数字焊机与工业机器人通信网关设计
arm开发·机器人
硅谷秋水7 小时前
世界链:潜运动中的世界模型思维
深度学习·计算机视觉·语言模型·机器人
不熬夜的熬润之8 小时前
KCF算法解析
人工智能·算法·计算机视觉·机器人
kyle~8 小时前
ROS2---客户端服务(rclcpp::Client)
c++·物联网·机器人·ros2
日月星辰cmc9 小时前
【开源】Groot2风格行为树可视化监控软件,能展示20个节点以上
机器人·开源软件·行为树
雪碧聊技术9 小时前
具身智能元年已至?智元机器人量产上汽产线,人形机器人不再“只会跳舞”
机器人
熵减纪元1 天前
亚马逊下场抢人形机器人了:Sprout 被收编,家庭陪伴赛道开始热起来
机器人
进击切图仔1 天前
Docker + tmux + ROS:持久化的机器人开发环境
docker·容器·机器人