AprilTag 入门:从一张黑白标签到机器人眼里的坐标

做机器人视觉定位时,经常会遇到一个很朴素的问题:相机看到了目标,但程序怎么知道这个目标在三维空间里的位置和姿态?

AprilTag 就是为这个问题准备的一类视觉标记。它看起来像二维码,但目的不是存储大量信息,而是让机器稳定地识别“这是哪个标签”以及“它相对相机在哪里”。在机器人、机械臂、无人机、移动小车、实验室标定里,它都很常见。

这篇文章结合一个 ROS 2 + MoveIt 2 + 四自由度机械臂的小项目,整理 AprilTag 的入门思路。文章不展开项目代码,只讲概念、流程和容易踩坑的地方,方便后面想把 AprilTag 接进自己项目的人快速上手。

1. AprilTag 是什么

AprilTag 是一种人工视觉标记系统。每个标签都有一个黑白方形图案,检测器可以从图像中识别出它的 ID,并根据相机内参和标签实际尺寸估计出标签相对相机的 6D 位姿,也就是位置加姿态。

简单说:

  • 图案告诉程序:这是哪个标签。
  • 标签边框告诉程序:这个正方形在图像里怎么变形了。
  • 相机内参和标签实际尺寸告诉程序:它离相机多远、朝向如何。

如果只想判断“看没看到某个标记”,AprilTag 可以做到;如果还想让机械臂去靠近它、让小车朝它走、让无人机根据它降落,那就要用到位姿估计。

2. 入门必须理解的几个关键词

Tag family

AprilTag 不是只有一种图案集合,而是分成不同 family,比如 tag36h11tag25h9 等。

这里的 36h11 可以粗略理解为:标签内部编码更丰富,抗误识别能力比较好,但图案也更细。一般机器人项目里,tag36h11 是很常见、很稳妥的入门选择。

检测器配置的 family 必须和打印出来的标签 family 一致。你打印的是 tag36h11,检测器也要按 36h11 去识别。

Tag ID

同一个 family 里有很多不同 ID 的标签。比如项目里使用的是 tag36h11 家族的 id=0 标签。

ID 的意义是区分目标:如果桌面上贴了多个标签,程序可以通过 ID 判断每个标签分别代表什么位置、物体或工位。

Tag size

这是 AprilTag 入门最容易被忽略、但又最关键的参数。size 指的是标签黑色外边框对应的实际物理边长,单位通常是米。

例如项目里使用的尺寸是 0.10,也就是 10 cm。

这个值会直接影响距离估计。如果你真实标签是 8 cm,却在配置里写成 10 cm,检测出来的位置就会系统性偏差。相机不会凭空知道纸上的标签有多大,这个信息必须由你告诉检测器。

Camera info

AprilTag 要算三维位姿,必须知道相机内参,包括焦距、主点、畸变参数等。在 ROS 里,这些信息通常通过 CameraInfo 消息发布。

如果只有图像,没有相机内参,检测器最多只能知道图像里有一个标签,很难可靠地恢复三维位置。

真实相机建议先完成标定;仿真或合成相机也要提供合理的内参。

TF frame

ROS 里常用 TF 表示坐标系之间的关系。AprilTag 被识别后,检测器通常会发布一个标签坐标系,比如项目里的 tag36h11:0

后续节点不需要直接处理图像,只要去查 TF,就可以知道:

  • 标签相对相机在哪里。
  • 标签相对机器人底座在哪里。
  • 机械臂末端应该移动到标签前方哪个位置。

这也是 AprilTag 在机器人项目里很舒服的一点:视觉模块负责“看见并发布坐标”,运动模块负责“读取坐标并规划运动”。

3. 一个典型 ROS 2 AprilTag 流程

结合这个项目,可以把 AprilTag 的完整链路抽象成下面几步:

  1. 准备一张指定 family 和 ID 的标签图像。
  2. 相机发布图像话题,例如 /camera/image_rect
  3. 相机同时发布内参话题,例如 /camera/camera_info
  4. AprilTag 检测节点订阅图像和相机内参。
  5. 检测节点根据配置识别指定 family 的标签。
  6. 检测成功后,发布对应标签的 TF 坐标系。
  7. 机械臂、移动机器人或其他业务节点读取 TF,并执行后续任务。

这个项目为了方便验证,没有一开始就依赖真实摄像头,而是使用了一个虚拟相机发布固定的 AprilTag 图像和相机内参。这样做的好处是排除了光照、相机驱动、标定误差等外部因素,先把 ROS 话题、AprilTag 检测、TF 和 MoveIt 规划这条链路跑通。

等虚拟链路稳定后,再替换成真实相机,会更容易定位问题。

4. 项目里的关键配置思路

项目中使用的 AprilTag 识别配置可以概括为:

  • 标签 family:36h11
  • 标签实际尺寸:0.10 m
  • 识别 ID:0
  • 标签 TF 名称:tag36h11:0
  • 图像话题:/camera/image_rect
  • 相机内参话题:/camera/camera_info

这几个参数基本覆盖了 AprilTag 入门时最重要的配置面。

其中 max_hamming 用来控制容错程度。值越大,越允许图案识别时存在一定误差,但误识别风险也会变高。入门调试时使用较严格的配置更容易排查问题。

z_up 和坐标系朝向有关。做机械臂或导航时,不同库、不同相机光学坐标系、不同机器人底座坐标系的轴向定义可能不一样。看到标签位置“对了但方向怪怪的”时,坐标系方向通常是第一批要检查的对象。

5. 为什么要先用虚拟相机

很多人第一次接 AprilTag,会同时面对这些问题:

  • 摄像头能不能正常出图?
  • 图像话题名字对不对?
  • 相机内参有没有发布?
  • 标签 family 配对了吗?
  • 标签尺寸写对了吗?
  • TF 有没有发布?
  • 机器人底座到相机的外参有没有接上?
  • MoveIt 规划失败是视觉问题还是运动规划问题?

如果所有东西一起上,很容易分不清是哪一环出了错。

项目使用虚拟 AprilTag 图像,相当于先固定视觉输入。这样可以先验证:

  • AprilTag 节点能不能检测到标签。
  • 标签 TF 能不能稳定发布。
  • 机械臂节点能不能读取标签位姿。
  • 规划目标能不能根据标签坐标生成。

这是一种很推荐的开发顺序:先让数据流闭环,再引入真实硬件的不确定性。

6. 真实相机接入时的检查清单

从虚拟相机切换到真实相机时,建议按下面顺序检查。

第一,确认图像话题存在,并且画面里能清楚看到标签。标签不要太小、不要反光、不要严重倾斜,也不要被遮挡。

第二,确认相机内参话题存在。没有 CameraInfo,位姿估计通常会出问题。使用 USB 摄像头时,最好先做一次相机标定。

第三,确认标签打印尺寸和配置尺寸一致。注意这里说的是实际物理边长,不是图片文件的像素大小。

第四,确认 family 和 ID 对得上。打印 tag36h11 就配置 36h11;打印 id=0 就不要在配置里只监听别的 ID。

第五,确认 TF 是否发布。能看到标签 TF,说明检测链路基本跑通;看不到 TF,就先不要急着调机械臂。

第六,确认相机坐标系到机器人坐标系的关系。如果要让机械臂根据标签运动,系统不仅要知道标签相对相机的位置,还要知道相机装在机器人哪里。

7. AprilTag 和机械臂结合时要注意什么

AprilTag 给出的通常是标签坐标系的位置和姿态,但机械臂不能直接“撞到标签中心”。更常见的做法是生成一个接近位姿,比如停在标签前方 15 cm 的位置。

这里会涉及三个坐标概念:

  • 标签坐标系:由 AprilTag 检测结果生成。
  • 相机坐标系:图像和深度估计的参考。
  • 机器人底座坐标系:MoveIt 规划通常使用的世界参考。

机械臂真正需要的是一个在机器人底座坐标系下的目标位姿。也就是说,系统需要通过 TF 把“标签在相机里在哪里”转换成“标签在机器人面前哪里”。

项目里还对 TF 做了多次采样和稳定性判断,这个思路很实用。现实图像会抖动,标签角点检测也会有噪声。如果每一帧都直接驱动机械臂,目标点可能会跳来跳去。先取几次稳定样本,再规划运动,会让系统表现更可靠。

8. 常见问题

能检测到标签,但距离不对

优先检查 size。真实标签边长和配置边长不一致,是距离错误的高频原因。其次检查相机内参是否来自当前相机,而不是复制了别的摄像头参数。

TF 有了,但机械臂运动方向不对

大概率是坐标系关系没理顺。重点看相机光学坐标系、标签坐标系、机器人底座坐标系之间的方向定义,以及相机到机器人底座的外参是否正确。

仿真能跑,真实相机不行

先不要怀疑运动规划。用可视化工具确认真实相机的图像、内参、检测结果和 TF 是否都正常。真实环境里最常见的问题是光照、反光、模糊、内参不准和标签尺寸不一致。

9. 推荐的学习路径

如果你刚开始学 AprilTag,可以按这个顺序来:

  1. 先只识别单个标签,不接机器人运动。
  2. 确认检测节点能输出标签 ID 和 TF。
  3. 用可视化工具观察相机坐标系和标签坐标系。
  4. 改变标签距离和角度,观察 TF 是否合理变化。
  5. 再把标签 TF 转换到机器人底座坐标系。
  6. 最后让机械臂或小车根据这个坐标执行动作。

不要一开始就把相机、机械臂、规划器、控制器、真实环境全部接上。AprilTag 本身不难,难的是把坐标链路接清楚。

10. 小结

AprilTag 的核心价值是:用一张容易打印、容易识别的黑白标签,把视觉问题变成一个清晰的坐标问题。

在 ROS 2 项目里,它通常承担“视觉定位入口”的角色:相机提供图像和内参,AprilTag 检测器发布标签 TF,后面的运动规划或业务逻辑只需要使用这个 TF。

这个项目展示的是一条很适合入门的路线:先用虚拟 AprilTag 图像跑通检测和 TF,再把标签位姿交给 MoveIt 里的机械臂流程。理解这条链路后,再换成真实相机、多个标签、复杂工位,思路也是一样的。

学 AprilTag 最重要的不是记参数,而是记住这句话:图像负责看见,内参负责算准,TF 负责把坐标传给机器人。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐