第一次接触机器人定位系统时,我被各种传感器数据和坐标转换搞得晕头转向。直到发现了robot_localization这个神器,它就像个智能大厨,能把IMU、轮速计、GPS这些"食材"完美融合,做出一道精准定位的"大餐"。这个ROS功能包的核心是两个滤波算法:EKF(扩展卡尔曼滤波)和UKF(无迹卡尔曼滤波),它们能处理各种传感器数据的不确定性和噪声。
实际项目中,我常用的是EKF节点,因为它计算量相对较小,适合大多数移动机器人场景。记得去年给园区巡检机器人做定位时,基础配置只用了IMU和轮速里程计,定位误差就控制在5厘米以内。后来加入GPS数据后,即使在露天广场这种开阔地带,也能保持稳定的定位精度。
配置传感器时最容易踩的坑就是话题命名不规范。上周调试时,我花了三小时才发现IMU数据没被接收,原因竟是话题名多了个斜杠。建议先用rostopic list确认所有传感器数据正常发布。
对于常见的传感器组合,这是我的配置模板:
xml复制<param name="odom0" value="/wheel_odom"/>
<param name="imu0" value="/imu/data"/>
<param name="pose0" value="/gps/pose"/>
特别注意:GPS数据需要先经过navsat_transform_node转换。有次项目就因为这个疏忽,导致机器人定位直接"飞"到几百米外。转换后的GPS话题建议命名为/gps/fix,这样可以直接对接EKF节点。
坐标系的正确配置是定位系统的骨架。新手常犯的错误是混淆map、odom和base_link的关系。简单来说:
map是全局固定坐标系(比如GPS的世界坐标)odom是局部固定坐标系(轮速里程计的起始点)base_link是机器人本体坐标系调试时一定要用tf_tree工具可视化检查。曾经有个项目因为odom到base_link的tf没发布,导致机器人"原地起飞"。正确的tf树应该像这样:
code复制map -> odom -> base_link
↑
EKF输出
process_noise_covariance(Q矩阵)是调参的重中之重,它决定了系统对运动模型的信任程度。经过多次实测,我总结出这些经验值:
| 状态量 | 轮式机器人 | 足式机器人 | 无人机 |
|---|---|---|---|
| X/Y位置 | 0.01 | 0.05 | 0.1 |
| Z位置 | 0.001 | 0.01 | 0.5 |
| 旋转(RPY) | 0.005 | 0.02 | 0.1 |
测量噪声(R矩阵)要根据传感器实际性能调整。有个简单方法:让机器人静止时记录传感器数据的标准差,这个值就可以作为初始R矩阵参数。
用rqt_plot实时监控/odometry/filtered话题是关键。我习惯同时绘制原始传感器数据和滤波后结果,这样能直观看到滤波效果。有次发现Z轴数据异常波动,最后发现是IMU没固定牢导致的。
另一个神器是rviz的Odometry显示。把不同里程计源和滤波结果用不同颜色显示,可以快速发现哪个传感器出了问题。记得有次调试时,GPS数据突然跳变,就是因为附近有金属反射信号。
室外机器人最怕GPS信号丢失。我的应对方案是:
sensor_timeout参数diagnostic_aggregator监控传感器状态two_d_mode参数应对短暂失效去年暴雨天测试时,这套方案让机器人在GPS中断5分钟后仍保持1米内的定位误差。关键是在Q矩阵中适当增加位置噪声参数,让系统更依赖IMU和轮速计。
当多个机器人需要共享定位信息时,要特别注意tf前缀处理。我的经验是:
odom_frame(如robot1/odom)tf_prefix参数避免冲突map_frame在仓库AGV项目中,这套配置让10台机器人能共享同一个地图定位,协同误差小于15厘米。记得当时调试时发现时间同步很重要,建议使用PTP协议同步各机器人的系统时钟。
默认的恒速度模型可能不适用于特殊机器人。比如四足机器人的运动模型就需要修改predict_to_current_time函数。我参考过的开源实现有:
修改后记得重新标定Q矩阵。有次给机械狗加自定义模型后,忘记调整角速度噪声参数,导致机器人转弯时定位抖动明显。
当传感器频率超过100Hz时,EKF可能成为计算瓶颈。这些优化方法很实用:
use_control选项减少预测计算frequency参数限制更新频率threaded模式并行处理传感器数据在自动驾驶项目中,经过这些优化后,EKF节点的CPU占用从35%降到了12%。特别提醒:线程模式下要注意数据竞争问题,建议用ros::Duration做小延迟同步。