搞自动驾驶定位、机器人导航、以及组合导航算法的人,应该都有过这种经历:想验证一套GNSS/INS融合算法,翻遍了开源数据集,要么只有普通单天线GNSS,要么IMU只有一个型号且频率不高,要么干脆没有高精度参考真值。我们在做多传感器融合定位时,最缺的其实不是算法,而是一份能“逼真地”模拟车载动态、同时记录多种不同等级IMU数据,还带厘米级参考轨迹的数据集。这篇就来聊聊一套多IMU车载GNSS/INS数据集的设计思路、里面到底有什么坑、以及拿到数据后怎么把它用起来。
先说清楚这套数据集能干什么、适合谁。它覆盖了GNSS/INS组合导航最关心的几个问题:不同等级IMU的误差特性对比、多IMU冗余融合、GNSS信号遮挡场景下的漂移评估、以及多传感器外参标定验证。适合正在做定位算法验证的同学、研究GNSS/INS紧组合或松组合的工程师,也适合那些刚入门组合导航、想找一份干净数据练手的学生。文中所有内容都是基于实际使用这类车载数据集的经验整理,不涉及厂商绑定,也不绕圈子,直接说干货。
1. 多IMU车载GNSS/INS数据集是什么,为什么值得关注
1.1 GNSS/INS融合的基本盘:为什么定位系统绕不开IMU
GNSS和IMU这对组合,一个是绝对测量、一个是相对推算,刚好互补。广义上来讲,GNSS接收机能够直接给出天线相位中心在地球坐标系下的位置、速度,误差不随时间累计,但更新频率低,通常10Hz左右,而且一旦进隧道、地下车库或者高层遮挡路段,就会出现丢星、多径,定位直接跳变甚至完全失效。IMU则相反,它测量物体本身的加速度和角速度,通过积分推算姿态、速度和位置,输出频率高,几百到上千赫兹,短期内非常平滑,但积分会累积误差,尤其是陀螺零偏和加速度计零偏的存在,会让位置漂移越滚越大。
GNSS/INS组合导航的核心,就是用卡尔曼滤波器把这两类观测融合起来。简单说,IMU负责“预测”,高频输出一个短时精确的位姿轨迹;GNSS负责“修正”,在低频观测到来时,校正IMU积分累积的误差,同时估计IMU的零偏、比例因子等误差参数。最终输出一个既平滑又绝对的位姿序列,这就是INS(Inertial Navigation System,惯性导航系统)最经典的用法。打个比方,IMU是盲人手里的拐杖,短距离非常靠谱;GNSS是路上的路标,隔一段出现一次;卡尔曼滤波就是那个不断用路标修正拐杖轨迹的大脑。
组合方式不同,修正的信息粒度也不同。松组合直接用GNSS解算出的位置、速度作为观测;紧组合则用伪距、伪距率等原始观测,在滤波器里联合估计;深组合更为底层,在跟踪环路层面参与信号处理。普通数据集一般只支持松组合和紧组合的验证,但不管哪种组合方式,IMU数据的质量直接决定了系统的下限。所以想评估一套GNSS/INS算法,手里必须有多类型的IMU数据。
1.2 多IMU不是“堆料”:它解决的是可靠性与可观性问题
很多初学者看到“多IMU”第一反应是“多加一个传感器,数据更冗余”。但真正跑到车载场景里,多IMU的收益远超冗余备份这个层面。
第一层是可靠性。车载环境里IMU偶尔会出问题,比如温度漂移过大、供电波动导致异常跳变、震动过大造成采样异常。如果只有单IMU,系统只能靠滤波器内部的残差检验去“硬扛”;如果装了两个以上IMU,可以通过一致性检验很快识别出哪个IMU的输出异常,直接切到健康通道,这在功能安全要求较高的场景里几乎是刚需。
第二层是异构互补。车载数据集通常会同时装战术级光纤陀螺IMU和低成本MEMS IMU。战术级IMU零偏稳定性非常好,但价格昂贵、体积大;MEMS IMU噪声大、零偏随温度变化明显,但带宽和动态范围通常更高。两个设备同时工作,可以评估低成本IMU在GNSS/INS算法里到底能跑成什么样,也可以设计一个“主MEMS+战术级校正”的融合策略,在成本和精度之间找平衡。
第三层是提高系统可观性。这里值得多说一句,因为很多同学不理解为什么“多装一个IMU”就能改善姿态估计。车辆在平面运动时,如果只有一个IMU装在车辆中心,车辆直线行驶过程中,侧向速度接近零这个约束对航向角的限制是有限的,尤其是低速状态。但当另一个IMU安装在车头或车尾时,两个IMU之间的杠杆臂会带来额外的运动学约束,转向时车头、车尾IMU会感受不同的角速度投影,这些信息在滤波器里会提高航向、外参甚至轮速计标定参数的可观性。直观表现就是,在某些GNSS短暂中断的弯道场景里,双IMU融合的姿态漂移明显比单IMU小。
当然,多IMU也带来新麻烦:每个IMU到车体坐标系的安装角、杠杆臂都必须准确标定;IMU之间的时间戳必须严格同步;不同IMU的数据率还不一样,解析和融合的复杂度都会增加。这部分内容,数据集本身通常不会替你完成,只能由使用者自己去处理,所以这也正是这套数据最有练习价值的地方。
2. 数据集整体构成与传感器方案选型
2.1 车载平台与传感器清单
拿到这套数据集之后,首先要看传感器安装清单,因为后续所有坐标系变换、时间戳对齐、外参标定都依赖这份清单。典型的多IMU车载GNSS/INS数据集,在硬配置上通常会包含以下几类传感器:
| 传感器 | 典型频率 | 精度/量级 | 主要用途 |
|---|---|---|---|
| GNSS接收机(双天线) | 10Hz | 厘米级RTK,航向0.1°级别 | 提供绝对位置、速度、航向参考 |
| 战术级IMU | 100~200Hz | 陀螺零偏0.5°/h以内 | 提供高稳定性的惯性基准 |
| 工业级/车规MEMS IMU | 100~200Hz | 陀螺零偏10°/h~数十°/h | 低成本场景、对比验证 |
| 轮速计/车辆CAN信息 | 100Hz左右 | 车速、轮速、转向角 | 非完整约束、里程计辅助 |
| LiDAR/相机 | 10Hz/30Hz | 点云、图像 | 多传感器融合、外参标定 |
| 基准站或后处理数据 | 1Hz~10Hz | 固定解/PPP | 生成参考轨迹 |
上表里的传感器并不是每套数据都全有,但多IMU车载数据集至少会保证“双天线GNSS接收机 + 2个以上不同类型的IMU + 轮速信息”这三类。这里要特别注意,GNSS接收机如果带双天线,意味着它可以输出的不仅包含位置速度,还能在动态条件下给出比较可靠的航向角,这对于验证单天线GNSS/INS算法和双天线辅助的差异非常有帮助。
2.2 时间同步体系:多传感器的地基
很多人在跑数据集的时候,最容易忽视的环节就是时间同步。GNSS坐标系、IMU积分、相机图像曝光时刻如果不在同一条时间线上,后面的融合算法再漂亮也白搭。
车载GNSS/INS系统的时间同步通常这样设计:GNSS接收机输出PPS秒脉冲,这个脉冲信号和UTC/GPS时间严格对齐,精度可以达到微秒级。主控板卡负责捕获PPS边沿,把本地时钟在整秒时刻“拉”回GPS时间,同时为所有IMU、相机、LiDAR输出硬件触发或记录时间戳。IMU这种连续输出设备一般直接硬件时间打戳,确保每个采样样点的时刻来自与PPS同步后的本地时钟;相机则通常用曝光信号(Exposure Active)上升沿打时间戳,这样才能精确到图像实际采集瞬间。
实际用数据集时,常见的情况是时间戳有偏差,比如IMU时间戳和GNSS时间戳之间差几十毫秒。这在松组合里还不至于立刻炸掉,但紧组合伪距率更新时误差会非常明显,因为多普勒观测对时间误差非常敏感。有些数据集会额外提供一个“真实时间戳修正表”,把每个IMU样点相对GNSS时间的偏差记录成时间差补偿。跑之前一定要先检查时间轴是否一致,别一上来就灌进滤波器。
2.3 标定:从IMU内参到外参
多IMU数据集的第二个核心价值,就是逼着你去面对标定问题。随便拿速度和姿态去融合,结果惨不忍睹时,十有八九都是标定没做好。
先看IMU内参。IMU输出的是加速度和角速度,它内部有三类误差:零偏、比例因子、安装误差。零偏是静态时输出不为零的部分,比例因子是输出与实际值的比值偏差,安装误差是三个敏感轴不是完全正交造成的偏差。常规做法是把IMU固定在六面体工装上,分别让每个轴朝上、朝下静置几十秒,通过最小二乘解算零偏、比例因子、安装误差矩阵。更精细的做法是采集长时间静止数据,用艾伦方差分析来分离量化噪声、角度随机游走、零偏不稳定性、速率斜坡等误差项,这些参数后面可以直接用于滤波器调噪声矩阵。
再看外参。IMU相对车体坐标系的安装角和杠杆臂,GNSS天线相位中心相对IMU的杠杆臂,都是必须精确已知的。GNSS天线相位中心往往不在天线的几何中心,双天线系统的两个天线相位中心距离和基线方向更是直接决定航向精度的基础。相机与IMU联合标定常用Kalibr或类似的工具箱,利用棋盘格序列图像来估计相对外参和时间延迟;LiDAR与IMU外参标定则利用连续点云配准和IMU积分结果做联合最小化。
网上经常看到有人问“lidar imu标定、imu雷达外参标定、相机imu联合标定怎么搞”,这类问题的答案通常都离不开一个底层思路:标定的本质是求两个坐标系之间的相对变换,以及传感器之间的时间延迟。采集数据时要充分激励6自由度运动,不要只走直线,否则某些轴的可观性不足,标定结果会非常不稳定。
3. 参考真值与数据格式:怎么把数据用好
3.1 参考轨迹怎么生产:后处理组合+双天线约束
评价一套GNSS/INS算法的优劣,必须有“真值”,也就是参考轨迹。这里要特别提醒一下,参考轨迹绝对不是实时输出的定位结果,否则就成了拿自己的算法验证自己,没有任何说服力。
通常的做法是,在采集数据的同时,用后处理的方式对GNSS原始观测和IMU数据进行反向平滑解算。后处理不像实时解算那样受限于计算资源和延迟,可以用双向滤波或者RTS平滑器,把整个时间序列从头到尾、从尾到头各解算一遍,再用Kalman平滑得到最优估计。另一方面,后处理可以融合未来的信息,GNSS模糊度固定也做得更稳健。如果采集过程中附近有已知控制点,还能引入基准站观测做双差固定解,位置精度可以做到厘米级。双天线GNSS接收机提供的航向约束也会用于参考轨迹解算,这样参考轨迹的姿态角尤其是航向角,比单天线时可靠得多。
不过参考轨迹也不是完美的。在立交桥下、树荫遮挡严重的路段,即使后处理,也可能存在少数时间段出现定位跳变。好的数据集一般在发布时会在参考轨迹里标注“解状态”,比如固定解、浮点解、单点解,还会提供前后向解算结果的一致性指标,使用者可以根据这些字段剔除不可靠的时间段。
3.2 数据组织与坐标系约定
数据集的可用性很大程度上取决于它的格式和坐标系约定规范不清楚。这一点做得好的数据集,会让人节省大量时间。
常见的数据格式包括ROS bag、CSV、HDF5三种。ROS bag适合直接喂给机器人系统,topic结构清晰;CSV适合数据量不大、希望快速学习的场景;HDF5则适合大规模数据压缩存储。不管哪种格式,每一帧数据都要有统一的时间戳基准,通常是GPS时间或UTC时间,精确到纳秒或微秒。要格外注意时间戳到底是采样时刻还是接收时刻,有些数据集时间戳是主控端收到数据的时刻,和传感器实际采样时刻存在固定的传输延迟。
坐标系方面,GNSS位置一般在ECEF(地心地固)坐标系或ENU(东-北-天)局部坐标系下给出,IMU的原始数据则在其自身的body frame下给出,通常定义为前右下或前左上。跑算法时需要注意,载体坐标系原点和IMU测量中心可能不重合,原因就是2.3节提到的杠杆臂。位置、姿态、速度的表达方式也要检查清楚:位置用经纬高还是ENU米制坐标,姿态用四元数还是欧拉角序列,旋转约定是左乘还是右乘,这些细节错了任何一个,融合结果都会莫名其妙地发散。
3.3 典型评价指标:ATE、RPE、漂移率
拿到数据、跑出结果之后,怎么客观评价算法?建议至少计算以下几类指标。
绝对轨迹误差(ATE)表示估计轨迹和参考轨迹在整段轨迹上的全局偏差,通常先用Umeyama或李代数方法对估计轨迹和参考轨迹做刚体对齐,再计算逐时刻的位置误差RMS。它对绝对定位精度非常敏感,适合评价GNSS/INS全局定位效果。相对位姿误差(RPE)则关注局部时间区间内的相对运动误差,例如每隔1秒、10秒或100米计算一次相对位移与相对姿态的偏差,更适合评估GNSS长时间中断时的IMU推算漂移程度。
GNSS/INS数据集还有一个特殊评价指标:GNSS中断段漂移率。一般会把参考轨迹中GNSS固定解缺失的路段单独截出来,统计估计轨迹在中断持续10秒、30秒、60秒内的位置和航向漂移。这个指标能直接反映IMU误差修正的效果,也是多IMU融合是否有效的关键对比维度。跑这种数据集时,建议一并输出轨迹误差的时间曲线和累计误差分布图,这样比只给一个数字更容易看出问题发生在哪里。
4. 实操过程:从数据到手跑通一个GNSS/INS融合
4.1 数据解析与时间对齐
拿到数据集之后,建议先别急着跑融合算法,而是写一个数据解析器,把时间轴、坐标系、参考轨迹状态彻底搞清楚。下面这段代码思路通常可以快速验证时间戳和插值逻辑:
import numpy as np import pandas as pd # 读取CSV数据 imu_df = pd.read_csv("imu_data.csv") # 列: gps_time, acc_x, acc_y, acc_z, gyr_x, gyr_y, gyr_z gnss_df = pd.read_csv("gnss_data.csv") # 列: gps_time, x_enu, y_enu, z_enu, vx, vy, vz, status # GNSS观测插值到每个IMU时刻 imu_time = imu_df["gps_time"].values gnss_time = gnss_df["gps_time"].values gnss_pos = gnss_df[["x_enu", "y_enu", "z_enu"]].values pos_interp = np.empty((len(imu_time), 3)) for i in range(3): pos_interp[:, i] = np.interp(imu_time, gnss_time, gnss_pos[:, i]) # 检查GNSS固定解状态是否可靠 print("GNSS fixed ratio:", (gnss_df["status"] == 4).mean())这段代码的核心是线性插值,把10Hz的GNSS观测对齐到100Hz或200Hz的IMU时刻。实际使用时要注意两点:一是插值不能跨越GNSS中断段,否则会把不同解状态的位置拉出虚假轨迹;二是如果GNSS频率低于IMU太多,且车辆处于强机动状态,线性插值本身会引入误差,更稳妥的做法是在滤波器预测阶段让GNSS观测保持低频更新,而不是强行提高观测频率。
如果你用的是ROS bag,那更简单,直接把IMU报文和GNSS报文按消息时间戳对齐即可。但要注意,ROS的时间戳和数据集里的GPS时间可能不一致,需要做一次时间偏移换算。
4.2 误差状态卡尔曼滤波ESKF的实现要点
GNSS/INS融合的工程实现主流方案是误差状态卡尔曼滤波(ESKF),也叫间接Kalman滤波。它的基本思路是:把IMU积分得到的标称状态当成“主线”,卡尔曼滤波只估计标称状态附近的误差状态,从而避免直接对四元数等非线性量做加权平均导致的不一致。
状态向量一般包含:位置误差、速度误差、姿态误差(用三维小角度向量表示)、陀螺零偏误差、加速度计零偏误差,以及GNSS天线杆臂误差等。预测阶段用IMU的陀螺和加表输出递推位置、速度、姿态,同时按IMU噪声功率谱密度推进协方差;更新阶段用GNSS位置和速度作为观测,按照先验噪声属性计算卡尔曼增益,修正误差状态并反馈到标称状态。
实现时有几个容易出问题的细节。第一,重力矢量必须在ENU坐标系下建模,天向加速度计测量包含了重力加速度,坐标系转错的话,位置会在竖直方向快速发散。第二,姿态误差的更新要区分左扰动还是右扰动,这会直接决定观测矩阵的符号和形式。第三,陀螺零偏、加速度计零偏的初始值不要随便设成0,最好先用静止段数据估计一下,否则系统需要较长时间才能收敛,而在收敛之前轨迹已经飘得没法看了。
多IMU融合的一种实现思路是:主IMU负责预测,第二个IMU的输出通过外参变换到主IMU坐标系后,作为角速度和线加速度的“冗余观测”加入更新,或者只用两个IMU的一致性构造一个故障检测残差。简单起见,第一版实验建议先跑单IMU与GNSS松组合,再去扩展多IMU模块,这样比较容易定位问题。
4.3 评估脚本与结果可视化
跑完滤波器后,用下面这段逻辑计算ATE和RPE,这是比较通用的评估流程:
from scipy.spatial.transform import Rotation def compute_ate(est_pos, ref_pos): # 1. 使用Umeyama算法进行轨迹对齐 R, t, s = umeyama_alignment(ref_pos, est_pos) est_pos_aligned = (est_pos @ R.T + t) * s # 2. 逐点计算欧氏距离误差 errors = np.linalg.norm(est_pos_aligned - ref_pos, axis=1) return errors.mean(), errors.std(), errors.max()对齐这一步非常关键。GNSS/INS的坐标系定义和参考轨迹可能差了一个固定的旋转和平移,不能直接把两个轨迹拿来比较。Umeyama算法有成熟的现成实现,比如EVO工具包里就内置了。计算ATE之前先做对齐,得到的是纯定位精度的差异;如果关心的是绝对地球坐标系下的误差,那就不做旋转对齐,直接比较ENU坐标,这样会更严格。
输出轨迹误差后,建议把误差随时间变化的曲线图、误差累计分布图,以及GNSS固定解状态图放在一起看。我实际跑数据的经验是,误差曲线里突然出现的“尖刺”,往往不是算法问题,而是某个时间段的GNSS解状态从固定解退化成了浮点解或者单点解,或者参考轨迹本身存在跳变。所以评估脚本里一定要连同解状态一起输出,避免误判算法问题。
5. 常见问题与避坑实录
5.1 时间同步偏差:结果忽好忽坏的元凶
多IMU车载数据集最容易藏雷的地方就是时间戳。常见情况是:数据集发布时IMU时间戳和GNSS时间戳没有严格对齐,偏差甚至达到几十毫秒。症状是松组合算法表现还行,但紧组合算法速度观测一进来就发散,或者位置误差在转弯时出现周期性偏置。
排查思路很简单:先把一段直线静止数据的IMU和GNSS速度打印出来,量出速度响应之间的时间延迟;或者在车辆急加速路段,看IMU加速度突变和GNSS速度变化之间的相位差。实测下来,只要时间偏差超过10毫秒,对紧组合的影响就非常明显了。解决问题的方法是做时间戳补偿,把GNSS观测投影到IMU时刻,或者反过来把IMU采样插值到GNSS观测时刻,但注意插值只能处理采样率差异,不能替代硬件同步。
5.2 静止初始化:零偏是GNSS/INS的“地基”
启动GNSS/INS系统时,如果直接进入运动状态,系统还没有机会估计IMU零偏,位置和姿态会在最初几秒内快速漂移。很多数据集在采集时,车辆启动前会有一段几十秒的静止段,这段数据绝不是无用的,应该利用它做静止初始化。
初始化步骤一般是这样:提取静止段的加速度计和陀螺仪输出,分别求均值,作为零偏的初始估计。横滚角和俯仰角可以由加速度计在重力方向的投影直接解算,航向角则可以由双天线GNSS航向、磁力计或上一时刻GNSS速度方向来给出。初始协方差矩阵也要按静止段的统计特性来设置,而不是随便填一组数。这样滤波器启动后能很快收敛,而不是在最初的几十秒里“摇摆”。
“imu重力对齐”这个操作也在这个阶段完成:加速度计的三轴测量值在静止时就是重力加速度在体坐标系下的投影,用这个矢量就能算出初始横滚、俯仰。航向角无法通过重力对齐,只能靠外部信息,这是很多初学组合导航的人最容易混淆的地方。
5.3 为什么imu的yaw还是会慢漂
即使有GNSS修正,有些系统在GNSS长时间中断的段落下,航向角还是会出现“慢漂”,位置误差也会随着中断时间呈二次曲线增长。这里要区分两个原因:一是GNSS中断期间,系统只能靠IMU积分,陀螺零偏未经修正时,航向误差会随时间线性累积,位置误差再对航向积分,自然非线性增长;二是单天线GNSS在正常的开阔环境下,虽然能通过速度方向约束航向,但车辆静止时这个约束消失,航向的可观性会变弱。
多IMU能改善一点,但无法彻底解决慢漂,因为漂移的本质是积分对零偏残差的响应。想抑制慢漂,通常要从外部组合入手:双天线GNSS航向、磁力计、轮速计非完整约束、视觉/激光里程计约束都可以。数据集里如果有轮速信息和双天线航向,建议把它加进对比实验,效果差异会非常直观。跑“里程计和imu融合定位”实验时尤其要注意,轮速计约束的前提是车辆不出现明显侧滑,高速变道时约束模型会失效,这在评估时要单独处理。
5.4 IMU标定与多传感器外参标定避坑
热词榜里“lidar imu标定、相机imu联合标定、imu雷达外参标定”反复出现,说明很多人在标定上吃过亏。我踩过的主要坑有三个:
第一个坑是采集数据时运动激励不够。标定外参和标定内参一样,也需要“激励”出所有轴的运动。如果车辆只做了直线加速和刹车,相机或LiDAR与IMU之间的旋转角某些分量完全不可观,求出来的外参会带巨大不确定性。正确做法是让车辆做“8”字绕圈、俯仰上坡、颠簸路面,激发横滚、俯仰、航向三个方向的充分运动。
第二个坑是时间延迟估计没做。传感器之间的硬件触发若未严格同步,标定残差里会存在明显的时间偏差分量。很多标定工具箱都支持时间延迟参数联合优化,一定要打开这个选项,而不是默认设为0。
第三个坑是坐标系定义混乱。标定结果通常给出的是“传感器A到传感器B”的变换,但不同工具箱输出的是传感器A坐标系下的变换还是在世界坐标系下的表示,方向和姿态序列也可能不一样。拿到标定结果后,一定要先做一个投影测试:把激光点云按外参投影到相机图像上,检查物体轮廓是否重合,重合了再往下走,否则先别碰融合算法。
最后分享一点实际使用的体会
这套多IMU车载GNSS/INS数据集跑下来,我最深的体会是,数据集的真正价值不只是给你一份“测试数据”,而是逼着你把GNSS/INS组合导航里最麻烦的工程细节全部过一遍:时间同步、惯性坐标系变换、静止初始化、外参标定、误差评估。很多人写算法时习惯直接套公式,一旦遇到“估计轨迹跟真值之间有个莫名其妙的固定偏移”“GNSS一更新位置就跳一下”这类问题,就不知道从哪排查了。而这一类问题,恰恰是在真实车载数据上才会暴露得淋漓尽致。
给想拿这个数据集做实验的同学一个建议:先别急着上自己的导航算法,先用官方基础样例跑通一遍,输出“双天线GNSS航向对比单天线”“GNSS中断60秒的IMU漂移”两个小实验,把数据特性摸清楚之后再动手改滤波器。这样后续调参时,你能很快判断误差究竟来自IMU,来自GNSS,还是来自自己的代码。数据集的坑很多,但把这些坑都踩过一遍之后,你对GNSS/INS组合导航的理解会上一个明显的台阶。