实验原理
NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式。GPS接收机根据NMEA-0183协议的标准规范,通过串口输出位置、速度等信息。随着GLONASS、北斗等卫星导航系统的逐渐成熟,NMEA-0183不再仅限于GPS设备的数据协议,而成为适用于各大卫星导航系统的标准协议。
NMEA-0183格式数据串的所有数据都采用ASCII文本字符表示,数据传输以“ ”开头,后面是语句头。语句头由五个字母组成,分为两部分:前两个字母表示“系统 I D ”,即表示该语句属于何种系统或设备,后三个字母表示“语句 I D ”,表示该语句关于何方面的数据。语句头后是数据体,包含不同的数据体字段,语句末尾为校验码(可选),以回车换行符 ‘ < C R > < L F > ‘ 结束,即 A S C I I 字符“回车”(十六进制的 0 D )和“换行”(十六进制的 0 A )。每行语句最多包含 82 个字符(包括回车换行符和 ‘ ”开头,后面是语句头。语句头由五个字母组成,分为两部分:前两个字母表示“系统ID”,即表示该语句属于何种系统或设备,后三个字母表示“语句ID”,表示该语句关于何方面的数据。语句头后是数据体,包含不同的数据体字段,语句末尾为校验码(可选),以回车换行符 `<CR><LF>` 结束,即ASCII字符“回车”(十六进制的0D)和“换行”(十六进制的0A)。每行语句最多包含82个字符(包括回车换行符和` ”开头,后面是语句头。语句头由五个字母组成,分为两部分:前两个字母表示“系统ID”,即表示该语句属于何种系统或设备,后三个字母表示“语句ID”,表示该语句关于何方面的数据。语句头后是数据体,包含不同的数据体字段,语句末尾为校验码(可选),以回车换行符‘<CR><LF>‘结束,即ASCII字符“回车”(十六进制的0D)和“换行”(十六进制的0A)。每行语句最多包含82个字符(包括回车换行符和‘`符号)。数据字段以逗号分隔识别,空字段保留逗号。以下是常用的语句类型及其包含的数据内容:
语句开头 | 数据内容 |
---|---|
$XXGGA | 全球定位数据 |
$XXGSA | 卫星PRN数据 |
$XXGSV | 卫星状态信息 |
$XXRMC | 运输定位数据 |
$XXVTG | 地面速度信息 |
$XXGLL | 大地坐标信息 |
$XXZDA | UTC时间和日期 |
其中,“XX”为系统ID,常见的系统ID有:“GP”表示GPS系统相关语句,“BD”表示北斗系统相关语句。
实验目的
- 深入理解卫星导航产品输出的NMEA0183格式电文;
- 能阅读NMEA导航电文,提取所需的定位数据。
实验内容及步骤
- 采集60秒以上NMEA数据。
- 解析GGA数据,整理为表格数据或画图(注意时间标签)。
- 解析RMC数据,整理为表格数据或画图。
- 解析GSA和GSV数据,整理为表格数据或画图(注意按卫星号分别存放)。
这是一个用MATLAB编写的解析NMEA-0183导航电文的实验程序,它可以将包含特定格式的导航数据文件解析为结构化的数据,并将数据写入Excel文件的不同工作表。以下是关于代码的一些解释和讲解:
1. 主程序 main()
主程序 main()
负责整个数据处理流程的执行,包括读取NMEA格式的数据文件、解析数据并将解析后的数据写入Excel文件。
2. 数据读取函数 readNMEA()
readNMEA()
函数用于从给定的文件名读取NMEA 0183格式的导航电文数据,并将数据存储为字符串数组。
3. 数据解析函数 parseNMEA()
parseNMEA()
函数根据语句类型解析NMEA数据,并将解析后的数据存储在结构化的数据结构中,以便后续处理和写入到Excel文件。
4. NMEA数据解析子函数
以下是各种不同类型的NMEA语句数据解析函数,每个函数用于解析特定类型的NMEA语句数据:
parseGNGGA()
: 解析GNGGA类型的数据parseGNRMC()
: 解析GNRMC类型的数据parseGNGSA()
: 解析GNGSA类型的数据parseGPGSV()
: 解析GPGSV类型的数据parseBDGSV()
: 解析BDGSV类型的数据
5. NMEA句子解析函数 parseNMEASentence()
parseNMEASentence()
函数将单个NMEA句子解析为结构化的数据,根据提供的字段名称,将每个字段的数据存储在一个结构体中。
6. 数据写入Excel函数 writeDataToExcel()
writeDataToExcel()
函数负责将解析后的数据按照指定的工作表顺序写入到Excel文件中,每个工作表对应一个特定类型的数据,数据以表格形式存储。
7. 实验步骤描述
实验步骤包括:
- 采集NMEA数据
- 解析GGA、RMC、GSA和GSV数据
- 将解析后的数据整理为表格数据或图表。
function main()
% 文件名
filename = 'data.txt';
%%filename='你的NMEA.txt文件的路径,你也可以把NEMA文件和这个.m文件放在一起,就如上图所示';
% 读取NMEA 0183格式的电文
data = readNMEA(filename);
% 解析NMEA数据
parsedData = parseNMEA(data);
% 将解析后的数据写入Excel文件
outputExcelFile = 'parsed_data.xlsx';
% 指定工作表顺序
sheetsOrder = {'GGA', 'RMC', 'GSA', 'GSV', 'GNGGA', 'GNGSA', 'GPGSV', 'BDGSV', 'GNRMC'};
writeDataToExcel(parsedData, outputExcelFile, sheetsOrder);
disp(['数据已成功解析并按指定顺序写入到 Excel 文件: ' outputExcelFile]);
end
function data = readNMEA(filename)
% 读取NMEA 0183格式的电文
fid = fopen(filename, 'r');
if fid == -1
error('无法打开文件');
end
% 逐行读取电文数据
data = textscan(fid, '%s', 'Delimiter', '\n', 'Whitespace', '');
data = data{1}; % 将数据转换为字符串数组
fclose(fid); % 关闭文件
end
function parsedData = parseNMEA(data)
% 初始化解析后的数据结构
parsedData.GNGGA = [];
parsedData.GNGSA = [];
parsedData.GPGSV = [];
parsedData.BDGSV = [];
parsedData.GNRMC = [];
parsedData.GGA = [];
parsedData.RMC = [];
parsedData.GSA = [];
parsedData.GSV = [];
% 遍历每行NMEA数据
for i = 1:numel(data)
sentence = data{i};
if startsWith(sentence, '$GNGGA')
parsedData.GNGGA = [parsedData.GNGGA; parseGNGGA(sentence)];
elseif startsWith(sentence, '$GNGSA')
parsedData.GNGSA = [parsedData.GNGSA; parseGNGSA(sentence)];
elseif startsWith(sentence, '$GPGSV')
parsedData.GPGSV = [parsedData.GPGSV; parseGPGSV(sentence)];
elseif startsWith(sentence, '$BDGSV')
parsedData.BDGSV = [parsedData.BDGSV; parseBDGSV(sentence)];
elseif startsWith(sentence, '$GNRMC')
parsedData.GNRMC = [parsedData.GNRMC; parseGNRMC(sentence)];
elseif startsWith(sentence, '$GGA')
parsedData.GGA = [parsedData.GGA; parseGNGGA(sentence)]; % 使用相同的解析函数
elseif startsWith(sentence, '$RMC')
parsedData.RMC = [parsedData.RMC; parseGNRMC(sentence)]; % 使用相同的解析函数
elseif startsWith(sentence, '$GSA')
parsedData.GSA = [parsedData.GSA; parseGNGSA(sentence)]; % 使用相同的解析函数
elseif startsWith(sentence, '$GSV')
parsedData.GSV = [parsedData.GSV; parseGPGSV(sentence)]; % 使用相同的解析函数
end
end
end
function gnggaData = parseGNGGA(sentence)
% 解析GNGGA数据
gnggaData = parseNMEASentence(sentence, ...
{'UTC', 'Latitude', 'LatitudeDirection', 'Longitude', 'LongitudeDirection', ...
'FixQuality', 'NumSatellites', 'HDOP', 'Altitude', 'HeightOfGeoid'});
end
function gnrmcData = parseGNRMC(sentence)
% 解析GNRMC数据
gnrmcData = parseNMEASentence(sentence, ...
{'UTC', 'Status', 'Latitude', 'LatitudeDirection', 'Longitude', 'LongitudeDirection', ...
'Speed', 'Course', 'Date', 'MagneticVariation'});
end
function gngsaData = parseGNGSA(sentence)
% 解析GNGSA数据
gngsaData = parseNMEASentence(sentence, ...
{'Mode', 'FixType', 'PRNs', 'PDOP', 'HDOP', 'VDOP'});
end
function gpgsvData = parseGPGSV(sentence)
% 解析GPGSV数据
gpgsvData = parseNMEASentence(sentence, ...
{'TotalSentences', 'SentenceNumber', 'TotalSatellites', 'Satellites'});
end
function bdgsvData = parseBDGSV(sentence)
% 解析BDGSV数据
bdgsvData = parseNMEASentence(sentence, ...
{'TotalSentences', 'SentenceNumber', 'TotalSatellites', 'Satellites'});
end
function parsedData = parseNMEASentence(sentence, fieldNames)
% 将NMEA句子解析为数据结构
parts = strsplit(sentence, ',');
parsedData = struct();
for i = 1:numel(fieldNames)
fieldName = fieldNames{i};
if i <= numel(parts)
parsedData.(fieldName) = strtrim(parts{i});
else
parsedData.(fieldName) = [];
end
end
end
function writeDataToExcel(parsedData, filename, sheetsOrder)
% 创建一个新的Excel文件
[~, sheetsIdx] = ismember(sheetsOrder, fieldnames(parsedData));
% 按指定顺序写入Excel文件
for s = 1:numel(sheetsOrder)
sheetName = sheetsOrder{s};
data = parsedData.(sheetName);
if ~isempty(data)
% 创建表格
T = struct2table(data);
% 写入Excel文件
if s == 1
writetable(T, filename, 'Sheet', sheetName);
else
writetable(T, filename, 'Sheet', sheetName, 'WriteMode', 'append');
end
end
end
end
8. 实验报告内容
实验报告应包括实验目的、实验流程图、实验过程描述、实验运行结果和实验代码。
该MATLAB代码实现了从NMEA 0183数据文件中解析导航电文数据,并将解析后的数据按照指定顺序写入Excel文件。通过该程序,您可以深入理解和处理卫星导航设备输出的NMEA格式数据。