
简介一套基于改进粒子滤波算法的无人机三维航迹预测Matlab实现面向无人机导航、航迹规划与状态估计方向的研究人员、工程师及高年级学生适合处理风速扰动、传感器噪声等非线性非高斯场景下的轨迹预测实战。压缩包共16个文件以14个m脚本为主涵盖粒子滤波及扩展卡尔曼滤波EKF、无迹卡尔曼滤波UKF等核心函数并包含LICENSE与README文档整体仅18KB结构紧凑便于通读与二次开发。已有322人学习下载源码从数据读取、粒子初始化、预测更新到重采样链条完整并给出main主程序和距离、残差计算等辅助脚本方便对照算法原理逐步调试。通过该工程可掌握改进粒子滤波在三维轨迹预测中的应用流程结合自适应重采样、交互式多模型等改进机制为实际无人机系统的自主飞行与避障研究提供可扩展的代码基础。1. 把粒子滤波改到无人机航迹预测上为什么标准PF在三维轨迹上不够用很多做无人机项目的人拿到“Matlab三维轨迹预测”第一反应是上EKF。但在实际飞行里GPS会丢星机载IMU噪声分布并不服从理想高斯无人机在侧风、转弯、爬升时加速度突变EKF和UKF在这种非线性非高斯场景下经常直接发散。这个标题给出的路线是改用粒子滤波Particle Filter, PF并做改进来解决“无人机下一段时间会飞到哪”的问题——也就是三维航迹预测不是事后滤波而是提前几秒到几十秒推算出未来位置。它适合两类人一类在做无人机避障、路径规划需要把预测结果喂给决策层另一类在做Matlab仿真验证手里有运动模型和GPS/INS量测数据想把滤波算法从卡尔曼族换到粒子滤波族并搞清楚改进点到底改在哪里。2. 运动模型先行状态向量、坐标系与非线性观测下的三维航迹预测2.1 状态向量的选择位置、速度、加速度与姿态取几维才合理粒子滤波的第一步不是写重采样而是确定状态向量。无人机三维航迹预测里最常见的状态向量是六维三个位置分量加三个速度分量即 X [x, y, z, vx, vy, vz]。这适合匀速直线巡航场景但一旦无人机进入盘旋或爬升段速度方向变化快六维模型的预测误差会明显偏大。我的做法是升到九维把三轴加速度也纳入状态X [x, y, z, vx, vy, vz, ax, ay, az]。代价是状态转移矩阵变大粒子采样时间变长但换来的是对机动动作的跟踪能力。% 九维匀速/匀加速混合模型的状态转移矩阵dt为采样周期 dt 0.1; F [1 dt 0.5*dt^2 0 0 0 0 0 0; 0 1 dt 0 0 0 0 0 0; 0 0 1 0 0 0 0 0 0; 0 0 0 1 dt 0.5*dt^2 0 0 0; 0 0 0 0 1 dt 0 0 0; 0 0 0 0 0 1 0 0 0; 0 0 0 0 0 0 1 dt 0.5*dt^2; 0 0 0 0 0 0 0 1 dt; 0 0 0 0 0 0 0 0 1];这段矩阵里位置、速度、加速度的关系是按匀加速运动拼接的。注意我保留了每个轴的“位置-速度-加速度”三段耦合而不是用blkdiag简单地塞三个二维块因为第三列和第六列、第九列的1/2dt²项在实际递推中承担着加速度对位置贡献的累积。参数上最容易被忽略的是dt。无人机IMU采样率常见是100Hz到400Hz如果仿真里dt取0.1那对应10Hz的滤波更新频率这个频率对避障决策来说偏慢如果量测更新频率低于10Hz粒子滤波的预测步会拉得很长位置不确定性快速增长。这里有一个工程直觉粒子滤波的粒子数与更新频率强相关更新频率越低需要的粒子数越多否则无法覆盖预测步产生的大范围分布。2.2 状态转移方程CV模型的局限与当前统计模型的自适应加速很多人直接拿匀速CV模型当状态转移方程这在无人机巡航段没问题但到了协调转弯段就会出状况。CV模型假设加速度为零粒子在一段时间内一直沿直线扩散实际无人机已经转了60度粒子云整体没有跟上量测更新时高权值粒子全部集中在旧方向滤波轨迹就“僵”住了。要解决这个问题除了在状态向量里加入加速度还需要让过程噪声Q能随机动强度变化。% 当前统计模型思路Q中加速度项随估计加速度绝对值自适应变化 Q zeros(9, 9); Q(3,3) 0.1; % x轴加速度噪声 Q(6,6) 0.1; % y轴加速度噪声 Q(9,9) 0.1; % z轴加速度噪声 % 自适应调整加速度估计大噪声也放大允许粒子更快改变速度方向 acc_norm norm(mean_particles_acc); % mean_particles_acc来自粒子集加速度均值 if acc_norm 1.0 Q(3,3) 0.5; Q(6,6) 0.5; Q(9,9) 0.5; end为什么这样改因为粒子滤波的预测步本质上是从状态转移分布中采样。Q越大采样出来的粒子扩散范围越宽跟踪机动目标的能力越强但Q过大会让匀速段的滤波方差膨胀轨迹抖动。常见的做法是把“当前统计模型”的机动加速度均值引入预测方程我这里用动态Q做近似省去对加速度均值的额外计算工程实现更简单。参数上1.0这个阈值取决于真实无人机的最大过载一般取最大加速度的50%左右需要根据机型调。2.3 坐标系与量测方程经纬高转ENU、GPS/INS量测噪声怎么建模坐标系是三维航迹预测里最容易翻车的点尤其GPS输出经纬高而运动模型用的是平面坐标。直接在经纬度坐标系里跑滤波不是不行但纬度方向与经度方向的地面距离比例不同量测噪声协方差R在不同分量上的差异会让粒子权值计算时马氏距离失真。常见做法是以起飞点或最近一次可靠定位为参考原点把GPS的经纬高转成ENU东-北-天坐标再做滤波。function [e, n, u] lla2enu(lat, lon, alt, lat0, lon0, alt0) % WGS84近似转换参考点取起飞点 a 6378137.0; e2 6.69437999014e-3; N a / sqrt(1 - e2 * sind(lat0)^2); x0 (N alt0) * cosd(lat0) * cosd(lon0); y0 (N alt0) * cosd(lat0) * sind(lon0); z0 (N * (1 - e2) alt0) * sind(lat0); N a / sqrt(1 - e2 * sind(lat)^2); x (N alt) * cosd(lat) * cosd(lon); y (N alt) * cosd(lat) * sind(lon); z (N * (1 - e2) alt) * sind(lat); dx x - x0; dy y - y0; dz z - z0; e -sind(lon0)*dx cosd(lon0)*dy; n -sind(lat0)*cosd(lon0)*dx - sind(lat0)*sind(lon0)*dy cosd(lat0)*dz; u cosd(lat0)*cosd(lon0)*dx cosd(lat0)*sind(lon0)*dy sind(lat0)*dz; end这段代码做的是WGS84椭球下的大地坐标转空间直角坐标再旋转到ENU。日常仿真够用不需要引入Mapping Toolbox。这里要注意Lat/Lon单位是度MATLAB的三角函数用角度制。量测噪声R的建模直接决定粒子权值质量。GPS水平位置噪声通常在1到3米高程在3到5米INS短时速度估计精度较高但长时间积分会漂移。如果只把位置作为量测输入R可以取diag([sigma_e^2, sigma_n^2, sigma_u^2])水平sigma_esigma_n2米天向sigma_u3米。这个取值不是玄学而是和GPS接收机的定位模式挂钩差分定位可以压到0.5米普通单点定位就是2到3米。仿真里R太小会让粒子快速退化R太大会让轨迹过于平滑、转弯细节丢失。EKF、UKF、粒子滤波在三维修正预测里的取舍我用一张表做过对比维度EKFUKF粒子滤波非线性处理一阶泰勒展开无损变换近似蒙特卡洛采样无模型近似非高斯噪声不适合效果有限天然支持计算量级低中高随粒子数线性增长机动场景表现易发散发散较少配合自适应Q可稳定跟踪3. 改进粒子滤波的三个主攻点重采样、机动检测与粒子数3.1 标准PF退化现象的量化有效粒子数Neff与重采样触发标准粒子滤波跑一段时间后大部分粒子的权值会趋近于零只有少数粒子权重很大这种退化现象会使得粒子集无法代表真实分布。要有量化指标才能改通常用有效粒子数Neff来判断退化程度function Neff getEffectiveParticles(w) Neff 1.0 / sum(w.^2); endNeff的取值范围是1到N。当Neff接近N时粒子多样性好当Neff接近1时说明只剩一个粒子起作用。我一般取Neff 0.5 * N作为重采样触发阈值低于这个值就执行重采样。有些论文取0.3或0.2区别在于越小的阈值触发重采样越少、粒子多样性保持更长但一旦触发退化风险更集中。实际工程中无人机航迹预测的粒子数上限受算力限制阈值太保守会让计算白费建议先从0.5试起。3.2 改进一系统重采样加正则化扰动保住粒子多样性重采样本身不是改进它是标准PF的必要步骤。但标准的多项式重采样有一个已知问题高权值粒子被复制多次低权值粒子被丢弃重采样后的粒子集中在一个或几个点上多样性丢失。粒子多样性一丢后续量测更新时没有粒子靠近真实位置轨迹就“哑”掉。工程上的补救是系统重采样配合正则化扰动。function new_particles systematicResample(particles, w, N) % 系统重采样把[0,1]区间按粒子数等分每个区间内随机取点 new_particles zeros(size(particles)); cdf cumsum(w); u0 rand() / N; idx 1; for i 1:N u u0 (i - 1) / N; while u cdf(idx) idx idx 1; end new_particles(i, :) particles(idx, :); end % 正则化扰动在复制后的粒子上加高斯抖动恢复多样性 cov_p cov(particles); jitter_scale 0.1 * sqrt(1 - Neff / N); for i 1:N new_particles(i, 1:3) new_particles(i, 1:3) ... jitter_scale * randn(1, 3) * chol(cov_p(1:3, 1:3)); end end扰动的幅度用jitter_scale控制0.1倍协方差根号是比较稳的经验值。严格的正则化粒子滤波会用Epanechnikov核生成非高斯扰动但工程上用高斯核近似多数场景下效果差异不明显。注意这里我只扰动位置分量速度和加速度不动因为速度和加速度的扰动会导致轨迹抖动变大无人机运动模型的速度状态本身有足够连续性。这段代码里有个细节扰动是在重采样后直接加到新粒子上这些粒子的权重需要全部重置为1/N下一次预测更新时会自然拉开多样性不需要额外处理权值。3.3 改进二机动检测动态调整过程噪声模型追得上转弯无人机轨迹预测的困难不在匀速段而在转弯和爬升段。改进办法很多常见的是交互多模型IMM在Matlab里实现复杂更轻量可靠的做法是机动检测量测更新后计算新息马氏距离超过阈值就认为当前处于机动状态并把过程噪声放大。% 新息马氏距离阈值量测为三维位置自由度395%置信对应7.815 innov_threshold 7.815; % 在每步量测更新后计算 innov z_obs - h_predict; % 三维新息 innov_mahal innov * inv_R * innov; if innov_mahal innov_threshold % 判定为机动放大Q中加速度项 Q(3,3) min(Q(3,3) * 2, 2.0); Q(6,6) min(Q(6,6) * 2, 2.0); Q(9,9) min(Q(9,9) * 2, 2.0); silence_cnt 0; else % 连续无机动时逐步缩小Q if silence_cnt 5 Q(3,3) max(Q(3,3) / 2, 0.1); Q(6,6) max(Q(6,6) / 2, 0.1); Q(9,9) max(Q(9,9) / 2, 0.1); end silence_cnt silence_cnt 1; end这里的关键参数是innov_threshold、Q的上下限、silence_cnt。自由度3的卡方分布95%分位数是7.815这个值一般不用改。Q的放大倍数设为2倍上限设2.0是为了防止噪声过大导致滤波方差无限膨胀。silence_cnt大于5再恢复Q意思是连续5步约0.5秒按10Hz都没有超出阈值才认为机动结束。这样处理比单纯看一步新息更稳无人机转弯中偶尔会出现单步新息回落的情况马上恢复Q会导致后续转弯重新发散。3.4 改进三粒子数自适应与实时性折中粒子数固定是标准PF的默认做法但无人机航迹预测的实时性要求意味着粒子数应该在Neff充足时减少在Neff紧张时增加。道理不复杂Neff接近N说明粒子分布和真实分布匹配度高此时粒子数可以下调而不明显损失精度Neff很小说明预测分布和量测分布偏差大需要增加粒子覆盖范围。N_min 1000; N_max 5000; N_current 3000; % 重采样后根据Neff动态调整下一次预测的粒子数 if Neff 0.7 * N_current N_next max(N_min, round(N_current * 0.8)); else N_next min(N_max, round(N_current * 1.2)); end粒子数调整的同时要处理粒子集大小的变化。减小粒子数时直接随机抽取增加粒子数时在现有粒子上复制再加微小扰动。这个逻辑必须在重采样之后立即执行因为重采样后的粒子权重是均匀的复制和删除不会引入权值畸变。这里有一个血泪教训动态调整粒子数时新粒子集要多备份一份状态否则下一次预测步里维度不匹配直接报错。4. 用Matlab实现完整的三维航迹预测从仿真数据到闭环跑通4.1 生成包含匀直、盘旋、爬升段的仿真三维轨迹验证粒子滤波改进效果最忌讳全程匀速直线仿真。匀速直线轨迹下标准PF和EKF都表现不错跑完看不出任何改进优势。我一般构造三段轨迹先匀速直线飞2秒再水平盘旋6秒最后爬升5秒这样覆盖三种运动模态分段点能看到误差跳变。% 生成仿真轨迹0-2s匀直2-8s盘旋8-13s爬升 dt 0.1; t_total 13; t 0:dt:t_total; n length(t); true_pos zeros(n, 3); true_vel zeros(n, 3); true_acc zeros(n, 3); % 初始位置与速度 true_pos(1, :) [0, 0, 50]; true_vel(1, :) [15, 0, 0]; for i 2:n if t(i) 2 acc_i [0, 0, 0]; elseif t(i) 8 % 水平盘旋向心加速度 v norm(true_vel(i-1, 1:2)); omega 0.3; % 角速度约0.3rad/s acc_i [v * omega * (-sin(atan2(true_vel(i-1,2), true_vel(i-1,1))) 1e-6), ... v * omega * cos(atan2(true_vel(i-1,2), true_vel(i-1,1))), 0]; else % 爬升段向上加速 acc_i [0, 0, 2.0]; end true_acc(i, :) acc_i; true_vel(i, :) true_vel(i-1, :) acc_i * dt; true_pos(i, :) true_pos(i-1, :) true_vel(i, :) * dt; end % 加GPS量测噪声 rng(42); sigma_e 2.0; sigma_n 2.0; sigma_u 3.0; measurements true_pos [sigma_e*randn(n,1), sigma_n*randn(n,1), sigma_u*randn(n,1)];盘旋段的acc_i计算方式简化处理了正常应该按新位置方向重新计算向心加速度仿真里这样近似不影响粒子滤波算法本身的验证。sigma_e和sigma_u要和前面R矩阵中对应方差一致否则量测生成端和滤波端模型不匹配属于自欺欺人这种错误在不少项目里出现过。4.2 粒子滤波主循环分步实现预测、更新、重采样主循环是整个代码的核心。粒子设为3000个状态九维每个粒子的初始位置以第一个量测为中心速度初始为15m/s水平方向加速度为零。N 3000; particles zeros(N, 9); particles(:, 1) measurements(1,1) randn(N,1)*2; particles(:, 2) measurements(1,2) randn(N,1)*2; particles(:, 3) measurements(1,3) randn(N,1)*3; particles(:, 4) 15; % vx particles(:, 5) 0; % vy particles(:, 6) 0; % vz particles(:, 7:9) 0; % 加速度初始为0 R diag([sigma_e^2, sigma_n^2, sigma_u^2]); inv_R inv(R); R_chol chol(R); weights ones(N, 1) / N; % Q中位置噪声设为0.5的平方量级速度噪声按IMU估算 Q eye(9) * 0.01; Q(3,3) 0.1; Q(6,6) 0.1; Q(9,9) 0.1; for k 2:n % 预测步把每个粒子按状态转移矩阵递推并加过程噪声 particles (F * particles); for j 1:N particles(j, :) particles(j, :) mvnrnd(zeros(9,1), Q); end % 量测更新 z_obs measurements(k, :); h_predict particles(:, 1:3); innov z_obs - h_predict; % 维度3xN % log-likelihood方式计算权值避免数值下溢 logw -0.5 * sum((inv_R * innov) .* innov, 1); logw logw - max(logw); weights exp(logw); weights weights / sum(weights); % 有效粒子数与机动检测 Neff 1 / sum(weights.^2); if Neff 0.5 * N [particles, weights] systematicResample(particles, weights, N); weights ones(N, 1) / N; end end这段代码的细节都在注释里了。关于权值计算用对数似然再指数化是为了防止某些粒子距离观测太远导致exp直接下溢为零这样所有粒子权重全零程序直接崩掉。mvnrnd调用需要Statistics Toolbox如果没有可以换成按维度独立生成randn再乘以sqrt(Q)对角线效果相同。机动检测部分我没有直接把Q更新的代码融进主循环避免循环体过长。实际使用中要在这个循环末尾加上第3.3节的判断逻辑并把动态调整后的Q传给下一轮预测步。4.3 输出三维轨迹、协方差与粒子散点怎么看算法有没有改对滤波跑完后要做两件事一是看估计轨迹是否贴真实轨迹二是看外推的预测轨迹是否发散。预测轨迹的生成方式是对结束时刻的粒子集继续向前递推K步不做量测更新取粒子均值作为预测位置。% 预测未来20步2秒 K 20; pred_pos zeros(K1, 3); pred_pos(1, :) mean(particles(:, 1:3), 1); for k 1:K particles (F * particles); for j 1:N particles(j, :) particles(j, :) mvnrnd(zeros(9,1), Q); end pred_pos(k1, :) mean(particles(:, 1:3), 1); end % 可视化三条曲线 figure; plot3(true_pos(:,1), true_pos(:,2), true_pos(:,3), b-, LineWidth, 1.5); hold on; plot3(measurements(:,1), measurements(:,2), measurements(:,3), k.); plot3(pred_pos(:,1), pred_pos(:,2), pred_pos(:,3), r--, LineWidth, 2); xlabel(东/m); ylabel(北/m); zlabel(天/m); legend(真实轨迹, 量测, 预测轨迹);看结果时不要只盯轨迹贴不贴核心指标有三个滤波轨迹与真实轨迹在盘旋段的偏差是否明显小于量测噪声预测轨迹在未来1秒内的误差是否在可接受范围预测轨迹末端的协方差是否合理膨胀。协方差的膨胀程度比轨迹本身更能说明粒子分布是否健康。我通常在预测末段同时画出3sigma椭球% 预测末端粒子协方差与3sigma椭球 cov_end cov(particles(:, 1:3)); [V, D] eig(cov_end); % 生成椭球面 [x_ell, y_ell, z_ell] ellipsoid(0,0,0,1,1,1); pts [x_ell(:); y_ell(:); z_ell(:)]; pts V * diag(sqrt(chi2inv(0.95, 3) * diag(D))) * pts; plot3(pred_pos(end,1)pts(1,:), pred_pos(end,2)pts(2,:), pred_pos(end,3)pts(3,:), g-);如果椭球又扁又长且方向与真实速度方向不一致说明Q设置得不对或粒子多样性已经丢失。正常的预测末端椭球应当在速度方向拉长垂直方向较窄这是运动模型的外推特性。5. 避坑无人机航迹预测中容易翻车的五个细节与排查方法5.1 过程噪声Q太小滤波发散成“僵直轨迹”先检查残差现象滤波轨迹平滑得过分但与真实轨迹的系统性偏差越来越大尤其在盘旋段估计轨迹几乎走直线量测点被当成噪声忽略。原因Q矩阵设置过小。粒子在预测步的扩散范围远小于真实机动的变化幅度量测新息始终落在粒子分布的尾部导致低权值粒子占主导滤波结果偏向旧状态。这是粒子滤波和卡尔曼族滤波器通病。解决先画新息序列逐点计算第3.3节的innov_mahal正常应像白噪声一样在3到8之间随机波动。如果连续几十步都超过阈值直接按经验加大Q位置项把Q(1,1)、Q(4,4)、Q(7,7)从0.01按10倍递增去测试直到新息序列回落到阈值以内。5.2 重采样触发过于频繁粒子多样性丢光轨迹“哑掉”现象轨迹估计误差不大但预测曲线一步比一步僵硬转弯处出现明显的折线没有弧度。粒子散点图显示所有粒子几乎重叠在同一位置。原因重采样阈值设得过高。Neff 0.7 * N就触发重采样导致每几步就拷贝一次高权值粒子粒子多样性持续损失最终整个粒子集坍缩成一个点云很密的球半径小于真实运动的不确定性范围。解决把触发阈值从0.5 * N降到0.3 * N并确保重采样函数里包含正则化扰动。如果降阈值后粒子分布仍然坍缩检查扰动系数jitter_scale0.1倍协方差偏保守可以放大到0.2。粒子滤波里的重采样不是越勤越好它是不得已而为之。5.3 坐标系混用经纬度直接做状态量预测值偏离真实轨迹现象位置估计视觉上勉强没问题但外推的预测轨迹方向偏得离谱往东的轨迹预测出来向北飘。原因把经纬度直接当成平面坐标放进F矩阵。经度1度的地面距离随纬度变化北纬30度和北纬60度差距巨大而状态转移矩阵假设x、y方向等距等速导致速度方向被扭曲。量测噪声权重也被扭曲因为R矩阵在经纬度单位下的方差物理意义错误。解决统一在ENU坐标系下滤波参考点取起飞点。量测进入滤波前先调用lla2enu转换滤波输出要在使用前转回经纬高。别在ECEF球坐标里处理位置量测除非你要跨很大地理范围。5.4 量测丢星与IMU掉频率权值崩溃与粒子枯竭的应对现象GPS丢星几十秒后信号恢复滤波轨迹突然大跳变或者粒子集中到很久以前的旧位置附近。原因丢星期间没有量测更新但主循环仍然把量测带入权值计算。常见处理是把丢失的量测置为零但零值不等于“无观测”滤波器会把0当作一个真实位置所有粒子向零点聚拢。重采样在这种条件下反复触发粒子多样性被消耗殆尽。解决丢星阶段要设置量测有效性标志位无效时跳过更新步只做预测步并且把Q放大到正常值的3到5倍让粒子均匀扩散。恢复量测后先计算新息马氏距离若超过卡方阈值比如20说明滤波分布可能已偏离此时要对粒子集做全局扰动而不是依赖单次重采样。if gps_valid(k) % 正常量测更新 else % 丢星预测步照常Q放大跳过权值计算 Q_used Q * 4; end注意放大Q的倍数不要持续累积丢星恢复后要立刻回到正常Q否则后期滤波方差过大会让预测轨迹呈“放射状”散开。5.5 粒子数与仿真步长的匹配Matlab单步耗时的瓶颈在哪现象仿真跑起来后单步耗时突增原来4000粒子时每秒能跑20步加到8000粒子后每秒只能跑5步实时性完全跟不上。有人把这归咎于电脑太差其实瓶颈往往在矩阵化和预计算上。原因粒子滤波的循环体里如果对每个粒子逐个计算状态转移、逐个做mvnrndN到5000以上时纯循环耗时呈线性放大。另外inv_R如果放在循环体内求逆每步重复计算一次3x3矩阵求逆虽然单次不慢但乘以几千粒子就撑不住了。解决把Q分解为一次性的Cholesky因子预测步噪声直接用randn生成再乘以因子量测更新一次性计算全部粒子的创新矩阵不做for循环。inv_R在循环外预计算。Matlab里parfor适合仿真后处理不适合实时滤波循环因为worker间通信耗时远超循环本身。6. 验证方法进阶用RMSE与发散检测判断改进是否有效再往前一步怎么落地粒子滤波改完不能只靠一张轨迹图就下结论。我一般会跑20轮蒙特卡洛仿真用同一个轨迹不同随机数种子计算每步的均方根误差RMSE看改进版在机动段是否稳定优于标准PF。RMSE代码很简单for trial 1:20 % 每轮重跑主循环记录每步估计位置与真实位置偏差 error_est(trial, k) norm(est_pos(k, :) - true_pos(k, :)); error_pred(trial, k) norm(pred_pos(k1, :) - true_pos(k1, :)); end rmse_est sqrt(mean(error_est.^2, 1)); rmse_pred sqrt(mean(error_pred.^2, 1));RMSE按时间逐点画出来能看到误差在哪里陡增。如果改动有效盘旋段和爬升段的RMSE峰值至少下降20%以上而不是整体平均误差微降、峰值不变。还有一个实用技巧是发散检测。预测外推K步后计算预测位置与真实位置的偏差如果偏差连续超过3倍预测协方差椭球说明算法在这一段已经失去预测意义。这时候不要硬等滤波器自己收敛直接重置粒子集把当前量测位置作为均值按R矩阵的量级重新撒粒子然后重新初始化速度估计。这是工程上比任何理论改进都管用的“后悔药”。我做这个方向踩过最大的坑是过度相信Q和R的默认值。第一次把Q设成0.01仿真波形非常漂亮滤波轨迹平顺但外推预测的方向整个偏掉因为粒子分布太窄未来状态被乐观估计。后来养成习惯每次跑完先在预测末端画3sigma椭球再决定要不要动参数。粒子滤波里没有一劳永逸的参数只有不断用残差和新息去校准的过程。希望帮到你。本文还有配套的精品资源点击获取