简介:面向无人机航迹预测与状态估计研究人员,这份Matlab项目基于改进粒子滤波算法实现三维轨迹预测,能够应对风速突变、动力学特性变化和传感器噪声等非线性非高斯场景。压缩包共16个文件,以14个m源码文件为核心,完整覆盖数据读取、粒子初始化、状态预测、权重更新、重采样等关键环节,并额外保留txt说明与md说明文档,便于快速了解运行方式与算法结构。已有322人浏览学习,适合具备一定Matlab基础、希望深入掌握粒子滤波及其改进策略的无人机开发者。通过实际轨迹数据的预测与对比分析,可以理解粒子滤波、EKF、UKF、UPF等多种滤波方法的差异,进而掌握自适应重采样、交互式多模型等优化手段。项目源码逻辑清晰、模块解耦,便于二次扩展,可作为课程设计、课题研究或工程项目的重要参考。
1. 轨迹升到三维之后,粒子滤波的问题不只在粒子数
无人机三维航迹预测常用于航迹规划、冲突预警和飞行仿真。项目里比较常规的做法是用 GPS 或 UWB 输出三维位置观测,再由滤波器预测未来几秒的位置。粒子滤波在这一类非线性估计里口碑很好,原因是不用像卡尔曼滤波那样强依赖高斯假设,可一旦状态从二维平面扩展到三维,标准粒子滤波会很快出现两种叠加症状:权重集中到极少数粒子上,重采样之后粒子又从少数几个位置复制出去。前者叫粒子退化,后者叫样本贫化,两者叠加时,航迹预测的结果往往表现为前期贴合、转弯后发散。
拿到带源码的这类 Matlab 工程时,许多人第一个调整对象是粒子数。把粒子数从 500 提到 5000,平面轨迹误差看起来小了,换一条带高度起伏、航向大转弯的轨迹,误差又回来了。原因是粒子数只能改善统计精度,无法修正运动模型与无人机真实机动之间的系统性偏差。所谓改进粒子滤波,改进重点并不在增大采样规模,而是把提议分布、重采样和模型切换统一到三维预测的任务里。这组实现的落地点就是这三件事,同时给出状态建模、参数边界和验证步骤,适合正在做无人机航迹预测仿真,或者想把手里的粒子滤波代码升级成三维版本的人。
2. 无人机三维运动模型与标准粒子滤波基线
2.1 三维航迹预测的状态空间该取多大
无人机三维航迹预测的状态向量,常见的是在东北天坐标系里取位置和速度共六维:[x, y, z, vx, vy, vz]。这里有个容易纠结的点:要不要把姿态角也放进去。工程里我的建议是不放。姿态解算是飞控内部的事,滤波预测只需要运动学层面的信息,把横滚、俯仰塞进状态只会让维度变高,粒子数量呈指数级上升,预测收益却很小。
六维状态下的常用运动模型有两种:
- 恒定速度模型,适合巡航直线段,状态转移矩阵是线性的。
- 恒定转弯率模型,适合水平转弯段,需要引入偏航角速率。
把两种模型统一到一个函数里,后续做模型切换时只改一个模式参数就行:
% state: [x y z vx vy vz],单位 m, m/s % dt:采样间隔;omega:偏航角速度;Q:过程噪声协方差 function x_next = state_predict(x, dt, omega, mode, Q) x_next = x; % 位置由速度积分得到 x_next(1:3) = x(1:3) + x(4:6) * dt; if mode == 0 % CV 模型:速度保持不变 elseif mode == 1 % 恒定转弯率:水平速度按航向角旋转 theta = omega * dt; R = [cos(theta) -sin(theta); sin(theta) cos(theta)]; x_next(4:5) = R * x(4:5); end if ~isempty(Q) x_next = x_next + mvnrnd(zeros(6,1), Q)'; end end代码逻辑与参数说明:第 4 到第 6 行用速度积分更新位置,mode=1时用二维旋转矩阵处理水平速度方向变化,高度通道不做旋转,因为无人机的垂直运动与偏航解耦。Q为空时只做纯前向推演,带Q时用于滤波采样。高度通道在 GPS 观测里通常精度比水平通道更好,所以垂直方向用带过程噪声的常速度模型即可,不需要额外引入加速度状态。
这里有一个常见误区:以为模型越复杂越好,一上来就上匀加速模型。实际上除非你手上有飞控的加速度遥测,否则匀加速模型引入的额外状态误差会吃掉建模收益。对我经手的多数无人机航迹预测场景,CV 加 CT 的两种模型组合已经足够覆盖典型运动。
2.2 标准粒子滤波在 Matlab 里的最小实现与退化观测点
标准粒子滤波包含四步:初始化、预测、权重更新、重采样。下面的代码是适合做调整基准的最小骨架,建议先把它跑通,再加改进点:
Np = 1000; % 粒子数 dim = 6; % 状态维度 x_pf = repmat(x_init, 1, Np) + mvnrnd(zeros(dim,1), P_init, Np)'; w = ones(Np,1) / Np; % 归一化权重 for k = 2:T % 预测步 for i = 1:Np x_pf(:,i) = state_predict(x_pf(:,i), dt, omega_est, model_mode, Q); end % 观测似然,z_obs 为 3 维位置观测 innov = z_obs(:,k) - x_pf(1:3,:); w = exp(-0.5 * sum((R_meas \ innov) .* innov, 1))'; w = w / sum(w); % 有效粒子数判据 Neff = 1 / sum(w.^2); if Neff < Np * 0.5 idx = datasample(1:Np, Np, 'Replace', true, 'Weights', w); x_pf = x_pf(:, idx); w = ones(Np,1) / Np; end end代码逻辑与参数说明:R_meas是三维观测噪声协方差,实际项目中取diag([sigma_x^2, sigma_y^2, sigma_z^2]);Neff是有效粒子数,低于Np * 0.5触发重采样,这个阈值相对保守。datasample是系统重采样的实现,它的问题在于低权重粒子直接清零,下一轮预测靠过程噪声慢慢恢复多样性。
如果直接用这段代码做多步前向预测,会发现:没有观测修正的纯预测段,粒子群沿状态转移矩阵不断扩散,粒子云越到后面越像一团椭球而不是一条航迹。这不是 bug,而是标准粒子滤波的本质局限。退化信号可以通过每一帧重采样后重复粒子占全部粒子的比例来观察,重采样次数越多,粒子在三维状态空间里聚成几个点的概率越大,多样性缺失就越明显。
3. 改进粒子滤波的落地实现:提议分布、重采样与模型切换
3.1 改进点一:基于观测辅助的提议分布
标准粒子滤波的采样来自先验状态转移分布,和当前观测没有直接关系。当三维航迹中出现快速转弯时,先验分布的中心与高似然区域偏离,粒子要依靠过程噪声扩散才能碰到观测,必然造成大量粒子权重接近零。
改进粒子滤波里最通用做法是引入观测信息构造提议分布。对无人机三维轨迹预测而言有一个天然优势:观测是三维位置,状态是六维位置加速度,虽然观测维数低但信息密度高,可以用位置残差去修正速度的均值方向,让粒子群更快靠近高似然区域:
% 预测之后立即用当前观测修正提议中心 for i = 1:Np x_mid = state_predict(x_pf(:,i), dt, omega_est, model_mode, []); innov = z_obs(:,k) - x_mid(1:3); % 位置残差折算到速度通道 x_prop = x_mid; x_prop(4:6) = x_mid(4:6) + Kv * innov; % 用提议噪声采样 x_prop = x_prop + mvnrnd(zeros(6,1), Q_prop)'; x_prop_all(:,i) = x_prop; % 记录权重比值 prior_w(i) = pdf_prior(x_mid, Q); % 从预测分布计算 q_w(i) = pdf_proposal(x_prop, Q_prop); % 从提议分布计算 end % 最终权重 = 观测似然 * 先验/提议比值 w = obs_likelihood(x_prop_all, z_obs(:,k), R_meas) .* prior_w ./ q_w; w = w / sum(w);代码逻辑与参数说明:Kv是位置误差对速度修正的增益,取值一般小于1/dt,避免速度被观测噪声过度放大。Q_prop是提议噪声协方差,决定粒子探索范围。修正后的权重不能只算观测似然,必须保留prior_w / q_w比值,否则提议分布偏移后会引入系统性偏差。改进后的直接效果是粒子群更快收敛到观测附近,批量权重更均匀,从根源上缓解退化。
注意:提议分布改进对观测噪声的敏感度比较高。如果
R_meas设置过小,观测噪声会被直接放大到速度通道,导致滤波输出抖动变大。
3.2 改进点二:残差重采样,减少样本贫化
标准系统重采样在样本贫化上的短板是:权重归一化后直接抽粒子,低权重粒子立即清零,抽出的大量重复粒子在下一轮预测时虽然会被过程噪声拉开,但只要观测没有明显刷新,粒子仍然重叠成几个点。残差重采样是更稳妥的替代方案,它分两步:先按Np * w的整数部分决定每个粒子的固定拷贝数,再对余数做一次随机权重采样:
function [x_res, w_res] = residualResample(x, w, Np) N = length(w); Nk = floor(Np .* w); % 每个粒子的固定复制数量 remN = Np - sum(Nk); % 剩余待分配粒子数 xPart = cell(N, 1); cnt = 0; for i = 1:N if Nk(i) > 0 xPart{i} = repmat(x(:,i), 1, Nk(i)); cnt = cnt + Nk(i); end end w_rem = Np .* w - Nk; w_rem = w_rem / sum(w_rem); idx_rem = datasample(1:N, remN, 'Replace', true, 'Weights', w_rem); x_res = zeros(size(x,1), Np); col = 0; for i = 1:N if ~isempty(xPart{i}) x_res(:, col+1:col+Nk(i)) = xPart{i}; col = col + Nk(i); end end for j = 1:remN x_res(:, col+j) = x(:, idx_rem(j)); end w_res = ones(Np,1) / Np; end代码逻辑与参数说明:Nk是权重整数倍部分,保证高权重粒子一定有几份拷贝;w_rem是去掉整数部分后的残余权重,它保留了低权重粒子的小概率存活机会。与系统重采样相比,残差重采样在同一帧内不会把粒子全部集中到最高权重那一点,多样性保持度更高。这个函数可以直接替换第一节里的datasample,改动范围小,收益直观。
3.3 改进点三:机动检测与模型切换
固定模型下的粒子滤波很难同时适配直线段和大幅转弯段。改进粒子滤波的第三个维度是让运动模型随飞行状态切换。工程中常用归一化新息平方作为机动检测量:
nis = innov' * (S \ innov); % innov 为3维位置残差, S 为新息协方差 model_mode = double(nis > chi2inv(0.95, 3));代码逻辑与参数说明:chi2inv(0.95, 3)是自由度 3 的卡方分布分位数,约 7.81。当nis超过该值,说明当前运动不再符合 CV 假设,需要切换到转弯模式。实际使用中为了防止模式频繁抖动,建议加迟滞条件:连续 2 帧 NIS 超标才切换,连续 2 帧恢复才退回 CV。切换后的omega_est可以由相邻两帧位置估算航向角速度,不需要额外传感器。
三个改进点的优先级建议:如果只选一个,先做残差重采样,收益最直接;如果观测噪声大,先做提议分布修正;如果轨迹里弯道多,机动检测优先级最高。以下是典型参数初始值参考:
| 参数 | 建议初值 | 调整方向 |
|---|---|---|
| 粒子数 Np | 1000 | 误差不再下降时停止增大 |
| Neff 阈值 | 0.5 * Np | 变小则重采样频率降低 |
| Kv 增益 | 0.5 / dt | 观测噪声大时调小 |
| Q_prop | 0.1 * Q | 探索范围过小时调大 |
| NIS 阈值 | chi2inv(0.95, 3) | 航迹抖动时调大 |
4. 三维航迹预测仿真:参数设置、误差对照与调参边界
4.1 生成三维航迹仿真场景
验证改进粒子滤波需要一个能体现转弯和高度变化的三维轨迹。通常做法是先定义航点,按固定采样率插值,再加测量噪声:
% 航点:起点 -> 右转 -> 爬升 -> 左转,模拟典型巡检路径 waypoints = [0 0 50; 100 0 50; 150 80 80; 150 160 80; 50 200 120]; t_sample = 0.1; % 10Hz 观测 traj_true = interpolate_waypoints(waypoints, t_sample); z_obs = traj_true + mvnrnd([0 0 0], R_meas, T)';参数作用说明:waypoints的第三个分量是高度,轨迹里带爬升段才能验证三维预测效果,只做平面轨迹看不出改进价值。R_meas推荐水平通道和垂直通道分开设置,例如diag([3^2, 3^2, 1.5^2]),因为 GPS 高度观测通常比水平精度好一些。
评价指标推荐两套:单步滤波 RMSE 和未来 5 秒前向预测 RMSE。三维预测的评价特殊性在于水平误差和高度误差要分开报告,只报三维合误差会把垂直精度的差异覆盖掉。
4.2 提升粒子滤波与标准粒子滤波的对照趋势
以我跑过的仿真经验,粒子数 1000、过程噪声取diag([0.5^2 0.5^2 0.5^2 0.3^2 0.3^2 0.3^2])时,标准粒子滤波在直线段能跟上轨迹,但在转弯处水平 RMSE 峰值通常比改进粒子滤波高 40% 到 70%。改进后的误差曲线没有明显尖峰,原因是 NIS 检测在转弯前几帧已经把模型切到 CT,粒子在高似然区域附近扩散,没有被直线段残差拖住。
这个对照数值依赖具体轨迹尺度和传感器噪声量级,不具绝对意义,但趋势稳定:
| 指标 | 标准粒子滤波 | 改进粒子滤波 |
|---|---|---|
| 直线段水平 RMSE | 两者接近 | 两者接近 |
| 转弯时刻水平 RMSE | 峰值明显 | 峰值收窄 |
| 高度通道 RMSE | 两者接近 | 略优 |
| 重采样后多样性 | 快速下降 | 保持较好 |
调参边界可以从两个方向观察。Neff阈值我一般取粒子数的 0.3 到 0.6 倍。阈值太小,比如 0.1 倍,重采样迟迟不发生,权重集中导致粒子提前失真;阈值太大,比如 0.8 倍,重采样过于频繁,多样性损失更快。这里的收敛值需要结合残差重采样一并进行,因为残差重采样本身比系统重采样更耐频繁触发。
4.3 调参时最常踩的四个坑
第一个坑:把过程噪声 Q 调得特别小,期望滤波输出更平滑。结果转弯处误差显著变大,因为粒子没有足够方差去覆盖转弯区域。过程噪声要匹配运动模型的不确定度,不是匹配滤波结果的期望轨道。
第二个坑:预测段沿用滤波时的 Q。滤波时 Q 建模的是相邻观测之间的不确定性,前向预测时噪声会随预测步长累积,建议按预测时间长度缩放 Q 的值。
第三个坑:初始速度协方差给得太大。三维位置观测不能直接提供速度信息,初始速度不确定度过大会让粒子群花掉几十帧才能收敛,造成前段预测整体滞后。
第四个坑:一次性打开全部改进点但不做消融对照。改进点之间相互影响,不逐个验证就无法定位哪段轨迹由哪个改进生效。跑实验时每个版本保留一组输出,方便定位问题。
5. 从离线仿真到在线预测:三个验证技巧与工程化要点
5.1 用残差白噪检查滤波一致性
RMSE 不能反映滤波是否真实匹配了运动趋势。实现之后我一般保存每个时间步的新息序列:
innov_seq(:, k) = z_obs(:,k) - x_pf(1:3, k);然后检查新息的自相关函数。如果三维航迹预测里的新息自相关呈现出明显的时序结构,说明模型没有完全捕获运动趋势,通常是机动检测延迟偏大或速度增益设置过小。此时优先调滤波侧,而不是去加噪声、加粒子。
5.2 多步前向预测看发散拐点
三维航迹预测真正关心的是未来 3 到 5 秒的航迹质量。在每一帧把滤波结果做多步无观测前向推演,分别记录第 1 秒、第 3 秒、第 5 秒后的粒子云形状,可以直接观察到发散拐点的位置。发散拐点通常出现在航向变化后 1 到 2 秒,此时把模型切换的滞后时间减小,可以看到预测尾部明显收窄。把发散拐点录成视频逐帧对比,比任何缩略图都有说服力。
5.3 在线化改造的提速技巧
在线实时链路里不需要整套 Matlab 逻辑都搬过去。常见做法是只把运动模型、观测似然和残差重采样这三个核心函数做代码生成或改写成 C 语言,观测预处理留在上游,NIS 检测作为事件驱动模块单独运行。在预测端补一个一帧延迟的对齐缓冲,可以让预测输出稳定对齐飞控侧数据。
如果只取一个技巧带走,那建议是:在自带完整历史记录的仿真工程里多写一个log_Neff输出。它可以在每一帧记录有效粒子数,直接反映重采样策略的效果,改进前后对比这条曲线的变化比任何误差曲线都更能直观解释粒子滤波的退化与恢复过程。
本文还有配套的精品资源,点击获取