ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

文件读写以及NMEA码中GPS信息的提取

2019-05-29 18:47:47  阅读:266  来源: 互联网

标签:buff read 码中 GPGSV location line GPS NMEA gps


首先先了解下什么是NMEA码,这里有很好的解释,就不直接搬运了

http://www.gpsbaby.com/wz/nmea.html

首先要找到包含GPS信息的文本行,即字符串GPGGA所在行

$GPGGA,052551.00,3409.341502,N,10853.663318,E,1,05,1.2,459.4,M,-28.0,M,,*4E

在实际的工程应用中,可能由于各种原因(比如设备在室内时就无法获取GPS信息),GPS信息并不是实时都可以获取准确的完整的值,因此在GPS.log文件内,会存在一些不完整的GPS信息。

$GPGGA,,,,,,0,,,,,,,,*66  //这是我在室内定位的GPS信息

所以要确定一个文本行确实存在完整的GPS信息,必须确认GPGGA, N/S, W/E 三个字符串均存在。然后再定位纬度所在位置,提取数值即可。

实现代码如下

#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<memory.h>
#include<stdlib.h>
#include<string.h>

#define FILE_PATH "/home/mr_han/code/exp/GPS.log"
#define READ_MAX 150
#define GPS_DATA 15
#define GPS_KEY "GPGGA"
#define bool char
#define true 1
#define false 0
void gps_cal(double p, char q, int *angle, float *min)//将原始GPS信息转换为度分形式
{
	*angle = p/100;		
	*min = (p-*angle*100)/60;

}
int Search_comma(char *p, int L)//由GPGGA纬度字段前的逗号即可找到得到纬度GPS信息
{
	while(p[L-1]!=',')
	{
		--L;
	}
	return L;
}
/*从文件中c查找完整GPS信息,参数依次为, 文件路径(名),纬度值,经度值, 经度,纬度*/
bool get_gps_data(const char *file_name, double *p, double *q, char *longitude, char *latitude)
{
	char *rw = NULL;
	int location = 0, i = 0, N=0,S=0,E=0,W=0;
	char read_line_buff[READ_MAX], gps[GPS_DATA];
	memset(gps, 0, GPS_DATA);
	FILE *fd = fopen(FILE_PATH, "r");
	if(fd == NULL)
	{
		printf("Open file error!\n");
		return false;
	}
	while(!feof(fd))
	{
		memset(read_line_buff, 0, READ_MAX);
		rw = fgets(read_line_buff, READ_MAX, fd);//每次从文件读取一行,
		if(rw == NULL)
			return false;
		if(strstr(read_line_buff, GPS_KEY)!=NULL)
		{

			N = (strchr(read_line_buff,'N')==NULL ? 0 : 1);
			S = (strchr(read_line_buff, 'S')==NULL ? 0 : 2);
			E = (strchr(read_line_buff, 'E')==NULL ? 0 : 4);
			W = (strchr(read_line_buff, 'W')==NULL ? 0 : 7);/
			i = N+S+E+W;
			/*完整的GPS,信息只可能存在 NE东经北纬、NW西经北纬、SE东经南纬、SW西经南纬,分别给四种组合不同的权值,用以确定是那种情况*/
			switch(i)//这里case可以调用函数用来代替goto语句
			{
				case 5: 
					*longitude = 'E';
					*latitude = 'N';
					i = 0;
					fclose(fd);
					goto NE;
				case 6: 
					*longitude = 'E';
					*latitude = 'S';
					i = 0;
					fclose(fd);
					goto SE;
				case 8: 
					*longitude = 'W';
					*latitude = 'N';
					i = 0;
					fclose(fd);
					goto NW;
				case 9: 
					*longitude = 'W';
					*latitude = 'S';
					i = 0;
					fclose(fd);
					goto SW;
				default: continue;
			}
		}
	}
NE:
	rw = strchr(read_line_buff, 'N');//strchr函数会在第一个参数字符串内找第二个参数字符,找到返回一个地址,找不到返回空
	location = rw - read_line_buff - 1;	//地址相减,得到数字,这一步主要是定位到纬度前的逗号,$GPGGA,052551.00,3409.341502,N location即N前的逗号
	location = Search_comma(read_line_buff,location);	//再向前定位上一个逗号即可找到GPS信息
	while(read_line_buff[location+1] != 'N')
		gps[i++] = read_line_buff[location++];
	*p = atof(gps);
	memset(gps, 0, GPS_DATA);
	i = 0;
	location = location+3;//3409.341502,N,10853.663318,E,纬度赋值完成后,location在N前逗号出,只需向后跳三位即可找到经度信息
	while(read_line_buff[location+1] != 'E')
		gps[i++] = read_line_buff[location++];
	*q = atof(gps);
	return true;

SE:
	rw = strchr(read_line_buff, 'S');
	location = rw - read_line_buff - 1;
	location = Search_comma(read_line_buff, location);	
	while(read_line_buff[location+1] != 'S')
		gps[i++] = read_line_buff[location++];
	*p = atof(gps);
	memset(gps, 0, GPS_DATA);
	i = 0;
	location = location + 3;
	while(read_line_buff[location+1] != 'E')
		gps[i++] = read_line_buff[location++];
	*q = atof(gps);
	return true;
NW:
	rw = strchr(read_line_buff, 'N');
	location = rw - read_line_buff - 1;
	location = Search_comma(read_line_buff, location);	
	while(read_line_buff[location+1] != 'N')
		gps[i++] = read_line_buff[location++];
	*p = atof(gps);
	memset(gps, 0, GPS_DATA);
	i = 0;
	location =location + 3;
	while(read_line_buff[location+1] != 'W')
		gps[i++] = read_line_buff[location++];
	*q = atof(gps);
	return true;
SW:
	rw = strchr(read_line_buff, 'S');
	location = rw - read_line_buff - 1;		
	location = Search_comma(read_line_buff, location);
	while(read_line_buff[location+1] != 'S')
		gps[i++] = read_line_buff[location++];
	*p = atof(gps);//atof函数可将字符串转为double后返回,转换失败返回0
	memset(gps, 0, GPS_DATA);
	i = 0;
	location =location + 3;
	while(read_line_buff[location+1] != 'W')
		gps[i++] = read_line_buff[location++];
	*q = atof(gps);
	return true;

}
char *print(char p)
{
	switch(p)
	{
		case 'S':return "南纬";
		case 's':return "南纬";
		case 'N':return "北纬";
		case 'n':return "北纬";
		case 'W':return "东经";
		case 'w':return "东经";
		case 'E':return "西经";
		case 'e':return "西经";
		default: return "经纬错误";
	}
}
int main()
{
	int angle=0;
	float min=0;
	char longitude=0, latitude=0;
	double gps_g=0, gps_i=0;//gps_g经度 gps_i纬度
	get_gps_data(FILE_PATH, &gps_i, &gps_g, &longitude, &latitude);
	printf("gps: %lf %c, %lf %c\n",gps_i, latitude, gps_g, longitude);

	/*gps_cal(gps_g, longitude, &angle, &min);
	printf("%s %d度%f分", print(longitude), angle, min);
	gps_cal(gps_i, latitude, &angle, &min);
	printf("	%s %d度%f分\n", print(latitude), angle, min);*/
	gps_cal(gps_i, latitude, &angle, &min);
	printf("%s %d度%f分", print(latitude), angle, min);
	gps_cal(gps_g, longitude, &angle, &min);
	printf("	%s %d度%f分\n", print(longitude), angle, min);
	return 0;
}

  效果如下

 

附测试用的GPS.log文件部分信息

$GPVTG,,T,,M,,N,,K,N*2C
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGGA,,,,,,0,,,,,,,,*66
$GPRMC,,V,,,,,,,,,,N*53
$GPGSV,3,1,10,10,49,322,50,12,15,119,40,20,78,352,49,25,09,151,39*7F
$GPGSV,3,2,10,32,28,272,48,14,13,260,,15,25,063,,21,41,203,*7B
$GPGSV,3,3,10,24,51,053,,27,,,*49
$GPVTG,,T,,M,,N,,K,N*2C
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGGA,,,,,,0,,,,,,,,*66
$GPRMC,,V,,,,,,,,,,N*53
$GPGSV,3,1,11,10,49,322,51,12,15,119,40,20,78,352,49,25,09,151,38*7E
$GPGSV,3,2,11,32,28,272,47,14,13,260,,15,25,063,,21,41,203,*75
$GPGSV,3,3,11,24,51,053,,27,,,,40,,,36*49
$GPGGA,052550.00,3409.338831,N,10853.658643,E,1,04,1.4,467.2,M,-28.0,M,,*43
$GPVTG,1.5,T,4.6,M,0.3,N,0.6,K,A*20
$GPRMC,052550.00,A,3409.338831,N,10853.658643,E,0.3,1.5,121218,3.1,W,A*25
$GPGSA,A,2,10,12,20,32,,,,,,,,,1.6,1.4,0.9*39
$GPGSV,3,1,11,10,49,322,51,12,15,119,40,14,13,260,29,15,25,063,30*77
$GPGSV,3,2,11,20,78,352,49,21,41,203,22,24,51,053,33,25,09,151,39*7E
$GPGSV,3,3,11,32,28,272,47,27,,,,40,,,38*4C
$GPGGA,052551.00,3409.341502,N,10853.663318,E,1,05,1.2,459.4,M,-28.0,M,,*4E
$GPVTG,1.5,T,4.6,M,0.0,N,0.0,K,A*25
$GPRMC,052551.00,A,3409.341502,N,10853.663318,E,0.0,1.5,121218,3.1,W,A*27
$GPGSA,A,2,10,12,20,24,32,,,,,,,,1.4,1.2,0.8*3A
$GPGSV,3,1,11,10,49,322,51,12,15,119,40,14,13,260,30,15,25,063,30*7F
$GPGSV,3,2,11,20,78,352,49,21,41,203,22,24,51,053,33,25,09,151,39*7E
$GPGSV,3,3,11,32,28,272,47,27,,,,40,,,38*4C
$GPGGA,052552.00,3409.340891,N,10853.662052,E,1,05,1.2,462.9,M,-28.0,M,,*42
$GPVTG,1.5,T,4.6,M,0.0,N,0.0,K,A*25
$GPRMC,052552.00,A,3409.340891,N,10853.662052,E,0.0,1.5,121218,3.1,W,A*2E
$GPGSA,A,2,10,12,20,24,32,,,,,,,,1.4,1.2,0.8*3A
$GPGSV,3,1,11,10,49,322,51,12,15,119,40,14,13,260,30,15,25,063,27*79
$GPGSV,3,2,11,20,78,352,49,21,41,203,20,24,51,053,31,25,09,151,39*7E
$GPGSV,3,3,11,32,28,272,47,27,,,,40,,,38*4C
$GPGGA,052553.00,3409.340173,N,10853.661041,E,1,05,1.2,465.3,M,-28.0,M,,*4A
$GPVTG,1.5,T,4.6,M,0.0,N,0.0,K,A*25
$GPRMC,052553.00,A,3409.340173,N,10853.661041,E,0.0,1.5,121218,3.1,W,A*2B
$GPGSA,A,2,10,12,20,24,32,,,,,,,,1.4,1.2,0.8*3A
$GPGSV,3,1,11,10,49,322,50,12,15,119,41,14,13,260,30,15,25,063,27*79
$GPGSV,3,2,11,20,78,352,49,21,41,203,20,24,51,053,32,25,09,151,39*7D
$GPGSV,3,3,11,32,28,272,46,27,,,,40,,,39*4C
$GPGGA,052554.00,3409.339925,N,10853.660214,E,1,05,1.2,466.6,M,-28.0,M,,*4D
$GPVTG,1.5,T,4.6,M,0.0,N,0.0,K,A*25
$GPRMC,052554.00,A,3409.339925,N,10853.660214,E,0.0,1.5,121218,3.1,W,A*2A
$GPGSA,A,2,10,12,20,24,32,,,,,,,,1.4,1.2,0.8*3A
$GPGSV,3,1,11,10,49,322,51,12,15,119,40,14,13,260,31,15,25,063,28*77
$GPGSV,3,2,11,20,78,352,49,21,41,203,21,24,51,053,32,25,09,151,39*7C
$GPGSV,3,3,11,32,28,272,46,27,,,,40,,,39*4C
$GPGGA,052555.00,3409.340026,N,10853.659458,E,1,05,1.2,466.2,M,-28.0,M,,*48
$GPVTG,1.5,T,4.6,M,0.0,N,0.0,K,A*25
$GPRMC,052555.00,A,3409.340026,N,10853.659458,E,0.0,1.5,121218,3.1,W,A*2B
$GPGSA,A,2,10,12,20,24,32,,,,,,,,1.4,1.2,0.8*3A
$GPGSV,3,1,11,10,49,322,51,12,15,119,40,14,13,260,30,15,25,063,28*76
$GPGSV,3,2,11,20,78,352,49,21,41,203,22,24,51,053,32,25,09,151,39*7F
$GPGSV,3,3,11,32,28,272,46,27,,,,40,,,39*4C
$GPGGA,052556.00,3409.339490,N,10853.658951,E,1,05,1.2,465.8,M,-28.0,M,,*40
$GPVTG,1.5,T,4.6,M,0.0,N,0.0,K,A*25

 

标签:buff,read,码中,GPGSV,location,line,GPS,NMEA,gps
来源: https://www.cnblogs.com/area-h-p/p/10940854.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有