在机器人自主导航领域,室内定位一直是技术实现的关键难点。传统方案如激光SLAM虽然精度高,但硬件成本让许多开发者望而却步。而基于视觉的ArUco二维码定位系统,则以其低成本和易部署的特点,成为学术研究和工业应用的理想选择。本文将带您从单目相机的基础识别开始,逐步升级到双目视觉的精准定位,最终实现与ROS导航栈的无缝集成。
选择相机时,我们需要在成本和精度之间找到平衡点。以下是两种方案的典型参数对照:
| 参数 | 普通USB单目相机 | 入门级双目相机 |
|---|---|---|
| 价格范围 | 200-500元 | 800-2000元 |
| 分辨率 | 720P-1080P | 640x480@60fps |
| 视场角(FOV) | 60-90度 | 单目70-100度 |
| 深度感知能力 | 无 | 0.3m-5m |
| 适用场景 | 二维位姿估计 | 三维空间定位 |
提示:对于预算有限的学校实验室或个人开发者,可以先从单目系统入手,待验证基础功能后再升级到双目方案。
ArUco标记的尺寸和质量直接影响识别效果。推荐使用以下参数生成标记:
bash复制# 安装aruco标记生成工具
sudo apt-get install ros-$ROS_DISTRO-aruco-msgs ros-$ROS_DISTRO-aruco
# 生成一个5x5的标记,ID为42,边长为100mm
rosrun aruco create_marker -d=0 -id=42 -s=0.1 marker42.png
关键打印注意事项:
安装aruco_ros包时,可能会遇到OpenCV版本兼容问题。以下是经过验证的安装流程:
bash复制cd ~/catkin_ws/src
git clone -b noetic-devel https://github.com/pal-robotics/aruco_ros
cd ~/catkin_ws
catkin_make
若编译报错CV_FILLED未定义,这是OpenCV4的API变更导致的。解决方法有两种:
-1cv::FILLED配置正确的launch文件是成功识别的关键。以下是典型配置示例:
xml复制<launch>
<arg name="marker_size" default="0.1" /> <!-- 标记边长,单位米 -->
<arg name="marker_id" default="42" />
<arg name="camera_frame" default="usb_cam" />
<node pkg="aruco_ros" type="single" name="aruco_single">
<remap from="/camera_info" to="/usb_cam/camera_info" />
<remap from="/image" to="/usb_cam/image_raw" />
<param name="image_is_rectified" value="false"/>
<param name="marker_size" value="$(arg marker_size)"/>
<param name="marker_id" value="$(arg marker_id)"/>
<param name="reference_frame" value="$(arg camera_frame)"/>
</node>
</launch>
启动后,可通过以下命令验证位姿数据:
bash复制rostopic echo /aruco_single/pose
双目标定是提升定位精度的关键步骤。推荐使用ROS官方标定工具:
bash复制rosrun camera_calibration cameracalibrator.py \
--size 8x6 \
--square 0.0245 \
right:=/stereo/right/image_raw \
left:=/stereo/left/image_raw \
left_camera:=/stereo/left \
right_camera:=/stereo/right
标定过程中的黄金法则:
标定完成后会生成以下关键参数:
| 参数名 | 物理意义 | 典型值范围 |
|---|---|---|
| D (畸变系数) | 径向和切向畸变 | [-0.5, 0.5] |
| K (内参矩阵) | 焦距和主点坐标 | 依分辨率而定 |
| R (旋转矩阵) | 左右相机相对姿态 | 单位矩阵附近 |
| T (平移向量) | 双目基线距离 | 0.05-0.2m |
| reprojection error | 重投影误差 | <0.15像素为优 |
注意:重投影误差超过0.3像素时,建议重新标定。常见问题源于标定板移动过快或光照条件不稳定。
正确的TF树是导航系统工作的基础。ArUco检测结果需要转换到机器人基坐标系:
python复制#!/usr/bin/env python
import tf
import rospy
from geometry_msgs.msg import PoseStamped
def pose_callback(msg):
br = tf.TransformBroadcaster()
# 假设相机到基座的变换是固定的
br.sendTransform((0.1, 0, 0.2),
tf.transformations.quaternion_from_euler(0, 0, 0),
rospy.Time.now(),
"base_link",
"camera_link")
# 发布标记到地图的变换
br.sendTransform((msg.pose.position.x,
msg.pose.position.y,
msg.pose.position.z),
(msg.pose.orientation.x,
msg.pose.orientation.y,
msg.pose.orientation.z,
msg.pose.orientation.w),
rospy.Time.now(),
"marker_42",
"camera_link")
rospy.init_node('tf_broadcaster')
rospy.Subscriber("/aruco_single/pose", PoseStamped, pose_callback)
rospy.spin()
将ArUco定位结果作为AMCL的初始位姿输入:
xml复制<param name="initial_pose_x" value="0.0" />
<param name="initial_pose_y" value="0.0" />
<param name="initial_pose_a" value="0.0" />
<param name="initial_cov_xx" value="0.25" />
<param name="initial_cov_yy" value="0.25" />
<param name="initial_cov_aa" value="0.25" />
python复制# 将/marker_42到/base_link的变换转换为地图坐标系下的位姿
# 这里假设第一个检测到的标记位置为地图原点
单标记易受遮挡影响,多标记系统可提高鲁棒性。实现策略包括:
在仓库AGV项目中,我们发现这些配置最有效:
光照条件对识别率的影响测试数据:
| 光照强度(lux) | 识别延迟(ms) | 成功率(%) |
|---|---|---|
| <100 | 120±25 | 65 |
| 100-500 | 80±15 | 92 |
| 500-1000 | 75±10 | 98 |
| >1000 | 85±20 | 90 |
最后提醒,系统集成后务必进行长时间稳定性测试。我们曾遇到过一个由USB供电不稳导致的偶发识别失败问题,改用独立电源后解决。