保姆级教程:用MATLAB复现一个完整的UKF滤波器,从理论推导到代码逐行解析

张开发
2026/4/18 21:20:28 15 分钟阅读

分享文章

保姆级教程:用MATLAB复现一个完整的UKF滤波器,从理论推导到代码逐行解析
从零实现无迹卡尔曼滤波MATLAB实战与原理精讲当我们需要对非线性系统进行状态估计时无迹卡尔曼滤波UKF往往比传统的扩展卡尔曼滤波EKF表现更出色。但很多学习者在理解算法原理后面对实际代码实现时仍会感到无从下手。本文将带你从理论到实践一步步构建完整的UKF滤波器每行代码都对应着数学公式的具象化表达。1. UKF核心原理与实现框架UKF的核心思想是通过精心选择的Sigma点来捕捉状态分布的特征避免了EKF中线性化带来的误差。想象一下你手中有一团橡皮泥代表状态分布UKF的做法不是把它压扁成平面线性化而是选取几个关键点来保持其立体形状。UKF的六大关键步骤Sigma点生成 - 从当前状态分布中采样代表性点集状态预测 - 将每个Sigma点通过非线性状态方程传播统计量预测 - 计算预测状态的均值和协方差观测预测 - 将预测的Sigma点通过观测方程映射观测统计量 - 计算预测观测的均值和协方差状态更新 - 结合实际观测更新状态估计在MATLAB中实现时我们需要特别注意几个易错点协方差矩阵平方根的计算方式权重向量的构造逻辑Sigma点遍历的实现技巧数值稳定性的保障措施2. 工程实现前的准备工作2.1 系统建模与参数初始化我们先定义一个典型的非线性系统作为测试案例。考虑一个二维平面运动的物体状态包括位置和速度% 系统维度参数 state_dim 4; % [px, py, vx, vy] measure_dim 2; % 只能观测位置 % 初始状态估计 x_est [0; 0; 1; 0.5]; % 初始位置和速度 P_est diag([0.1, 0.1, 0.05, 0.05]); % 初始协方差 % 过程噪声和观测噪声 Q diag([0.01, 0.01, 0.005, 0.005]); % 过程噪声协方差 R diag([0.1, 0.1]); % 观测噪声协方差 % 非线性状态方程 (CTRV模型) f (x) [ x(1) x(3)*dt; x(2) x(4)*dt; x(3); x(4) ]; % 非线性观测方程 (只能观测位置) h (x) [x(1); x(2)];2.2 UKF参数配置UKF性能很大程度上取决于几个关键参数的设置参数推荐值作用说明α1e-3~1控制Sigma点分布范围β2包含先验分布信息(高斯分布取2)κ0次要缩放参数通常设为0alpha 1e-3; beta 2; kappa 0; lambda alpha^2*(state_dim kappa) - state_dim; % 权重计算 Wm [lambda/(state_dimlambda); ones(2*state_dim,1)/(2*(state_dimlambda))]; Wc [(lambda/(state_dimlambda)) (1-alpha^2beta); ones(2*state_dim,1)/(2*(state_dimlambda))];注意权重向量Wm用于计算均值Wc用于计算协方差两者在第一个权重上略有不同3. Sigma点生成与传播实现3.1 安全的矩阵平方根计算Sigma点生成需要计算协方差矩阵的平方根。直接使用sqrtm函数在数值不稳定时可能失败我们采用更稳健的Cholesky分解function S chol_safe(P) [S, p] chol(P); if p 0 [V,D] eig(P); D max(D,0); S V*sqrt(D); end end3.2 Sigma点生成与预测基于当前状态和协方差生成Sigma点并通过状态方程传播% 生成Sigma点 sqrt_P chol_safe((state_dimlambda)*P_est); X_sigma [x_est, x_est*ones(1,state_dim)sqrt_P, ... x_est*ones(1,state_dim)-sqrt_P]; % 状态预测 X_pred zeros(state_dim, 2*state_dim1); for i 1:2*state_dim1 X_pred(:,i) f(X_sigma(:,i)); end % 计算预测均值和协方差 x_pred X_pred * Wm; P_pred Q; % 先加入过程噪声 for i 1:2*state_dim1 P_pred P_pred Wc(i)*(X_pred(:,i)-x_pred)*(X_pred(:,i)-x_pred); end关键细节在计算预测协方差时我们先将过程噪声Q加入再叠加Sigma点带来的不确定性4. 观测更新与状态修正4.1 观测预测与统计量计算将预测的Sigma点通过观测方程映射并计算相关统计量% 观测Sigma点 Z_sigma zeros(measure_dim, 2*state_dim1); for i 1:2*state_dim1 Z_sigma(:,i) h(X_pred(:,i)); end % 观测预测统计量 z_pred Z_sigma * Wm; P_zz R; % 先加入观测噪声 P_xz zeros(state_dim, measure_dim); for i 1:2*state_dim1 dz Z_sigma(:,i) - z_pred; P_zz P_zz Wc(i)*(dz)*dz; P_xz P_xz Wc(i)*(X_pred(:,i)-x_pred)*dz; end4.2 卡尔曼增益与状态更新最终的状态更新步骤与标准卡尔曼滤波类似但基于UKF计算出的统计量% 卡尔曼增益计算 K P_xz / P_zz; % 实际观测 (这里模拟含噪声的观测) z_actual h(true_state) sqrt(R)*randn(measure_dim,1); % 状态更新 x_est x_pred K*(z_actual - z_pred); P_est P_pred - K*P_zz*K;常见问题排查如果协方差矩阵失去正定性尝试加入小的正则化项观测预测与实际情况偏差过大时检查观测模型是否正确滤波器发散时适当增大过程噪声Q的值5. 完整仿真循环与性能分析将上述步骤整合到时间循环中我们可以对UKF性能进行全面评估% 初始化记录变量 true_states zeros(state_dim, Nsteps); estimates zeros(state_dim, Nsteps); observations zeros(measure_dim, Nsteps); for k 1:Nsteps % 真实状态演化 true_state f(true_state) sqrt(Q)*randn(state_dim,1); % UKF预测步骤 [x_pred, P_pred] ukf_predict(x_est, P_est, f, Q, lambda, Wm, Wc); % 生成观测 z h(true_state) sqrt(R)*randn(measure_dim,1); % UKF更新步骤 [x_est, P_est] ukf_update(x_pred, P_pred, z, h, R, lambda, Wm, Wc); % 记录数据 true_states(:,k) true_state; estimates(:,k) x_est; observations(:,k) z; end性能评估指标% 位置RMSE pos_err sqrt(mean((true_states(1:2,:) - estimates(1:2,:)).^2, 2)); % 速度估计误差 vel_err sqrt(mean((true_states(3:4,:) - estimates(3:4,:)).^2, 2)); % 协方差一致性检验 innov observations - h(estimates); NIS sum(innov.*(P_zz\innov), 1); % 标准化创新平方和通过调整UKF参数和噪声模型观察这些指标的变化可以深入理解UKF的性能特点。在实际应用中建议先用仿真数据验证滤波器性能再部署到真实系统。

更多文章