从玩具车到AGV手把手教你用ARUCO二维码给ROS机器人做个简易‘路标’定位系统去年在指导大学生机器人竞赛时有个队伍拿着他们的TurtleBot3问我老师我们预算有限能不能不用激光雷达实现室内定位这个问题让我想起了十年前用反光板和二维码做AGV导航的工业案例。今天我们就用这个思路教大家用几分钱成本的ARUCO二维码为ROS机器人搭建一套高性价比的虚拟路标系统。1. 为什么选择ARUCO定位方案在机器人定位领域我们常面临这样的困境激光SLAM精度高但设备昂贵一套LIDAR动辄上万元轮式编码器成本低却存在累积误差视觉SLAM对算力要求较高。而ARUCO二维码定位就像是在环境中布置数字路标每个标记都带有唯一ID和已知尺寸机器人通过摄像头识别这些标记就能快速确定自身方位。这套方案有三大突出优势成本极低普通USB摄像头100-300元 打印的二维码几分钱/张部署灵活标记可随意粘贴、移动无需改造环境教育价值完整涵盖图像处理、坐标变换、位姿估计等机器人核心技术提示ARUCO是Augmented Reality University of Cordoba的缩写这种二维码专为增强现实设计比普通QR码具有更高的识别率和抗干扰能力。2. 环境搭建与工具准备2.1 硬件配置清单设备类型推荐型号预算范围开发平台Raspberry Pi 4B400-600元单板计算机NVIDIA Jetson Nano800-1200元USB摄像头Logitech C920200-300元机器人底盘TurtleBot3 Burger3000-5000元二维码打印材料亚光铜版纸200g20元/100张2.2 软件环境安装首先确保已安装ROS NoeticUbuntu 20.04或ROS MelodicUbuntu 18.04然后执行以下命令安装ARUCO相关功能包sudo apt-get install ros-$ROS_DISTRO-aruco ros-$ROS_DISTRO-aruco-msgs ros-$ROS_DISTRO-aruco-ros cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/pal-robotics/aruco_ros catkin_make遇到CV_FILLED报错时编辑simple_double.cpp文件将所有CV_FILLED替换为-1即可。这个参数表示绘制实心圆新版本OpenCV中常量定义发生了变化。3. 创建你的虚拟路标系统3.1 生成ARUCO标记使用在线生成器创建不同ID的标记推荐尺寸10cm×10cmimport cv2 import numpy as np dictionary cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250) markerImage np.zeros((700, 700), dtypenp.uint8) markerImage cv2.aruco.generateImageMarker(dictionary, 42, 700, markerImage, 1) cv2.imwrite(marker42.png, markerImage)关键参数说明DICT_6X6_250表示使用6×6比特的字典包含250个不同标记数字42标记的唯一ID0-249700输出图像分辨率3.2 摄像头标定实战未标定的摄像头就像近视眼看到的图像会有畸变。执行单目标定rosrun camera_calibration cameracalibrator.py \ --size 8x6 \ --square 0.024 \ image:/usb_cam/image_raw \ camera:/usb_cam操作要点使用棋盘格标定板建议打印A4尺寸在摄像头前移动标定板覆盖整个视野当所有进度条变绿后点击CALIBRATE保存生成的ost.yaml文件到~/.ros/camera_info/4. 实现机器人定位功能4.1 启动识别节点创建single.launch文件配置识别参数launch arg namemarkerId default42/ arg namemarkerSize default0.1/ !-- 单位米 -- arg namecamera_frame defaultusb_cam/ arg namemarker_frame defaultaruco_marker/ node pkgaruco_ros typesingle namearuco_single remap from/camera_info to/usb_cam/camera_info / remap from/image to/usb_cam/image_raw / param nameimage_is_rectified valueTrue/ param namemarker_size value$(arg markerSize)/ param namemarker_id value$(arg markerId)/ param namereference_frame value$(arg camera_frame)/ param namecamera_frame value$(arg camera_frame)/ param namemarker_frame value$(arg marker_frame) / /node /launch启动顺序roslaunch usb_cam usb_cam.launchroslaunch aruco_ros single.launchrostopic echo /aruco_single/pose4.2 坐标变换与定位获取的位姿数据是相对于摄像头的需要转换到机器人坐标系。创建TF广播节点#!/usr/bin/env python import rospy import tf from geometry_msgs.msg import PoseStamped def pose_callback(msg): br tf.TransformBroadcaster() 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(), base_link, camera_link) rospy.init_node(marker_tf_broadcaster) rospy.Subscriber(/aruco_single/pose, PoseStamped, pose_callback) rospy.spin()5. 进阶应用与性能优化5.1 多标记协同定位当环境中布置多个标记时可以显著提高定位可靠性。修改launch文件使用markers节点node pkgaruco_ros typemarkers namearuco_markers remap from/camera_info to/usb_cam/camera_info / remap from/image to/usb_cam/image_raw / param namemarker_size value0.1/ param namemarker_id value50,51,52,53/ param namereference_frame valuemap/ /node5.2 常见问题排查指南故障现象可能原因解决方案无法识别标记光照条件差增加补光灯或使用反光材质标记位姿数据跳动严重摄像头帧率过低更换高帧率摄像头≥30fps识别距离突然变短标记尺寸参数设置错误检查launch文件中的marker_size只能识别部分标记字典类型不匹配确保生成和识别使用相同字典在实验室测试中我们使用10cm×10cm的标记在2米距离内能达到±1cm的定位精度。当标记倾斜角度小于45度时识别成功率保持在95%以上。