手眼标定
MoveIt Calibration 软件包提供了用于相机手眼标定(hand-eye calibration)的插件和图形界面。标定既适用于刚性安装在机器人基座坐标系中的相机(eye-to-hand,眼在手外),也适用于安装在末端执行器上的相机(eye-in-hand,眼在手上)。本教程介绍的是 eye-in-hand 的情形。

虽然只使用仿真环境就可以完成本教程的大部分内容,但要真正完成一次标定,你需要一台机械臂和一个相机。
如果尚未完成,请务必先完成 Getting Started 中的步骤。另外,按照 Setup Assistant 教程中的说明设置你的机械臂,使其能够配合 MoveIt 工作。
本教程还需要一个相机,该相机需要发布图像以及带有良好内参标定参数和准确坐标系的 sensor_msgs/CameraInfo 主题。(如有必要,可以使用 camera_calibration 软件包进行相机内参标定。)
克隆并构建 MoveIt Calibration 仓库
Section titled “克隆并构建 MoveIt Calibration 仓库”在你的工作空间 src 目录中,克隆 MoveIt Calibration:
git clone git@github.com:moveit/moveit_calibration.git然后,确保你已安装相应的依赖并构建该软件包:
rosdep install -y --from-paths . --ignore-src --rosdistro melodiccatkin buildsource devel/setup.sh启动 RViz 并加载标定插件
Section titled “启动 RViz 并加载标定插件”为你的机器人启动相应的 MoveIt demo。例如,roslaunch panda_moveit_config demo.launch。
在 RViz 的 “Panels” 菜单中,选择 “Add New Panel”:

然后,选择 “HandEyeCalibration” 面板类型:

添加的面板默认激活 “Target” 标签页。
创建并打印标定靶标
Section titled “创建并打印标定靶标”现在我们来创建一个可视化标定靶标。该靶标具有在图像数据中易于识别的独特图案,通过提供靶标尺寸的测量值,可以估计靶标在相机坐标系中的位姿。进行手眼标定时,我们不需要知道靶标的精确位置——只要靶标在机器人基座坐标系中保持静止,就可以从 5 个或更多位姿的序列中估计出手眼标定结果。
在 “Target” 标签页的 “Target Params” 区域,我们使用默认的靶标参数:
- markers, X:3
- markers, Y:4
- marker size (px):200
- marker separation (px):20
- marker border (bits):1
- ArUco dictionary:DICT_5X5_250
点击 “Create Target” 按钮创建靶标图像:

使用 “Save Target” 按钮保存靶标图像,并打印出来。你可以随意调整靶标参数,观察它们对靶标外观的影响,但务必记下你实际打印靶标所使用的参数—后续需要输入相同的参数才能识别该靶标。
靶标必须保持平整,这样相机才能可靠地定位它。将它平放在一个平面上即可,也可以安装到一块板上。测量标记宽度(其中一个黑色方块的外侧尺寸)以及标记之间的间距。在 “Target Params” 区域的相应输入框中以米为单位输入这些值。同时,在 “Image Topic” 和 “CameraInfo Topic” 下拉菜单中选择相应的主题。
最后,将靶标放置在机器人附近,使相机能够轻松看到它。
第二个标签页名为 “Context”,包含进行标定所需的几何信息。
- 将 “Sensor configuration” 设置为 “Eye-in-hand”。
- “Sensor frame” 是相机光学坐标系(采用 REP 103 规定的右-下-前标准)。
- “Object frame” 是由标定靶标定义的坐标系,默认名为 “handeye_target”。
- “End-effector frame” 是与相机刚性连接的机器人连杆。
- “Robot base frame” 是标定靶标保持静止的坐标系。

FOV 区域控制 RViz 中相机视场的渲染。要查看 FOV,请添加一个 “MarkerArray” 显示,并将其设置为监听 “/rviz_visual_tools” 主题。(它可能不会立即显示。)
最后,为相机位姿设置初始猜测值并非必须,但值得注意的是,一旦计算出标定结果,这些字段会自动更新为新的标定值。
接下来,我们将采集一个标定数据集。我们需要采集多个样本以确保标定质量良好。机器人的运动学提供了末端执行器在机器人基座坐标系中的位姿,而如上所述,标定靶标在相机坐标系中的位姿可以被估计出来。如果靶标在机器人基座坐标系中的位姿精确已知,那么只需一次对相机-靶标变换的观测就可以恢复相机在末端执行器坐标系中的位姿。相机到末端执行器的直接变换等价于相机→靶标→基座→连杆→末端执行器的复合变换链。然而,更好的做法是像 Kostas Daniilidis 的这篇论文 中描述的那样,结合多个位姿的信息,将靶标在基座坐标系中的位姿从方程中消去。
因此,标定数据集中的每个样本都是一对位姿:末端执行器在机器人基座坐标系中的位姿,以及标定靶标在相机坐标系中的位姿。一旦采集了五个这样的样本,就可以计算标定结果。
“Calibrate” 标签页提供采集数据集以及计算和导出标定结果的工具。此时在 RViz 显示中添加一个图像面板也很有帮助,可以在相机视图中看到靶标检测结果,该结果发布在 /handeye_calibration/target_detection 主题上。

在 “Calibrate” 标签页中,你可以在 “AX=XB Solver” 下拉菜单中选择要使用的标定求解器。Daniilidis 求解器(来自上文引用的论文)是默认选项,在大多数情况下都是不错的选择。“Planning Group” 是将要记录的规划组,因此应设置为机械臂对应的组(在 panda_moveit_config 软件包中,应使用 panda_arm 组)。
当靶标出现在机械臂相机中,且靶标检测图像中在靶标上渲染出坐标轴时,你就可以采集第一个标定样本(位姿对)了。点击 “Manual calibration” 区域中的 “Take sample” 按钮,一个新样本就会添加到面板左侧的 “Pose samples” 列表中。展开一个样本后,你会看到它包含两个变换:基座到末端执行器(base-to-end-effector)和相机到靶标(camera-to-target)。
接下来,你可以使用 “MotionPlanning” 面板将机械臂移动到新位姿,或者使用机器人的示教器或自由驱动模式(如果有的话),然后再次点击 “Take sample”。务必在每对位姿之间加入一些旋转,并且不要总是绕同一轴旋转—至少需要两个旋转轴才能唯一解出标定结果(原因见上面链接的 Daniilidis 论文)。
手动采集样本时,机器人关节状态会被记录下来,这样以后可以用相同的位姿重新标定。已记录状态的数量显示在面板底部进度条的右侧,可以使用 “Settings” 区域中的 “Save joint states” 按钮将状态保存到文件中。
计算标定结果
Section titled “计算标定结果”采集到五个样本后,就会自动执行一次标定,之后每添加一个新样本都会更新标定结果。再多采集几个样本,标定结果会有显著改善,通常在 12 到 15 个样本左右趋于平稳。如上所述,位置和姿态将显示在 “Context” 标签页上,发布的 TF 也会随之更新。点击 “Save camera pose” 导出标定结果。这会创建一个包含静态变换发布器的 launch 文件,其中带有标定后的相机变换。