简介本资源是面向导航定位领域科研人员与高校师生的GNSS信号接收模拟工具包聚焦GPS信号建模、多径效应分析及INS/GNSS组合导航算法验证。NaveGo-master由circusjwz与coriolis_master团队开发提供从卫星信号生成、IMU误差建模到卡尔曼滤波融合的完整仿真链路可支撑接收机算法调试、教学实验设计及系统性能评估。压缩包共65个文件50.4MB含55个MATLAB源码.m实现核心导航解算如kalman.m、ins_gnss.m、coriolis.m、5个.mat数据文件用于仿真验证、2个说明文档README.md、LICENSE、1个.kml地理可视化文件及1个.txt许可文件目录结构清晰划分为examples、conversions、allan-variance等模块覆盖合成数据生成、Allan方差分析、ECEF/NED坐标转换等关键环节。目前已有129人学习下载适合具备MATLAB基础的中高级用户开展GNSS/INS仿真研究与课程实践。 顺着 NaveGo-master.zip 这个文件名点进来的朋友多半和我一样是想用 MATLAB 做 GNSS/INS 组合导航验证的。这个压缩包在许多论坛和网盘里流传文件名经常被系统自动续成 NaveGo-master.zip_GNSS MASTER_NaveGo-master_circusjwz_coriolis m我第一次看到时也是满头问号coriolis 不是物理里那个科里奥利效应吗怎么会出现在一个 GNSS 工具箱的名字里等我把包里的代码真正跑通才发现这个看似不起眼的关键词恰恰是惯性导航机械编排里最容易忽略、也最影响模型完整性的一个角落。这篇东西不是把 README 复述一遍而是我从下载、解压、喂数据到看结果这一路上踩过的坑和梳理清楚的东西给打算用 NaveGo 做组合导航的朋友一个可以直接参照的路径。1. 我为什么会盯上NaveGo一个能跑起来的GNSS/INS集成工具箱先说背景。去年我手头要做的是一个低成本车载导航验证项目一块 MEMS 级别 IMU一个普通单频 GNSS 模块目标是评估松组合方案到底能把定位精度做到什么水平。一开始我图省事打算在有名的商业导航软件里跑一圈仿真但一是授权问题麻烦二是黑盒方案里我根本看不到姿态、速度、位置每一步是怎么算的出了问题只能干瞪眼。后来在 GitHub 上翻到了 NaveGo名字是 Navigation Goes 的缩写一个用 MATLAB 写的开源 GNSS/INS 集成工具箱瞬间觉得这就是我要的东西。NaveGo 的价值不在于它有多炫酷的界面而在于它把整套组合导航链路完整地摊开了。你给它喂进去两类数据一类是 IMU 输出的加速度和角速度另一类是 GNSS 输出的经纬高和速度它内部先用惯性机械编排把姿态、速度、位置推算出来再用扩展卡尔曼滤波EKF拿 GNSS 观测去修正惯导误差。整个过程是松组合的典型结构代码量不大但每一步都有对应的函数非常适合想弄懂组合导航到底是怎么把两个传感器揉在一起的人。适合看这篇文章的大致有三类人一是正在学惯性导航理论、想把课本上的机械编排方程变成可运行代码的学生二是做车载、机器人、无人机导航需要一个开源基线做对比验证的工程师三是像我这样手里有真实 IMU 和 GNSS 模块想快速搭一个原型评估精度的开发者。如果你只是需要一键出图的成品工具那 NaveGo 可能反而会让你失望因为它对数据格式、坐标系、时间同步都有要求——但这些要求恰恰是组合导航里最该学的东西。我之前也试过自己从零写机械编排写到速度更新方程时总是怀疑符号对不对尤其是科里奥利项那部分动不动就把 (2\omega_{ie}^n\omega_{en}^n) 的符号弄反。NaveGo 的好处就是提供了一个经过很多人验证过的参考实现等效于有个经验丰富的同事把他的代码摊在桌面上说你看这里应该这么处理。2. 拆开NaveGo-master.zip目录里的每个文件是干什么的把压缩包解压之后目录结构大致是这样的不同版本可能有小差异但核心模块基本一致NaveGo-master/ ├── README.md ├── LICENSE ├── data/ │ ├── dataset1.mat │ └── dataset2.mat ├── functions/ │ ├── ins.m │ ├── kf_init.m │ ├── kf_prediction.m │ ├── kf_update.m │ ├── imu_read.m │ ├── gnss_read.m │ ├── coriolis.m │ ├── align_hb.m │ └── plot_results.m ├── scripts/ │ ├── run_example.m │ └── ... └── doc/ └── NaveGo_documentation.pdf第一次拿到这个包的人最容易犯的错是直接双击run_example.m然后报错找不到函数。原因很简单MATLAB 不会自动搜索子目录里的函数你必须先把整个目录加入路径我通常执行这行addpath(genpath(NaveGo-master));这里多提一句如果你把压缩包放在中文路径下或者文件名里带空格某些 MATLAB 版本偶尔会出一些莫名其妙的加载问题。我的习惯是统一放到D:\work\NaveGo-master这种纯英文、无空格的路径里省得后面排查半天。接下来分清主次。functions目录是绝对核心其中ins.m是惯性导航机械编排它接收上一时刻的姿态、速度、位置和当前 IMU 采样输出新的姿态、速度、位置整个惯导推算的主循环就靠它。kf_prediction.m和kf_update.m是 EKF 的时间更新和量测更新前者把惯导误差协方差往前推后者在 GNSS 观测到来时对误差状态做修正。kf_init.m负责给滤波器赋初值包括初始姿态、初始协方差矩阵和噪声矩阵。我特别想提醒的是coriolis.m也就是标题里那个关键词。很多初看代码的人会以为它是个中间辅助函数不重要结果真正动手改代码、把科里奥利项删掉测试时才发现它对速度更新的影响是结构性的。这个我们下一节专门展开讲。另外data目录里通常带几个.mat数据集是官方用来演示的仿真数据。不要一上来就用自己的 IMU 报文去测试那样会把数据格式错误和算法问题混在一起特别难排查。先把内置数据跑通一遍再把数据替换成自己的这个顺序能省掉大量无意义的调试时间。3. 真正决定精度的是一个函数coriolis、地球自转与INS机械编排为什么一个工具箱里会专门出现 coriolis 这个词因为在惯性导航里我们是在地球这个不断自转的参考系里解算载体运动的。想象一下你站在旋转木马上沿着木马半径往外走即使你走的速度很慢也会感觉到一股横向的力把你推向一边这就是科里奥利效应。地球就是一个转速很慢的旋转木马约 7.292115e-5 rad/s但任何相对地球运动的物体只要导航时间足够长、运动速度足够快这个效应都会积累成可观测的误差。在 NED 坐标系下惯导速度微分方程的标准形式是[ \dot{v}^n C_b^n f^b - (2\omega_{ie}^n \omega_{en}^n) \times v^n g^n ]其中 (C_b^n f^b) 是比力投影(g^n) 是重力矢量中间那一项就是科里奥利加速度和运输率的合成。(2\omega_{ie}^n) 是地球自转角速度在导航坐标系下的投影(\omega_{en}^n) 是载体在地球表面运动导致的导航系相对地球系的转动两者共同作用在速度向量上产生一个虚拟加速度。NaveGo 里不管用什么名字封装本质上都在处理这个式子。用伪代码表示它在某个函数里做的事情大致是% 地球自转角速度在NED下的投影L为纬度 w_ie_n [wie*cos(L); 0; -wie*sin(L)]; % 运输率v为NED速度R_M/R_N为子午圈和卯酉圈曲率半径 w_en_n [v(2)/(R_Nh); -v(1)/(R_Mh); -v(2)*tan(L)/(R_Nh)]; % 科里奥利加速度 coriolis_acc cross(2*w_ie_n w_en_n, v);很多人看到这个伪代码会有一个疑问MEMS IMU 噪声那么大这个科里奥利项到底有多大我算过一个具体数字假设载体以 20 m/s 的速度在纬度 45 度的地方向北行驶那么 (2\omega_{ie}^n \times v^n) 带来的哥式加速度大约是 (2 \times 7.292 \times 10^{-5} \times 20 \times \sin(45^\circ))差不多 (0.002 m/s^2)。这个量级确实比 MEMS 加速度计噪声小但如果机械编排里完全忽略它速度会持续积累一个偏置一分钟就能带来约 0.12 m/s 的速度误差再积分到位置上就是可观的漂移。在 GNSS/INS 松组合系统里GNSS 虽然能通过滤波不断修正速度误差但如果你在模型里漏掉了科里奥利项EKF 的预测模型和真实物理过程就不匹配滤波器会拿错误的增益去折中所有误差最终导致位置解出现难以解释的残差。我在调试时试过把科里奥利项置零结果单靠 GNSS 更新也能勉强收敛但组合解的位置误差明显变大尤其在车辆转弯、速度方向快速变化的时候误差波动非常剧烈。所以这个项不是高精度光纤陀螺系统才需要考虑的东西模型完备性对任何精度的 IMU 都有意义。还有一个很容易犯的误导是坐标系混用。不同教材和工具箱有的用 NED有的用 ENU符号和顺序完全不同。NaveGo 默认的导航坐标系是 NED角度单位是弧度加速度单位是 m/s²角速度单位是 rad/s。如果你从自己的 IMU 驱动里读出来的是度每秒、或者把数据喂成了 ENU 顺序出来的轨迹要么发散、要么每个转弯方向都是反的。我建议拿到代码后第一件事是确认坐标系定义把单位换算逻辑写清楚不要指望后面滤波自己纠偏。4. 让NaveGo在你的MATLAB上跑起来数据准备和实操记录下面说点能直接照做的内容。以我下载的版本为例整个运行流程分四步。第一步是准备数据。NaveGo 的惯例是把 IMU 和 GNSS 各存一个数据文件IMU 数据通常包含时间、姿态角有的版本是四元数、三轴加速度、三轴角速度GNSS 数据包含时间、纬度、经度、高度、北向速度、东向速度、地向速度。如果你用的是内置数据集直接load(dataset1.mat)就能拿到结构体如果你要用自己的数据就必须按照它的格式整理成同样的结构这是整个项目里最枯燥但最关键的环节。第二步是读取和初始化。常见的主程序逻辑大致是addpath(genpath(NaveGo-master)); % 读取IMU和GNSS数据具体函数名和参数以你下载的版本为准 imu imu_read(my_imu_data.txt); gnss gnss_read(my_gnss_data.txt); % 初始化滤波器设置初始姿态、协方差、噪声矩阵 nav kf_init(imu, gnss);第三步是主循环。松组合的基本逻辑是每个 IMU 采样时刻先用ins.m做机械编排把姿态、速度、位置往前推一步如果有新的 GNSS 观测就调用kf_update.m做量测更新把误差状态修正回惯导解算结果。简化的循环长这样for i 1:length(imu) % IMU机械编排姿态、速度、位置更新 nav ins(nav, imu(i)); % 判断当前时刻有没有GNSS观测 k find(gnss.time imu(i).time, 1, first); if ~isempty(k) % 如果这一拍有GNSS数据就做EKF量测更新 nav kf_update(nav, gnss(k)); end end这里我要单独提醒一句如果你在实际运行中看到各种维度对不上的报错大概率不是算法问题而是数据结构问题。NaveGo 的函数对字段名很敏感比如 IMU 结构体里加速度字段是acc还是accel、角速度字段是gyro还是omega不同版本可能不一样。最稳妥的办法是先disp(imu)和disp(gnss)看一眼实际字段名再对照函数内部代码里的引用方式改数据时直接对齐字段而不是去改函数的读取逻辑。第四步是画图和保存结果。plot_results.m或者你自己写绘图代码把组合导航解算出来的轨迹叠加在 GNSS 原始轨迹上输出位置、速度误差曲线。这一步不是可有可无的因为只看最终数据你是看不出滤波器发没发散的必须靠曲线判断。我在实操中发现一个非常实用的技巧第一次跑通时先用官方内置数据集然后观察纯惯导输出和组合输出之间的差异。纯惯导在几十秒内就会明显漂移组合输出应该紧贴 GNSS 轨迹这个对比能帮你快速判断主循环到底通没通。如果组合输出和 GNSS 轨迹差得离谱十有八九是单位换算或者坐标系方向出了问题而不是滤波参数不行。5. 跑完仿真之后如何确认结果不是在自嗨很多新手把仿真跑完看到曲线出来了就认为项目完成了但实际上确认结果对比让程序跑起来更考验基本功。我在用 NaveGo 做评估时一般按下面这个顺序检查输出。先看轨迹整体趋势。把组合导航位置叠加到 GNSS 原始轨迹上看是否重合。松组合系统里GNSS 的位置观测对惯导漂移有强修正作用所以组合轨迹不应该偏离 GNSS 轨迹太远。如果整体形状对、但局部有锯齿通常是时间同步或者杆臂补偿做得不够好。如果整体形状都不对比如向北走变成了向东走那就是坐标系或者姿态初始值有问题。再看速度误差和位置误差的时间序列。NaveGo 内置数据通常有真值轨迹可以直接算误差。我习惯把误差画在一个图上同时叠加滤波协方差 P 矩阵对角线开方得到的标准差带。一个正常的滤波输出误差应该大致落在 3 倍标准差带内如果误差曲线不断穿出带子或者标准差带不收敛说明滤波器的噪声模型和实际数据不匹配。这个时候不要急着调 Q 和 R先回头检查单位、坐标系和数据结构这些问题不解决调参就是白费力气。还要特别关注 GNSS 观测频率和 IMU 采样频率的比例。常见 IMU 是 100 Hz 到 200 HzGNSS 是 1 Hz 到 10 Hz这个差距很正常。但要注意时间戳精度IMU 和 GNSS 时间戳如果来自不同时钟系统会有固定的时间延迟。我遇到过 GNSS 数据比 IMU 晚 100 毫秒的情况直接导致每到一个 GNSS 观测时滤波更新用的位置和惯导推算值之间存在系统性偏差最终位置误差表现为一圈一圈的振荡。解决方法是先做时间同步对齐或者干脆在读取数据时做插值让每个 GNSS 观测时刻都有严格对齐的 IMU 状态。最后也是我特别想强调的不要只盯着组合解要看纯惯导的漂移特性。把 GNSS 更新去掉用同一段 IMU 数据跑一遍机械编排观察纯惯导在 10 秒、30 秒、60 秒的位置漂移。这一步能暴露 IMU 零偏、标度因数误差和初始对准误差而这些误差在组合解里往往被 GNSS 掩盖了。只有先把纯惯导的漂移特征摸清楚才能理解为什么滤波器会出现某些修正行为也才能判断最后的组合结果是不是合理。6. 从NaveGo到自己的组合导航原型可以接着做的事一旦你把 NaveGo 的内置数据跑通下一步大概率是想让它处理自己传感器的数据。这里有几条实际的路可以走按难度和收益排列。第一件事解析真实 GNSS 模块的 NMEA 数据。市面上的 GNSS 模组输出的基本都是 NMEA 语句最常见的是 GGA 和 RMC。GGA 里有经纬度、高程和定位状态RMC 里有地面速度、航向和日期时间。要把这些数据变成 NaveGo 能用的格式需要把 NMEA 里的度分格式换算成十进制度把节换算成米每秒。这个转换逻辑不复杂但精度很容易被忽略比如纬度的 DDMM.MMMM 格式如果按十进制度直接解析误差会大到直接把滤波器打爆。建议写一个小的解析脚本先把原始 NMEA 转成标准 CSV再对照 NaveGo 的读取函数做字段映射。第二件事处理真实 IMU 的原始报文。不同 IMU 模组的输出格式差异很大有的直接给物理单位有的是原始 ADC 码值需要根据量程和灵敏度换算。这里最容易出错的是坐标轴方向IMU 的 x/y/z 和 NaveGo 的 NED 坐标系往往不是一回事可能需要对调或者反号。我自己的经验是先在静止状态下采集一段数据看加速度计三个轴的输出是不是稳定对应重力方向陀螺仪零偏是不是接近零然后再动起来做转动测试确认每个轴的方向和正负号。第三件事杆臂补偿。GNSS 天线的相位中心和 IMU 的测量中心不可能完全重合两者之间有一个固定的空间向量。在车载场景下这个向量可能只有几十厘米但如果你对位置精度要求高必须把它考虑进去。否则车辆转弯时GNSS 位置和 IMU 位置之间的几何差异会被当成误差引入滤波器。NaveGo 的模型里不一定默认包含杆臂补偿需要你自己在量测更新前做一步坐标变换。第四件事调 EKF 的噪声参数。Q 矩阵描述 IMU 的加速度计噪声和陀螺仪噪声R 矩阵描述 GNSS 位置和速度测量噪声。NaveGo 的kf_init.m会把这两个矩阵设成一组默认值这组默认值只对内置数据集有效。换了自己的传感器之后Q 和 R 必须根据实际数据重新标定。一个比较笨但有效的做法是拿一段静止数据统计加速度计和陀螺仪的 Allan 方差或者标准差作为 Q 矩阵的原始依据拿一段移动数据对比 GNSS 输出和已知轨迹之间的误差估算 R 矩阵。调参的过程很枯燥但它直接决定了滤波器的收敛速度和最终精度。我个人的体会是NaveGo 这个工具箱最值钱的地方不是它自带的那几个仿真数据集而是它把整套组合导航的骨架搭好之后逼着你去理解每一个数据字段、每一个坐标系、每一个噪声参数背后的物理含义。我最初只是为了快速出一个结果结果在把真实 IMU 和 GNSS 数据接入 NaveGo 的过程中反而把教科书里那些公式和实际工程问题串起来了。建议你也这样走一遍先跑通内置数据再替换真实数据最后再去动滤波参数这个顺序下来组合导航里那些死知识基本就变成你自己的了。本文还有配套的精品资源点击获取