单元 8 · AprilTag识别与位姿显示机器人视觉实战课程

单元 8

8. AprilTag识别与位姿显示

本章使用ROS2、AprilTag和OpenCV完成机器人视觉标签识别。程序从深度相机获取RGB图像和相机标定信息,识别tag36h11标签,计算标签相对相机的三维位置和姿态,并在RViz2中同时显示机器人模型、标签坐标系、标签标记和实时检测画面。

7个学习部分

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_1tag_2tag_3坐标系。
  • 使用ROS2话题和TF2命令读取标签检测结果与三维位姿。
  • 调整标签尺寸、降采样倍数和汉明距离参数,并比较识别效果。

8.1.2 实验学习路径

AprilTag基础概念 → 准备并测量标签 → 启动基础识别 → 查看图像与RViz2 → 使用命令行读取检测结果 → 调整检测参数 → 恢复默认配置。

8.2 · AprilTag识别与位姿显示

AprilTag视觉基础

课程内容

8.2.1 什么是AprilTag

AprilTag是一种用于机器人视觉定位的黑白人工标记。每张标签由黑白方格组成,程序能够从图像中获得以下信息:

  • 标签所属的标签族,例如tag36h11
  • 标签ID,例如123
  • 标签中心点和四个角点在图像中的像素坐标。
  • 标签相对摄像头的三维位置和旋转姿态。

AprilTag不仅可以表示编号,还可以作为机器人定位、自动停靠、机械臂抓取和相机标定的空间基准。

8.2.2 标签族与ID

标签族规定了标签内部的数据位数量、编码方式和可纠正的错误数量。本课程使用:

TEXT
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 从二维图像到三维位姿

相机图像只能直接提供二维像素位置。程序结合以下数据计算标签三维位姿:

  1. 标签四个角点的像素坐标。
  2. 相机内参,包括焦距和主点位置。
  3. 相机畸变参数。
  4. 标签的实际边长。

程序使用PnP方法估计标签相对相机的平移和旋转,并通过TF2发布标签坐标系。

TEXT
标签四角像素坐标 + 相机内参 + 标签实际尺寸
                    ↓
                  PnP
                    ↓
         标签相对相机的三维位姿
                    ↓
             /tf中的tag_1等坐标系

8.2.4 标签打印与测量

  1. 使用tag36h11标签族生成或下载ID为123的标签。

  2. 打印时关闭“适应页面”“缩放到纸张”等自动缩放选项。

  3. 标签四周保留完整的白色区域,不要紧贴黑色外框裁剪。

  4. 打印后测量黑色外边框的实际边长。本课程默认值为:

TEXT
33 mm = 0.033 m
  1. 将标签固定在平整、坚硬的表面,避免标签弯曲、反光或出现折痕。

8.3 · AprilTag识别与位姿显示

基础实验:识别AprilTag并查看三维位姿

25~30分钟 · 入门
预计时间 难度 前置内容
25~30分钟 入门 8.1课程导读、8.2 AprilTag视觉基础

8.3.1 你将完成什么

启动课程程序后,机器人机械臂首先执行初始动作,随后启动深度相机、AprilTag检测节点和RViz2。

将ID为123的标签放入摄像头视野后:

  • 实时图像使用绿色线条标记标签四边。
  • 红色圆点标记标签中心。
  • 图像显示标签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为123tag36h11标签。
  • 标签黑色外边框边长与配置值33 mm一致。
  • 机械臂周围没有人员和障碍物。
  • 没有运行其他会占用深度相机或机器人控制器的程序。

8.3.4 开始实验

  1. 启动机器人,并使用NoMachine连接机器人远程桌面。关于连接方法,可参考 1 教程资料/1 机器人快速使用指南/ROSOrin Pro使用手册/7.2直连模式连接步骤

  2. 点击系统桌面的终端图标,打开命令行终端。

  3. 输入以下命令,停止APP自启服务:

Terminal
sudo systemctl stop start_app_node.service
  1. 确认其他视觉课程和相机Launch已经停止。若某个程序仍在运行,请返回对应终端按“Ctrl+C”。

  2. 清除机械臂周围障碍物,然后输入以下命令启动课程程序:

Terminal
/home/ubuntu/ros2_ws/src/apriltag_course/scripts/run_course.sh

当前命令行终端需要保持运行。

  1. 等待RViz2窗口打开。第一次启动时,模型和相机可能需要数秒完成初始化。

  2. 手持ID为1的标签,使标签正面朝向摄像头,并放置在摄像头视野中央。

  3. 缓慢改变标签的距离、位置和角度,观察检测图像和RViz2中的变化。

  4. 依次更换ID为23的标签,然后尝试同时放入两张或三张标签。

8.3.5 查看实验结果

实时检测图像

检测图像的话题为:

TEXT
/apriltag/detections_image

程序正常识别后,检查以下内容:

  • 标签四周出现绿色边框。
  • 标签中心出现红色圆点。
  • 标签旁显示id=1id=2id=3
  • ID旁显示margin=检测质量数值。
  • 画面左上角显示Detected tags: N,其中N为当前识别数量。

decision_margin越大,通常表示当前标签黑白区域区分越明显。该值适合用于同一环境下的相对比较,不建议作为所有环境通用的固定合格线。

RViz2三维界面

RViz2默认包含以下显示项:

显示项 作用 正确现象
RobotModel 显示机器人三维模型 能够看到机器人底盘、机械臂和相机模型。
AprilTag TF 显示机器人、相机和标签坐标系 识别后出现tag_1tag_2tag_3
Tag Markers 显示标签平面和可选ID文字 标签位置出现绿色薄板;启用apriltag_label命名空间后显示ID文字。
Detection Image 显示实时检测图像 能够看到标签边框、中心、ID和检测数量。
Grid 提供三维空间参考 机器人模型位于网格附近。

RViz2的Fixed Frame默认为:

TEXT
base_footprint

当标签在摄像头前移动时,tag_1等坐标系会相对机器人同步移动。标签绕自身旋转时,标签坐标轴方向也会发生变化。

图:RViz2同时显示检测图像、机器人模型以及tag_1标签TF坐标系。

8.3.6 观察识别结果

课程启动后,主要通过RViz2观察AprilTag识别结果:

  • Detection Image中查看标签数量、ID、margin检测质量、标签边框和中心点。
  • 在三维区域中查看机器人模型以及tag_1tag_2tag_3坐标系的位置和方向。
  • 缓慢移动或旋转标签,观察检测图像和三维坐标系是否同步变化。

8.3.7 结束实验

  1. 返回运行run_course.sh的命令行终端。

  2. 按“Ctrl+C”停止程序。

  3. 等待AprilTag检测、RViz2、相机和机器人控制节点退出。

  4. 输入以下命令恢复APP自启服务:

Terminal
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分钟 · 进阶
预计时间 难度 前置内容
25~30分钟 进阶 已完成8.3基础实验

本节需要修改的配置文件为:

TEXT
/home/ubuntu/ros2_ws/src/apriltag_course/config/tags.yaml

8.4.1 备份并打开配置文件

  1. 确认课程程序已经停止。如果程序仍在运行,请返回对应终端按“Ctrl+C”。

  2. 输入以下命令进入配置目录:

Terminal
cd /home/ubuntu/ros2_ws/src/apriltag_course/config
  1. 备份默认配置:
Terminal
cp -n tags.yaml tags.yaml.bak
  1. 打开配置文件:
Terminal
gedit tags.yaml

修改完成后按“Ctrl+S”保存并关闭编辑器。配置修改后停止并重新运行课程程序即可生效。

8.4.2 调整图像降采样倍数

默认参数为:

YAML
detector:
  decimate: 1.0

decimate用于降低四边形检测阶段的图像分辨率。数值越大,参与检测的像素越少,处理速度通常越快,但远距离小标签更容易漏检。

建议依次测试以下参数:

decimate 预期现象
1.0 使用完整分辨率,远距离和小标签检测能力较好,计算量较大。
1.5 速度和识别距离之间的折中。
2.0 处理负载降低,但远距离标签更容易漏检。

每次修改后,使用同一张标签、相同光照和相同移动路径,记录最大稳定识别距离和检测频率。

8.4.3 调整最大汉明距离

默认参数为:

YAML
max_hamming: 2

汉明距离表示检测到的编码与标准标签编码之间不同的数据位数量。允许纠正少量错误可以提高污损或低质量画面下的识别能力,但过度放宽会降低结果可靠性。

建议对比:

max_hamming 预期现象
0 只接受完全匹配的编码,结果严格,但低质量画面可能漏检。
1 允许纠正1位错误。
2 本课程默认值,容错能力较高。

测试时不要故意大面积遮挡标签。可以逐渐增加观察距离或改变标签角度,比较不同参数下的稳定性。

8.4.4 验证标签尺寸对位姿的影响

默认尺寸为:

YAML
size: 0.033
tag:
  sizes: [0.033, 0.033, 0.033]
  1. 将ID为1的标签固定在距离摄像头约0.5 m的位置。

  2. 使用默认尺寸启动程序,并记录:

Terminal
ros2 run tf2_ros tf2_echo depth_cam_frame tag_1
  1. 停止程序,将size和三个tag.sizes临时修改为:
YAML
size: 0.066
tag:
  sizes: [0.066, 0.066, 0.066]
  1. 重新启动程序,在不移动标签和摄像头的情况下再次记录位姿。

配置尺寸增大为原来的2倍后,程序估计的平移距离也会接近原来的2倍。这说明标签尺寸直接决定三维位姿的尺度。

8.4.5 可选拓展:增加ID 4标签

如果已经准备tag36h11的ID 4标签,可以在配置中增加一项。

将:

YAML
tag:
  ids: [1, 2, 3]
  frames: [tag_1, tag_2, tag_3]
  sizes: [0.033, 0.033, 0.033]

修改为:

YAML
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 记录实验结果

每次修改参数并重新启动课程程序后,新建一个终端,输入以下命令查看检测频率:

Terminal
ros2 topic hz /apriltag/detections

将标签稳定放置在摄像头画面内,持续观察约10 s。终端会输出类似结果:

TEXT
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 恢复默认配置

完成参数实验后,停止课程程序并输入:

Terminal
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:

TEXT
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 保存课程界面的显示项目和视角。

图像经过检测和可视化后的数据关系如下:

TEXT
摄像头图像与标定信息
        ↓
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为参考。课程涉及的主要坐标关系如下:

TEXT
base_footprint
    └─ ...机器人与相机安装坐标系...
           └─ depth_cam_frame
                  ├─ tag_1
                  ├─ tag_2
                  └─ tag_3

tag_1tag_2tag_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距离不准确
  • 测量标签黑色外边框的实际边长。
  • 确认sizetag.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识别与位姿显示

参考资料

课程内容