MoveIt 中的启动文件
MoveIt 的许多教程以及你实际遇到的 MoveIt 包都会使用 ROS 2 启动文件。
本教程详细讲解一个典型的 Python 启动文件,该文件搭建了一个可运行的 MoveIt 示例。我们将通过逐步分析 入门教程启动文件 来说明。
如果你对启动文件本身不熟悉,请先参阅 ROS 2 文档。
加载 MoveIt 配置
Section titled “加载 MoveIt 配置”MoveIt 需要若干配置参数,包括机器人描述和语义描述文件(URDF 与 SRDF)、运动规划和运动学插件、轨迹执行等。这些参数通常包含在 MoveIt 配置 包中。
在 Python 启动文件中引用 MoveIt 配置包的一种便捷方式是使用 MoveItConfigsBuilder 工具,如下所示:
from moveit_configs_utils import MoveItConfigsBuilder
# Define xacro mappings for the robot description filelaunch_arguments = { "robot_ip": "xxx.yyy.zzz.www", "use_fake_hardware": "true", "gripper": "robotiq_2f_85", "dof": "7",}
# Load the robot configurationmoveit_config = ( MoveItConfigsBuilder( "gen3", package_name="kinova_gen3_7dof_robotiq_2f_85_moveit_config" ) .robot_description(mappings=launch_arguments) .trajectory_execution(file_path="config/moveit_controllers.yaml") .planning_scene_monitor( publish_robot_description=True, publish_robot_description_semantic=True ) .planning_pipelines( pipelines=["ompl", "stomp", "pilz_industrial_motion_planner"] ) .to_moveit_configs())启动 Move Group
Section titled “启动 Move Group”所有 MoveIt 配置参数加载完毕后,你就可以使用这套参数启动 Move Group 接口。
from launch_ros.actions import Node
run_move_group_node = Node( package="moveit_ros_move_group", executable="move_group", output="screen", parameters=[moveit_config.to_dict()],)使用 RViz 可视化
Section titled “使用 RViz 可视化”正如 RViz 快速入门 教程中所介绍的,你可以使用 RViz 可视化机器人模型并执行运动规划任务。
以下代码通过一个启动参数接收 RViz 配置文件名,将其拼接为指向已知包目录的相对路径,并在启动 RViz 可执行文件时作为参数传入。
from launch.actions import DeclareLaunchArgumentfrom launch.substitutions import LaunchConfiguration, PathJoinSubstitutionfrom launch_ros.substitutions import FindPackageShare
# Get the path to the RViz configuration filerviz_config_arg = DeclareLaunchArgument( "rviz_config", default_value="kinova_moveit_config_demo.rviz", description="RViz configuration file",)rviz_base = LaunchConfiguration("rviz_config")rviz_config = PathJoinSubstitution( [FindPackageShare("moveit2_tutorials"), "launch", rviz_base])
# Launch RVizrviz_node = Node( package="rviz2", executable="rviz2", output="log", arguments=["-d", rviz_config], parameters=[ moveit_config.robot_description, moveit_config.robot_description_semantic, moveit_config.robot_description_kinematics, moveit_config.planning_pipelines, moveit_config.joint_limits, ],)向 tf2 发布变换
Section titled “向 tf2 发布变换”ROS 生态中的许多工具使用 tf2 库来表示坐标变换,这是使用 MoveIt 进行运动规划的重要组成部分。
因此,我们的启动文件包含向 tf2 发布静态变换和动态变换的节点。在本例中,我们需要:
- 在
world坐标系与机器人描述的基坐标系base_link之间发布一个静态变换。 - 一个 robot state publisher 节点,它监听机器人的关节状态,利用机器人的 URDF 模型计算坐标系变换,并将其发布到
tf2。
# Static TFstatic_tf = Node( package="tf2_ros", executable="static_transform_publisher", name="static_transform_publisher", output="log", arguments=["--frame-id", "world", "--child-frame-id", "base_link"],)
# Publish TFrobot_state_publisher = Node( package="robot_state_publisher", executable="robot_state_publisher", name="robot_state_publisher", output="both", parameters=[moveit_config.robot_description],)为轨迹执行设置 ros2_control
Section titled “为轨迹执行设置 ros2_control”MoveIt 通常会生成关节轨迹,然后将其发送给能够执行这些轨迹的机器人控制器。最常见的做法是连接 ros2_control 库来实现这一点。
ros2_control 既可以连接真实机器人硬件,也可以连接 Gazebo、NVIDIA Isaac Sim 等基于物理的模拟器中的机器人。此外,它还提供了 mock components 功能,用于简单、理想化的模拟。在本例中,这是在 URDF 层面通过前面定义的 use_fake_hardware xacro 参数来配置的。核心思想是:无论启动的是模拟硬件还是真实硬件,ros2_control 的启动方式都保持不变。
启动 ros2_control 需要启动一个控制器管理器节点,然后生成轨迹执行所需的一系列控制器。在本例中,我们包含:
- 一个关节状态广播器(joint state broadcaster),它发布关节状态,这是机器人状态发布器向
tf2发送坐标系所必需的。 - 一个用于机械臂执行器的关节轨迹控制器(joint trajectory controller)。
- 一个用于平行爪式夹爪的夹爪动作控制器(gripper action controller)。
ros2_controllers_path = os.path.join( get_package_share_directory("kinova_gen3_7dof_robotiq_2f_85_moveit_config"), "config", "ros2_controllers.yaml",)ros2_control_node = Node( package="controller_manager", executable="ros2_control_node", parameters=[ros2_controllers_path], remappings=[ ("/controller_manager/robot_description", "/robot_description"), ], output="both",)
joint_state_broadcaster_spawner = Node( package="controller_manager", executable="spawner", arguments=[ "joint_state_broadcaster", "--controller-manager", "/controller_manager", ],)
arm_controller_spawner = Node( package="controller_manager", executable="spawner", arguments=["joint_trajectory_controller", "-c", "/controller_manager"],)
hand_controller_spawner = Node( package="controller_manager", executable="spawner", arguments=["robotiq_gripper_controller", "-c", "/controller_manager"],)启动所有节点
Section titled “启动所有节点”最后,我们可以告诉启动文件实际启动前面各节中描述的所有内容。
# ... all our imports go here
def generate_launch_description():
# ... all our other code goes here
return LaunchDescription( [ rviz_config_arg, rviz_node, static_tf, robot_state_publisher, run_move_group_node, ros2_control_node, joint_state_broadcaster_spawner, arm_controller_spawner, hand_controller_spawner, ] )