在移动机器人导航领域,精确定位是完成路径规划、避障等高级任务的基础前提。传统的单一传感器定位方案往往存在局限性:里程计虽然采样频率高,但存在累积误差;GPS提供全局定位但更新频率低且易受环境影响。因此,多传感器融合定位成为工业界和学术界的共同选择。
扩展卡尔曼滤波(EKF)作为经典的状态估计算法,能够有效融合不同特性的传感器数据。其核心优势在于:
我在多个机器人项目中实测发现,相比单独使用里程计,EKF融合方案能将定位误差降低60-80%,特别是在GPS信号不稳定的室内外过渡区域效果尤为显著。
机器人2D定位的状态向量通常包含位置和朝向角:
code复制x = [x坐标, y坐标, 航向角θ]^T
运动模型描述状态如何随时间演变。对于差分驱动机器人,常用的是基于里程计的运动模型:
python复制def motion_model(x_prev, u):
"""
x_prev: 上一时刻状态 [x,y,θ]
u: 控制输入 [Δx,Δy,Δθ]
"""
Δx, Δy, Δθ = u
θ = x_prev[2]
x_new = x_prev[0] + Δx*cos(θ) - Δy*sin(θ)
y_new = x_prev[1] + Δx*sin(θ) + Δy*cos(θ)
θ_new = θ + Δθ
return np.array([x_new, y_new, θ_new])
观测模型描述状态如何映射到传感器读数。对于GPS:
python复制def observation_model(x):
return x[:2] # 仅返回x,y坐标
EKF通过泰勒展开对非线性模型进行一阶线性近似。运动模型的雅可比矩阵计算如下:
python复制def compute_motion_jacobian(x, u):
Δx, Δy, Δθ = u
θ = x[2]
F = np.array([
[1, 0, -Δx*sin(θ)-Δy*cos(θ)],
[0, 1, Δx*cos(θ)-Δy*sin(θ)],
[0, 0, 1]
])
return F
观测模型的雅可比矩阵相对简单:
python复制H = np.array([
[1, 0, 0],
[0, 1, 0]
])
EKF的标准流程分为两个阶段:
预测阶段:
更新阶段:
关键提示:在实际实现时,应避免直接求逆矩阵,而采用数值更稳定的解法如Cholesky分解。
里程计:
GPS:
过程噪声Q和观测噪声R的设定直接影响滤波效果:
python复制# 过程噪声 - 与运动量成正比
Q = np.diag([
0.1*abs(Δx) + 0.01,
0.1*abs(Δy) + 0.01,
0.05*abs(Δθ) + 0.001
])
# 观测噪声 - 固定值基于GPS精度
R = np.diag([3.0**2, 3.0**2]) # 假设GPS标准差3米
实测调参技巧:
GPS信号可能突然跳变,采用新息检测过滤异常:
python复制innovation = z - h(x_pred)
S = H @ P_pred @ H.T + R
mahalanobis_dist = innovation.T @ np.linalg.inv(S) @ innovation
if mahalanobis_dist > chi2_threshold:
# 拒绝此次观测
x_new = x_pred
P_new = P_pred
经验阈值χ²_threshold通常取9-16(对应3-4σ置信区间)。
完整的EKF定位系统包含以下模块:
matlab复制classdef EKFLocalization
properties
x; % 状态向量 [x;y;θ]
P; % 协方差矩阵
Q; % 过程噪声
R; % 观测噪声
chi2_threshold = 9; % 卡方检验阈值
end
methods
function obj = predict(obj, u)
% 预测步骤实现
end
function obj = update(obj, z)
% 更新步骤实现
end
end
end
matlab复制function obj = predict(obj, u)
% 状态预测
theta = obj.x(3);
obj.x(1) = obj.x(1) + u(1)*cos(theta) - u(2)*sin(theta);
obj.x(2) = obj.x(2) + u(1)*sin(theta) + u(2)*cos(theta);
obj.x(3) = obj.x(3) + u(3);
% 计算雅可比矩阵
F = [1 0 -u(1)*sin(theta)-u(2)*cos(theta);
0 1 u(1)*cos(theta)-u(2)*sin(theta);
0 0 1];
% 协方差预测
obj.P = F * obj.P * F' + obj.Q;
end
matlab复制function obj = update(obj, z)
H = [1 0 0; 0 1 0];
% 计算卡尔曼增益
S = H * obj.P * H' + obj.R;
K = obj.P * H' / S;
% 新息检测
innovation = z - H * obj.x;
mahalanobis = innovation' / S * innovation;
if mahalanobis > obj.chi2_threshold
warning('GPS观测异常,已忽略');
return;
end
% 状态更新
obj.x = obj.x + K * innovation;
obj.P = (eye(3) - K * H) * obj.P;
end
良好的初始化能加速滤波器收敛:
matlab复制P0 = diag([10^2, 10^2, (pi/2)^2]); % 位置±10m,角度±90°
matlab复制IKH = eye(3) - K*H;
P_new = IKH * P_pred * IKH' + K * R * K';
matlab复制P = (P + P')/2;
现象:误差持续增大,估计轨迹偏离真实路径
可能原因:
解决方案:
现象:位置估计在真实值附近来回跳动
可能原因:
解决方案:
现象:位置估计尚可,但角度逐渐偏离
可能原因:
解决方案:
除里程计和GPS外,可引入:
根据传感器表现动态调整Q和R:
matlab复制% 基于新息协方差自适应
alpha = 0.1; % 平滑系数
S = H*P*H' + R;
R = (1-alpha)*R + alpha*(innovation*innovation');
当非线性较强时,可考虑:
在实际机器人导航系统中,EKF定位模块通常与建图、路径规划等模块协同工作。一个典型的架构是:
code复制传感器数据 → EKF定位 → 地图匹配 → 路径规划 → 运动控制
通过这样的处理流程,机器人能够实现从底层定位到高层决策的完整自主导航功能。