首页  编辑  

GPS数据格式

Tags: /超级猛料/Hardware.硬件相关/其它硬件/   Date Created:

GPS 数据格式

GPS 抖动检测:

关于车辆管理的软件。发现当车辆静止时,GPS接收器收到的数据、方向、速度都在不停的跳动,从而造成车子停止时,车子在地图上不停的乱跳的现象。

GPS 最后的 *后面的两个字符为校验和,其计算方式为从$到*之间所有字符的XOR值(不包括$和*):

function Checksum(const s: string): string;

var

 sum: Byte;

 i : Integer;

begin

 sum := Ord(s[2]);

 for i := 3 to Length(s) - 1 do

   sum := sum xor ord(s[i]);

 Result := IntToHex(sum, 2);

end;

function Test(): string;

begin

 //$GPGGA,041147.000,2214.6493,N,11334.9579,E,1,07,1.0,7.8,M,-3.8,M,,0000*4F

 Result := Checksum('$GPGGA,041147.000,2214.6493,N,11334.9579,E,1,07,1.0,7.8,M,-3.8,M,,0000*');

end;

这里谈一些解决方法或这方面的资料。

普通GPS误差+/-10m,不乱跑是不正常的

一般的解决办法是读NMEA数据中的速度值为零时,就不去更新地图上的经纬度。如果你的速度和经纬度都是在不断地微动(早期的SurF板就一直解决不了这个问题),那就没办法了。

几个老问题,硬件的因素不好控制,目前还是软件判断做补救工作:

1.检测到的状态为静止时,强制速度为0;

2.速度为0时,强制方向为0;

3.至于漂移问题,可以通过比较上次定位数据的经纬度差的绝对值(同时包括时间)来判定;

至于纯硬件问题,有的模块漂移100m都是可能的

要解决得硬件配合

1、若有行车记录仪检测到车速就能精确解决;

2、或者当车熄火时,硬件定位仪应能检测的到,根据熄火状态去漂移

就目前来看,静态漂移很难完全避免

从硬件的角度,选择好的接收板;从软件的角度,单纯从速度、位置的瞬时值肯定很不好判断。GPS每秒更新数据,而物体的运动轨迹一般是连续的而不是杂乱无章的,状态的变化一般是渐渐的,而不是突变。可以考虑连续的几个瞬时值的变化过程。

建议从以下两个方面综合判断

1.方向的变化:

     方向变化过于频繁,一会左转一会右转,一会向东,一会向西,基本上是漂移。     正常行驶很少见方向频繁的不连续变化的。

2.位置的变化

     在1秒之内,两个位置之间的距离达到50米以上(180KM/H),对于汽车和轮船基本上有问题,当然,飞机除外。

如果是车载,可以根据速度判断,静态漂移速度值一般不会大于5km/h。

从硬件的角度看,有的gps模块是可以判断是否是在静漂状态的

目前,如果卫星漂移会造成一些问题,开发的轨迹回放是把数据库中的速度为0的过滤掉,这样就没有问题了

Simple Text Output Format:

The simple text (ASCII) output contains time, position, and velocity data in the fixed width fields (not delimited) defined in the following table:

   FIELD DESCRIPTION:      WIDTH:  NOTES:

   ----------------------- ------- ------------------------

   Sentence start          1       Always '@'

   ----------------------- ------- ------------------------

  /Year                    2       Last two digits of UTC year

 | ----------------------- ------- ------------------------

 | Month                   2       UTC month, "01".."12"

T | ----------------------- ------- ------------------------

i | Day                     2       UTC day of month, "01".."31"

m | ----------------------- ------- ------------------------

e | Hour                    2       UTC hour, "00".."23"

 | ----------------------- ------- ------------------------

 | Minute                  2       UTC minute, "00".."59"

 | ----------------------- ------- ------------------------

  \Second                  2       UTC second, "00".."59"

   ----------------------- ------- ------------------------

  /Latitude hemisphere     1       'N' or 'S'

 | ----------------------- ------- ------------------------

 | Latitude position       7       WGS84 ddmmmmm, with an implied

 |                                 decimal after the 4th digit

 | ----------------------- ------- ------------------------

 | Longitude hemishpere    1       'E' or 'W'

 | ----------------------- ------- ------------------------

 | Longitude position      8       WGS84 dddmmmmm with an implied

P |                                 decimal after the 5th digit

o | ----------------------- ------- ------------------------

s | Position status         1       'd' if current 2D differential GPS position

i |                                 'D' if current 3D differential GPS position

t |                                 'g' if current 2D GPS position

i |                                 'G' if current 3D GPS position

o |                                 'S' if simulated position

n |                                 '_' if invalid position

 | ----------------------- ------- ------------------------

 | Horizontal posn error   3       EPH in meters

 | ----------------------- ------- ------------------------

 | Altitude sign           1       '+' or '-'

 | ----------------------- ------- ------------------------

 | Altitude                5       Height above or below mean

  \                                sea level in meters

   ----------------------- ------- ------------------------

  /East/West velocity      1       'E' or 'W'

 |     direction

 | ----------------------- ------- ------------------------

 | East/West velocity      4       Meters per second in tenths,

 |     magnitude                   ("1234" = 123.4 m/s)

V | ----------------------- ------- ------------------------

e | North/South velocity    1       'N' or 'S'

l |     direction

o | ----------------------- ------- ------------------------

c | North/South velocity    4       Meters per second in tenths,

i |     magnitude                   ("1234" = 123.4 m/s)

t | ----------------------- ------- ------------------------

y | Vertical velocity       1       'U' (up) or 'D' (down)

 |     direction

 | ----------------------- ------- ------------------------

 | Vertical velocity       4       Meters per second in hundredths,

  \    magnitude                   ("1234" = 12.34 m/s)

   ----------------------- ------- ------------------------

   Sentence end            2       Carriage return, '0x0D', and

                                   line feed, '0x0A'

   ----------------------- ------- ------------------------

If a numeric value does not fill its entire field width, the field is padded

with leading '0's (eg. an altitude of 50 meters above MSL will be output as "+00050").

Any or all of the data in the text sentence (except for the sentence start

and sentence end fields) may be replaced with underscores to indicate

invalid data.

GPS 解码函数,NMEA0183解码函数:

const

 CIMaxSatInfo = 4;

type

 TSatInfo = packed record /// GPS信息

   PRN: integer;         // 卫星号码

   EL,AZ: integer;       // 仰角、方位

   SN: integer;          // 信号噪音比

 end;

 TGPSInfo = packed record /// 解码后的GPS信息结构

   UTCTime: TDateTime; /// GPS时间, UTC 格式,不包含日期

   Longitude : Double; /// 经度

   Latitude : Double; /// 纬度

   LatHemi, LonHemi: Char;// N、S、E、W

   Altitude : Double; /// 海拔高度

   Speed : Double; /// 速度

   Course: Double; /// 方向

   Fix: string[10]; /// 定位方式

   SatInfo: Array [1..CIMaxSatInfo] of TSatInfo;

 end;

 TGPSTimePoint = packed record  /// GPS 三参数组:时间,经度,纬度

   Time: TDateTime;

   Longitude: Double;

   Latitude: Double;

 end;

 

 /// GPS移动方向,八个方向

 TDirection = (gdNone, gdW2E, gdE2W, gdS2N, gdN2S, gdES2WN, gdWS2EN, gdWN2ES, gdEN2WS);

// [2007-9-13]Kingron: 解码GPS数据,NMEA0183格式,每次一条信令,非连续

// 处理GPS发来的所有数据

//$PGRME,45.3,M,,M,45.3,M*00

//Estimated Error Information (PGRME)

//The GARMIN Proprietary sentence $PGRME reports estimated position error

//information.

//$PGRME,<1>,M,<2>,M,<3>,M*hh<CR><LF>

//<1> Estimated horizontal position error (HPE), 0.0 to 999.9 meters

//<2> Estimated vertical position error (VPE), 0.0 to 999.9 meters

//<3> Estimated position error (EPE), 0.0 to 999.9 meters

//下面是一些样本数据

//$GPGSV,3,1,09,05,18,043,43,11,04,290,44,14,59,034,43,15,01,184,*70

//$GPGSV,3,2,09,16,13,200,,18,22,153,,23,44,160,,25,54,288,51*7E

//$GPGSV,3,3,09,30,46,061,30,,,,,,,,,,,,*45

//$PGRME,45.3,M,,M,45.3,M*00

//$GPRMC,131558,A,2818.7145,N,10944.4235,E,000.0,000.0,1n0503,002.0,W*61

//$GPGGA,131558,2818.7145,N,10944.4235,E,1,04,4.6,238.2,M,-25.4,M,,*66

//$GPGSA,A,2,05,11,14,,,,,25,,,,,4.6,4.6,*1A

function DecodeGPS(const msg: string; var GPSInfo: TGPSInfo): Boolean;

 function GetNextItem(start: integer; len: integer; var tmp: string):integer;

 var

   i: integer;

 begin

   tmp := '';

   result := 0;

   i := start + 1;

   while (msg[i] <> '$') and (msg[i] <> ',') and (msg[i] <> '*') and (i<Len) do begin

     tmp := tmp + msg[i];

     inc(i);

     inc(result);

   end;

 end;

 function CountChar(start: integer; len: integer):integer;

 var

   i: integer;

 begin

   i:=start;

   Result := 0;

   while (msg[i] <> Chr($0d)) and (msg[i] <> Chr($0a)) and (msg[i] <> '$') and (i<Len) do begin

     if msg[i] = ',' then inc(Result);

     inc(i);

   end;

 end;

var

 CurPos,strLen: integer;

 tmpStr: string;

 tmpFloat: Double;

 tmpi,i: integer;

begin

 CurPos := 0;

 strLen := Length(msg);

 while CurPos<strLen do begin

   while (msg[CurPos] <> '$') and (CurPos<strLen) do inc(CurPos);

   CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

   if tmpStr = 'GPGGA' then begin

     if CountChar(CurPos,strLen) = 14 then begin

       //$GPGGA,131558,2818.7145,N,10944.4235,E,1,04,4.6,238.2,M,-25.4,M,,*66

       //$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>*hh<CR><LF>

       //<1> UTC时间, hhmmss

       //<2> 纬度, ddmm.mmmm (输出前导零)

       //<3> 南北, N or S

       //<4> 经度, dddmm.mmmm (输出前导零)

       //<5> 东西, E or W

       //<6> GPS质量评估, 0 = 不能定位, 1 = 非差分定位

       //, 2 = 差分定位(DGPS), 6 = 估计

       //<7> 使用中的卫星数量, 00 to 12 (输出前导零)

       //<8> Horizontal dilution of precision, 0.5 to 99.9

       //<9> 海拔高度, -9999.9 to 99999.9 米

       //<10> Geoidal height, -999.9 to 9999.9 meters

       //<11> 差分GPS(RTCM SC-104)数据寿命, number of seconds since last valid

       //RTCM transmission (非差分时为空)

       //<12> 差分GPS参考站ID, 0000 to 1023 (输出前导零,非差分时为空)

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       GPSInfo.UTCTime := MyTimeToStr(tmpStr, GPSInfo.UTCTime);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       tmpFloat := StrToFloatDef(tmpStr,0) / 100;

       GPSInfo.Longitude := Int(tmpFloat) + (Frac(tmpFloat) * 5) / 3;

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       GPSInfo.LatHemi := tmpStr[1];

       if GPSInfo.LatHemi = 'S' then GPSInfo.Latitude := -1 * GPSInfo.Latitude;

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       tmpFloat := StrToFloatDef(tmpStr,0) / 100;

       GPSInfo.Longitude := Int(tmpFloat) + (Frac(tmpFloat) * 5) / 3;

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       GPSInfo.LonHemi := tmpStr[1];

       if GPSInfo.LonHemi = 'W' then GPSInfo.Longitude := -1 * GPSInfo.Longitude;

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       GPSInfo.Altitude := StrToFloatDef(tmpStr,0);

     end;

   end else if tmpStr = 'GPGSA' then begin

     if CountChar(CurPos,strLen) = 17 then begin

       //卫星状态表

       //$GPGSA,A,2,05,11,14,,,,,25,,,,,4.6,4.6,*1A

       //$GPGSA,<1>,<2>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<4>,<5>,<6>

       //*hh<CR><LF>

       //<1> Mode, M = manual, A = automatic

       //<2> 定位状态, 1 = not available, 2 = 2D, 3 = 3D

       //<3> 卫星号码,最多12个

       //<4> Position dilution of precision, 0.5 to 99.9

       //<5> Horizontal dilution of precision, 0.5 to 99.9

       //<6> Vertical dilution of precision, 0.5 to 99.9

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       case StrToIntDef(tmpStr,0) of

         2: GPSInfo.Fix := '2D Fix';

         3: GPSInfo.Fix := '3D Fix';

       else

         GPSInfo.Fix := 'No Fix';

       end;

     end;

   end else if tmpStr = 'GPRMC' then begin

     if CountChar(CurPos,strLen) = 11 then begin

       //Recommended Minimum Specific GPS/TRANSIT Data (RMC)

       //$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh<CR><LF>

       //$GPRMC,131558,A,2818.7145,N,10944.4235,E,000.0,000.0,1n0503,002.0,W*61

       //<1> UTC time of position fix, hhmmss format

       //<2> Status, A = Valid position, V = NAV receiver warning

       //<3> Latitude, ddmm.mmmm format (leading zeros will be transmitted)

       //<4> Latitude hemisphere, N or S

       //<5> Longitude, dddmm.mmmm format (leading zeros will be transmitted)

       //<6> Longitude hemisphere, E or W

       //<7> Speed over ground, 000.0 to 999.9 knots (leading zeros will be transmitted)

       //<8> Course over ground, 000.0 to 359.9 degrees, true (leading zeros will be

       //transmitted)

       //<9> UTC date of position fix, ddmmyy format

       //<10> Magnetic variation, 000.0 to 180.0 degrees (leading zeros will be transmitted)

       //<11> Magnetic variation direction, E or W (westerly variation adds to true course)

       //<12> Mode indicator (only output if NMEA 2.30 active), A = Autonomous, D =

       //Differential, E = Estimated, N = Data not valid

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       GPSInfo.Speed := StrToFloatDef(tmpStr,0);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       GPSInfo.Course := StrToFloatDef(tmpStr,0);

     end;

   end else if tmpStr = 'GPGSV' then begin

     if CountChar(CurPos,strLen) = 19 then begin

       //$GPGSV,3,1,09,05,18,043,43,11,04,290,44,14,59,034,43,15,01,184,*70

       //$GPGSV,3,2,09,16,13,200,,18,22,153,,23,44,160,,25,54,288,51*7E

       //$GPGSV,3,3,09,30,46,061,30,,,,,,,,,,,,*45

       //$GPGSV,<1>,<2>,<3>,<4>,<5>,<6>,<7>,...<4>,<5>,<6>,<7>*hh<CR><LF>

       //<1> Total number of GSV sentences to be transmitted

       //<2> Number of current GSV sentence

       //<3> Total number of satellites in view, 00 to 12 (leading zeros will be transmitted)

       //<4> Satellite PRN number, 01 to 32 (leading zeros will be transmitted)

       //<5> 卫星仰角, 00-90度

       //<6> 卫星方位角, 000-359度

       //<7> 卫星信号噪音比 00-99db

       //NOTE: Items <4>,<5>,<6> and <7> repeat for each satellite in view to a maximum of

       //four (4) satellites per sentence. Additional satellites in view information must be

       //sent in subsequent sentences. These fields will be null if unused.

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       tmpi := StrToIntDef(tmpStr,1);

       CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

       for i:= 1 to CIMaxSatInfo do begin

         CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

         GPSInfo.SatInfo[(tmpi-1)*4 + i].PRN := StrToIntDef(tmpStr,0);

         CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

         GPSInfo.SatInfo[(tmpi-1)*4 + i].EL := StrToIntDef(tmpStr,0);

         CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

         GPSInfo.SatInfo[(tmpi-1)*4 + i].AZ := StrToIntDef(tmpStr,0);

         CurPos:= CurPos + 1 + GetNextItem(CurPos,strLen,tmpStr);

         GPSInfo.SatInfo[(tmpi-1)*4 + i].SN := StrToIntDef(tmpStr,0);

       end;

     end;

   end;

   inc(CurPos);

 end;

 Result := True;

end;

GPS.rar (211.7KB)