Skip to content

URDF 与 SRDF

MoveIt 2 从 URDF(Unified Robot Description Format,统一机器人描述格式)开始——这是 ROS 和 ROS 2 中描述机器人的原生格式。在本教程中,你可以找到 URDF 的相关资源、重要提示,以及 MoveIt 2 特定要求的清单。

注意:尽管以上文档是为 ROS 编写的,但只要把命令从 ROS 改为 ROS 2(例如:rosrun -> ros2 run 或 roslaunch -> ros2 launch),所有文档依然有效。

本节列出了一系列提示,帮助你确保生成的 URDF 能够与 MoveIt 2 正常配合使用。在开始将 MoveIt 2 用于你的机器人之前,请务必通读这些提示。

关节名称不应包含以下任何特殊字符:-, [, ], (, )

我们希望尽快取消这些限制。

某些 URDF 除了机器人的关节限位之外还设置了安全限制。以下是针对 Panda head pan 关节的安全控制器示例:

<safety_controller k_position="100" k_velocity="1.5" soft_lower_limit="-2.857" soft_upper_limit="2.857"/>

“soft_lower_limit” 字段和 “soft_upper_limit” 字段指定了该关节的关节位置限位。MoveIt 2 会将这些限位与 URDF 中指定的关节硬限位进行比较,并选择更保守的限位。

注意:如果 safety_controller 中的 “soft_lower_limit” 和 “soft_upper_limit” 被设为 0.0,你的关节将无法移动。MoveIt 2 依赖你指定正确的机器人模型。

MoveIt 2 使用 URDF 中指定的网格(mesh)进行碰撞检查。URDF 允许你分别为可视化和碰撞检查指定两组网格。一般来说,可视化网格可以很精细、很美观,但碰撞网格应尽可能简化。网格中的三角形数量会直接影响碰撞检查所需的时间。整个机器人的三角形数量应保持在数千个的量级。

测试 URDF 并确保一切正常非常重要。ROS URDF 软件包提供了 check_urdf 工具。要使用该工具验证你的 URDF,请按照此处的说明操作。

有很多可供 ROS 机器人使用的 URDF。

SRDF(Semantic Robot Description Format,语义机器人描述格式)是对 URDF 的补充,它指定了关节组、默认机器人配置、额外的碰撞检查信息,以及完整描述机器人位姿可能需要的附加变换。生成 SRDF 的推荐方式是使用 MoveIt Setup Assistant。

URDF 只包含机器人物理关节的信息。通常还需要定义额外的关节,来指定机器人根连杆相对于世界坐标系的位姿。在这种情况下,使用虚拟关节来表示这种连接。例如,像 PR2 这样在平面内移动的机器人,使用一个平面虚拟关节将世界坐标系连接到机器人的坐标系。固定式机器人(如工业机械臂)则应使用固定关节连接到世界坐标系。

被动关节是机器人上无驱动的关节,例如差速驱动机器人上的被动脚轮。它们在 SRDF 中被单独指定,以确保运动规划或控制流水线中的各组件知道这些关节无法被直接控制。如果你的机器人有无驱动脚轮,应将它们指定为被动关节。

“组”(有时称为 JointGroup 或 Planning Group)是 MoveIt 2 中的核心概念。MoveIt 2 总是针对某个特定组进行操作——它只会移动正在规划的组中的关节,其他关节保持静止。(可以通过创建一个包含所有关节的组,来实现机器人所有关节都可移动的运动规划。)一个组就是一组关节和连杆的集合,可以通过以下几种方式指定:

一个组可以指定为关节的集合。每个关节的所有子连杆都会自动包含在该组中。

一个组也可以指定为连杆的集合,这些连杆的所有父关节也会被包含在该组中。

串联链通过基连杆和末端连杆来指定。链中的末端连杆是链中最后一个关节的子连杆,基连杆则是链中第一个关节的父连杆。

一个组也可以由多个其他组组合而成。例如,你可以将 left_arm 和 right_arm 定义为两个组,然后定义一个名为 both_arms 的新组来包含这两个组。

机器人中的某些组可以被赋予末端执行器这一特殊标识。末端执行器通常通过一个固定关节连接到另一个组(如手臂)。注意,在指定末端执行器组时,务必确保末端执行器与其所连接的父组之间没有共同连杆。

默认的自碰撞矩阵生成器(Setup Assistant 的组成部分)会搜索机器人上可以安全禁用碰撞检查的连杆对,以减少运动规划的处理时间。当连杆对总是处于碰撞状态、永远不会碰撞、在机器人默认位姿下处于碰撞状态,或者这些连杆在运动学链上彼此相邻时,它们就会被禁用。采样密度指定了用于自碰撞检查的随机机器人位姿数量。密度越高,计算时间越长;密度越低,则更有可能错误地禁用本不应禁用的连杆对。默认值是 10,000 次碰撞检查。碰撞检查采用并行方式执行,以缩短处理时间。

SRDF 还可以存储机器人的固定配置。一个典型的示例是为机械臂定义 HOME 位置。配置以字符串 id 存储,之后可以用该 id 恢复配置。

有关 SRDF 语法的信息,请阅读 ROS SRDF Wiki 页面 上的更多细节。

MoveIt 中所有使用 RobotModel 的组件都需要访问 URDF 和 SRDF 才能正常工作。在 ROS 1 中,这是通过将两者的 XML 作为字符串参数(分别是 /robot_description 和 /robot_description_semantic)加载到全局参数服务器来实现的。ROS 2 没有全局参数服务器,因此确保所有相关节点都能访问这些参数需要一些额外的工作。

一种选择是为每个需要这些参数的节点设置参数,这通常通过启动文件(launch file)完成。

加载 URDF 通常使用 xacro,因此加载过程如下所示:

from launch_ros.parameter_descriptions import ParameterValue
from launch.substitutions import Command
robot_description = ParameterValue(Command(['xacro ', PATH_TO_URDF]),
value_type=str)

与此同时,SRDF 必须显式读取。

with open(PATH_TO_SRDF, 'r') as f:
semantic_content = f.read()

然后将这些值加载到每个节点中。

move_group_node = Node(package='moveit_ros_move_group', executable='move_group',
output='screen',
parameters=[{
'robot_description': robot_description,
'robot_description_semantic': semantic_content,
# More params
}],
)

另一种方法是将这两个字符串作为话题发布。这种模式已经用于 Robot State Publisher,它会在 /robot_description 话题上发布 std_msgs/msg/String 消息。这可以在启动文件中完成:

rsp_node = Node(package='robot_state_publisher',
executable='robot_state_publisher',
respawn=True,
output='screen',
parameters=[{
'robot_description': robot_description,
'publish_frequency': 15.0
}]
)

你也可以告诉 MoveIt 节点发布该话题。

move_group_node = Node(package='moveit_ros_move_group', executable='move_group',
output='screen',
parameters=[{
'robot_description': robot_description,
'publish_robot_description': True,
# More params
}],
)

将机器人描述作为话题发布只需执行一次,而不需要每个需要该描述的节点都重复发布。

类似地,我们也可以把 SRDF 发布为 std_msgs/msg/String 消息。这要求启动文件中有一个节点设置了该参数,并将参数 publish_robot_description_semantic 设为 True。

move_group_node = Node(package='moveit_ros_move_group', executable='move_group',
output='screen',
parameters=[{
'robot_description_semantic': semantic_content,
'publish_robot_description_semantic': True,
# More params
}],
)

然后所有其他节点都可以订阅该话题来获取发布的字符串消息。

在 MoveIt 代码的许多地方,机器人的描述和语义信息都是使用 RDFLoader 类加载的。该类会先尝试从节点参数中读取,如果失败,则尝试在短时间内订阅 String 话题。如果两种方式都无法获取参数,就会在控制台打印一条警告。