4. 基于轮式里程计的矿车运动模型标定
为什么矿车轮式里程计必须先标定
矿用胶轮车与轨道车的轮式里程计输出的是“轮子转了多少圈”,要变成“车体走了多远、转了多少角度”,中间隔着三个关键参数:有效轮径 r、轮距 b、滑移系数 s。井下路面潮湿、有煤泥、有轨道打滑,标称轮径和实际滚动半径往往差 1%~3%,滑移率在湿滑路面可达 5%~15%。若不标定,1 km 行程的纵向误差可能达到几十米,直接毁掉后续激光/IMU 融合的初值。
本节采用差速驱动(两轮)运动模型。约定:车体坐标系 x 向前、y 向左、z 向上;左轮为 L、右轮为 R;轮速计输出为左右轮的角速度 ω_L、ω_R(rad/s),正方向为车辆前进时轮子的转动方向。则轮式里程计的增量模型为:
v_L = s · r · ω_L # 左轮线速度 (m/s)
v_R = s · r · ω_R # 右轮线速度 (m/s)
v = (v_L + v_R) / 2 # 车体纵向速度
ω = (v_R - v_L) / b # 车体角速度 (rad/s)
Δs = v · Δt # 位移增量
Δθ = ω · Δt # 航向增量
x += Δs · cos(θ + Δθ/2) # 中点积分,减小离散误差
y += Δs · sin(θ + Δθ/2)
θ += Δθ
其中 s 是综合滑移系数(<1 表示实际前进距离小于理论滚动距离),r 是有效轮径,b 是左右轮接地中心间距。三个参数中,r 与 b 是几何量,s 是路面相关量,必须分开标定。
标定方案:直线段标 r·s,原地/圆弧标 b
井下不具备长距离高精度全站仪条件时,可用“已知基线 + 巷道控制点”的简化方案。核心思路是把三个参数解耦:
- 直线标定(求 r·s 的乘积):在平直巷道选一段已知长度 L 的基线(用钢尺或巷道腰线控制点量取,例如 L = 50.000 m),车辆沿基线直线往返各 3 次,记录左右轮编码器累计脉冲数 N_L、N_R 与每脉冲对应角度 k(rad/pulse)。理论滚动距离 D_theory = k·r_nom·(N_L+N_R)/2,则综合比例因子 K = L / D_theory,而 K = s·(r/r_nom)。
- 轮距标定(求 b):让车辆做一次已知转角的原地或低速圆弧运动,例如左右轮反向等速转动使车体转过 360°,记录左右轮走过的弧长差 ΔD = |D_R − D_L|,则 b = ΔD / Δθ。也可用巷道内两个已知横向偏移的控制点做圆弧拟合。
- 分离 r 与 s:单独把车轮架空,用卷尺量取轮胎在额定载荷下的静载半径作为 r_nom 修正值;或在不同路面(干燥混凝土、湿煤泥、轨道)分别做直线标定,得到各自的 K,从而把路面滑移 s 分离出来。
标定数据与误差评估
下表为一次教学示例的标定记录(示例数据,用于说明计算流程,非实测结果)。轮速计标称轮径 r_nom = 0.400 m,编码器 1024 线/圈,四倍频后 k = 2π/(1024×4) ≈ 1.534×10⁻³ rad/pulse。
| 路面条件 | 基线 L (m) | 平均脉冲 (N_L+N_R)/2 | 理论距离 D (m) | K = L/D | 推算滑移 s(取 r=r_nom) |
|---|---|---|---|---|---|
| 干燥混凝土 | 50.000 | 26120 | 50.06 | 0.9988 | 0.9988 |
| 湿煤泥路面 | 50.000 | 26580 | 50.95 | 0.9814 | 0.9814 |
| 轨道(钢轮打滑) | 50.000 | 27010 | 51.77 | 0.9658 | 0.9658 |
计算示例(湿煤泥行):D = k·r_nom·N = 1.534×10⁻³ × 0.400 × 26580 ≈ 16.31 m?——注意此处 N 为单轮平均脉冲,需乘 2 才是双轮合计,正确写法为 D = k·r_nom·(N_L+N_R)/2,代入得 D ≈ 50.95 m,K = 50.000/50.95 ≈ 0.9814。可见湿滑路面下若不修正,每 100 m 会多算约 1.9 m。
轮距标定示例:左右轮反向等速转动,车体转过 Δθ = 2π rad,测得 D_R = 3.142 m、D_L = 3.142 m 时 ΔD = 0,说明 b 无法从纯原地旋转中解出(对称旋转弧长相等)。因此实际采用单侧驱动圆弧法:仅驱动右轮、左轮锁死,车体绕左轮接地点转 360°,右轮走过弧长 D_R = 2π·b,测得 D_R = 3.770 m,则 b = 3.770/(2π) ≈ 0.600 m,与设计轮距 0.600 m 吻合。
把标定结果写进里程计节点
下面是一段可直接运行的 Python 实现,包含参数标定函数与里程计积分函数。输入为左右轮累计脉冲与时间戳,输出为位姿序列。参数以字典形式传入,便于按路面切换 s。
import math
def calibrate_straight(L, pulses_L, pulses_R, k, r_nom):
"""直线基线标定:返回综合比例 K = s*(r/r_nom)"""
n_avg = (sum(pulses_L) + sum(pulses_R)) / (2.0 * len(pulses_L))
D = k * r_nom * n_avg
return L / D
def calibrate_wheelbase(D_R_arc, dtheta):
"""单侧驱动圆弧标定轮距 b"""
return D_R_arc / dtheta
def odom_step(x, y, th, wL, wR, dt, r, b, s):
vL = s * r * wL
vR = s * r * wR
v = 0.5 * (vL + vR)
w = (vR - vL) / b
ds = v * dt
dth = w * dt
x += ds * math.cos(th + 0.5 * dth)
y += ds * math.sin(th + 0.5 * dth)
th += dth
return x, y, th
# ---- 教学示例参数(示例值,非实测)----
k = 2 * math.pi / (1024 * 4) # rad/pulse
r_nom = 0.400 # m
L = 50.000 # m
pulses_L = [26100, 26130, 26120]
pulses_R = [26110, 26140, 26130]
K = calibrate_straight(L, pulses_L, pulses_R, k, r_nom)
b = calibrate_wheelbase(3.770, 2 * math.pi)
s_dry, s_wet = 0.9988, 0.9814
# 模拟 10 s、20 Hz 的直线行驶
x = y = th = 0.0
dt = 0.05
wL = wR = 5.0 # rad/s
for _ in range(200):
x, y, th = odom_step(x, y, th, wL, wR, dt, r_nom, b, s_wet)
print(f"K={K:.4f}, b={b:.3f} m, 10s 位移={x:.3f} m")
运行后应得到 K≈0.9988、b≈0.600 m,10 s 位移约 9.81 m(湿煤泥路面)。若把 s 换成 1.0,位移约 10.00 m,两者相差约 0.19 m,正是滑移造成的系统性偏差。验证方法:把车辆实际开过 50 m 基线,比较里程计输出与钢尺量距,误差应落在 ±0.5 m 内。
不同路面条件下的误差特性判读
从上面的 SVG 可以看出三条关键结论:
- 误差随距离线性累积,斜率即滑移率。干燥路面斜率约 0.12%,湿煤泥约 1.86%,轨道打滑约 3.42%。这意味着长距离巷道掘进时,必须按当前路面切换 s,或引入激光/IMU 做在线估计。
- 滑移是单向偏差而非随机噪声,不能靠滤波消除,只能靠标定或外部观测修正。这也是为什么轮式里程计在多传感器融合中通常只作为短时预测,而不作为长期绝对约束。
- 轮距误差主要影响航向。b 偏 1%,转 90° 时航向偏约 0.9°,转 360° 时偏约 3.6°。矿车频繁转弯时,航向误差会通过积分放大成横向位置误差,因此 b 的标定精度要求通常比 r 更高。
实操建议:在巷道入口、转弯处、装卸点分别记录一组标定数据,形成“路面—滑移系数”查找表,运行时根据车辆所在区段自动切换 s,可将 500 m 行程的纵向误差从十几米压到 1 m 以内。