
简介组合导航通过融合GPS与INS数据提升定位精度与鲁棒性卡尔曼滤波是其核心算法。这份资源以MATLAB实现GPS与INS联合导航的卡尔曼滤波适用于导航专业研究生、本科生以及从事组合导航开发的工程技术人员。压缩包共3个文件包括2个m脚本和1个mat数据文件分别实现滤波主程序、位置速度姿态解算演示及轨迹数据集整体仅620KB。目前已有1096人学习下载。程序覆盖状态方程、量测方程、系统噪声与量测噪声建模、卡尔曼增益计算以及预测-更新循环等关键环节可直接运行并观察滤波融合效果帮助理解GPS高精度但可能失锁、INS连续但存在累积误差的特性互补也为深入学习多传感器融合、自适应卡尔曼滤波或粒子滤波提供实践参考。1. 组合导航为什么必须上卡尔曼滤波做组合导航的人绕不开卡尔曼滤波这个话题。不管是无人机、自动驾驶车辆还是机器人、手持测绘设备只要涉及到多个传感器最常见的是IMU和GNSS的数据融合卡尔曼滤波几乎是默认的第一选择。你可能会问为什么不是简单的加权平均为什么不是互补滤波卡尔曼滤波到底解决了什么问题先说结论组合导航的核心矛盾是IMU短时间精度高但会漂移GNSS长时间稳定但更新率低、容易丢信号。两个传感器各自有优缺点单独用哪个都不可靠。卡尔曼滤波的价值在于它能在数学上按照各自的误差特性“聪明地”分配权重让IMU的高频信息和GNSS的绝对位置信息互相弥补得到一套既平滑又不容易跑偏的姿态和位置估计。这个过程叫数据融合卡尔曼滤波是其中适用性最广、工程上最成熟的实现方法。我早期做惯导/GNSS组合时一开始也用互补滤波觉得参数简单、调起来快。但一旦车辆转弯半径小、加减速剧烈或者GNSS出现短暂的丢星互补滤波的缺陷立刻暴露——它没法显式建模传感器误差也不会告诉你当前估计的置信度是多少。卡尔曼滤波天生就带“误差协方差矩阵”这个协方差不仅是数学上的中间产物它在工程里直接派上用场可以输出一个质量指标告诉下游系统“现在定位有多可信”这在自动驾驶的决策模块里非常关键。更深一层卡尔曼滤波之所以在组合导航里地位几乎不可替代是因为它基于预测-修正的框架IMU负责高频预测GNSS负责周期性修正。这种框架天然贴合组合导航的时间结构。所以说理解了组合导航里的卡尔曼滤波等于同时理解了传感器融合的通用框架。这篇文章就带大家从原理到代码把组合导航里卡尔曼滤波的实现细节完整过一遍。2. 两种主流组合方案以及我为什么先选了松耦合组合导航的工程实现上按信息融合的深度大致分松耦合和紧耦合两大类。很多人上来就问哪种好我的回答是先搞懂松耦合再决定要不要上紧耦合。松耦合的思路很清楚IMU和GNSS各自先独立解算IMU输出姿态、速度、位置GNSS接收机输出自身的经纬高和速度然后滤波器拿GNSS的结果当作观测值去修正IMU的推算结果。两个传感器“各干各的”滤波器在高层做融合。这个方案实现简单、排错直观对GNSS接收机几乎没有额外要求市面上一堆接收机都能直接用。紧耦合就复杂得多它直接把GNSS的原始观测量伪距、载波相位、多普勒引入滤波器和IMU的数据在更底层融合。好处是在GNSS卫星数量少、信号被遮挡的时候紧耦合依然能利用部分观测量维持定位而且能反过来辅助接收机提高信号跟踪能力在城市峡谷这类场景下优势明显。代价是状态向量维度膨胀滤波模型复杂对接收机输出的原始数据格式有硬性要求开发和调试周期完全不是一个量级。我的建议是做第一款产品原型先走松耦合。原因很实际——松耦合的状态模型和代码调试链路都短能让你先把卡尔曼滤波的预测、更新、调参整个循环跑通攒下经验。等松耦合版本稳定了再评估是否需要引入紧耦合应对弱信号场景。这不是技术上的妥协而是工程节奏的取舍。我见过太多团队一上来就啃紧耦合几个月过去连基础滤波都没调稳反而卡在伪距残差处理和接收机数据解析的坑里出不来。从算法架构看松耦合和紧耦合的主滤波器结构其实相似差别在观测方程的量测向量和量测矩阵上。松耦合的观测是GNSS解算出来的位置速度紧耦合的观测是各卫星的伪距和多普勒。理解了松耦合的观测方程怎么写后续扩展到紧耦合只是把观测模型换掉的问题。3. 状态方程与观测方程的搭建过程卡尔曼滤波落地到一个具体系统第一步就是写状态方程和观测方程。这一步直接决定滤波器的上限后面的代码只是把这个数学模型翻译成程序而已。组合导航里最经典的是基于误差状态也叫间接法的建模方式。3.1 为什么用误差状态而不是全状态直接对姿态四元数、速度、位置这些全量状态做滤波没人这么干。因为姿态运动学方程是非线性的而且四元数有归一化约束直接滤波很容易发散。更好的做法是维护一个主惯导解算通道它输出全量的姿态、速度、位置卡尔曼滤波器只估计这些量的“误差”——姿态误差角、速度误差、位置误差再对IMU的陀螺零偏、加速度计零偏做在线估计。滤波器修正的是误差量修正完反馈给主通道主通道再继续往外推。这套结构工程上极其成熟大家口中的“INS/GNSS松耦合组合导航”基本都是这么搭的。误差状态做状态量有实打实的好处误差量通常很小满足线性假设正好契合卡尔曼滤波的线性高斯前提状态方程也变得简单很多非线性项可以在小误差假设下直接线性化。收敛性和数值稳定性都比全状态滤波好控制。3.2 状态向量与P矩阵维度设计我常用的15维状态向量如下姿态误差角3维横滚、俯仰、航向三个方向的失准角速度误差3维导航坐标系下的三轴速度误差位置误差3维纬度、经度、高度误差陀螺零偏3维三轴陀螺的常值漂移加速度计零偏3维三轴加速度计的常值偏差为什么是15维不是12维也不是18维12维的常见配置是去掉加速度计零偏在一些精度要求不高的场景够用18维则会再加上IMU的刻度因子误差、安装误差角等等。对大多数松耦合组合导航需求15维是性价比最高的默认配置——陀螺零偏和加计零偏是所有IMU都有的主要误差项不估计它们滤波器的长期精度会明显变差。误差状态协方差矩阵P的初始值我习惯按“对当前状态不确定度的第一性判断”来设。比如姿态失准角初始不确定度假设为0.1度量级换算弧度后平方放进P位置不确定度则结合GNSS单点定位精度来设水平方向设10米量级高度方向设15米甚至更大因为高度通道本身可观测性弱不能给太小。P矩阵初始化太小滤波器会“过于自信”观测来了也懒得修太大则前期收敛慢。3.3 离散化处理与F矩阵、G矩阵连续时间下的系统方程上机实现时必须离散化。最常用的是一阶泰勒近似F_d I F * dtdt是IMU的更新周期。对于100Hz的IMUdt就是0.01秒。一阶近似在绝大多数组合导航场景下精度足够因为误差状态的动态变化相对缓慢而且每次GNSS观测更新还会修正不必追求太高阶的离散化精度。F矩阵里各误差项之间的耦合关系是建模的关键。姿态误差方程里包含了陀螺零偏和速度误差的影响速度误差方程里包含了姿态误差通过比力投影产生的影响、位置误差引起重力变化的影响、加速度计零偏的影响位置误差方程则直接由速度误差积分而来。这些耦合关系写错一个符号滤波器就可能发散或者收敛到错误值。过程噪声矩阵Q的设计我后面专门用一节来讲。它代表了IMU噪声和模型不确定性对误差状态演化的驱动强度是卡尔曼滤波里最难调、也最影响实际效果的部分。3.4 观测方程的建立松耦合模式下观测值来自GNSS接收机输出的位置和速度。观测方程写成z H * x v其中z是“GNSS量测减去惯导推算得到的同位置处量测”的差值也就是新息的计算基础。H矩阵的构造很直观位置观测对应位置误差状态的位置误差速度观测对应速度误差状态。所以H矩阵是稀疏的大部分位置为0只要在对应位置上放1再叠加上位置误差从经纬度到米的尺度变换系数就行。这里有个容易被忽略的细节经纬度的单位是度和弧度而滤波器的位置误差状态通常用米来表示。观测方程里必须把GNSS给出的经纬度转换成以米为单位的局部坐标系偏移或者把位置误差状态从米映射回经纬度增量。换算系数是纬度方向的1度对应约111320米经度方向则要乘以纬度的余弦值。这个系数错了观测更新的新息量级就全错了滤波器直接发散。我第一次写的时候就是漏了cos(lat)结果中纬度测试一切正常拿到高纬度地区实测直接就飘了。观测噪声矩阵R的设置相对直观反映GNSS接收机输出的位置和速度噪声。单点定位的GNSS水平位置噪声设个几米到十几米速度噪声设个0.1到0.5米/秒大致合理。RTK模式下位置噪声可以压到厘米级甚至毫米级速度噪声也会更小。R矩阵设大了滤波收敛慢设小了则容易把GNSS的跳变噪声直接引入输出需要根据接收机实际工况灵活配。4. 滤波器的完整实现步骤与关键参数调节数学模型搭完之后卡尔曼滤波的代码实现就有章可循了。整套流程可以拆成四个步骤初始化、时间更新预测、量测更新修正、反馈校正。下面给出可直接用的实现框架。4.1 初始化环节最容易犯的错初始化要干的活包括设置状态向量初值、P矩阵初值、Q矩阵、R矩阵、以及IMU和GNSS的时间基准。很多人在这步犯的错是P矩阵直接用经验值没结合传感器实际精度校准Q矩阵干脆照搬论文里的数值不去验证它和实际IMU噪声特性的匹配度。我的做法是先把IMU静止放几分钟采集陀螺和加速度计的数据算Allan方差或至少算个标准差。陀螺零偏稳定性、角度随机游走、加速度计噪声密度这些参数直接决定了Q矩阵的数量级。没有这一步后面调参就是盲人摸象。静止数据还能用来估计初始姿态把加速度计测得的重力方向作为水平参考初始航向如果GNSS速度足够大也可以用航迹方向来近似。时间基准要特别注意IMU和GNSS的时间戳必须统一到同一个时钟域。GNSS接收机输出的是GPS时间或者UTC时间IMU则是本地时钟。两者不同步会导致GNSS观测的“当前时刻”和滤波器预测状态对应的“时刻”不一致等价于给观测值叠了一个随时间变化的虚假误差。解决方案通常是用IMU时间作为基准通过PPS脉冲对齐或软同步算法把GNSS观测值内插到IMU时刻上。4.2 时间更新与量测更新的代码框架用伪代码来写整个滤波循环大概是这样的// 主循环每个IMU周期执行一次 for each IMU sample: // 1. 惯导解算更新姿态、速度、位置用当前IMU原始数据 ins_predict(imu_data) // 2. 时间更新传播误差状态和协方差 Phi computeStateTransitionMatrix(imu_data, dt) Qd computeDiscreteNoiseCovariance(Q, dt) x_pred Phi * x_est P_pred Phi * P_est * Phi Qd // 3. 如果这个时刻有GNSS观测执行量测更新 if gnss_observation_available: z computeMeasurementResidual(gnss_data, ins_output) H buildMeasurementMatrix() R buildMeasurementNoiseCovariance() K P_pred * H * inv(H * P_pred * H R) x_corr x_pred K * z P_corr (I - K * H) * P_pred * (I - K * H) K * R * K // 4. 反馈校正把误差状态补偿到主惯导解算结果里 ins_correction(x_corr)这里有个细节协方差更新公式我写的是Joseph形式而不是更常见的P (I - KH)P。Joseph形式在数值上更稳定尤其当滤波收敛后P矩阵数值变得很小普通形式的减法可能引入数值误差导致P失去对称正定性。组合导航的工程代码里这个细节值得保留。还有一个工程细节状态转移矩阵Phi不是常数它依赖IMU当前测量值比力、角速度所以每个周期都要重新计算。千万别为了省计算量把Phi固定下来组合导航的载体会经历各种各样的机动固定Phi在机动大的时候滤波结果会明显变差。4.3 Q矩阵和R矩阵的物理含义与调节方法Q矩阵是过程噪声协方差代表你对状态预测模型的不信任程度R矩阵是量测噪声协方差代表你对GNSS观测的不信任程度。Q/R的相对大小直接决定滤波器在预测和观测之间如何折中。Q设得大滤波器更相信观测结果容易带上观测噪声Q设得小滤波器更相信预测结果平滑但滞后GNSS一旦有跳变修正不过来。Q矩阵的初始化应该来源于IMU器件本身的噪声参数而不是拍脑袋。具体来说陀螺角度随机游走ARW决定了姿态误差的噪声驱动强度陀螺零偏不稳定性决定了零偏状态的噪声驱动强度加速度计速度随机游走决定了速度误差的噪声驱动强度这些参数从IMU数据手册里能查到用Allan方差实测更准。把单位换算成离散域后填入Q矩阵的对应位置。实际调参的时候我的习惯是先保证静止和匀速直线运动下滤波不发散姿态误差能收敛到0.1度以内然后做加减速和转弯机动观察位置误差曲线有没有明显的滞后或超调最后在有GNSS遮挡的环境里跑看滤波器在GNSS短暂失效时能不能靠IMU保持住短时精度。每一步对应不同参数姿态收敛对应姿态误差的Q和初始P机动跟随对应速度、位置误差的QGNSS失效时的漂移则主要考验零偏估计质量和IMU本身的精度。R矩阵的调节相对直观可以根据GNSS接收机输出的定位精度指标比如接收机内部的HDOP、VDOP以及厂商给的CEP值来做自适应。一个取巧的做法是在开阔环境下让载体静止连续记录GNSS输出的位置和速度算这些值的标准差填入R矩阵这就是接收机在该工况下的实际噪声水平。5. 数据同步、传感器误差与在线标定的工程细节很多时候组合导航效果不好不是卡尔曼滤波理论没搞明白而是工程细节掉链子。数据同步和传感器误差特性没处理好滤波器数学上再完美也白搭。5.1 时间同步的两种实用方案时间同步在组合导航里的重要性怎么强调都不为过。GNSS在一个时刻给出的位置必须和IMU状态预测到同一个时刻的位置相减残差才有意义。如果时间偏差达到几十毫秒车辆以30米/秒行驶时位置残差就会引入1米级误差直接破坏滤波精度。我实际用过的方案有两种。第一种简单粗暴GNSS接收机输出PPS脉冲PPS的上升沿对齐到UTC整秒主控芯片在PPS中断里给当前IMU数据打时间戳然后以这个整秒为基准推算各IMU采样的精确时刻。这样IMU和GNSS的时间基准就硬同步到同一个脉冲源上了。这个方案可靠但需要额外的硬件中断支持。第二种是软同步GNSS给出的每个数据帧自带时间戳接收机输出的位置速度在某个时刻有效IMU持续累积用两个IMU采样时刻之间的线性插值算出GNSS有效时刻对应的IMU状态值再进行量测更新。软同步不需要额外硬件但插值误差会随IMU数据率的降低而增加一般要求IMU输出率至少100Hz以上。5.2 杆臂误差一个经常被忽视的硬误差如果GNSS天线不在IMU的安装中心实际产品里几乎都不在两者之间就存在一个固定的空间偏移叫杆臂。车辆转弯时GNSS天线位置和IMU位置的速度方向、大小都不一样如果不补偿滤波残差会出现明显的转弯耦合误差表现为每转一次弯位置就偏一下。补偿公式不复杂v_gnss v_imu omega_imu × l_ant其中omega是IMU测得的角速度l_ant是从IMU中心指向GNSS天线相位中心的杆臂向量。这个公式在每次GNSS速度观测之前都要用。杆臂向量需要精确量测用尺子量或直接用标定方法求。我见过有人疏忽了这个补偿转弯时组合导航结果出现周期性的锯齿状误差排查很久才发现是杆臂没补。5.3 零偏在线估计的意义卡尔曼滤波状态向量里加入陀螺零偏和加速度计零偏本质上就是让滤波器利用观测数据在线估计这些误差。这对IMU选型很有意义如果IMU零偏稳定性差但滤波器能持续在线估计并补偿实际系统性能可以明显优于IMU的名义指标。但零偏估计也有副作用它和姿态误差之间存在耦合。陀螺零偏和航向误差在GNSS/INS组合里尤其难以完全区分需要足够的机动来激励。直线行驶时航向误差和陀螺零偏的可观测性都很弱这时估计值容易互相“打架”。实际表现就是车辆长时间直线行驶后航向可能有缓慢漂移一旦出现转弯滤波器又能快速纠正回来。想改善这一点就需要让载体有充分的角运动激励或者引入磁力计等额外的航向参考。6. 实测中的异常排查与调参经验代码写完了模型搭好了参数设定了进到实测阶段才是真正的考场。这里分享几类我实际踩过的异常以及对应的排查思路。6.1 滤波器发散的一种常见模式现象系统运行几分钟后位置误差越来越大P矩阵对角元素快速增长有的甚至变成天文数字。原因排查链路先看时间更新是否正常——在静止模式下将观测更新禁用记录P矩阵的增长速度如果P的增长和理论预期差太多通常是F矩阵或Q矩阵写错了。再看观测方程——打印每一步的H矩阵和z向量检查量测残差的量级是否合理。残差如果是数千米量级而H矩阵对应系数是1那观测值和状态之间肯定存在单位或坐标系上的不一致。检查反馈校正——是否存在重复补偿比如校正了一次状态下一个周期又基于未复位的状态做了补偿导致误差被反复叠加。实际工作中我遇到最多的是第2类。比如把GNSS输出的纬度直接当成米来用或者漏了经纬度到米的比例系数残差量级就会和状态量差好几个数量级滤波器必发无疑。6.2 收敛慢怎么办现象静止状态下姿态收敛要几十秒甚至几分钟或者GNSS信号恢复后位置误差要很久才能修正回来。排查思路P矩阵初值是否过小如果初始姿态不确定度只有0.01度但实际可能有几度滤波器一开始就“过信”收敛自然慢。把P初值调大到符合实际不确定度的水平。过程噪声Q是否过小Q过小导致滤波器认为预测很准观测只能一点点修正。适度增大姿态误差对应的过程噪声可以加快收敛。观测更新频率是否太低松耦合模式下GNSS输出率往往只有10Hz甚至1Hz观测更新频率低同样会拖慢收敛速度。可以检查是否有数据丢帧或者把观测更新改成“有数据就更新”。6.3 高度通道为什么容易飘高度通道是组合导航里公认的难点。GNSS高度精度天生比水平精度差气压计也不是所有平台都有而惯导的高度通道在短期内会被垂直加速度误差积分迅速拉偏。映射到滤波器上就是位置误差状态里的高度项可观测性弱收敛慢。我常用的处理技巧在Q矩阵里适当增大高度方向的加速度计噪声驱动让滤波器对高度预测不那么自信更愿意相信观测。如果GNSS高度确实抖动比较大在R矩阵里把高度观测噪声设得比水平方向更大一些避免把GNSS高度噪声直接带进输出。如果平台上有气压计考虑增加一个气压计观测通道。气压计短期稳定性好、输出率高的特点正好补GNSS高度的短板。6.4 调参顺序与验收标准调参顺序我归纳为四步按顺序来能省掉大量交叉排查的时间静态调参IMU静止不动GNSS固定。目标是姿态误差收敛稳定速度近似为零位置漂移缓慢。这个阶段主要调P初值和姿态相关Q。动态校核载体做直线加减速、匀速转弯等标准动作。目标是速度跟随及时位置轨迹贴合车道线转弯时位置无锯齿。这个阶段主要调速度、位置相关Q和杆臂补偿。遮挡工况进入楼宇或树荫遮挡环境。目标是在GNSS短暂中断时位置漂移可控信号恢复后能快速收敛。这个阶段主要验证零偏估计质量和IMU纯推算精度。长跑稳定性连续跑30分钟以上关注是否有缓慢发散、P矩阵是否收敛到合理量级、零偏估计是否平稳。每一步都有明确的验收指标比如静态姿态误差小于0.1度、位置漂移小于几米每分钟、中速转弯位置误差小于0.5米等。没有量化指标的调参很容易陷入“调了很久但不知道好不好”的状态。最后分享一个我个人的习惯每次调完参数一定把P矩阵的变化曲线导出来看一遍。P矩阵不减到稳态、或者某个对角元素一直跳来跳去说明对应的状态量没有被观测充分激励这是个很好的诊断工具。组合导航的卡尔曼滤波实现原理书上都有但在真机上跑稳、跑准靠的就是这些细颗粒度的工程调试。希望这篇文章能把你在从公式到实机的路上拉近一大截。本文还有配套的精品资源点击获取