10楼#
发布于:2005-03-11 09:13
<h3>Real-Time Satellite Tracking</h3>
Knowing the location of satellites is important when determining howprecise readings are and how stable a GPS fix is. Because GPS precisionwill be covered in detail in Part Two of this series, this section willfocus on interpreting satellite location and signal strength. <p>There are twenty-fouroperational satellites in orbit. Satellites are spaced in orbit so thatat any time a minimum of six satellites will be in view to usersanywhere in the world. Satellites are constantly in motion, which isgood because it prevents the existence of "blind spots" in the worldwith little or no satellite visibility. Just like finding stars in thesky, satellite locations are described as the combination of an azimuthand an elevation. As mentioned above, azimuth measures a directionaround the horizon. Elevation measures a degree value up from thehorizon between 00 and 900, where 00 represents the horizon and 900represents "zenith," directly overhead. So, if the device says asatellite's azimuth is 450 and its elevation is 450, the satellite islocated halfway up from the horizon towards the northeast. In additionto location, devices report each satellite's "Pseudo-Random Code" (orPRC), which is a number used to uniquely identify one satellite fromanother.</p><p>Here's an example of a $GPGSV sentence:</p><pre>$GPGSV,3,1,10,24,82,023,40,05,62,285,32,01,62,123,00,17,59,229,28*70</pre><p>Each sentence contains up to four blocks of satellite information,comprised of four words. For example, the first block is "24,82,023,40"and the second block is "05,62,285,32" and so on. The first word ofeach block gives the satellite's PRC. The second word gives eachsatellite's elevation, followed by azimuth and signal strength. If thissatellite information were to be shown graphically, it would look likeFigure 1-1.</p><p><img src="http://www.codeguru.com/dbfiles/get_image.php?id=8079;lbl=FIGURE11_JPG;ds=20041229"></p><p><b>Figure 1-1:</b> Graphical representation of a $GPGSV sentence,where the center of the circle marks the current position and the edgeof the circle marks the horizon.</p><p>Perhaps the most important number in this sentence is the"signal-to-noise ratio" (or SNR for short). This number indicates howstrongly a satellite's radio signal is being received. Remember,satellites transmit signals at the same strength, but things such astrees and walls can obscure a signal beyond recognition. Typical SNRvalues are between zero and fifty, where fifty means an excellentsignal. (SNR can be as high as ninety-nine, but I've never seenreadings above fifty, even in wide open sky.) In Figure 1-1, the greensatellites indicate a strong signal, whereas the yellow satellitesignifies a moderate signal. (In Part Two, I will provide a way toclassify signal strengths.) Satellite #1's signal is completelyobscured. Listing 1-7 shows the interpreter after it is expanded toread satellite info.</p><p><b>Listing 1-7:</b> The interpreter is improved to interpret the location of GPS satellites currently in view.</p><pre>'******************************************************* '** Listing 1-7. Extracting satellite information '******************************************************* 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() Public Event SatelliteReceived(ByVal pseudoRandomCode As Integer, _ ByVal azimuth As Integer, _ ByVal elevation As Integer, _ ByVal signalToNoiseRatio As Integer) ' 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 "$GPGSV" Return ParseGPGSV(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) ; "0" ' 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) ; "0" ' 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 ' Interprets a "Satellites in View" NMEA sentence Public Function ParseGPGSV(ByVal sentence As String) As Boolean Dim PseudoRandomCode As Integer Dim Azimuth As Integer Dim Elevation As Integer Dim SignalToNoiseRatio As Integer ' Divide the sentence into words Dim Words() As String = GetWords(sentence) ' Each sentence contains four blocks of satellite information. 'Read each block and report each satellite's information Dim Count As Integer For Count = 1 To 4 ' Does the sentence have enough words to analyze? If (Words.Length - 1) >= (Count * 4 + 3) Then ' Yes. Proceed with analyzing the block. Does it contain any ' information? If Words(Count * 4) <> "" And Words(Count * 4 + 1) <> "" _ And Words(Count * 4 + 2) <> "" _ And Words(Count * 4 + 3) <> "" Then ' Yes. Extract satellite information and report it PseudoRandomCode = CType(Words(Count * 4), Integer) Elevation = CType(Words(Count * 4 + 1), Integer) Azimuth = CType(Words(Count * 4 + 2), Integer) SignalToNoiseRatio = CType(Words(Count * 4 + 2), Integer) ' Notify of this satellite's information RaiseEvent SatelliteReceived(PseudoRandomCode, Azimuth, _ Elevation, SignalToNoiseRatio) End If End If Next ' 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</pre> </p> |
|
|
11楼#
发布于:2005-03-11 09:14
<h3>A World-Class Interpreter</h3>
International readers may have spotted a subtle problem early onthat was not handled in the listings—numbers were being reported in thenumeric format used in the United States! Countries such as Belgium andSwitzerland, which use different formats for numbers, requireadjustments to the interpreter to work at all. Fortunately, the .NETframework includes built-in support for converting numbers amongdifferent cultures, so the changes to the interpreter required arestraightforward. In the interpreter, the only fractional value isspeed, so only one change is necessary. The <b>NmeaCultureInfo</b> variable represents the culture used for numbers within NMEA sentences. The <b>Double.Parse</b>method is then used with this variable to convert speed into themachine's local culture. Listing 1-8 shows the completed interpreter,now ready for use internationally.</p><p><b>Listing 1-8:</b> The completed interpreter, suitable for use anywhere in the world.</p><pre>'************************************************************* '** Listing 1-8. Adding support for international cultures '************************************************************* Imports System.Globalization Public Class NmeaInterpreter ' Represents the EN-US culture, used for numers in NMEA sentences Private NmeaCultureInfo As New CultureInfo("en-US") ' Used to convert knots into miles per hour Private MPHPerKnot As Double = Double.Parse("1.150779", _ NmeaCultureInfo) ' 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() Public Event SatelliteReceived(ByVal pseudoRandomCode As Integer, _ ByVal azimuth As Integer, _ ByVal elevation As Integer, _ ByVal signalToNoiseRatio As Integer) ' 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 "$GPGSV" Return ParseGPGSV(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) ; "0" ' 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) ; "0" ' 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. Parse the speed and convert it to MPH Dim Speed As Double = Double.Parse(Words(7), NmeaCultureInfo) * _ MPHPerKnot ' Notify of the new speed RaiseEvent SpeedReceived(Speed) ' Are we over the highway speed limit? If Speed > 55 Then RaiseEvent SpeedLimitReached() 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 ' Interprets a "Satellites in View" NMEA sentence Public Function ParseGPGSV(ByVal sentence As String) As Boolean Dim PseudoRandomCode As Integer Dim Azimuth As Integer Dim Elevation As Integer Dim SignalToNoiseRatio As Integer ' Divide the sentence into words Dim Words() As String = GetWords(sentence) ' Each sentence contains four blocks of satellite information. ' Read each block and report each satellite's information Dim Count As Integer For Count = 1 To 4 ' Does the sentence have enough words to analyze? If (Words.Length - 1) >= (Count * 4 + 3) Then ' Yes. Proceed with analyzing the block. Does it contain any ' information? If Words(Count * 4) <> "" And Words(Count * 4 + 1) <> "" _ And Words(Count * 4 + 2) <> "" _ And Words(Count * 4 + 3) <> "" Then ' Yes. Extract satellite information and report it PseudoRandomCode = CType(Words(Count * 4), Integer) Elevation = CType(Words(Count * 4 + 1), Integer) Azimuth = CType(Words(Count * 4 + 2), Integer) SignalToNoiseRatio = CType(Words(Count * 4 + 2), Integer) ' Notify of this satellite's information RaiseEvent SatelliteReceived(PseudoRandomCode, Azimuth, _ Elevation, SignalToNoiseRatio) End If End If Next ' 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 </pre> |
|
|
12楼#
发布于:2005-03-11 09:16
<h3>Final Thoughts</h3>
You should now have a good understanding that an NMEA interpreter isall about extracting words from sentences. You can harness the power ofsatellites to determine your location, synchronize your computer clock,find your direction, watch your speed, and point to a satellite in thesky on a cloudy day. This interpreter will also work with the .NETCompact Framework without any modifications. If sentences were alsostored in a file, the interpreter can be used to play back an entireroad trip. These are all great features, especially considering thesmall size of the class, but is this interpreter ready to drive yourcar? Not quite yet. There is one important topic remaining which isrequired to make GPS applications safe for the real world: precision. <p>GPS devices aredesigned to report any information they find, even if the informationis inaccurate. In fact, information about the current location can beoff as much as half a football field, even when devices are equippedwith the latest DGPS and WAAS correction technologies! Unfortunately,several developers are not aware of this problem. There are somethird-party components out there that are not suitable for commercialapplications that require enforcing a minimum level of precision. Keepthis article handy, however, because in Part Two of this series, I willexplain precision enforcement in detail and take the interpreter evenfurther to make it suitable for professional, high-precisionapplications!</p><p><font><i>(To be continued...)</i></font></p><p>[Please indicate your interest in part two by rating this article.]</p><p> <b>About the Author</b> Jon Person is the author of the award-winning "<a href="http://www.gpsdotnet.com/" target="_blank" >GPS.NET Global Positioning SDK</a>"component and has consulted for military companies and the ForestService on GPS solutions. Jon frequently writes about GPS applicationdevelopment and welcomes all questions and comments atinfo@gpsdotnet.com. </p><p><li><a href="http://www.codeguru.com/dbfiles/get_file/PartOneListings.zip?id=8079;lbl=PARTONELISTINGS_ZIP;ds=20041229" target="_blank" >PartOneListings.zip</a> - Listings for Part One (Visual Basic.NET) </li><li><a href="http://www.codeguru.com/dbfiles/get_file/WritingGPSApplications2_demo_gpsdotnet.zip?id=8079;lbl=WRITINGGPSAPPLICATIONS2_DEMO_GPSDOTNET_ZIP;ds=20041229" target="_blank" >WritingGPSApplications2_demo_gpsdotnet.zip</a> - Demonstration using GPS.NET SDK <p></p></li><!--content_stop--><table border="0" cellpadding="3" width="100%"> <tr> <td align="left" valign="top"> </td></tr></table></p> </p> |
|
|
13楼#
发布于:2005-03-24 01:05
有用VC开发的没
|
|
14楼#
发布于:2005-03-24 09:27
没。有C#的
自己去翻译吧 |
|
|
15楼#
发布于:2006-01-08 22:02
需要使用gps.net组件的,这个组件要收费的。<img src="images/post/smile/dvbbs/em01.gif" /><img src="images/post/smile/dvbbs/em02.gif" /><img src="images/post/smile/dvbbs/em03.gif" />
|
|
16楼#
发布于:2006-01-12 08:45
<P>好东西</P>
|
|
17楼#
发布于:2006-03-08 13:40
<P>谢谢lz ,lz 没必要这么累的,我很感兴趣的看了,很好,现在试验一下~~~~~</P><img src="images/post/smile/dvbbs/em02.gif" /><img src="images/post/smile/dvbbs/em03.gif" />
|
|
18楼#
发布于:2006-04-04 14:03
bucuo!!
|
|
19楼#
发布于:2006-04-16 13:14
楼主辛苦了! 非常感谢!<img src="images/post/smile/dvbbs/em01.gif" />
|
|