技术开发 频道

WM平台上如何开发出自己的GPS导航

  一个世界级的解析器

  国际读者可能已经发现了一个微妙的问题,这不是在上市初期处理-数字被在美国使用的数字格式报告!如比利时和瑞士使用不同的数字格式,需要调整解析器以便在所有的地方工作。幸运的是,NET框架,其中包括内置支持不同文化之间的转换数量,因此对解析器必要的改变很简单。在解析器中,唯一的分数值是速度,因此只有一处改动是必要的。NmeaCultureInfo变量代表NMEA语句内使用数字的文化。Double.Parse方法使用这个变量用于将速度转换成机器的地方文化。列表1-8显示了完整的解析器,现在可以在国际上用了。

  代码片段:

  1 *************************************************************
  2
  3 '**  Listing 1-8.  Adding support for international cultures
  4
  5 '*************************************************************
  6
  7 Imports System.Globalization
  8 Public Class NmeaInterpreter
  9
10   ' Represents the EN-US culture, used for numbers in NMEA sentences
11   Private NmeaCultureInfo As New CultureInfo("en-US")
12   ' Used to convert knots into miles per hour
13   Private MPHPerKnot As Double = Double.Parse("1.150779", NmeaCultureInfo)
14   ' Raised when the current location has changed
15   Public Event PositionReceived(ByVal latitude As String,_
16                                 ByVal longitude As String)
17   Public Event DateTimeChanged(ByVal dateTime As DateTime)
18   Public Event BearingReceived(ByVal bearing As Double)
19   Public Event SpeedReceived(ByVal speed As Double)
20   Public Event SpeedLimitReached()
21   Public Event FixObtained()
22   Public Event FixLost()
23   Public Event SatelliteReceived(ByVal pseudoRandomCode As Integer, _
24     ByVal azimuth As Integer, _
25     ByVal elevation As Integer, _
26     ByVal signalToNoiseRatio As Integer)
27   ' Processes information from the GPS receiver
28   Public Function Parse(ByVal sentence As String) As Boolean
29     ' Discard the sentence if its checksum does not match our calculated
30     ' checksum
31     If Not IsValid(sentence) Then Return False
32     ' Look at the first word to decide where to go next
33     Select Case GetWords(sentence)(0)
34       Case "$GPRMC"      ' A "Recommended Minimum" sentence was found!
35         Return ParseGPRMC(sentence)
36       Case "$GPGSV"
37         Return ParseGPGSV(sentence)
38       Case Else
39         ' Indicate that the sentence was not recognized
40         Return False
41     End Select
42   End Function
43   ' Divides a sentence into individual words
44   Public Function GetWords(ByVal sentence As String) As String()
45     Return sentence.Split(","c)
46   End Function
47   ' Interprets a $GPRMC message
48   Public Function ParseGPRMC(ByVal sentence As String) As Boolean
49     ' Divide the sentence into words
50     Dim Words() As String = GetWords(sentence)
51     ' Do we have enough values to describe our location?
52     If Words(3) <> "" And Words(4) <> "" _
53     And Words(5) <> "" And Words(6) <> "" Then
54       ' Yes. Extract latitude and longitude
55       Dim Latitude As String = Words(3).Substring(0, 2) & "°"  ' Append hours
56       Latitude = Latitude & Words(3).Substring(2) & """"    ' Append minutes
57       Latitude = Latitude & Words(4)     ' Append the hemisphere
58       Dim Longitude As String = Words(5).Substring(0, 3) & "°" ' Append hours
59       Longitude = Longitude & Words(5).Substring(3) & """"    ' Append minutes
60       Longitude = Longitude & Words(6)     ' Append the hemisphere
61       ' Notify the calling application of the change
62       RaiseEvent PositionReceived(Latitude, Longitude)
63     End If
64     ' Do we have enough values to parse satellite-derived time?
65     If Words(1) <> "" Then
66       ' Yes. Extract hours, minutes, seconds and milliseconds
67       Dim UtcHours As Integer = CType(Words(1).Substring(0, 2), Integer)
68       Dim UtcMinutes As Integer = CType(Words(1).Substring(2, 2), Integer)
69       Dim UtcSeconds As Integer = CType(Words(1).Substring(4, 2), Integer)
70       Dim UtcMilliseconds As Integer
71       ' Extract milliseconds if it is available
72       If Words(1).Length > 7 Then
73         UtcMilliseconds = CType(Single.Parse(Words(1).Substring(6), _
74                       CultureInfo.InvariantCulture) * 1000, Integer)
75       End If
76       ' Now build a DateTime object with all values
77       Dim Today As DateTime = System.DateTime.Now.ToUniversalTime
78       Dim SatelliteTime As New System.DateTime(Today.Year, Today.Month, _
79         Today.Day, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds)
80       ' Notify of the new time, adjusted to the local time zone
81       RaiseEvent DateTimeChanged(SatelliteTime.ToLocalTime)
82     End If
83     ' Do we have enough information to extract the current speed?
84     If Words(7) <> "" Then
85       ' Yes.  Parse the speed and convert it to MPH
86       Dim Speed As Double = Double.Parse(Words(7), NmeaCultureInfo) _
87                           * MPHPerKnot
88       ' Notify of the new speed
89       RaiseEvent SpeedReceived(Speed)
90       ' Are we over the highway speed limit?
91       If Speed > 55 Then RaiseEvent SpeedLimitReached()
92     End If
93     ' Do we have enough information to extract bearing?
94     If Words(8) <> "" Then
95       ' Indicate that the sentence was recognized
96       Dim Bearing As Double = CType(Words(8), Double)
97       RaiseEvent BearingReceived(Bearing)
98     End If
99     ' Does the device currently have a satellite fix?
100     If Words(2) <> "" Then
101       Select Case Words(2)
102         Case "A"
103           RaiseEvent FixObtained()
104         Case "V"
105           RaiseEvent FixLost()
106       End Select
107     End If
108     ' Indicate that the sentence was recognized
109     Return True
110   End Function
111   ' Interprets a "Satellites in View" NMEA sentence
112   Public Function ParseGPGSV(ByVal sentence As String) As Boolean
113     Dim PseudoRandomCode As Integer
114     Dim Azimuth As Integer
115     Dim Elevation As Integer
116     Dim SignalToNoiseRatio As Integer
117     ' Divide the sentence into words
118     Dim Words() As String = GetWords(sentence)
119     ' Each sentence contains four blocks of satellite information.
120     ' Read each block
121     ' and report each satellite's information
122     Dim Count As Integer
123     For Count = 1 To 4
124       ' Does the sentence have enough words to analyze?
125       If (Words.Length - 1) >= (Count * 4 + 3) Then
126         ' Yes. Proceed with analyzing the block. Does it contain any information?
127         If Words(Count * 4) <> "" And Words(Count * 4 + 1) <> "" _
128         And Words(Count * 4 + 2) <> "" And Words(Count * 4 + 3) <> "" Then
129           ' Yes. Extract satellite information and report it
130           PseudoRandomCode = CType(Words(Count * 4), Integer)
131           Elevation = CType(Words(Count * 4 + 1), Integer)
132           Azimuth = CType(Words(Count * 4 + 2), Integer)
133           SignalToNoiseRatio = CType(Words(Count * 4 + 2), Integer)
134           ' Notify of this satellite's information
135           RaiseEvent SatelliteReceived(PseudoRandomCode, Azimuth, Elevation, _
136             SignalToNoiseRatio)
137         End If
138       End If
139     Next
140     ' Indicate that the sentence was recognized
141     Return True
142   End Function
143   ' Returns True if a sentence's checksum matches the calculated checksum
144   Public Function IsValid(ByVal sentence As String) As Boolean
145     ' Compare the characters after the asterisk to the calculation
146     Return sentence.Substring(sentence.IndexOf("*") + 1) = GetChecksum(sentence)
147   End Function
148   ' Calculates the checksum for a sentence
149   Public Function GetChecksum(ByVal sentence As String) As String
150     ' Loop through all chars to get a checksum
151     Dim Character As Char
152     Dim Checksum As Integer
153     For Each Character In sentence
154       Select Case Character
155         Case "$"c
156           ' Ignore the dollar sign
157         Case "*"c
158           ' Stop processing before the asterisk
159           Exit For
160         Case Else
161           ' Is this the first value for the checksum?
162           If Checksum = 0 Then
163             ' Yes. Set the checksum to the value
164             Checksum = Convert.ToByte(Character)
165           Else
166             ' No. XOR the checksum with this character's value
167             Checksum = Checksum Xor Convert.ToByte(Character)
168           End If
169       End Select
170     Next
171     ' Return the checksum formatted as a two-character hexadecimal
172     Return Checksum.ToString("X2")
173   End Function
174 End Class
175

  最后的思考

  您现在应该有一个很好的了解,即1个NMEA解析器是从语句中提取所有相关的字。您可以利用卫星有权决定您的位置,与您的计算机时钟同步,找到你的方向,查看你的速度,阴天时指向天空中的卫星。这种解析器也将使用.NET Compact Framework而没有任何修改。如果语句也存储在文件中,解析器可以用来播放整个客场之旅。这些都是伟大的功能,尤其是考虑到类的如此小的尺寸,但这种解析器是否准备好了驾驶您的汽车以及飞机?我还没有。还有一个重要议题就是在现实世界中使GPS应用变得更安全:精度。 GPS设备用来记录他们发现的任何信息,即使信息是不准确的。

  事实上,关于当前的位置信息,误差可达半个足球场,即使设备上安装了最新的DGPS和WAAS校正技术!不幸的是,一些开发商并没有意识到这个问题。有一些第三方组件,不适合商业应用,需要加强最低水平的精度。在本系列的第2部分,我会详细解释精度执法,使解析器进一步适合于更专业高精密的应用!

0
相关文章