posts - 9,  comments - 2,  trackbacks - 0
GPS编码格式及C语言解码

引自http://www.sciencenet.cn/m/user_content.aspx?id=260661

有关磁偏角和地图定位的问题: 
    地图的方向:上北、下南、左西、右东是大多数地图的方向,但这可不是通用原则,如果地图上有方向标,可以通过方向标了解到这些。 

    地磁极是接近南极和北极的,但并不和南极、北极重合,一个约在北纬72°、 西经96°处;一个约在南纬70°、东经150°处。磁北极距地理北极大约相差1500km。现在磁北极的位置在加拿大北方,在一天中磁北极的位置也是不停的变动,它的轨迹大致为一椭圆形,磁北极平均每天向北以40m。

    目前磁北极正在逐渐离开加拿大,大约于2005年进入俄罗斯境内。 东经25度地区,磁偏角在1-2度之间;北纬25度以上地区,磁偏角大于2度;若在西经低纬度地区,磁偏角是5-20度;西经45度以上,磁偏角为25-50度。

    在我国,正常情况下,磁偏角最大可达6度,一般情况为2-3度。 在我国除部分磁力异常的地方外,一般磁偏角都是西偏。

    磁偏角还是不断有规律变化的,地图上的磁偏角只是测图时的磁偏角(磁北比真北偏左,加上磁偏角;磁北比真北偏右,减去磁偏角;在我国一般是加上)。

    使用地图本身所注的磁偏角要注意出版年限,地图太老误差较大。

GPS 0183协议GGA、GLL、GSA、GSV、RMC、VTG解释

$GPGGA 
例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F 
字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息 
字段1:UTC 时间,hhmmss.sss,时分秒格式 
字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0) 
字段3:纬度N(北纬)或S(南纬) 
字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0) 
字段5:经度E(东经)或W(西经) 
字段6:GPS状态,0=未定位,1=非差分定位,2=差分定位,3=无效PPS,6=正在估算 
字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0) 
字段8:HDOP水平精度因子(0.5 - 99.9) 
字段9:海拔高度(-9999.9 - 99999.9) 
字段10:地球椭球面相对大地水准面的高度 
字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空) 
字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空) 
字段13:校验值 

$GPGLL 
例:$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D 
字段0:$GPGLL,语句ID,表明该语句为Geographic Position(GLL)地理定位信息 
字段1:纬度ddmm.mmmm,度分格式(前导位数不足则补0) 
字段2:纬度N(北纬)或S(南纬) 
字段3:经度dddmm.mmmm,度分格式(前导位数不足则补0) 
字段4:经度E(东经)或W(西经) 
字段5:UTC时间,hhmmss.sss格式 
字段6:状态,A=定位,V=未定位 
字段7:校验值 

$GPGSA 
例:$GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A 
字段0:$GPGSA,语句ID,表明该语句为GPS DOP and Active Satellites(GSA)当前卫星信息 
字段1:定位模式,A=自动手动2D/3D,M=手动2D/3D 
字段2:定位类型,1=未定位,2=2D定位,3=3D定位 
字段3:PRN码(伪随机噪声码),第1信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段4:PRN码(伪随机噪声码),第2信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段5:PRN码(伪随机噪声码),第3信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段6:PRN码(伪随机噪声码),第4信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段7:PRN码(伪随机噪声码),第5信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段8:PRN码(伪随机噪声码),第6信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段9:PRN码(伪随机噪声码),第7信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段10:PRN码(伪随机噪声码),第8信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段11:PRN码(伪随机噪声码),第9信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段12:PRN码(伪随机噪声码),第10信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段13:PRN码(伪随机噪声码),第11信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段14:PRN码(伪随机噪声码),第12信道正在使用的卫星PRN码编号(00)(前导位数不足则补0) 
字段15:PDOP综合位置精度因子(0.5 - 99.9) 字段16:HDOP水平精度因子(0.5 - 99.9) 
字段17:VDOP垂直精度因子(0.5 - 99.9) 
字段18:校验值 

$GPGSV 
例:$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70 
字段0:$GPGSV,语句ID,表明该语句为GPS Satellites in View(GSV)可见卫星信息 
字段1:本次GSV语句的总数目(1 - 3) 
字段2:本条GSV语句是本次GSV语句的第几条(1 - 3) 
字段3:当前可见卫星总数(00 - 12)(前导位数不足则补0) 
字段4:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0) 
字段5:卫星仰角(00 - 90)度(前导位数不足则补0) 
字段6:卫星方位角(00 - 359)度(前导位数不足则补0) 
字段7:信噪比(00-99)dbHz 
字段8:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0) 
字段9:卫星仰角(00 - 90)度(前导位数不足则补0) 
字段10:卫星方位角(00 - 359)度(前导位数不足则补0) 
字段11:信噪比(00-99)dbHz 
字段12:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0) 
字段13:卫星仰角(00 - 90)度(前导位数不足则补0) 
字段14:卫星方位角(00 - 359)度(前导位数不足则补0) 
字段15:信噪比(00-99)dbHz 
字段16:校验值 

$GPRMC 
例:$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50 
字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息 
字段1:UTC时间,hhmmss.sss格式 
字段2:状态,A=定位,V=未定位 
字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0) 
字段4:纬度N(北纬)或S(南纬) 
字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0) 
字段6:经度E(东经)或W(西经) 
字段7:速度,节,Knots 
字段8:方位角,度 
字段9:UTC日期,DDMMYY格式 
字段10:磁偏角,(000 - 180)度(前导位数不足则补0) 
字段11:磁偏角方向,E=东W=西 
字段16:校验值 

$GPVTG 
例:$GPVTG,89.68,T,,M,0.00,N,0.0,K*5F 
字段0:$GPVTG,语句ID,表明该语句为Track Made Good and Ground Speed(VTG)地面速度信息 
字段1:运动角度,000 - 359,(前导位数不足则补0) 
字段2:T=真北参照系 
字段3:运动角度,000 - 359,(前导位数不足则补0) 
字段4:M=磁北参照系 
字段5:水平运动速度(0.00)(前导位数不足则补0) 
字段6:N=节,Knots 
字段7:水平运动速度(0.00)(前导位数不足则补0) 
字段8:K=公里/时,km/h 
字段9:校验值 

GPS编码格式及C语言解码

       GPS接收机只要处于工作状态就会源源不断地把接收并计算出的GPS导航定位信息通过串口传送到计算机中。前面的代码只负责从串口接收数据并将其放置于缓存,在没有进一步处理之前缓存中是一长串字节流,这些信息在没有经过分类提取之前是无法加以利用的。因此,必须通过程序将各个字段的信息从缓存字节流中提取出来,将其转化成有实际意义的,可供高层决策使用的定位信息数据。同其他通讯协议类似,对GPS进行信息提取必须首先明确其帧结构,然后才能根据其结构完成对各定位信息的提取。
    对于本文所使用的GPS OEM模块,其发送到计算机的数据主要由帧头、帧尾和帧内数据组成,根据数据帧的不同,帧头也不相同,主要有"$GPGGA"、"$GPGSA"、"$GPGSV"以及"$GPRMC"等。这些帧头标识了后续帧内数据的组成结构,各帧均以回车符和换行符作为帧尾标识一帧的结束。
    对于通常的情况,我们所关心的定位数据如经纬度、速度、时间等均可以从"$GPRMC"帧中获取得到,该帧的结构及各字段释义如下:
   $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>*hh   
     <1> 当前位置的格林尼治时间,格式为hhmmss   
     <2> 状态, A 为有效位置, V为非有效接收警告,即当前天线视野上方的卫星个数少于3颗。
     <3> 纬度, 格式为ddmm.mmmm   
     <4> 标明南北半球, N 为北半球、S为南半球   
     <5> 径度,格式为dddmm.mmmm   
     <6> 标明东西半球,E为东半球、W为西半球   
     <7> 地面上的速度,范围为0.0到999.9   
     <8> 方位角,范围为000.0到 359.9 度   
     <9> 日期, 格式为ddmmyy   
     <10> 地磁变化,从000.0到 180.0 度   
     <11> 地磁变化方向,为E 或 W   
    至于其他几种帧格式,除了特殊用途外,平时并不常用,虽然接收机也在源源不断地向主机发送各种数据帧,但在处理时一般先通过对帧头的判断而只对"$GPRMC"帧进行数据的提取处理。如果情况特殊,需要从其他帧获取数据,处理方法与之也是完全类似的。
    由于帧内各数据段由逗号分割,因此在处理缓存数据时一般是通过搜寻ASCII码"$"来判断是否是帧头,在对帧头的类别进行识别后再通过对所经历逗号个数的计数来判断出当前正在处理的是哪一种定位导航参数,并作出相应的处理。
    下面就是对缓存Data中的数据进行解帧处理的主要代码,本文在此只关心时间(日期和时间)和地理坐标(经、纬度):     for(int i=0;i  if(Data=='$') file://帧头,SectionID为逗号计数器   
       SectionID=0;   
       if(Data==10){ file://帧尾 }  
       if(Data==',') file://逗号计数   
           SectionID++;  
       else {   
           switch(SectionID){    
                 case 1: file://提取出时间     
                      m_sTime+=Data;     
                      break;    
                 case 2: file://判断数据是否可信(当GPS天线能接收到有3颗GPS卫星时为A,可信)     
                      if(Data=='A')      
                           GPSParam[m_nNumber].m_bValid=true;      
                           break;    
                 case 3: file://提取出纬度      
                      m_sPositionY+=Data;      
                      break;    
                 case 5: file://提取出经度      
                      m_sPositionX+=Data;      
                      break;                     
                 case 9: file://提取出日期      
                      m_sDate+=Data;      
                      break;      
                      default:      
                      break;   
                    }  
                 }
             }   
    现在已将所需信息提取到内存,即时间、日期以及经纬度分别保存在CString型变量 m_sTime、m_Data、m_sPositionY和m_sPositionX中。
    在实际应用中往往要根据需要对其做进一步的运算处理,比如从GPS接收机中获得的时间信息为格林尼治时间,因此需要在获取时间上加8小时才为我国标准时间。而且GPS使用的WGS-84坐标系也与我国采用的坐标系不同,有时也要对此加以变换。而这些变换运算必须通过数值运算完成,因此需要将前面获取的字符型变量转化为数值型变量,这部分工作可放在检测到帧尾完成: 

::strcpy(buf,m_sTime); 
str.Format("%c%c",buf[0],buf[1]); 
GPSParam[m_nNumber].m_nHour=(atoi(str)+8)%24; file://提取出小时并转化为24小时制北京时间 
file://buf第2、3字节为分钟,4、5字节为秒,提取方法同上 …… 

::strcpy(buf,m_sDate); 
str.Format("%c%c",buf[0],buf[1]); file://提取出月份 file://buf第2、3字节为天,4、5字节为年,提取方法同上 …… ::strcpy(buf,m_sPositionY); 
str.Format("%c%c",buf[0],buf[1]); 
PositionValue=atoi(str); 
str.Format("%c%c%c%c%c%c%c",buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8]); GPSParam[m_nNumber].m_dPositionY=PositionValue*60+atof(str); file://提取出纬度 …… 

::strcpy(buf,m_sPositionX); 
if(m_sPositionX.GetLength()==10) file://经度超过90度(如东经125度) 
      {  
            str.Format("%c%c%c",buf[0],buf[1],buf[2]);  
            PositionValue=atoi(str); str.Format("%c%c%c%c%c%c%c",buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9]);  GPSParam[m_nNumber].m_dPositionX=PositionValue*60+atof(str); file://提取出经度(单位为分)
      }
if(m_sPositionX.GetLength()==9) file://经度未超过90度(如东经89度) 
     {  file://处理方法同上,只是buf的第0、1字节为度数,2~9为分数。
     }   
     到此为止,已将时间和经纬度信息提取到GPS结构数组GPSParam中的各个变量中去,后续的处理和高层决策可根据该结构中存储的数据作出相应的处理。 

posted on 2011-01-07 19:41 Chavin 阅读(760) 评论(0)  编辑 收藏 引用 所属分类: 转载

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理