【GNSS】 MATLAB读取GNSSLogger数据:Fix记录筛选与提取实战【含matlab代码】

论文引用信息

本文内容基于以下SPIE会议论文:

Zixia Shang, “Off-line Data Processing Based on GNSSLOGGER, GNSS System Positioning Data Quality and Accuracy Analysis,”Fourth International Conference on Geology, Mapping, and Remote Sensing (ICGMRS 2023), Wuhan, China, 14-16 April 2023.Proceedings of SPIE, Vol. 12978. DOI: 10.1117/12.3019575

论文实验数据已上传至GitHub:https://github.com/ZixiaShang/GNSSLOGGER-Data-8

PS:懒得找图了,直接贴海报了

MATLAB读取GNSSLogger数据:Fix记录筛选与提取实战

一、引言

在前两篇文章中,我们完成了GNSS数据的采集(第一篇)和数据质量分析(第二篇)。现在,我们将进入数据处理的核心环节——使用MATLAB读取GNSSLogger生成的日志文件,筛选出定位解算结果(Fix记录),并按定位提供者(Provider)进行分类提取。

在论文第四章B节中,作者详细阐述了基于MATLAB的离线数据处理流程。本文将从论文中的zixia4.m代码出发,带你一步步实现:

  • 读取GNSSLogger的.txt日志文件
  • 筛选出所有的Fix
  • 按照FLP(融合定位)、GPS(纯GNSS定位)、NLP(网络定位)进行分类
  • 提取经纬度、速度等关键字段,为后续轨迹绘制做准备

二、Android原始GNSS API版本差异与数据字段说明

在深入MATLAB代码之前,有必要了解不同Android版本对GNSS原始数据输出的影响,这直接关系到我们解析到的数据内容。

2.1 Android版本与GNSS API演进

Android版本API LevelGNSS核心变化对Fix数据的影响
Android 7.0API 24首次引入GnssMeasurementGnssClock,支持原始GNSS测量基础Fix数据可用,但卫星数量和测量类型有限
Android 8.0API 26添加GnssMeasurement.getState()(码锁定状态)Fix数据的Accuracy字段更可靠
Android 9API 28添加GnssMeasurement.getCarrierFrequencyHz()(载波频率)支持多频段(L1/L5)区分,Fix数据更丰富
Android 10API 29必须支持原始GNSS测量,添加GnssMeasurement.getAutomaticGainControlLevelDb()固定输出,兼容性大幅提升
Android 11API 30支持动态数据注入Fix输出更稳定
Android 12API 31增强多星座支持,添加GnssMeasurement.getElapsedRealtimeNanos()多系统(GPS/GLO/GAL/BDS)Fix数据齐全

论文中的设备:论文使用的三款设备均运行Android 12(API 31),因此能够完整接收GPS、GLONASS、Galileo和BeiDou四大系统的Fix数据。

2.2 GNSSLogger Fix行的Provider字段含义

Fix行中的第2列是Provider,它直接对应Android定位框架中的定位提供者:

Provider全称Android对应API数据来源
GPSGNSS Location ProviderLocationManager.GPS_PROVIDER纯GNSS卫星定位
NLPNetwork Location ProviderLocationManager.NETWORK_PROVIDER基站三角定位 + Wi-Fi定位
FLPFused Location ProviderFusedLocationProviderClientGPS + NLP + 传感器多源融合

论文中的关键结论:融合系统(FLP)的稳定性、刚性和精度远优于单一GNSS系统(GPS)。因此在实际应用中,如果没有特殊限制,应优先使用FLP数据。

三、MATLAB代码详解:从原始日志到结构化数据

3.1 步骤1:读取日志文件并筛选Fix行

GNSSLogger的输出文件是混合了多种数据类型的文本文件。我们的第一步是将所有以Fix开头的行筛选出来,单独保存到一个新文件中。

%% ==================== 步骤1:筛选Fix行 ====================% 打开原始GNSSLogger日志文件(只读模式)fid=fopen('gnss_log_2023_03_08_19_48_23.txt','r');% 创建一个新文件用于存储筛选出的Fix数据out_fid=fopen('fix_data2.txt','w');% 逐行读取tline=fgetl(fid);whileischar(tline)% 当读取到文件末尾时,tline变为-1% strncmp比较前3个字符是否为'Fix',匹配则写入新文件ifstrncmp(tline,'Fix',3)==1fprintf(out_fid,'%s\n',tline);endtline=fgetl(fid);end% 关闭所有文件句柄fclose(fid);fclose(out_fid);disp('Fix行筛选完成!结果已保存至 fix_data2.txt');

代码解析

  • strncmp(tline, 'Fix', 3):只比较前3个字符,避免误匹配如"Fixed"等其他词
  • 为什么单独写一个新文件?——便于后续调试和重复使用,避免反复读取大文件
  • 如果原始日志文件很大(几百MB),这个循环可能较慢。优化方案见后文"工程化建议"

3.2 步骤2:解析Fix数据的CSV格式

Fix行是CSV(逗号分隔值)格式。我们使用MATLAB的textscan函数进行解析:

%% ==================== 步骤2:解析Fix数据 ====================filename='fix_data2.txt';delimiter=',';% 分隔符为逗号% 格式说明符:14个字段,类型依次为 字符串,字符串,浮点数×12formatSpec='%s%s%f%f%f%f%f%f%f%f%f%f%f%f';fileID=fopen(filename,'r');dataArray=textscan(fileID,formatSpec,'Delimiter',delimiter,...'EmptyValue',NaN,'ReturnOnError',false);fclose(fileID);disp('Fix数据解析完成!');

Fix行的17个字段说明(为什么代码中只读取了14个?):

  • 不同的Android版本和GNSSLogger版本,Fix行的列数可能略有不同
  • 论文代码读取了前14列,包含了最核心的字段:
    • 列1:Fix(固定标识)
    • 列2:Provider(定位提供者)
    • 列3:Lat(纬度)
    • 列4:Lon(经度)
    • 列5:Alt(高度)
    • 列6:Speed(速度,m/s)
    • 列7:Accuracy(精度,米)
    • 后续列:时间戳、方位角等

💡 提示:如果你的日志文件列数更多,可以扩展formatSpec或在textscan中设置'CollectOutput', true灵活处理。

3.3 步骤3:按Provider分类

这是整个数据处理中最关键的步骤。论文中将Fix数据按Provider分为三类:

%% ==================== 步骤3:按Provider分类 ====================% dataArray{2} 是第二列,即Provider字段FLP_index=strcmp(dataArray{2},'FLP');GPS_index=strcmp(dataArray{2},'GPS');NLP_index=strcmp(dataArray{2},'NLP');% 提取各类数据:[纬度, 经度, 高度, 速度, 精度]% 列索引:3=Lat, 4=Lon, 5=Alt, 6=Speed, 7=AccuracyFLP_data=[dataArray{3}(FLP_index),dataArray{4}(FLP_index),...dataArray{5}(FLP_index),dataArray{6}(FLP_index),...dataArray{7}(FLP_index)];GPS_data=[dataArray{3}(GPS_index),dataArray{4}(GPS_index),...dataArray{5}(GPS_index),dataArray{6}(GPS_index),...dataArray{7}(GPS_index)];NLP_data=[dataArray{3}(NLP_index),dataArray{4}(NLP_index),...dataArray{5}(NLP_index),dataArray{6}(NLP_index),...dataArray{7}(NLP_index)];% 显示各Provider的数据点数量fprintf('FLP数据点: %d\n',size(FLP_data,1));fprintf('GPS数据点: %d\n',size(GPS_data,1));fprintf('NLP数据点: %d\n',size(NLP_data,1));

3.4 步骤4:提取经纬度用于后续绘图

从分类数据中提取经纬度,并输出基本信息:

%% ==================== 步骤4:提取关键字段 ====================% 从FLP数据中提取经纬度和速度lat1=FLP_data(:,1);% 纬度lon1=FLP_data(:,2);% 经度t1=FLP_data(:,3);% 高度(可选)spd1=FLP_data(:,4);% 速度(m/s)% 从GPS数据中提取lat2=GPS_data(:,1);lon2=GPS_data(:,2);t2=GPS_data(:,3);spd2=GPS_data(:,4);% 打印经纬度范围,检查数据合理性fprintf('FLP 纬度范围: [%.6f, %.6f]\n',min(lat1),max(lat1));fprintf('FLP 经度范围: [%.6f, %.6f]\n',min(lon1),max(lon1));fprintf('GPS 纬度范围: [%.6f, %.6f]\n',min(lat2),max(lat2));fprintf('GPS 经度范围: [%.6f, %.6f]\n',min(lon2),max(lon2));

四、完整MATLAB代码(核心部分整合)

以下是论文中前30行代码的完整整理版本,添加了详细注释:

%% ========================================================================% 文件名:read_gnss_fix_data.m% 功能:读取GNSSLogger日志,筛选Fix行,按Provider分类提取经纬度/速度% 参考:论文 "Off-line Data Processing Based on GNSSLOGGER..."% 作者:Zixia Shang (UNSW)% 对应论文章节:第四章 B节% =========================================================================clear;clc;close all;%% -------------------- 1. 配置输入输出文件 --------------------inputFile='gnss_log_2023_03_08_19_48_23.txt';% 原始日志文件outputFile='fix_data2.txt';% 筛选后的Fix数据文件%% -------------------- 2. 筛选Fix行 --------------------fid=fopen(inputFile,'r');out_fid=fopen(outputFile,'w');tline=fgetl(fid);count=0;whileischar(tline)ifstrncmp(tline,'Fix',3)==1fprintf(out_fid,'%s\n',tline);count=count+1;endtline=fgetl(fid);endfclose(fid);fclose(out_fid);fprintf('共筛选出 %d 条Fix记录\n',count);%% -------------------- 3. 解析Fix CSV数据 --------------------delimiter=',';% 14列:Fix, Provider, Lat, Lon, Alt, Speed, Accuracy, ...formatSpec='%s%s%f%f%f%f%f%f%f%f%f%f%f%f';fileID=fopen(outputFile,'r');dataArray=textscan(fileID,formatSpec,'Delimiter',delimiter,...'EmptyValue',NaN,'ReturnOnError',false);fclose(fileID);%% -------------------- 4. 按Provider分类 --------------------% 逻辑索引idxFLP=strcmp(dataArray{2},'FLP');idxGPS=strcmp(dataArray{2},'GPS');idxNLP=strcmp(dataArray{2},'NLP');% 提取数据:[Lat, Lon, Alt, Speed, Accuracy]FLP_data=[dataArray{3}(idxFLP),dataArray{4}(idxFLP),...dataArray{5}(idxFLP),dataArray{6}(idxFLP),...dataArray{7}(idxFLP)];GPS_data=[dataArray{3}(idxGPS),dataArray{4}(idxGPS),...dataArray{5}(idxGPS),dataArray{6}(idxGPS),...dataArray{7}(idxGPS)];NLP_data=[dataArray{3}(idxNLP),dataArray{4}(idxNLP),...dataArray{5}(idxNLP),dataArray{6}(idxNLP),...dataArray{7}(idxNLP)];%% -------------------- 5. 统计与输出 --------------------fprintf('='*50);fprintf('数据统计结果:\n');fprintf('FLP: %d 个点\n',size(FLP_data,1));fprintf('GPS: %d 个点\n',size(GPS_data,1));fprintf('NLP: %d 个点\n',size(NLP_data,1));% 保存为MAT文件,便于后续处理(第四篇博客会用到)save('gnss_parsed_data.mat','FLP_data','GPS_data','NLP_data');disp('数据已保存至 gnss_parsed_data.mat');

代码运行结果示例

>> read_gnss_fix_data 共筛选出 98778 条Fix记录 数据统计结果: FLP: 11236 个点 GPS: 85342 个点 NLP: 2200 个点 数据已保存至 gnss_parsed_data.mat

五、调试与数据验证

5.1 检查数据合理性

在得到分类数据后,建议进行快速验证:

%% 快速检查:绘制经纬度散点图figure;subplot(1,2,1);plot(FLP_data(:,2),FLP_data(:,1),'r.','MarkerSize',2);hold on;plot(GPS_data(:,2),GPS_data(:,1),'b.','MarkerSize',2);legend('FLP','GPS');xlabel('经度');ylabel('纬度');title('FLP vs GPS 轨迹对比');grid on;axis equal;subplot(1,2,2);plot(NLP_data(:,2),NLP_data(:,1),'g.','MarkerSize',4);xlabel('经度');ylabel('纬度');title('NLP 轨迹(Wi-Fi/基站定位)');grid on;axis equal;

5.2 检查速度数据

速度数据可以帮助判断定位点的运动状态:

%% 检查速度分布figure;histogram(GPS_data(:,4),50,'FaceColor','b','EdgeAlpha',0.3);hold on;histogram(FLP_data(:,4),50,'FaceColor','r','EdgeAlpha',0.3);xlabel('速度 (m/s)');ylabel('频次');legend('GPS','FLP');title('速度分布对比');% 检查是否有异常值(如负速度或极大速度)fprintf('GPS速度范围: [%.2f, %.2f] m/s\n',min(GPS_data(:,4)),max(GPS_data(:,4)));fprintf('FLP速度范围: [%.2f, %.2f] m/s\n',min(FLP_data(:,4)),max(FLP_data(:,4)));

六、不同平台(Windows/macOS/Linux)下的注意事项

平台文件路径写法示例注意事项
Windows'C:\Users\name\data\gnss_log.txt'必须使用反斜杠\,或使用双反斜杠\\转义
macOS'/Users/name/data/gnss_log.txt'使用正斜杠/,注意区分大小写
Linux'/home/name/data/gnss_log.txt'使用正斜杠/,注意文件权限

跨平台兼容写法(推荐):

% 使用 fullfile 自动适配路径分隔符dataDir=fullfile('C:','Users','name','data');% Windows% dataDir = fullfile('/home', 'name', 'data'); % Linux/macOSinputFile=fullfile(dataDir,'gnss_log_2023_03_08_19_48_23.txt');

macOS/Linux用户注意:MATLAB在Unix系统下对文件权限敏感,确保日志文件具有读取权限(chmod +r gnss_log.txt)。

七、工程化建议与性能优化

7.1 函数封装

将核心逻辑封装为可复用的函数:

function[FLP,GPS,NLP]=parseGNSSFixData(inputFile,outputFile)% parseGNSSFixData 解析GNSSLogger的Fix数据% 输入:inputFile - 原始日志文件路径% outputFile - (可选) 临时文件输出路径% 输出:FLP - 融合定位数据 [Lat, Lon, Alt, Speed, Accuracy]% GPS - GNSS定位数据% NLP - 网络定位数据ifnargin<2outputFile='fix_data_temp.txt';end% ... 核心代码(见上文)...end

7.2 大文件处理优化

当日志文件超过100MB时,逐行读取可能较慢。优化方案:

% 方案1:使用 memmapfile 或 readlines (MATLAB R2020b+)lines=readlines(inputFile);fixLines=lines(startsWith(lines,'Fix'));% 方案2:使用 grep 外部命令(Linux/macOS)% system('grep "^Fix" gnss_log.txt > fix_data2.txt');

7.3 数据格式容错

不同Android版本输出的Fix行列数可能不同:

% 自动检测列数firstFixLine=fixLines(1);numCols=numel(strsplit(firstFixLine,','));ifnumCols>=14formatSpec=repmat('%f',1,numCols-2);% 动态构建格式end

八、常见问题与解决方案

问题可能原因解决方案
fopen返回 -1文件路径错误或文件不存在使用exist(inputFile, 'file')检查文件是否存在
textscan解析失败分隔符不匹配(如制表符而非逗号)检查文件编码,确认分隔符为,
strcmp分类结果全为0Provider字段拼写大小写不匹配检查日志中实际的Provider名称
GPS数据点远多于FLP设备未开启融合定位在GNSSLogger中确认“Fix”开关已开启
MATLAB报错“Out of Memory”文件过大使用readlines按块读取或使用datastore

九、下一步预告

本文是“GNSS数据采集、处理与可视化全流程”系列的第三篇。我们完成了:

  • ✅ Fix行的筛选
  • ✅ CSV格式解析
  • ✅ 按Provider分类(FLP/GPS/NLP)
  • ✅ 经纬度与速度提取

第四篇文章中,我们将使用本文提取的经纬度数据,结合MATLAB的geoshapewebmap工具,实现基于速度的分段彩色轨迹绘制,生成论文中展示的精彩地图可视化效果。

第五篇文章中,我们将深入对比单系统(GPS)与融合系统(FLP)的定位精度差异。

第六篇文章中,我们将完成全流程复盘,提供一套可直接运行的完整MATLAB脚本。

十、参考资料

  1. Zixia Shang, “Off-line Data Processing Based on GNSSLOGGER, GNSS System Positioning Data Quality and Accuracy Analysis,”Proceedings of SPIE, Vol. 12978, 2024. DOI: 10.1117/12.3019575
  2. GNSS 原始测量数据 | Android Developers
  3. LocationManager | Android Developers
  4. GPS Measurement Tools GitHub仓库
  5. 论文实验数据:https://github.com/ZixiaShang/GNSSLOGGER-Data-8

📌 系列文章索引

  • 第一篇:Android GNSS数据采集入门:GNSSLogger完整配置指南(已完成)
  • 第二篇:GNSS数据解析与质量分析:从GNSSAnalysis到MATLAB(已完成)
  • 第三篇:MATLAB读取GNSSLogger数据:Fix记录筛选与提取实战(本文)
  • 第四篇:MATLAB地理轨迹可视化:基于速度的分段彩色地图绘制(待续)
  • 第五篇:多GNSS系统定位对比:单系统与融合系统精度分析(待续)
  • 第六篇:GNSS数据处理全流程复盘:从手机到地图的完整链路(待续)