分享
 
 
 

设计文档: GPS应用开发

王朝other·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

设计文档: GPS应用开发by vcbear

关键字:

GPS:Global Position System, 全球定位系统

NMEA:National Marine Electronics Association 全国海洋电子协会

SiFR:u-blox公司的GPS模块二进制数据协议

WGS 84:World Geodetic System 1984

LLA: Longitude/Latitude/Altitude经纬度和海拔

简述:

本文介绍采用GPS接受模块,GIS控件开发GPS/GIS应用软件的一些要点。不涉及复杂的地理信息理论,主要是针对协议和接口的应用开发

一:GPS 模块应用

GPS(全球定位系统)接受硬件上已经模块化,这里主要基于我使用过的u-blox TIM GPS(以下简称TimGPS)来介绍。

TimGPS模块如图(几乎是1:1比例):

此模块提供和GPS卫星通信的功能,对外提供FFC20接口,可以给它增加电源,接口板,串口模块,使之可以通过串口和计算机连接。

如何开发串口程序在本文中不再介绍,无论在windows/linux下开发串口串口程序都是很简单的事情。

TimGPS对外提供标准NMEA协议和厂家自己的SiRF二进制协议。

1.1 NMEA(National Marine Electronics Association) 0183协议

NMEA 0183是一种航海、海运方面有关于数字信号传递的标准,此标准定义了电子信号所需要的传输协议,传输数据时间。这个协议是文本格式的。大致如下

Start Sequence

Payload

Checksum

End Sequence

消息头

消息体,具体数据和NMEA消息字相关,数据之间用逗号(,)间隔。

2243.4976,N,11414.7289,E,091828.819,A

校验码,格式为*[16进制数]如*2C

回车换行

<CR> <LF>4

协议头,格式为输出:$GPxxx,xxx为输出消息字如GLL.输入:$PSRF<MID>MID为输入消息字.

1.1.1NMEA协议输出和输入消息NMEA协议有以下输出消息

消息字

内容

GGA

时间,位置,定位数据

GLL

经纬度,UTC格式时间,位置和状态数据

GSA

接收机模式和卫星工作数据,包括位置和水平/竖直稀释精度等。稀释精度(Dilution of Precision)是个地理定位术语.一个接收器可以在同一时间得到许多颗卫星定位信息,但在精密定位上,只要四颗卫星讯号即已足够了

GSV

接收机能接收到的卫星信息,包括卫星ID,海拔,方位角,信噪比等

MSS

信号比(SNR),信号强度,频率,比特率

RMC

日期,时间,位置,方向,速度数据。是最常用的一个消息

VTG

相对地面的方向和速度数据

ZDA

时间和日期数据。

和地理信息密切的相关的消息如下,各消息之间包含的信息字段有出入也有重复,在一轮消息循环里,各消息相同的字段中包含相同的地理数据。可以综合多个消息,来获取完整的数据。

日期

时间

纬度

经度

海拔

定位状态

卫星数

地面速度

方向角

GGA

GLL

RMC

VTG

ZDA

以下为u-lox厂商扩充的输出消息

PSRF150

OK-to-send指令,在节电模式中表示进入工作状态

PSRF161

硬件状态报告

工作在NMEA模式时,TimGPS可以有以下输入消息.输入消息一般是用于控制GPS的运行的。

消息字

内容

100

设置串口参数和协议

101

XYZ导航坐标初始化。输入参数按 WGS84坐标系确定

102

设置DGPS端口

103

设置或查询数据输出频率。可以设置每个NMEA消息的是否输出和输出频率

104

输入当前经纬度和海拔来初始化模块

105

开发调试数据开关

106

(u-blox)可以改变大地基准坐标系,默认是WGS-84坐标系

107

(u-blox)配置节电模式

108

(u-blox)进入下载模式,更新Flash

MSK

设置MSK信号接收机参数

每个协议的具体格式,可以到网上下载具体的NMEA协议。

1.1.2 NMEA消息的接收和解析当接收机工作在NMEA协议时,以一定的速率向外输出数据。如

$GPGGA,140144.000,2232.2513,N,11401.6763,E,1,04,,20.3,M,,M,,0000*58

$GPGLL,2232.2513,N,11401.6763,E,140144.000,A*35

$GPRMC,140144.000,A,2232.2513,N,11401.6763,E,9.17,,140703,,*12

$GPVTG,,T,,M,9.17,N,17.0,K*47

$GPGGA,140148.000,2232.2654,N,11401.6738,E,1,04,,36.1,M,,M,,0000*5F

$GPGLL,2232.2654,N,11401.6738,E,140148.000,A*37

$GPRMC,140148.000,A,2232.2654,N,11401.6738,E,12.95,,140703,,*20

$GPVTG,,T,,M,12.95,N,24.0,K*77

最好将所有的消息输出速率设置为相同的(使用输入指令103),或者根据具体情况打开或关闭一些不不需要的消息。

消息里各字段的格式都不复杂,以下几个稍微注意:

l 经纬度的表示法为ddmm.mmmm和方向指示,以纬度举例:当纬度为9730.765,方向指示为N,则表示为北半球的97度30.765分.有的地理信息组件使用经纬度的时候不用度分秒表示法,而是用浮点数表示法,那么97度30.765分就约等于97.5(97+30.765/60)度。

l 方向角以正北向为0度,正东向为90度,也就是顺时针方向从0度增加到359度

l 校验码为一个消息包(包括消息头和体)里每个ASCII字符的值依次进行异或得到,算法(c++代码)如下

unsigned char CheckSum(string s)

{

unsigned char c = 0;

for(int o=1;o<s.size();o++)

{

unsigned char h = s[o];

c ^= h;

}

return c;

}

sprintf(StrCheckSum,"*%02X",CheckSum(data) );

一般的地理数据,只取RMC消息包就够了,如果还需要其他的数据,比如当前卫星数,卫星状态等等,又或者接受机本身关闭了RMC消息包,只输出其他的消息包,那么就需要解析其他消息包。

应用程序逐行分析消息包。我的做法是先将消息包按逗号分割原则解析成一个字符数组,然后根据包头指令字,按协议含义取数组里的字符串。

ParseMessage(sMessage,Array)); //将一行消息解析到字符串数组Array里

if (Array[0].CompareTo("$GPRMC") ==0 ) //是RMC消息

{

if(Array.size()!=12) //要求有12个字段

return -1;

//以下依次填充RMC数据结构

recRMC Rmc

Rmc.UTCTime = Array[1];

Rmc.Status = Str2Char(Array[2]);

Rmc.Latitude = Array[3];

Rmc.Latitude.DirIndicator = Str2Char(Array[4]);

Rmc.Longitude = Array[5];

Rmc.Longitude.DirIndicator = Str2Char(Array[6]);

Rmc.SpeedOverGround = Str2Num(Array[7]);

Rmc.CourseOverGround = Str2Num(Array[8]);

Rmc.Date = Array[9];

Rmc.Magnetic[0] = Str2Char(Array[10]);

Rmc.Checksum = (int)Str2Hex(Array[11]);

//检查CheckSum,

return CheckSum(Rmc.CheckSum,sMessage);

}

以类似的方法构造解析其他消息的函数。组消息包则是依次将字段转成字符串连接起来,最后附加校验码即可。

1.2 SiFR协议.SiFR协议是GPS模块厂商制定的二进制协议,提供了对GPS模块操作的更多接口,厂家号称此协议(用于操作本家的模块)更稳定,更高效,更容易操作。

1.2.1协议格式消息头

消息体长度

消息体

校验码

消息结束符

双字节

0xA0

0xA2

双字节

长度小于1023字节的数据

双字节

双字节

0xB0

0xB3

具体消息格式可以参考厂家提供的协议文档(GPS.G2-X-01003-E.pdf)。

1.2.2 日志操作SiFR包括了读取地理数据,刷写Flash,配置GPS模块参数,读取/擦写日志等一系列的操作。以日志操作最为有用。TimGPS可以脱离计算机运行,将所到之处的地理信息保存在内部存储器里,然后再接上计算机,获取地理信息日志,得到携带该GPS的载体在一段时间里运行轨迹。

读取Log的大致过程是 :

读取Log Sector信息,得到最小Sector号和最大Sector号,依次发指令读取每个Sector的Log信息,并解析转换成NMEA协议消息。

擦除Log时,虽然u-blox提供了全部擦除指令,实际应用的时候发现该指令成功率不高。还是依次发指令逐个擦除比较好。

TimGPS的log格式定义在厂家提供的TIM_Data_Logger_Manual(GPS.G2-SW-02015).pdf里。

日志中包含的消息如下

消息号

消息名

字节数

内容

111

NONE

1

无数据

100

FIX_FULL

9

全部地理定位信息

100

FIX_INCL

5

地理定位信息,增量数据

000

FIX_INCM

4

地理定位信息,增量数据, 在字节上比FIX_INCL少一个

110

FIX_INCS

3

地理定位信息,增量数据,使用更少的字节数

101

GPIO_FULL

3

GPIO( General-purpose_input/output)数据

011

GPIO_INC

2

GPIO数据,增量数据

001

ESCAPE

不定

用于扩展

以上所有消息都是二进制编码,按位存储,解析消息需要使用二进制位操作。

消息解析成功后,u-blox建议按以下逻辑处理这些消息

WHILE (Data) --读入新数据

--获取消息类型,并根据消息类型得到对应消息的字节数

IF (Type = EMPTY) THEN -- 空数据,跳过

ELSE IF (Type = FIX_FULL) THEN - 保存时间信息,保存位置,速度和其他模式信息

ELSE IF ((Type = FIX_INCL) OR (Type = FIX_INCM) OR (Type = FIX_INCS)) THEN

-- 将时间和位置增量数据叠加到最近一个定位记录上,保存速度数据

ELSE IF (Type = GPIO_FULL) THEN -- 保存时间和GPIO数据

ELSE IF (Type = GPIO_INC) THEN -- 叠加时间到最近一个GPIO数据的时间字段上,保存GPIO数据

ELSE IF (Type = ESCAPE) THEN --处理自定义数据

-- END IF

END WHILE

1.2.3WGS84->LLA转换问题在分析其日志的过程中,遇到一个问题,就是TimGPS二进制日志保存的坐标数据是以WGS84大地坐标系为准的,大地坐标系的XYZ轴如下:

要得到经纬度和海拔(LLA:Longitude/Latitude/Altitude)坐标,需要一些椭球体、基准面及地图投影的知识。

后来从网上找到一个Fortune77写的WGS84->GLL换算函数,将其转成C/C++的函数:

void wgsxyz2lla(double x,double y,double z,double *lat,double *lon,double *alt)

{

double pi = 3.14159265357;

longA_EARTH = 6378137;

double flattening = 1/298.257223563;

double NAV_E2 = (2-flattening)*flattening; // also e^2

double rad2deg = 180/pi;

double wlon,wlat,walt,rhosqrd,rho,templat,tempalt,rhoerror,zerror;

double slat,clat,q,r_n,drdl,invdet,aa,bb,cc,dd;

if ((x == 0.0) & (y == 0.0))

wlon = 0.0;

else

wlon = atan2(y, x)*rad2deg;

if ((x == 0.0) & (y == 0.0) & (z == 0.0))

{

printf("WGS xyz at center of earth");

wlon = 360;

wlat = 360;

walt = 6378137;

}

else

{

rhosqrd = x*x + y*y;

rho = sqrt(rhosqrd);

templat = atan2(z, rho);

tempalt = sqrt(rhosqrd + z*z) - A_EARTH;

rhoerror = 1000.0;

zerror = 1000.0;

while ((Dabs(rhoerror) > 1e-6) | (Dabs(zerror) > 1e-6))

{

slat = sin(templat);

clat = cos(templat);

q = 1 - NAV_E2*slat*slat;

r_n = A_EARTH/sqrt(q);

drdl = r_n*NAV_E2*slat*clat/q; // d(r_n)/d(latitutde)

rhoerror = (r_n + tempalt)*clat - rho;

zerror = (r_n*(1 - NAV_E2) + tempalt)*slat - z;

aa = drdl*clat - (r_n + tempalt)*slat;

bb = clat;

cc = (1 - NAV_E2)*(drdl*slat + r_n*clat);

dd = slat;

invdet = 1.0/(aa*dd - bb*cc);

templat = templat - invdet*(+dd*rhoerror -bb*zerror);

tempalt = tempalt - invdet*(-cc*rhoerror +aa*zerror);

}

wlat = templat*rad2deg;

walt = tempalt;

}

if(lon )*lon = wlon;

if(lat )*lat = wlat;

if(alt )*alt = walt;

}

结语:开发GPS应用软件的要点在于理解相关的协议和接口,仔细处理协议字段。

《基础GIS系统应用开发》 Comming soon....

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有