正文

怎样写一个GPS应用程序—介绍12005-11-13 14:28:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/iamben250/6873.html

分享到:

怎样写一个GPS应用程序1—介绍
作者: YuL (http://www.cnblogs.com/yul/)
 

原文:How to Write a GPS Application - Introduction
作者:
Jon Person   翻译:YuL (http://www.cnblogs.com/yul/)

需要什么样的GPS应用程序才能满足商业级的要求呢,像安装在车里的导航器一样?而且,GPS数据是怎么被解释,从而应用于实际工作中的呢?在这两部分里,我将和大家一起探讨这两个问题,并且给你编写商业级GPS应用程序必要的技巧,让专业的GPS设备能够更好的为你所用。

一句重要的语句

第一部分将探讨描述GPS原始数据的工作。实际上这个工作已经被国家舰船电子协会(下面简称NMEA,www.nmea.org)给简化了许多,该网站介 绍了一个正广泛应用于GPS主流设备的工业标准。为了给广大的开发人员一个良好的开端,我选择使用的一些VS.NET的源代码来自我的“GPS.NET Global Position SDK”组件。(为了简短这些代码,我去掉了诸如多线程和错误处理的部分。)

NMEA数据通过一个“逗号分隔的语句”来传递,这个语句包含的信息都基于语句的第一个单词。这里有五十种以上类型的语句,不过真正的一个描述仅仅需要处理少量的采集数据。最终常用的NMEA语句是“推荐最小”语句,它以“$GPRMC.”开头。这里有个一例子:

$GPRMC,040302.663,A,3939.7,N,10506.6,W,0.27,358.86,200804,,*1A

这条语句基本上包含了GPS应用程序所需的全部数据:纬度、经度、速度、方向、卫星时间、状态以及磁场变量。

第一步就是要写一个方法来解释NMEA数据,这个方法需要完成两件事:将每条语句分解为独立的单词,和检查首单词是否有效。清单 1-1 就是这个描述类的开始部分。

清单 1-1:一个NMEA描述的核心功能是将NMEA语句分解成单个的单词。

'**  Listing 1-1.  The core of an NMEA interpreter
'*******************************************************
Public Class NmeaInterpreter
  ' 处理来自GPS接收器的信息
  Public Function Parse(ByVal sentence As String) As Boolean
    ' 将语句分解为单词
    Dim Words() As String = GetWords(sentence)
    ' 通过匹配首单词来决定下一步的工作
    Select Case Words(0)
      Case "$GPRMC"      ' 一条“推荐最小”的语句被找到!
        ' 标示这条语句为可用
        Return True
      Case Else
        ' 标示这条语句为不可用
        Return False
    End Select
  End Function
  ' 将语句分解为单词
  Public Function GetWords(ByVal sentence As String) As String()
    Return sentence.Split(","c)
  End Function
End Class

接下来一步就是要分析提取出来的信息了,让我们从纬度和经度开始吧。纬度和经度存储格式为“DDD°MM’SS.S,”,其中D表示时(也可以叫 “度”),M表示分,S表示秒。坐标可以简单表示为“DD°MM.M’”或者直接就表示为“DD°.”语句中第四个单词(“3939.7,”)以度和分的 形式表示当前的纬度为39°39.7’。头两个字符(39)表示度,余下的部分(39.7)表示分。经度和纬度是相同的结构,从这个语句来看要注意,头三 个字符表示经度的度(105°06.6’)。第五和第七个单词标示“半球”,其中“N”代表“北半球”,“W”代表“西经”。半球信息放在数字部分后面组 成完整的测量信息。

我还发现NMEA描述在事件驱动下使工作更容易完成。这是因为并不是按照特定的顺序来获取数据。一个事件驱动类为一应用程序给出了它最具灵活性和响应性的 描述。因此,我也将使用事件来设计描述,从而获取信息。PositionReceived是第一个事件,它将记录当前获得的纬度和经度。清单 1-2 扩展这个描述器,来报告当前位置。

清单 1-2:这个描述器可以报告当前的纬度和经度。

'*******************************************************
'*************  清单 1-2. 从语句中提取信息  *************
'*******************************************************
Public Class NmeaInterpreter
  ' 当前位置变化时,记录新位置
  Public Event PositionReceived(ByVal latitude As String, _
                                ByVal longitude As String)
  ' 处理GPS接收器的信息
  Public Function Parse(ByVal sentence As String) As Boolean
    ' 通过匹配首单词来决定下一步的工作
    Select Case GetWords(sentence)(0)
      Case "$GPRMC"      ' 一条“推荐最小”的语句被找到!
        Return ParseGPRMC(sentence)
      Case Else
        ' 标示这条语句为不可用
        Return False
    End Select
  End Function
  ' 将语句分解为单词
  Public Function GetWords(ByVal sentence As String) As String()
    Return sentence.Split(","c)
  End Function
  ' 描述 $GPRMC 消息
  Public Function ParseGPRMC(ByVal sentence As String) As Boolean
    ' 将语句分解为单词
    Dim Words() As String = GetWords(sentence)
    ' 我们是否有足够的数据来描述当前位置?
    If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
      Words(6) <> "" Then
      ' 是,则提取纬度和经度
      Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' 获取度
      Latitude = Latitude & Words(3).Substring(2) & """"      ' 获取分
      Latitude = Latitude & Words(4)    ' 获取半球
      Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' 获取度
      Longitude = Longitude & Words(5).Substring(3) & """"    ' 获取分
      Longitude = Longitude & Words(6)    ' 获取半球
      ' 将该变化通知应用程序
      RaiseEvent PositionReceived(Latitude, Longitude)
    End If
    ' 表示该语句可用
    Return True
  End Function
End Class

当然,我们肯定注意到了当没有接受到任何信息时,有些GPS设备将报告空值。因此,在解意描述前先判断每个单词是一个很不错的想法。如果你需要打度的符号(°),那么按Alt健并且用数字键盘输入“0176”就OK了。

检验和(Checksum)就是采用XOR的方法来计算美元符($)和星号(*)之间的字节。这个检验和是用来与语句的检验和比较的。如果检验和不匹配, 语句将被弃用。这个做法是很有效的,因为GPS设备每隔很短的时间就返回一批相同的信息。利用检验和的比较能力,描述就可以剔除每一无效的语句。清单 1-3 扩展描述器类来完成这个功能。

清单 1-3:这个描述器可以检测错误并且仅仅解意释放错误NMEA数据

'**  清单 1-3. 检测并处理NMEA错误
'*******************************
Public Class NmeaInterpreter
  ' 当前位置变化时,记录新位置
  Public Event PositionReceived(ByVal latitude As String, _
                                ByVal longitude As String)
  ' 处理GPS接收器的信息
  Public Function Parse(ByVal sentence As String) As Boolean
    ' 如果检验和不能和我们计算的检验和匹配,那么丢弃它
    If Not IsValid(sentence) Then Return False
    ' 通过匹配首单词来决定下一步的工作
    Select Case GetWords(sentence)(0)
      Case "$GPRMC"      ' 一条“推荐最小”的语句被找到!
        Return ParseGPRMC(sentence)
      Case Else
        ' 标示这条语句为不可用
        Return False
    End Select
  End Function
  ' 将语句分解为单词
  Public Function GetWords(ByVal sentence As String) As String()
    Return sentence.Split(","c)
  End Function
  ' 描述 $GPRMC 消息
  Public Function ParseGPRMC(ByVal sentence As String) As Boolean
    ' 将语句分解为单词
    Dim Words() As String = GetWords(sentence)
    ' 我们是否有足够的数据来描述当前位置?
    If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
      Words(6) <> "" Then
      ' 是,则提取纬度和经度
      Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' 获取度
      Latitude = Latitude & Words(3).Substring(2) & """"      ' 获取分
      Latitude = Latitude & Words(4)    ' 获取半球
      Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' 获取度
      Longitude = Longitude & Words(5).Substring(3) & """"    ' 获取分
      Longitude = Longitude & Words(6)    ' 获取半球
      ' 将该变化通知应用程序
      RaiseEvent PositionReceived(Latitude, Longitude)
    End If
    ' 表示该语句可用
    Return True
  End Function
  ' 如果检验和匹配,则返回TRUE
  Public Function IsValid(ByVal sentence As String) As Boolean
    ' 星号计算后比较字符
    Return sentence.Substring(sentence.IndexOf("*") + 1) = GetChecksum(sentence)
  End Function
  ' 计算语句的检验和
  Public Function GetChecksum(ByVal sentence As String) As String
    ' 通过循环获得检验和
    Dim Character As Char
    Dim Checksum As Integer
    For Each Character In sentence
      Select Case Character
        Case "$"c
          ' 忽略美元符号
        Case "*"c
          ' 遇到星号则停止计算
          Exit For
        Case Else
          ' 是否为检验和的第一个值?
          If Checksum = 0 Then
            ' 是。将该值赋给检验和
            Checksum = Convert.ToByte(Character)
          Else
            ' 否。采用XOR算法和当前检验和值计算,并将结构赋给检验和
            Checksum = Checksum Xor Convert.ToByte(Character)
          End If
      End Select
    Next
    ' 返回一个十六进制的检验和
    Return Checksum.ToString("X2")
  End Function
End Class

时间是GPS技术的基础,因为距离通过光速来测量得到的。每个GPS卫星包含四个原子钟,它将在一段以十亿分之一秒为单位的时间内计量它的射线传播。一个 强大的特性是仅用很少的代码,这些原子钟可以和精确到毫秒的电脑钟同步。$GPRMC语句的第二个单词(040302.663)包含了卫星时间,这个时间 是用压缩格式表示的。头两个字符表示小时,接下来两个字符表示分钟,再下来两个字符表示秒,最后小数部分表示毫秒。因此,这个时间是4:03: 02.663 AM。然而,卫星报告的时间是国际时间(GMT+0),因此,这个时间必须被调整到区域的当地时间。清单 1-4 添加支持将卫星时间利用DateTime.ToLocalTime方法转换到当地时间的功能。

清单 1-4:这个类可以无线地即时将原子钟同步到你的电脑钟

'********************************************************
'**  Listing 1-4.  Add support for satellite-derived time
'********************************************************
Public Class NmeaInterpreter
  ' Raised when the current location has changed
  Public Event PositionReceived(ByVal latitude As String, _
                                ByVal longitude As String)
  Public Event DateTimeChanged(ByVal dateTime As DateTime)
  ' Processes information from the GPS receiver
  Public Function Parse(ByVal sentence As String) As Boolean
    ' Discard the sentence if its checksum does not match our   
    ' calculated checksum
    If Not IsValid(sentence) Then Return False
    ' Look at the first word to decide where to go next
    Select Case GetWords(sentence)(0)
      Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
        Return ParseGPRMC(sentence)
      Case Else
        ' Indicate that the sentence was not recognized
        Return False
    End Select
  End Function
  ' Divides a sentence into individual words
  Public Function GetWords(ByVal sentence As String) As String()
    Return sentence.Split(","c)
  End Function
  ' Interprets a $GPRMC message
  Public Function ParseGPRMC(ByVal sentence As String) As Boolean
    ' Divide the sentence into words
    Dim Words() As String = GetWords(sentence)
    ' Do we have enough values to describe our location?
    If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _     
      Words(6) <> "" Then
      ' Yes. Extract latitude and longitude
      Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' Append hours
      Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
      Latitude = Latitude & Words(4)    ' Append the hemisphere
      Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
      Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
      Longitude = Longitude & Words(6)    ' Append the hemisphere
      ' Notify the calling application of the change
      RaiseEvent PositionReceived(Latitude, Longitude)
    End If
    ' Do we have enough values to parse satellite-derived time?
    If Words(1) <> "" Then
      ' Yes. Extract hours, minutes, seconds and milliseconds
      Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
      Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
      Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
      Dim UtcMilliseconds As Integer
      ' Extract milliseconds if it is available
      If Words(1).Length > 7 Then
          UtcMilliseconds = CType(Words(1).Substring(7), Integer)
      End If
      ' Now build a DateTime object with all values
      Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
      Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
        Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
      ' Notify of the new time, adjusted to the local time zone
      RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
    End If
    ' Indicate that the sentence was recognized
    Return True
  End Function
  ' Returns True if a sentence's checksum matches the calculated checksum
  Public Function IsValid(ByVal sentence As String) As Boolean
    ' Compare the characters after the asterisk to the calculation
    Return sentence.Substring(sentence.IndexOf("*") + 1) = _
      GetChecksum(sentence)
  End Function
  ' Calculates the checksum for a sentence
  Public Function GetChecksum(ByVal sentence As String) As String
    ' Loop through all chars to get a checksum
    Dim Character As Char
    Dim Checksum As Integer
    For Each Character In sentence
      Select Case Character
        Case "$"c
          ' Ignore the dollar sign
        Case "*"c
          ' Stop processing before the asterisk
          Exit For
        Case Else
          ' Is this the first value for the checksum?
          If Checksum = 0 Then
            ' Yes. Set the checksum to the value
            Checksum = Convert.ToByte(Character)
          Else
            ' No. XOR the checksum with this character's value
            Checksum = Checksum Xor Convert.ToByte(Character)
          End If
      End Select
    Next
    ' Return the checksum formatted as a two-character hexadecimal
    Return Checksum.ToString("X2")
  End Function
End Class

GPS设备分析你的位置根据时间计算速度和方向。本文开头部分的$GPRMC语句也包含这几个部分。速度总是被报告为哩/小时,并且方向被报告为方位角 (azimuth,以水平顺时针测量,范围为0°到360°,其中0°表示正北,90°表示正东,其它的依次类推)。这里要用到一个简单的数学计算,将哩 /小时转换为公里/小时。在清单 1-5 中你将再次看到GPS数据被一行代码描述出来,这就如同一个汽车超速所展示出的那样。

清单 1-5:这个类现在可以告诉你要去哪里,而且可以帮你少领超速罚单

'**  Listing 1-5.  Extracting speed and bearing
'*******************************************************
Public Class NmeaInterpreter
  ' Raised when the current location has changed
  Public Event PositionReceived(ByVal latitude As String, _
                                ByVal longitude As String)
  Public Event DateTimeChanged(ByVal dateTime As DateTime)
  Public Event BearingReceived(ByVal bearing As Double)
  Public Event SpeedReceived(ByVal speed As Double)
  Public Event SpeedLimitReached()
  ' Processes information from the GPS receiver
  Public Function Parse(ByVal sentence As String) As Boolean
    ' Discard the sentence if its checksum does not match our calculated
    ' checksum
    If Not IsValid(sentence) Then Return False
    ' Look at the first word to decide where to go next
    Select Case GetWords(sentence)(0)
      Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
        Return ParseGPRMC(sentence)
      Case Else
        ' Indicate that the sentence was not recognized
        Return False
    End Select
  End Function
  ' Divides a sentence into individual words
  Public Function GetWords(ByVal sentence As String) As String()
    Return sentence.Split(","c)
  End Function
' Interprets a $GPRMC message
Public Function ParseGPRMC(ByVal sentence As String) As Boolean
    ' Divide the sentence into words
    Dim Words() As String = GetWords(sentence)
    ' Do we have enough values to describe our location?
    If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
      Words(6) <> "" Then
      ' Yes. Extract latitude and longitude
      Dim Latitude As String = Words(3).Substring(0, 2) & "°" ' Append hours
      Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
      Latitude = Latitude & Words(4)    ' Append the hemisphere
      Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
      Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
      Longitude = Longitude & Words(6)    ' Append the hemisphere
      ' Notify the calling application of the change
      RaiseEvent PositionReceived(Latitude, Longitude)
    End If
    ' Do we have enough values to parse satellite-derived time?
    If Words(1) <> "" Then
      ' Yes. Extract hours, minutes, seconds and milliseconds
      Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
      Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
      Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
,       Dim UtcMilliseconds As Integer
      ' Extract milliseconds if it is available
      If Words(1).Length > 7 Then UtcMilliseconds = _
                                      CType(Words(1).Substring(7), Integer)
      ' Now build a DateTime object with all values
      Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
      Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
        Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
      ' Notify of the new time, adjusted to the local time zone
      RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
    End If
    ' Do we have enough information to extract the current speed?
    If Words(7) <> "" Then
      ' Yes.  Convert it into MPH
      Dim Speed As Double = CType(Words(7), Double) * 1.150779
      ' If we're over 55MPH then trigger a speed alarm!
      If Speed > 55 Then RaiseEvent SpeedLimitReached()
      ' Notify of the new speed
      RaiseEvent SpeedReceived(Speed)
    End If
    ' Do we have enough information to extract bearing?
    If Words(8) <> "" Then
      ' Indicate that the sentence was recognized
      Dim Bearing As Double = CType(Words(8), Double)
      RaiseEvent BearingReceived(Bearing)
    End If
    ' Indicate that the sentence was recognized
    Return True
  End Function
  ' Returns True if a sentence's checksum matches the calculated checksum
  Public Function IsValid(ByVal sentence As String) As Boolean
    ' Compare the characters after the asterisk to the calculation
    Return sentence.Substring(sentence.IndexOf("*") + 1) = _                                                   
      GetChecksum(sentence)
  End Function
  ' Calculates the checksum for a sentence
  Public Function GetChecksum(ByVal sentence As String) As String
    ' Loop through all chars to get a checksum
    Dim Character As Char
    Dim Checksum As Integer
    For Each Character In sentence
      Select Case Character
        Case "$"c
          ' Ignore the dollar sign
        Case "*"c
          ' Stop processing before the asterisk
          Exit For
        Case Else
          ' Is this the first value for the checksum?
          If Checksum = 0 Then
            ' Yes. Set the checksum to the value
            Checksum = Convert.ToByte(Character)
          Else
            ' No. XOR the checksum with this character's value
            Checksum = Checksum Xor Convert.ToByte(Character)
          End If
      End Select
    Next
    ' Return the checksum formatted as a two-character hexadecimal
    Return Checksum.ToString("X2")
  End Function
End Class

这个$GPRMC语句包含一个用“fix”表示的值。它表示你现在获得的信号强度至少来自三颗卫星,这样就足够用来计算你当前的位置了。如果有四颗卫星的 话,还可以获得高程信息。$GPRMC语句的第三个单词“A”表示“活动的”的意思,那么我们就知道当前的信号是可用的,如果是“V”,则表示不可用。清 单 1-6 包含的代码可以用来检查这个字符并报告是否可用。

清单 1-6:这个描述起现在可以让我们获知设备的数据是否是“fix”的

'*******************************************************
'**  Listing 1-6.  Extracting satellite fix status
'*******************************************************
Public Class NmeaInterpreter
  ' Raised when the current location has changed
  Public Event PositionReceived(ByVal latitude As String, _
                                ByVal longitude As String)
  Public Event DateTimeChanged(ByVal dateTime As DateTime)
  Public Event BearingReceived(ByVal bearing As Double)
  Public Event SpeedReceived(ByVal speed As Double)
  Public Event SpeedLimitReached()
  Public Event FixObtained()
  Public Event FixLost()
  ' Processes information from the GPS receiver
  Public Function Parse(ByVal sentence As String) As Boolean
    ' Discard the sentence if its checksum does not match our calculated
    ' checksum
    If Not IsValid(sentence) Then Return False
    ' Look at the first word to decide where to go next
    Select Case GetWords(sentence)(0)
      Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
        Return ParseGPRMC(sentence)
      Case Else
        ' Indicate that the sentence was not recognized
        Return False
    End Select
  End Function
  ' Divides a sentence into individual words
  Public Function GetWords(ByVal sentence As String) As String()
    Return sentence.Split(","c)
  End Function
' Interprets a $GPRMC message
Public Function ParseGPRMC(ByVal sentence As String) As Boolean
    ' Divide the sentence into words
    Dim Words() As String = GetWords(sentence)
    ' Do we have enough values to describe our location?
    If Words(3) <> "" And Words(4) <> "" And Words(5) <> "" And _
      Words(6) <> "" Then
      ' Yes. Extract latitude and longitude
      Dim Latitude As String = Words(3).Substring(0, 2) & "°"  ' Append hours
      Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
      Latitude = Latitude & Words(4)    ' Append the hemisphere
      Dim Longitude As String = Words(5).Substring(0, 3) & "°"  ' Append hours
      Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
      Longitude = Longitude & Words(6)    ' Append the hemisphere
      ' Notify the calling application of the change
      RaiseEvent PositionReceived(Latitude, Longitude)
    End If
    ' Do we have enough values to parse satellite-derived time?
    If Words(1) <> "" Then
      ' Yes. Extract hours, minutes, seconds and milliseconds
      Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
      Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
      Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
      Dim UtcMilliseconds As Integer
      ' Extract milliseconds if it is available
      If Words(1).Length > 7 Then UtcMilliseconds = _                                
        CType(Words(1).Substring(7), Integer)
      ' Now build a DateTime object with all values
      Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
      Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
        Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
      ' Notify of the new time, adjusted to the local time zone
      RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
    End If
    ' Do we have enough information to extract the current speed?
    If Words(7) <> "" Then
      ' Yes.  Convert it into MPH
      Dim Speed As Double = CType(Words(7), Double) * 1.150779
      ' If we're over 55MPH then trigger a speed alarm!
      If Speed > 55 Then RaiseEvent SpeedLimitReached()
      ' Notify of the new speed
      RaiseEvent SpeedReceived(Speed)
    End If
    ' Do we have enough information to extract bearing?
    If Words(8) <> "" Then
      ' Indicate that the sentence was recognized
      Dim Bearing As Double = CType(Words(8), Double)
      RaiseEvent BearingReceived(Bearing)
    End If
    ' Does the device currently have a satellite fix?
    If Words(2) <> "" Then
      Select Case Words(2)
        Case "A"
          RaiseEvent FixObtained()
        Case "V"
          RaiseEvent FixLost()
      End Select
    End If
    ' Indicate that the sentence was recognized
    Return True
  End Function
  ' Returns True if a sentence's checksum matches the calculated checksum
  Public Function IsValid(ByVal sentence As String) As Boolean
    ' Compare the characters after the asterisk to the calculation
    Return sentence.Substring(sentence.IndexOf("*") + 1) = GetChecksum(sentence)
  End Function
  ' Calculates the checksum for a sentence
  Public Function GetChecksum(ByVal sentence As String) As String
    ' Loop through all chars to get a checksum
    Dim Character As Char
    Dim Checksum As Integer
    For Each Character In sentence
      Select Case Character
        Case "$"c
          ' Ignore the dollar sign
        Case "*"c
          ' Stop processing before the asterisk
          Exit For
        Case Else
          ' Is this the first value for the checksum?
          If Checksum = 0 Then
            ' Yes. Set the checksum to the value
            Checksum = Convert.ToByte(Character)
          Else
            ' No. XOR the checksum with this character's value
            Checksum = Checksum Xor Convert.ToByte(Character)
          End If
      End Select
    Next
    ' Return the checksum formatted as a two-character hexadecimal
    Return Checksum.ToString("X2")
  End Function
End Class

如你所看到的,整个信息被打包在一条单一的NMEA语句中。现在这个$GPRMC语句已经完全被描述出来了,这个描述器可以扩展用来支持第二条语句:$ GPGSV,这个语句实时地表达了卫星的形态。

对于确定数据精确度和GPS稳定性,卫星的位置是非常重要的信息。既然GPS精确读将被详细地在这两部分介绍,那么这一部分将主要描述卫星位置和信号的强度。

卫星二十四小时在轨道上运转着,它们在任一时间、任一地点上都至少有六颗能被用户看到。卫星不断地监测地球,这样就避免出现一些盲点或者卫星无法看到的地 方。就像在天空中找星星一样,卫星的位置被表示为一个方位角和高程。如前面所述,方位角为直接水平测量。高程测量则为一个与水平面的夹角,其中0°表示水 平,90°表示为“天顶”(或者说是头顶)。因此,如果设备说卫星的方位角为45°且高程为45°,那么卫星现在的位置就是处于水平的东北方向,高度为一 半的位置。另外对于卫星位置,设备报告每个卫星的“随机伪代码”(简称PRC),这个数值用来唯一标示一个卫星。

 

阅读(3208) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册