Skip to content

控制器配置

MoveIt 通常将机械臂的运动指令发布到 JointTrajectoryController。本教程假设你使用 MoveGroup 来控制机器人,而不是 MoveItCpp 或 MoveIt Servo。一个最小的配置需要以下内容:

  1. 一个 YAML 配置文件。按照最佳实践,我们建议将其命名为 moveit_controllers.yaml。该文件告诉 MoveIt 有哪些控制器可用、每个控制器与哪些关节相关联,以及 MoveIt 控制器接口类型(FollowJointTrajectory 或 GripperCommand)。示例控制器配置文件。

  2. 一个 launch 文件。该 launch 文件必须加载 moveit_controllers yaml 文件,并指定 moveit_simple_controller_manager/MoveItSimpleControllerManager。yaml 文件加载后会作为参数传递给 Move Group 节点。示例 Move Group launch 文件。

  3. 启动相应的 ros2_control JointTrajectoryController。这部分独立于 MoveIt 2 生态。ros2_control 启动示例。每个 JointTrajectoryController 都提供一个 action 接口,MoveIt 会根据 yaml 配置自动连接到该接口。

  4. 需要注意的是,你的机器人不一定非要用 ros2_control,也可以编写自定义的 action 接口。不过,99% 的用户都会选择 ros2_control。

控制器管理器的基类称为 MoveItControllerManager(MICM)。MICM 的子类之一称为 Ros2ControlManager(R2CM),它是与 ros2_control 交互的最佳方式。R2CM 可以解析来自 MoveIt 的轨迹指令中的关节名称,并激活相应的控制器。例如,它可以在“同时控制一个规划组中的两个机械臂”和“控制单个机械臂”之间自动切换。要使用 R2CM,只需在 launch 文件中设置 moveit_manage_controllers = true。R2CM launch 文件示例。

上文描述了如何启动关节轨迹控制器的 action 接口。此外,MoveIt 还通过 action 接口支持平行夹爪控制。本节介绍这两种选项的参数。

  1. FollowJointTrajectory 控制器接口

    参数如下:

    • name:控制器的名称。(重要说明见下面的调试信息)
    • action_ns:控制器的 action 命名空间。(重要说明见下面的调试信息)
    • type:所使用的 action 类型(此处为 FollowJointTrajectory)。
    • default:是否为默认控制器。MoveIt 在与特定规划组通信时会优先选择默认控制器。
    • joints:此接口所涉及的所有关节的名称。
  2. GripperCommand 控制器接口

    参数如下:

    • name:控制器的名称。(重要说明见下面的调试信息)
    • action_ns:控制器的 action 命名空间。(重要说明见下面的调试信息)
    • type:所使用的 action 类型(此处为 GripperCommand)。
    • default:是否为默认控制器。MoveIt 在与特定规划组通信时会优先选择默认控制器。
    • joints:此接口所涉及的所有关节的名称。
    • command_joint:控制夹爪实际状态的单个关节。这是唯一发送给控制器的值。必须是上面 joints 中的关节之一。如果未指定,将使用 joints 中的第一项。
    • parallel:设置此参数时,joints 应为包含 2 个关节的列表,下发的指令值为两个关节值之和。

(TODO:更新为 ROS 2)

对于每个控制器,可以选择设置 allowed_execution_duration_scaling 和 allowed_goal_duration_margin 参数,它们是对全局值 trajectory_execution/allowed_execution_duration_scaling 和 trajectory_execution/allowed_goal_duration_margin 的控制器级覆盖。与全局值不同,控制器特有的值不能在运行时动态重新配置。这些参数用于计算允许的轨迹执行时长:先缩放预期的执行时长,再加上余量。如果超过该时长,轨迹将被取消。控制器特有的参数可以按如下方式设置:

controller_list:
- name: arm_controller
action_ns: follow_joint_trajectory
type: FollowJointTrajectory
allowed_execution_duration_scaling: 1.2
allowed_goal_duration_margin: 0.5

使用 MoveIt ROS Control 接口时,你可以配置几个参数来优化其行为:

controller_service_call_timeout(double,默认值:3.0 秒)

该参数控制 MoveIt 等待控制器管理器服务(如 list_controllers 和 switch_controller)响应的时长。在资源受限的系统或网络拥塞的情况下,控制器发现和切换操作可能超过默认超时时间。适当增大此参数可以避免超时问题。

ros_control_namespace(string,默认值:/)

ros_control 节点的命名空间。

# In your moveit_controllers.yaml configuration
ros_control_namespace: /my_robot
controller_service_call_timeout: 5.0 # Increase timeout to 5 seconds

(TODO:更新为 ROS 2)

你的机器人上的 FollowJointTrajectory 或 GripperCommand 接口必须在命名空间 /name/action_ns 中通信。在上面的示例中,你应该能在机器人上看到以下主题(使用 ros2 topic list):

  • /panda_arm_controller/follow_joint_trajectory/goal
  • /panda_arm_controller/follow_joint_trajectory/feedback
  • /panda_arm_controller/follow_joint_trajectory/result
  • /hand_controller/gripper_action/goal
  • /hand_controller/gripper_action/feedback
  • /hand_controller/gripper_action/result

你还应该能看到(使用 ros2 topic info topic_name)这些主题由你机器人上的控制器以及 move_group 节点发布/订阅。

(TODO:更新为 ROS 2)

当你运行 move group 节点 时,你可能需要将 /joint_states 主题重映射到 /robot/joint_states,否则 MoveIt 将无法获得关节的反馈。要进行这种重映射,可以为你的节点创建一个简单的 launch 文件,如下所示:

<node pkg="moveit_ros_move_group" type="move_group" name="any_name" output="screen">
<remap from="joint_states" to="robot/joint_states"/>
</node>

或者,你也可以创建一个订阅正确主题的订阅者,通过回调确保 move group 的起始状态与实际关节角度一致。

MoveIt 提供了几个选项来调整执行管线的行为和安全检查。在 moveit_config 包中编辑 trajectory_execution.launch.xml 文件即可修改以下参数:

  • execution_duration_monitoring:设为 false 时,如果轨迹在底层控制器一侧的执行时间超过预期,不会抛出错误。
  • allowed_goal_duration_margin:在触发轨迹取消之前允许超出预期执行时间的余量(在缩放之后应用)。
  • allowed_start_tolerance:用于验证轨迹第一个点与当前机器人状态是否一致的关节值容差。设为零时,将跳过执行后等待机器人停止的过程。

MoveIt 控制器管理器(这个叫法多少有点名不副实)是连接自定义底层控制器的接口。把它理解为 控制器接口 更为恰当。对于大多数用例,如果你的机器人控制器已经为 FollowJointTrajectory 提供了 ROS action,那么自带的 MoveItSimpleControllerManager 就足够了。如果使用 ros_control,自带的 MoveItRosControlInterface 也是理想之选。

然而,对于某些应用,你可能需要一个更定制化的控制器管理器。这里提供了一个自定义控制器管理器的示例模板。

如果没有实体机器人,使用 ros2_control 可以非常轻松地进行仿真,无需 Ignition 或 Gazebo,只用 RViz 就够了。ros2_control_demos 仓库中的所有示例都是仿真的。

所有控制器名称都会以其 ros_control 节点的命名空间作为前缀。因此,控制器名称不应包含斜杠,也不能命名为 /。对于特定节点,MoveIt 可以决定启动或停止哪些控制器。由于 MoveIt 只处理注册了分配器插件的控制器,如果某个待启动的控制器需要特定资源,MoveIt 会根据各控制器已声明的资源依赖关系来停止相应的控制器。

使用 ROS Control 接口管理器进行控制器切换时,你可以通过 controller_service_call_timeout 参数(默认值:3.0 秒)配置控制器管理器服务调用的超时时间。在控制器切换可能超过默认超时时间的复杂配置中,这一点尤其有用。

Ros2ControlManager 有一个变体:Ros2ControlMultiManager。Ros2ControlMultiManager 可用于管理多个 ros_control 节点。它的工作方式是为每个节点创建一个 Ros2ControlManager 实例,以各自的命名空间进行实例化,并负责正确的任务委派。要使用它,必须在 launch 文件中添加:

<param name="moveit_controller_manager" value="moveit_ros_control_interface::Ros2ControlMultiManager" />

controller_service_call_timeout 参数也可以通过 Ros2ControlMultiManager 设置,该值将被所有发现的控制器管理器使用。