1. 为什么地下车库是轮速里程计的“噩梦”?
如果你玩过扫地机器人或者自己捣鼓过移动机器人,肯定对SLAM(即时定位与地图构建)不陌生。简单说,就是让机器人在未知环境里,一边走一边知道自己在哪里,同时还能画出一张地图。这事儿听起来很酷,但真干起来,尤其是在地下车库这种地方,坑多得能让你怀疑人生。今天咱们不聊那些高大上的激光雷达或者视觉SLAM,就聊聊一个最基础、最便宜,但也最让人又爱又恨的传感器——轮速里程计,也叫轮速仪。
轮速里程计的原理特别简单,就像我们小时候玩的四驱车,通过数车轮转了多少圈,来推算车子跑了多远、转了多少度。在开阔、平坦、笔直的路上,这玩意儿其实挺准的。但一进地下车库,好戏就开始了。首先,地面材质五花八门,有光滑的环氧地坪,有粗糙的水泥地,还有带纹路的防滑带,每种地面对轮胎的摩擦系数都不一样,直接导致“打滑”或“滑移”。你以为轮子转了10圈,车子前进了10米,可能实际上只走了9.8米,那0.2米的误差就这么悄无声息地积累起来了。
更头疼的是转弯。地下车库通道窄,柱子多,动不动就是90度甚至更急的弯。机器人转弯时,左右轮速度差很大,而且轮胎与地面之间会发生复杂的侧向滑动,这可不是简单的几何模型能完美描述的。我实测过很多次,一个直角弯转下来,航向角(就是机器人头的朝向)误差累积个三五度是家常便饭。几圈绕下来,机器人自己“以为”的位置和它“实际”在地图上的位置,可能就差出好几米了,这就是所谓的“累积误差爆炸”。所以,很多新手会觉得,轮速里程计在地下库里根本没法用,数据漂得跟喝醉了酒一样。但我的经验是,它并非一无是处,关键在于你怎么认识它、处理它,把它从“猪队友”变成“神助攻”。
2. 从数据到模型:轮速里程计的“基本功”修炼
想把轮速里程计用好,第一步不是上什么高级算法,而是把最基础的“数据预处理”和“运动模型”搞明白。这就像练武先扎马步,基础不牢,后面全白搭。
2.1 数据预处理:给原始信号“洗个澡”
从电机编码器出来的原始脉冲信号,可不能直接拿来算位移。这里面噪音多着呢。首先是刻度误差,你的轮子周长标称是0.5米,但充气程度、负载重量不同,实际周长可能就在0.498到0.502米之间波动。我建议在项目开始前,找个长直道,让机器人匀速跑个20米,用卷尺实际测量,反复几次取平均,把这个系数校准准。这步做得好,直线误差能直接降低好几个百分点。
其次是采样与积分。编码器信号频率很高,比如100Hz,但你的SLAM算法可能只在50Hz下运行。这里就涉及到怎么把高频的轮子转动增量,正确地累加到每个SLAM周期里。最怕的就是不同步和丢数据。我踩过的坑是,负责读取编码器的线程和负责位姿估计的线程时间戳没对齐,导致有些数据被重复积分,有些被漏掉,轨迹一下子就歪了。后来我统一用硬件触发或者高精度系统时钟来打时间戳,确保每个脉冲都被准确记录在正确的时间间隔里。
还有一个容易被忽略的是异常值过滤。比如轮子瞬间卡到个小石子,或者因为地面湿滑空转了一下,会产生一个极大或极小的速度值。如果不处理,这一下子就能把位姿“带飞”。我的土办法是加一个简单的滑动窗口滤波器:计算过去一段时间(比如0.1秒)内的速度均值和标准差,如果当前速度值超出了均值±3倍标准差的范国,就认为它是异常值,用上一个正常值或者均值替代。虽然简单,但非常有效。
2.2 运动模型选择:双轮差速的“两种算法”
对于最常见的双轮差速机器人,如何根据左右轮的速度或位移推导出整机的运动,主要有两种主流模型。网上很多文章只提一种,但其实区别不小。
模型一:基于瞬时旋转中心(ICR)的几何模型。 这是教科书里最经典的模型。它假设机器人在极短的时间间隔内,是绕着某个瞬时中心做圆弧运动。公式很优美,直接通过左右轮的速度差和轮距,就能算出旋转角速度和前进速度。在ROS的robot_pose_ekf等包里,默认用的就是这种模型。它的优点是计算量小,直观。但它的一个强假设是:两个轮子与地面之间都是纯滚动,没有滑动。在地下车库转弯时,这个假设经常被打破。
模型二:基于位姿增量的递推模型。 这个模型不那么“几何”,更“数值”一些。它不假设瞬时圆弧,而是直接计算每个周期内,左右轮各自走过的弧长,然后通过解算来更新机器人的位姿。它相当于对机器人的运动做了更直接的数值积分。有些文献里也把它叫做“航迹推演”模型。
我写了一段简化的Python代码来对比这两种模型在转弯时的差异:
import numpy as np
def model_icr(v_left, v_right, wheelbase, dt):
"""模型一:瞬时旋转中心模型"""
linear_vel = (v_right + v_left) / 2.0
angular_vel = (v_right - v_left) / wheelbase
delta_theta = angular_vel * dt
# 当角速度很小时,避免除零,用近似
if abs(angular_vel) < 1e-6:
delta_x = linear_vel * dt * np.cos(theta)
delta_y = linear_vel * dt * np.sin(theta)
else:
radius = linear_vel / angular_vel
delta_x = radius * (np.sin(theta + delta_theta) - np.sin(theta))
delta_y = radius * (np.cos(theta) - np.cos(theta + delta_theta))
return delta_x, delta_y, delta_theta
def model_increment(s_left, s_right, wheelbase):
"""模型二:位姿增量模型"""
delta_s = (s_right + s_left) / 2.0
delta_theta = (s_right - s_left) / wheelbase
# 计算本体系下的位移
if abs(delta_theta) < 1e-6:
# 直行
delta_x_body = delta_s
delta_y_body = 0
else:
# 弧线运动
radius = delta_s / delta_theta
delta_x_body = radius * np.sin(delta_theta)
delta_y_body = radius * (1 - np.cos(delta_theta))
return delta_x_body, delta_y_body, delta_theta
# 模拟一个急转弯:右轮快,左轮慢
v_left, v_right = 0.1, 0.5 # m/s
wheelbase = 0.6 # 轮距,米
dt = 0.1 # 秒
s_left, s_right = v_left * dt, v_right * dt
# 分别用两种模型计算位姿增量
delta_x1, delta_y1, delta_theta1 = model_icr(v_left, v_right, wheelbase, dt)
delta_x_body2, delta_y_body2, delta_theta2 = model_increment(s_left, s_right, wheelbase)
print(f"模型一(ICR)结果: delta_x={delta_x1:.3f}m, delta_y={delta_y1:.3f}m, delta_theta={delta_theta1:.3f}rad")
print(f"模型二(增量)结果: delta_x_body={delta_x_body2:.3f}m, delta_y_body={delta_y_body2:.3f}m, delta_theta={delta_theta2:.3f}rad")
跑一下你会发现,在转弯半径很小(即角速度很大)的时候,两种模型算出的delta_theta(角度变化)是一样的,但delta_x和delta_y(位置变化)会有细微差别。这个差别在单次计算中微不足道,但经过几百上千次积分后,就会导致最终估计的轨迹产生明显的分离和旋转。在我之前的项目中,用同一段地下车库数据,两种模型跑出的轨迹整体形状相似,但整个坐标系会有一个微小的偏转,就像两张同样的图片,但一张被稍微旋转了几度。所以,选择哪个模型并不是绝对的,关键是要和你后续的传感器融合框架匹配,并且在整个系统中保持一致性。
3. 实战:如何评估与优化轮速里程计的精度?
理论懂了,模型选了,接下来就得真刀真枪地看看这东西在地下车库里到底准不准,不准的话又该怎么优化。评估离不开一个靠谱的“尺子”,也就是地面真值。在地下车库,GPS信号为零,常用的真值来源有:高精度惯导、激光雷达SLAM建图后优化出的轨迹、或者事先铺设的UWB超宽带定位系统。
3.1 设计一个科学的评测实验
假设我们有一个还不错的地下车库激光SLAM建好的地图,我们可以让机器人沿着固定路线跑,用激光匹配定位得到一个相对高精度的轨迹作为参考真值。同时,记录下轮速里程计的数据。评测的关键步骤如下:
- 时间戳对齐:这是所有多传感器数据融合的基础,没对齐,后面全错。轮速计频率高(如50Hz),参考轨迹频率低(如10Hz)。不能简单取最近点,要用插值。比如,对于参考轨迹上的某个时刻
t_ref,找到轮速里程计轨迹上刚好在t_ref之前和之后的两个点,然后按时间线性插值出t_ref时刻轮速里程计估计的位置。这个插值误差必须控制在毫秒级。 - 计算相对位移误差:直接比较绝对坐标意义不大,因为轮速里程计没有全局校正,漂移是必然的。我们应该分段计算误差。比如,每隔5米或10米,截取一段轨迹,分别计算这段路上,轮速里程计估计的位移向量和参考轨迹的位移向量,然后比较两者的方向和长度差异。这能告诉我们,在短距离内,轮速里程计的可靠性如何。
- 重点关注转弯段:把路径中的直线段和转弯段分开分析。我通常会把转弯开始前2米到转弯结束后2米的数据单独拎出来。计算转弯过程中的航向角误差累积和位置误差累积。你会发现,绝大多数误差都爆发在转弯阶段。
为了更直观,我们可以把误差统计做成表格:
| 路径段类型 | 平均位移误差(米/每10米) | 平均航向误差(度/每90度转弯) | 主要误差来源分析 |
|---|---|---|---|
| 直线环氧地坪 | 0.05 - 0.15 | 不适用 | 刻度系数误差,轻微打滑 |
| 直线水泥糙面 | 0.10 - 0.25 | 不适用 | 颠簸导致编码器读数抖动,摩擦系数变化 |
| 90度标准弯 | 0.30 - 0.80 | 3 - 8 | 内外轮滑移率不同,模型不匹配 |
| 急弯(掉头) | 0.50 - 1.50 | 5 - 15 | 严重侧滑,旋转中心偏离几何中心 |
从这个表可以清晰看到,转弯是误差的重灾区。直线段误差虽然小,但会随着距离累积;转弯误差则是单次爆发性强,直接“带偏”航向。
3.2 针对性的优化策略
知道了误差在哪,我们就可以“对症下药”了。
对于直线累积误差,光靠改进轮速计本身很难根除。我的策略是 “定期归零”。利用地下车库的结构特征,比如,当激光雷达检测到机器人经过一个门框、柱子或者特定的墙面拐角时,我们可以认为这是一个特征鲜明的“关键点”。一旦识别到这些关键点,就触发一个校正:假设在通过这个点的瞬间,轮速里程计在垂直于走廊方向的位置误差为零(因为机器人通常沿走廊中心行驶),然后对轮速里程计的侧向位置进行一次轻量级的校正。这相当于给漂移设置了一个“锚点”,防止它无限发散。
对于转弯误差,优化空间更大。首先是模型补偿。我们可以通过实验,标定出在不同转弯半径下,左右轮的实际滑移率。比如,发现机器人左转时,右轮(外侧轮)的实际行进距离总是比编码器读数多1%,左轮(内侧轮)少0.5%。我们就可以在模型计算时,引入一个与转弯方向和曲率相关的滑移补偿系数。虽然这是个经验值,但在类似环境(如同一个车库)里效果显著。
其次,可以引入低成本的IMU(惯性测量单元)。一个几十块钱的MPU6050芯片就很有用。轮速计在转弯时航向角误差大,而IMU的陀螺仪在短时间内的角度积分相对准确。我们可以用卡尔曼滤波器或者互补滤波器,把轮速计推算的位置、速度和IMU测得的角速度、加速度融合起来。具体来说,在直线段,信任轮速计;在检测到角速度变大(开始转弯)时,逐步提高陀螺仪数据在航向角估计中的权重。这样就能有效抑制转弯造成的航向漂移。融合时要注意,IMU数据噪声大,尤其是便宜的MEMS器件,需要设计好滤波参数。
4. 误差分析与系统集成:让轮速计成为可靠的“基石”
经过预处理、模型选择和针对性优化,我们的轮速里程计应该已经比原始数据靠谱多了。但到了实际SLAM系统中,它扮演什么角色,又该如何与其他传感器共处呢?
4.1 深入理解误差来源
轮速里程计的误差不是随机的,它有很强的规律性,主要分为系统性误差和非系统性误差。
系统性误差就像一把刻度不准的尺子,每次量都犯同样的错。包括:
- 刻度系数误差:轮子周长不准。
- 轮距误差:两个轮子之间的实际距离与模型参数不符。
- 安装偏差:编码器轴与轮轴不同心,存在偏心误差。
这些误差可以通过标定来大幅减小。标定不需要昂贵设备,让机器人在空旷场地走一个精确的正方形或圆形,测量起点和终点的位置偏差,通过数学方法就能反解出刻度系数和轮距的误差量,并在软件中补偿掉。我一般在新机器人上线或更换轮胎后,都会做一次这个标定。
非系统性误差则与环境和个人操作有关,难以完全预测和补偿:
- 打滑/滑移:这是地下车库最大的敌人。加速、刹车、转弯、地面有砂砾或水渍都会引起。
- 地面不平:车库地面常有缓坡、减速带或接缝。轮子上下颠簸时,实际行进距离与在平面上的投影距离不符。
- 轮胎形变:负载不同,轮胎被压扁的程度不同,有效滚动半径也在变。
对于非系统性误差,我们的目标不是消除它(不可能完全消除),而是探测它和降低其影响。例如,可以通过监测左右轮速度的突然异常差异来探测单侧打滑;通过IMU检测到异常的垂向加速度来感知颠簸。当探测到这些异常事件时,SLAM系统可以暂时降低对轮速里程计的信任权重,或者切换到以其他传感器(如激光)为主的运动估计模式。
4.2 在SLAM系统中的正确打开方式
在现代SLAM框架中,如Cartographer、LOAM或其变种,轮速里程计通常不作为唯一的运动估计源。它的最佳角色是提供一个高频、短期相对准确的运动预测。
以谷歌Cartographer为例,它前端使用扫描匹配进行精细定位,但扫描匹配需要一个好的初始位姿猜测,否则容易匹配失败或陷入局部最优。轮速里程计就在这里发挥巨大作用:在两次激光扫描的间隔(比如0.1秒),用轮速里程计来预测机器人在这0.1秒内移动了多少,为本次扫描匹配提供一个非常靠近真实值的初始猜测。这能极大提高扫描匹配的成功率和速度。
在滤波框架(如EKF-SLAM)或图优化框架(如GTSAM)中,轮速里程计的数据通常作为相邻位姿节点之间的约束边添加到图中。这条边的“强度”(信息矩阵的逆)需要根据我们前面分析的误差情况来动态设置。在直线、平地,这条边可以很强;在转弯、颠簸路段,这条边就要相应调弱,告诉优化器“我这个数据不太准,你别全信”。
我个人的经验是,一个调校良好的轮速里程计,虽然自己单独运行的轨迹会漂移,但它提供的相对运动信息,在几米、十几米的短距离内,其平滑性和连续性往往比单纯的激光匹配或视觉里程计还要好。它能有效弥补激光匹配在特征稀少的长走廊中的抖动问题,也能在视觉里程计因光照突变失效时提供兜底的运动信息。所以,千万不要因为它有累积误差就弃之不用,把它看作一个优秀的“短跑选手”,用其他传感器(激光、视觉、IMU)来做“定期校正”和“全局导航”,才能构建出稳定、鲁棒的SLAM系统。在地下车库这个充满挑战的环境里,多传感器融合不是可选项,而是必选项,而轮速里程计,永远是那个最踏实、最基础的融合基石。
2448



被折叠的 条评论
为什么被折叠?



