单元 8
8. AprilTag识别与位姿显示
本章使用ROS2、AprilTag和OpenCV完成机器人视觉标签识别。程序从深度相机获取RGB图像和相机标定信息,识别tag36h11标签,计算标签相对相机的三维位置和姿态,并在RViz2中同时显示机器人模型、标签坐标系、标签标记和实时检测画面。
8.1 · AprilTag识别与位姿显示
课程导读
本章使用ROS2、AprilTag和OpenCV完成机器人视觉标签识别。程序从深度相机获取RGB图像和相机标定信息,识别tag36h11标签,计算标签相对相机的三维位置和姿态,并在RViz2中同时显示机器人模型、标签坐标系、标签标记和实时检测画面。
课程程序已经集成机器人控制器、机械臂初始动作、Aurora深度相机、AprilTag检测节点和RViz2。使用一条Launch命令即可启动完整实验。
8.1.1 本章能完成什么
完成本章学习后,用户可以:
- 使用一条ROS2 Launch命令启动机器人、相机、AprilTag检测和RViz2。
- 识别
tag36h11标签的ID、中心点和四个角点。 - 在实时图像中查看标签边框、ID、标签族和检测质量。
- 在RViz2中观察机器人模型以及
tag_1、tag_2、tag_3坐标系。 - 使用ROS2话题和TF2命令读取标签检测结果与三维位姿。
- 调整标签尺寸、降采样倍数和汉明距离参数,并比较识别效果。
8.1.2 实验学习路径
AprilTag基础概念 → 准备并测量标签 → 启动基础识别 → 查看图像与RViz2 → 使用命令行读取检测结果 → 调整检测参数 → 恢复默认配置。
8.2 · AprilTag识别与位姿显示
AprilTag视觉基础
8.2.1 什么是AprilTag
AprilTag是一种用于机器人视觉定位的黑白人工标记。每张标签由黑白方格组成,程序能够从图像中获得以下信息:
- 标签所属的标签族,例如
tag36h11。 - 标签ID,例如
1、2和3。 - 标签中心点和四个角点在图像中的像素坐标。
- 标签相对摄像头的三维位置和旋转姿态。
AprilTag不仅可以表示编号,还可以作为机器人定位、自动停靠、机械臂抓取和相机标定的空间基准。
8.2.2 标签族与ID
标签族规定了标签内部的数据位数量、编码方式和可纠正的错误数量。本课程使用:
tag36h11
其中:
36表示标签包含36个数据位。h11表示标签编码之间具有较大的汉明距离,有利于降低误识别概率。- 同一标签族内的每张标签使用不同ID进行区分。
课程默认使用下表中的标签:
| 标签族 | 标签ID | 标签边长 | TF坐标系名称 |
|---|---|---|---|
tag36h11 |
1 |
0.033 m |
tag_1 |
tag36h11 |
2 |
0.033 m |
tag_2 |
tag36h11 |
3 |
0.033 m |
tag_3 |
8.2.3 从二维图像到三维位姿
相机图像只能直接提供二维像素位置。程序结合以下数据计算标签三维位姿:
- 标签四个角点的像素坐标。
- 相机内参,包括焦距和主点位置。
- 相机畸变参数。
- 标签的实际边长。
程序使用PnP方法估计标签相对相机的平移和旋转,并通过TF2发布标签坐标系。
标签四角像素坐标 + 相机内参 + 标签实际尺寸
↓
PnP
↓
标签相对相机的三维位姿
↓
/tf中的tag_1等坐标系
8.2.4 标签打印与测量
-
使用
tag36h11标签族生成或下载ID为1、2和3的标签。 -
打印时关闭“适应页面”“缩放到纸张”等自动缩放选项。
-
标签四周保留完整的白色区域,不要紧贴黑色外框裁剪。
-
打印后测量黑色外边框的实际边长。本课程默认值为:
33 mm = 0.033 m
- 将标签固定在平整、坚硬的表面,避免标签弯曲、反光或出现折痕。
8.3 · AprilTag识别与位姿显示
基础实验:识别AprilTag并查看三维位姿
| 预计时间 | 难度 | 前置内容 |
|---|---|---|
| 25~30分钟 | 入门 | 8.1课程导读、8.2 AprilTag视觉基础 |
8.3.1 你将完成什么
启动课程程序后,机器人机械臂首先执行初始动作,随后启动深度相机、AprilTag检测节点和RViz2。
将ID为1、2或3的标签放入摄像头视野后:
- 实时图像使用绿色线条标记标签四边。
- 红色圆点标记标签中心。
- 图像显示标签ID和
decision_margin。 - RViz2显示绿色标签平面和标签TF坐标轴,并可选显示ID文字。
- 标签移动或旋转时,RViz2中的标签坐标系同步变化。

图:RViz2同时显示机器人模型与tag_1标签TF坐标系。
8.3.2 实验目标
完成本实验后,用户可以:
- 正确启动和关闭AprilTag课程程序。
- 使用ID 1、2、3标签完成单标签和多标签识别。
- 区分二维检测结果和三维TF位姿。
- 使用ROS2命令检查图像、检测消息和TF。
- 根据画面现象排查标签族、标签尺寸和光照问题。
8.3.3 实验准备
开始实验前,请确认:
- 机器人已正常启动,并通过NoMachine连接远程桌面。
- 相机连接正常,摄像头镜头无遮挡。
- 已准备ID为
1、2和3的tag36h11标签。 - 标签黑色外边框边长与配置值
33 mm一致。 - 机械臂周围没有人员和障碍物。
- 没有运行其他会占用深度相机或机器人控制器的程序。
8.3.4 开始实验
-
启动机器人,并使用NoMachine连接机器人远程桌面。关于连接方法,可参考 1 教程资料/1 机器人快速使用指南/ROSOrin Pro使用手册/7.2直连模式连接步骤。
-
点击系统桌面的终端图标,打开命令行终端。
-
输入以下命令,停止APP自启服务:
sudo systemctl stop start_app_node.service
-
确认其他视觉课程和相机Launch已经停止。若某个程序仍在运行,请返回对应终端按“Ctrl+C”。
-
清除机械臂周围障碍物,然后输入以下命令启动课程程序:
/home/ubuntu/ros2_ws/src/apriltag_course/scripts/run_course.sh
当前命令行终端需要保持运行。
-
等待RViz2窗口打开。第一次启动时,模型和相机可能需要数秒完成初始化。
-
手持ID为
1的标签,使标签正面朝向摄像头,并放置在摄像头视野中央。 -
缓慢改变标签的距离、位置和角度,观察检测图像和RViz2中的变化。
-
依次更换ID为
2和3的标签,然后尝试同时放入两张或三张标签。
8.3.5 查看实验结果
实时检测图像
检测图像的话题为:
/apriltag/detections_image
程序正常识别后,检查以下内容:
- 标签四周出现绿色边框。
- 标签中心出现红色圆点。
- 标签旁显示
id=1、id=2或id=3。 - ID旁显示
margin=检测质量数值。 - 画面左上角显示
Detected tags: N,其中N为当前识别数量。
decision_margin越大,通常表示当前标签黑白区域区分越明显。该值适合用于同一环境下的相对比较,不建议作为所有环境通用的固定合格线。
RViz2三维界面
RViz2默认包含以下显示项:
| 显示项 | 作用 | 正确现象 |
|---|---|---|
RobotModel |
显示机器人三维模型 | 能够看到机器人底盘、机械臂和相机模型。 |
AprilTag TF |
显示机器人、相机和标签坐标系 | 识别后出现tag_1、tag_2或tag_3。 |
Tag Markers |
显示标签平面和可选ID文字 | 标签位置出现绿色薄板;启用apriltag_label命名空间后显示ID文字。 |
Detection Image |
显示实时检测图像 | 能够看到标签边框、中心、ID和检测数量。 |
Grid |
提供三维空间参考 | 机器人模型位于网格附近。 |
RViz2的Fixed Frame默认为:
base_footprint
当标签在摄像头前移动时,tag_1等坐标系会相对机器人同步移动。标签绕自身旋转时,标签坐标轴方向也会发生变化。

图:RViz2同时显示检测图像、机器人模型以及tag_1标签TF坐标系。
8.3.6 观察识别结果
课程启动后,主要通过RViz2观察AprilTag识别结果:
- 在
Detection Image中查看标签数量、ID、margin检测质量、标签边框和中心点。 - 在三维区域中查看机器人模型以及
tag_1、tag_2、tag_3坐标系的位置和方向。 - 缓慢移动或旋转标签,观察检测图像和三维坐标系是否同步变化。
8.3.7 结束实验
-
返回运行
run_course.sh的命令行终端。 -
按“Ctrl+C”停止程序。
-
等待AprilTag检测、RViz2、相机和机器人控制节点退出。
-
输入以下命令恢复APP自启服务:
sudo systemctl restart start_app_node.service
APP自启服务恢复后,机械臂可能再次执行系统初始动作,请保持机械臂周围区域空旷。
8.3.8 完成标准
满足以下条件即表示完成本节实验:
- 能够使用一条命令启动机器人、相机、AprilTag检测和RViz2。
- ID 1、2、3至少能够分别完成一次稳定识别。
- 检测图像能够显示绿色边框、红色中心点、标签ID和检测数量。
- RViz2能够同时显示机器人模型、标签Marker和标签TF。
- 移动标签时,图像标记和RViz2坐标系能够同步变化。
- 能够使用
tf2_echo查看标签相对相机的三维位姿。 - 能够使用“Ctrl+C”结束程序并恢复APP自启服务。
8.4 · AprilTag识别与位姿显示
核心进阶实验:调整AprilTag检测参数
| 预计时间 | 难度 | 前置内容 |
|---|---|---|
| 25~30分钟 | 进阶 | 已完成8.3基础实验 |
本节需要修改的配置文件为:
/home/ubuntu/ros2_ws/src/apriltag_course/config/tags.yaml
8.4.1 备份并打开配置文件
-
确认课程程序已经停止。如果程序仍在运行,请返回对应终端按“Ctrl+C”。
-
输入以下命令进入配置目录:
cd /home/ubuntu/ros2_ws/src/apriltag_course/config
- 备份默认配置:
cp -n tags.yaml tags.yaml.bak
- 打开配置文件:
gedit tags.yaml
修改完成后按“Ctrl+S”保存并关闭编辑器。配置修改后停止并重新运行课程程序即可生效。
8.4.2 调整图像降采样倍数
默认参数为:
detector:
decimate: 1.0
decimate用于降低四边形检测阶段的图像分辨率。数值越大,参与检测的像素越少,处理速度通常越快,但远距离小标签更容易漏检。
建议依次测试以下参数:
| decimate | 预期现象 |
|---|---|
1.0 |
使用完整分辨率,远距离和小标签检测能力较好,计算量较大。 |
1.5 |
速度和识别距离之间的折中。 |
2.0 |
处理负载降低,但远距离标签更容易漏检。 |
每次修改后,使用同一张标签、相同光照和相同移动路径,记录最大稳定识别距离和检测频率。
8.4.3 调整最大汉明距离
默认参数为:
max_hamming: 2
汉明距离表示检测到的编码与标准标签编码之间不同的数据位数量。允许纠正少量错误可以提高污损或低质量画面下的识别能力,但过度放宽会降低结果可靠性。
建议对比:
| max_hamming | 预期现象 |
|---|---|
0 |
只接受完全匹配的编码,结果严格,但低质量画面可能漏检。 |
1 |
允许纠正1位错误。 |
2 |
本课程默认值,容错能力较高。 |
测试时不要故意大面积遮挡标签。可以逐渐增加观察距离或改变标签角度,比较不同参数下的稳定性。
8.4.4 验证标签尺寸对位姿的影响
默认尺寸为:
size: 0.033
tag:
sizes: [0.033, 0.033, 0.033]
-
将ID为
1的标签固定在距离摄像头约0.5 m的位置。 -
使用默认尺寸启动程序,并记录:
ros2 run tf2_ros tf2_echo depth_cam_frame tag_1
- 停止程序,将
size和三个tag.sizes临时修改为:
size: 0.066
tag:
sizes: [0.066, 0.066, 0.066]
- 重新启动程序,在不移动标签和摄像头的情况下再次记录位姿。
配置尺寸增大为原来的2倍后,程序估计的平移距离也会接近原来的2倍。这说明标签尺寸直接决定三维位姿的尺度。
8.4.5 可选拓展:增加ID 4标签
如果已经准备tag36h11的ID 4标签,可以在配置中增加一项。
将:
tag:
ids: [1, 2, 3]
frames: [tag_1, tag_2, tag_3]
sizes: [0.033, 0.033, 0.033]
修改为:
tag:
ids: [1, 2, 3, 4]
frames: [tag_1, tag_2, tag_3, tag_4]
sizes: [0.033, 0.033, 0.033, 0.033]
同时,config/visualizer.yaml中的tag_frame_prefix: tag_会使可视化节点使用tag_4作为Marker参考坐标系,无需修改Python程序。
8.4.6 记录实验结果
每次修改参数并重新启动课程程序后,新建一个终端,输入以下命令查看检测频率:
ros2 topic hz /apriltag/detections
将标签稳定放置在摄像头画面内,持续观察约10 s。终端会输出类似结果:
average rate: 12.03
min: 0.078s max: 0.091s std dev: 0.003s window: 12
其中,average rate表示检测话题的平均发布频率,单位为赫兹(Hz)。将该数值填写到下表的“检测频率”一栏,记录完成后按“Ctrl+C”停止输出。
完成实验后填写下表:
| 实验参数 | 测试值 | 检测频率 | 最大稳定距离 | 位姿稳定性 | 结论 |
|---|---|---|---|---|---|
decimate |
1.0 / 1.5 / 2.0 |
||||
max_hamming |
0 / 1 / 2 |
||||
size |
0.033 / 0.066 |
记录时应保持标签、光照、相机分辨率和测试路径一致。
不同参数对检测频率的影响并不相同:decimate会改变参与检测的图像像素数量,通常对频率影响最明显;max_hamming主要影响编码纠错范围,对频率的影响通常较小;size用于将标签图像尺寸换算为三维位姿,通常不会明显改变检测频率,但错误的尺寸会导致距离估计不准确。实验时应以实测结果为准。
8.4.7 恢复默认配置
完成参数实验后,停止课程程序并输入:
cd /home/ubuntu/ros2_ws/src/apriltag_course/config
cp tags.yaml.bak tags.yaml
cmp -s tags.yaml tags.yaml.bak && echo "默认配置恢复成功"
终端显示“默认配置恢复成功”后,重新启动课程程序,确认ID 1、2、3能够正常识别。
8.5 · AprilTag识别与位姿显示
程序简要分析
本节只介绍课程程序的主要数据流和输出。检测参数的调整方法可参考8.4节。
8.5.1 程序工作流程
运行课程脚本后,Launch文件会启动机器人和摄像头、AprilTag检测节点、可视化节点以及RViz2:
run_course.sh
↓
apriltag_course.launch.py
├─ 启动机器人并执行初始动作
├─ 启动深度摄像头
├─ 识别AprilTag并计算位姿
├─ 绘制检测图像和标签Marker
└─ 在RViz2中显示机器人与检测结果
摄像头提供RGB图像和标定信息。AprilTag节点根据图像中的四角位置、标签实际边长和相机参数,计算标签ID及其相对于摄像头的三维位姿。
8.5.2 主要文件
课程程序位于/home/ubuntu/ros2_ws/src/apriltag_course,主要文件如下:
| 文件 | 作用 |
|---|---|
scripts/run_course.sh |
加载ROS2环境并启动课程。 |
launch/apriltag_course.launch.py |
统一启动机器人、摄像头、检测节点、可视化节点和RViz2。 |
config/tags.yaml |
设置标签族、实际边长、ID和检测参数。 |
apriltag_course/camera_frame_relay.py |
将检测所用图像和相机信息关联到depth_cam_frame。 |
apriltag_course/tag_visualizer.py |
绘制边框、ID和margin,并生成RViz2标签Marker。 |
rviz/apriltag_course.rviz |
保存课程界面的显示项目和视角。 |
图像经过检测和可视化后的数据关系如下:
摄像头图像与标定信息
↓
camera_frame_relay
↓
AprilTag检测节点 ──> 标签ID与三维位姿
↓
tag_visualizer ────> 检测图像与标签Marker
8.5.3 检测结果与坐标系
课程主要使用以下三个输出:
| 名称 | 作用 |
|---|---|
/apriltag/detections |
输出标签ID、角点和检测质量,也是8.4节测量检测频率所使用的话题。 |
/apriltag/detections_image |
输出绘制边框、ID和margin后的实时图像。 |
/apriltag/markers |
在RViz2中标记标签的三维位置。 |
标签位姿以摄像头坐标系depth_cam_frame为参考。课程涉及的主要坐标关系如下:
base_footprint
└─ ...机器人与相机安装坐标系...
└─ depth_cam_frame
├─ tag_1
├─ tag_2
└─ tag_3
tag_1、tag_2和tag_3分别对应ID为1、2和3的标签。只有摄像头识别到相应标签时,该标签坐标系才会出现在RViz2和TF中。
8.6 · AprilTag识别与位姿显示
常见问题
8.6.1 启动时提示package 'imu_calib' not found
该问题表示课程脚本版本过旧,错误过滤了机器人控制器需要的厂家依赖。确认使用当前版本:
cd /home/ubuntu/ros2_ws
colcon build --packages-select apriltag_course --symlink-install
/home/ubuntu/ros2_ws/src/apriltag_course/scripts/run_course.sh
当前脚本应能从/home/ubuntu/third_party/third_party_ws/install/imu_calib找到该包。
8.6.2 有相机画面但始终Detected tags: 0
- 确认标签属于
tag36h11,不要混用其他标签族。 - 优先使用ID 1、2和3进行课程实验。
- 保持标签完整进入画面,四周白色区域不要被遮挡。
- 避免强烈反光、逆光、运动模糊和严重倾斜。
- 将标签移近摄像头,确认黑色方格在图像中具有足够像素。
8.6.3 能识别ID,但TF距离不准确
- 测量标签黑色外边框的实际边长。
- 确认
size和tag.sizes均使用米作为单位。 - 检查相机是否发布有效的
CameraInfo。 - 标签应保持平整,弯曲或折叠会影响位姿估计。
ros2 topic echo /depth_cam/rgb0/camera_info --once
8.6.4 相机提示设备占用或话题重复
通常是另一个视觉程序或相机Launch仍在运行。返回对应终端按“Ctrl+C”,确认旧程序退出后再启动课程。不要同时运行两个depth_camera.launch.py。
若机器人控制器和相机必须保持运行,可使用:
/home/ubuntu/ros2_ws/src/apriltag_course/scripts/run_course.sh initialize_robot:=false start_camera:=false
8.7 · AprilTag识别与位姿显示
参考资料
- AprilTag官方实现:https://github.com/AprilRobotics/apriltag
- AprilTag官方标签图片:https://github.com/AprilRobotics/apriltag-imgs
- ROS2 Humble
apriltag_ros文档:https://docs.ros.org/en/ros2_packages/humble/api/apriltag_ros/ - RViz2用户文档:https://docs.ros.org/en/ros2_packages/humble/api/rviz2/