Soup's Blog

Back

ROS2_Moveit2_Ur5e_Grasp项目详解(三):ur5e_gripper_sim_control文件详解Blur image

上一篇文章详细介绍了simulation.launch.py的内容,接下来我们进一步了解launch_setup函数中的代码:

dual_ur5e_gripper_control_launch = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            [FindPackageShare("ur5e_gripper_moveit_config"), "/launch", "/ur5e_gripper_sim_control.launch.py"]
        ),
        launch_arguments={
            "launch_rviz": "true",
        }.items(),
    )
python

可以看到这个代码调用了ur5e_gripper_moveit_config包下的launch目录下的ur5e_gripper_sim_control.launch.py文件,并传入参数launch_rviz,这个代码的作用是加载URDF模型并启动Gazebo仿真环境。

注意,这里使用了FindPackageShare。在ROS 2中,FindPackageShare 函数会

  1. 首先查找已安装的包(在install目录中)
  2. 然后才会查找系统安装的包(如/opt/ros/humble/share/)
  3. 不会直接查找src目录中的源文件

接下来,我们查看ur5e_gripper_sim_control.launch.py的源代码(路径为/home/whisper/ros2_ws/install/ur5e_gripper_moveit_config/share/ur5e_gripper_moveit_config/launch/ur5e_gripper_sim_control.launch.py,但是代码内容与src目录下是一样的):

第一步,先看generate_launch_description函数#

  1. 函数首先创建一个空列表declared_arguments,用于存储所有要声明的launch参数。这些参数可以在运行launch文件时通过命令行进行配置。
  2. 我打印了declared_arguments内容如下: 在这里插入图片描述 可以理解为generate_launch_description函数为launch_setup函数指定了需要加载的参数文件

第二步,看launch_setup函数#

代码如下:

接下来我们在launch_setup函数中对参数值进行解析并打印,内容如下: 在这里插入图片描述 补充

  • DeclareLaunchArgument:用于声明一个可以在启动时传递的参数(命令行参数)。
  • LaunchConfiguration:用于获取和使用在启动时通过 DeclareLaunchArgument 声明并传递的参数的值。
  • 在ROS 2的launch系统中,LaunchConfiguration是一个惰性求值的对象,它只在launch过程中才会被解析为实际值。因此,要获取其实际值,必须在launch上下文环境中使用.perform(context)方法。

launch_setup代码解析一:#

## RViz配置文件路径
    rviz_config_file = PathJoinSubstitution(
        [FindPackageShare(description_package), "rviz", "view_robot.rviz"]
    )
python

这段代码设置了rviz的路径,使用了PathJoinSubstitution组件,与下面的构建路径的方式不同。

register_depth_launch = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            [FindPackageShare("vision"), "/launch", "/register_depth.launch.py"]
        ),
    )
python

区别如下: 在这里插入图片描述 PythonLaunchDescriptionSource是用来加载launch文件的,而PathJoinSubstitution是用来加载其他配置文件的。

launch_setup代码解析二:#

## 机器人描述内容(通过xacro处理URDF文件生成)
    robot_description_content = Command(
        [
            PathJoinSubstitution([FindExecutable(name="xacro")]),
            " ",
            PathJoinSubstitution(
                [FindPackageShare(description_package), "urdf", description_file]
            ),
        ]
    )
    robot_description = {"robot_description": robot_description_content}
    print(f"\033[95mrobot_description: {robot_description}\033[0m")
python

这段代码用于生成机器人的描述内容,通过调用xacro工具处理URDF文件来生成完整的机器人描述。

  1. Command

    • 这是一个用于执行系统命令的工具类
    • 它允许在launch过程中动态执行命令并获取输出结果
    • 命令将在launch时执行,而不是在launch文件解析时执行
  2. PathJoinSubstitution([FindExecutable(name=“xacro”)]):

    • FindExecutable(name=“xacro”)用于查找xacro可执行文件的完整路径
    • PathJoinSubstitution在这里实际上只是将结果转换为字符串
  3. 空格字符串 ” ”:

    • 这是在命令中添加空格分隔符
  4. 第二个PathJoinSubstitution:

    • 构建URDF文件的路径
    • FindPackageShare(description_package)查找包含机器人描述的包
    • “urdf”是子目录名
    • description_file是URDF/XACRO文件名(默认为”ur5e_gripper.urdf.xacro”)

整体功能是构建并执行以下形式的命令:

xacro /home/whisper/ros2_ws/install/ur5e_gripper_moveit_config/share/ur5e_gripper_moveit_config/urdf/ur5e_gripper.urdf.xacro
python

执行这个命令会输出处理后的完整URDF描述,其中所有xacro宏和参数都已展开。

最终,robot_description字典将被用作robot_state_publisher节点的参数:

robot_state_publisher_node = Node(
    package="robot_state_publisher",
    executable="robot_state_publisher",
    output="both",
    parameters=[{"use_sim_time": True}, robot_description],  ## 在这里使用
)
python

这是一个Node对象的定义,用于在launch文件中启动一个ROS 2节点。每个节点都需要指定一个包(package)和可执行文件(executable)来运行。Node的理解参考博客

各参数说明

  • package=“robot_state_publisher”:

    • 指定节点所属的ROS 2包名
    • robot_state_publisher是一个专门用于发布机器人状态的系统包
  • executable=“robot_state_publisher”:

    • 指定要运行的可执行文件名
    • 这是robot_state_publisher包中的主可执行文件
  • output=“both”:

    • 指定节点输出(日志)的处理方式
    • “both”表示同时输出到屏幕和日志文件
    • 其他选项包括”screen”(仅屏幕)、“log”(仅日志文件)等
  • parameters=[{“use_sim_time”: True}, robot_description]:

    • 指定传递给节点的参数列表
    • 这是一个包含两个元素的列表:
      • {“use_sim_time”: True}: 设置参数,告诉节点使用仿真时间而不是系统时间
        • 这在Gazebo仿真环境中非常重要,因为仿真时间可能与实际系统时间不同
        • 当设置为True时,节点将订阅/clock话题获取仿真时间
      • robot_description: 包含机器人描述的参数字典
        • 这包含了通过xacro命令生成的完整URDF描述
        • robot_state_publisher使用这个描述来了解机器人的结构和关节关系

launch_setup代码解析三:#

## RViz可视化节点(根据launch_rviz参数决定是否启动)
rviz_node = Node(
    package="rviz2",
    executable="rviz2",
    name="rviz2",
    output="log",
    arguments=["-d", rviz_config_file],
    condition=IfCondition(launch_rviz),
)
python
  • package=“rviz2”: 指定ROS 2包名,这里是RViz可视化工具包

  • executable=“rviz2”: 指定要运行的可执行文件名

  • name=“rviz2”: 指定节点名称

  • output=“log”: 输出设置为日志模式,将输出记录到日志文件而不是显示在终端

  • arguments=[“-d”, rviz_config_file]: 启动参数

    • -d参数指定RViz配置文件
    • rviz_config_file是之前定义的配置文件路径
  • condition=IfCondition(launch_rviz): 启动条件

    • 只有当launch_rviz参数为true时才会启动这个节点
    • 这使得RViz的启动变得可选和灵活

launch_setup代码解析四:#

## 关节状态广播器
    joint_state_broadcaster_spawner = Node(
        package="controller_manager",
        executable="spawner",
        arguments=["joint_state_broadcaster", "--controller-manager", "/controller_manager"],
    )
python

这是一个使用控制器管理器的spawner工具来启动关节状态广播器的节点。

  • package=“controller_manager”: 指定ROS 2包名,这里是控制器管理器包

  • executable=“spawner”: 指定要运行的可执行文件名,spawner是用于加载和启动控制器的工具

  • arguments: 传递给spawner的参数列表

    • joint_state_broadcaster: 要启动的控制器名称,用于广播关节状态
    • —controller-manager: 指定控制器管理器的参数
    • /controller_manager: 控制器管理器的服务名称

这个节点的作用是启动关节状态广播器控制器,它会发布机器人关节的状态信息(如位置、速度等)到/joint_states话题,供其他节点(如robot_state_publisher)使用。这是机器人仿真和控制中必需的组件。

launch_setup代码解析五:#

## UR5e机械臂控制器
    ur5e_arm_controller_spawner = Node(
        package="controller_manager",
        executable="spawner",
        arguments=["ur5e_arm_controller", "-c", "/controller_manager"],
    )
python

这是一个使用控制器管理器的spawner工具来启动UR5e机械臂控制器的节点。

  • package=“controller_manager”: 指定ROS 2包名,这里是控制器管理器包

  • executable=“spawner”: 指定要运行的可执行文件名,spawner是用于加载和启动控制器的工具

  • arguments: 传递给spawner的参数列表

    • ur5e_arm_controller: 要启动的控制器名称,这是专门为UR5e机械臂配置的控制器
    • -c: 控制器管理器的简写参数选项
    • /controller_manager: 控制器管理器的服务名称

这个节点的作用是启动UR5e机械臂控制器,它负责控制机械臂的关节运动。与之前启动的关节状态广播器不同,这个控制器是用来发送控制指令给机械臂的,使机械臂能够按照指定的轨迹运动。这是控制真实或仿真机械臂所必需的组件。

launch_setup代码解析六:#

## Gazebo仿真环境
    gazebo = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            [FindPackageShare("gazebo_ros"), "/launch", "/gazebo.launch.py"]
        ),
        launch_arguments={
            "world": gazebo_world_file,
        }.items(),
    )
python
  • PythonLaunchDescriptionSource: 指定要包含的launch文件来源

    • FindPackageShare(“gazebo_ros”): 查找gazebo_ros包的共享目录
    • 路径组合为: gazebo_ros包路径/launch/gazebo.launch.py
    • 这是Gazebo ROS包提供的标准launch文件
  • launch_arguments: 传递给被包含launch文件的参数

    • “world”: gazebo_world_file: 指定Gazebo要加载的世界文件路径
    • gazebo_world_file是之前定义的世界文件路径变量

注意,这里使用的gazebo.launch.py是官方包提供的

launch_setup代码解析七:#

## 在Gazebo中生成机器人实体
    gazebo_spawn_robot = Node(
        package="gazebo_ros",
        executable="spawn_entity.py",
        name="spawn_ur",
        arguments=["-entity", "ur5e_gripper", "-topic", "robot_description"],
        output="screen",
    )
python

这是一个用于在Gazebo仿真环境中生成机器人模型实体的节点,通过调用Gazebo ROS包提供的spawn_entity.py脚本来实现。

  • package=“gazebo_ros”: 指定ROS 2包名,这里是Gazebo ROS接口包

  • executable=“spawn_entity.py”: 指定要运行的可执行文件名,这是Gazebo ROS包提供的用于在仿真中生成实体的Python脚本

  • name=“spawn_ur”: 指定节点名称

  • output=“screen”: 输出设置为屏幕模式,将输出显示在终端上

  • arguments: 传递给spawn_entity.py脚本的参数列表

    • -entity: 指定要创建的实体名称
    • ur5e_gripper: 实体名称,这里命名为ur5e_gripper
    • -topic: 指定从中获取机器人描述的话题
    • robot_description: 话题名称,即之前定义的机器人描述参数

工作原理 这个节点通过以下步骤工作:

  1. 从robot_description话题获取机器人的URDF描述
  2. 在Gazebo仿真环境中创建名为ur5e_gripper的实体
  3. 将获取到的URDF描述应用到新创建的实体上

总结#

这个launch文件的主要功能是启动UR5e机械臂与Robotiq夹爪的完整Gazebo仿真环境,包括机器人模型加载、控制器配置、可视化界面和仿真世界设置。文件通过声明多个可配置参数(如描述包、描述文件、是否启动RViz等)来提供灵活性,并按正确顺序启动各个必要组件:首先启动Gazebo仿真环境和机器人状态发布器,然后加载关节状态广播器、机械臂控制器和夹爪控制器,最后在仿真环境中生成机器人实体。整个启动过程还考虑了依赖关系,例如确保在关节状态广播器启动后再启动RViz,以保证各组件能够正确协同工作。

ROS2_Moveit2_Ur5e_Grasp项目详解(三):ur5e_gripper_sim_control文件详解
http://www.soupcola.top/blog/ros2_blogs/ros2_blogs-3
Author Soup Cola
Published at 2026年2月3日