From eb61c55302366e134b10b723efbe76fe4dba680e Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Wed, 29 Jul 2020 12:15:43 -0700 Subject: [PATCH] Added DTM, GBS, GRS and VLW message types --- src/NmeaParser/Nmea/Dtm.cs | 149 +++++++++++++++++++++++++++++++++++++ src/NmeaParser/Nmea/Gbs.cs | 135 +++++++++++++++++++++++++++++++++ src/NmeaParser/Nmea/Grs.cs | 134 +++++++++++++++++++++++++++++++++ src/NmeaParser/Nmea/Vlw.cs | 56 ++++++++++++++ 4 files changed, 474 insertions(+) create mode 100644 src/NmeaParser/Nmea/Dtm.cs create mode 100644 src/NmeaParser/Nmea/Gbs.cs create mode 100644 src/NmeaParser/Nmea/Grs.cs create mode 100644 src/NmeaParser/Nmea/Vlw.cs diff --git a/src/NmeaParser/Nmea/Dtm.cs b/src/NmeaParser/Nmea/Dtm.cs new file mode 100644 index 0000000..2924d6c --- /dev/null +++ b/src/NmeaParser/Nmea/Dtm.cs @@ -0,0 +1,149 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System; + +namespace NmeaParser.Messages +{ + /// + /// Local geodetic datum and datum offsets from a reference datum. + /// + /// + /// This sentence is used to define the datum to which a position location and geographic + /// locations in subsequent sentences, is referenced. Latitude, longitude and altitude offsets + /// from the reference datum, and the selection of reference datum, are also provided. + /// + /// The datum sentence should be transmitted immediately prior to every positional sentence (e.g., GLL, + /// BWC, WPL) that is referenced to a datum other than WGS84, which is the datum recommended by IMO. + /// + /// + /// For all datums the DTM sentence should be transmitted prior to any datum change and periodically at + /// intervals of not greater than 30 seconds. + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")] + [NmeaMessageType("--DTM")] + public class Dtm : NmeaMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Dtm (string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 6) + throw new ArgumentException("Invalid DTM", "message"); + LocalDatumCode = message[0]; + if (message[1].Length > 0) + LocalDatumSubdivisionCode = message[1][0]; + LatitudeOffset = NmeaMessage.StringToDouble(message[2]); + LongitudeOffset = NmeaMessage.StringToDouble(message[3]); + AltitudeOffset = NmeaMessage.StringToDouble(message[4]); + ReferenceDatumCode = message[5]; + } + + /// + /// Local datum code + /// + /// + /// Three character alpha code for local datum. If not one of the listed earth-centered datums, or 999 + /// for user defined datum, use IHO datum code from International Hydrographic Organization Publication S-60 + /// Appendices B and C. String.Empty if unknown. + /// + /// Users should be aware that chart transformations based on IHO S60 parameters may result in significant + /// positional errors when applied to chart data. + /// + /// + /// Common known datum codes are: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
CodeDatum
W84WGS 84
W72WGS 72
S85SGS 85
P90PE 90
999User Defined
OthersIHO Datum Code
+ ///
+ ///
+ public string LocalDatumCode { get; } + + /// + /// Local datum subdivision code. + /// + /// + /// One character subdivision datum code when available or user defined reference character + /// for user defined datums, null field otherwise. Subdivision character from IHO Publication S-60 + /// Appendices B and C. + /// + public char? LocalDatumSubdivisionCode { get; } + + /// + /// Latitude Offset, decimal degrees + /// + /// + /// Latitude and longitude offsets are positive numbers, the altitude offset may be negative. Offsets + /// change with position; position in the local datum is offset from the position in the reference datum in the directions + /// indicated: + /// P_local_datum = P_ref_datum + offset + /// + public double LatitudeOffset { get; } + + /// + /// Longitude Offset in minutes + /// + /// + /// Latitude and longitude offsets are positive numbers, the altitude offset may be negative. Offsets + /// change with position; position in the local datum is offset from the position in the reference datum in the directions + /// indicated: + /// P_local_datum = P_ref_datum + offset + /// + public double LongitudeOffset { get; } + + /// + /// Altitude Offset in minutes + /// + /// + /// Latitude and longitude offsets are positive numbers, the altitude offset may be negative. Offsets + /// change with position; position in the local datum is offset from the position in the reference datum in the directions + /// indicated: + /// P_local_datum = P_ref_datum + offset + /// + public double AltitudeOffset { get; } + + /// + /// Reference datum code + /// + /// + /// + /// Common known datum codes are: + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
CodeDatum
W84WGS 84
W72WGS 72
S85SGS 85
P90PE 90
+ ///
+ ///
+ public string ReferenceDatumCode { get; } + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Gbs.cs b/src/NmeaParser/Nmea/Gbs.cs new file mode 100644 index 0000000..c83edc6 --- /dev/null +++ b/src/NmeaParser/Nmea/Gbs.cs @@ -0,0 +1,135 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System; +using System.Globalization; + +namespace NmeaParser.Messages +{ + /// + /// GNSS Satellite Fault Detection + /// + /// + /// + /// This sentence is used to support Receiver Autonomous Integrity Monitoring (RAIM). Given that a GNSS + /// receiver is tracking enough satellites to perform integrity checks of the positioning quality of the position + /// solution a sentence is needed to report the output of this process to other systems to advise the system + /// user.With the RAIM in the GNSS receiver, the receiver can isolate faults to individual satellites and not + /// use them in its position and velocity calculations.Also, the GNSS receiver can still track the satellite and + /// easily judge when it is back within tolerance.This sentence shall be used for reporting this RAIM + /// information. To perform this integrity function, the GNSS receiver must have at least two observables in + /// addition to the minimum required for navigation.Normally these observables take the form of additional + /// redundant satellites. + /// + /// + /// If only GPS, GLONASS, Galileo, BDS, QZSS, NavIC (IRNSS) is used for the reported position solution + /// the talker ID is GP, GL, GA, GB, GQ, GI respectively and the errors pertain to the individual system.If + /// satellites from multiple systems are used to obtain the reported position solution the talker ID is GN and + /// the errors pertain to the combined solution. + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")] + [NmeaMessageType("--GBS")] + public class Gbs : NmeaMessage, ITimestampedMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Gbs (string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 8) + throw new ArgumentException("Invalid GBS", "message"); + FixTime = StringToTimeSpan(message[0]); + LatitudeError = NmeaMessage.StringToDouble(message[1]); + LongitudeError = NmeaMessage.StringToDouble(message[2]); + AltitudeError = NmeaMessage.StringToDouble(message[3]); + if (int.TryParse(message[4], System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int id)) + SatelliteId = id; + MissedDetectionProbability = NmeaMessage.StringToDouble(message[5]); + BiasEstimate = NmeaMessage.StringToDouble(message[6]); + StandardDeviation = NmeaMessage.StringToDouble(message[7]); + } + /// + /// UTC time of the GGA or GNS fix associated with this sentence. + /// + public TimeSpan FixTime { get; } + + TimeSpan ITimestampedMessage.Timestamp => FixTime; + + /// + /// Expected Error in latitude + /// + /// + /// Expected error in meters due to bias, with noise = 0 + /// + public double LatitudeError { get; } + + /// + /// Expected Error in longitude + /// + /// + /// Expected error in meters due to bias, with noise = 0 + /// + public double LongitudeError { get; } + + /// + /// Expected Error in altitude + /// + /// + /// Expected error in meters due to bias, with noise = 0 + /// + public double AltitudeError { get; } + + /// + /// ID number of most likely failed satellite + /// + /// + /// + /// Satellite ID numbers. To avoid possible confusion caused by repetition of satellite ID numbers when using + /// multiple satellite systems, the following convention has been adopted: + ///
    + ///
  • a) GPS satellites are identified by their PRN numbers, which range from 1 to 32.
  • + ///
  • b) The numbers 33-64 are reserved for SBAS satellites. The SBAS system PRN numbers are 120-138. + /// The offset from NMEA SBAS SV ID to SBAS PRN number is 87. A SBAS PRN number of 120 + /// minus 87 yields the SV ID of 33. The addition of 87 to the SV ID yields the SBAS PRN number.
  • + ///
  • c) The numbers 65-96 are reserved for GLONASS satellites. GLONASS satellites are identified by + /// 64+satellite slot number.The slot numbers are 1 through 24 for the full GLONASS constellation + /// of 24 satellites, this gives a range of 65 through 88. The numbers 89 through 96 are available if + /// slot numbers above 24 are allocated to on-orbit spares. + ///
  • + ///
  • See Note 3 for other GNSS not listed in a), b), or c) above to determine meaning of satellite ID when Talker ID GN is used
  • + ///
+ ///
+ /// + ///
+ public int? SatelliteId { get; } + + /// + /// Probability of missed detection for most likely failed satellite + /// + public double MissedDetectionProbability { get; } + + /// + /// Estimate of bias in meters on most likely failed satellite + /// + public double BiasEstimate { get; } + + /// + /// Standard deviation of bias estimate + /// + public double StandardDeviation { get; } + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Grs.cs b/src/NmeaParser/Nmea/Grs.cs new file mode 100644 index 0000000..8e99a61 --- /dev/null +++ b/src/NmeaParser/Nmea/Grs.cs @@ -0,0 +1,134 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace NmeaParser.Messages +{ + /// + /// GNSS Range Residuals + /// + /// + /// + /// This sentence is used to support Receiver Autonomous Integrity Monitoring (RAIM). Range residuals can be + /// computed in two ways for this process. The basic measurement integration cycle of most navigation filters + /// generates a set of residuals and uses these to update the position state of the receiver. + /// + /// + /// These residuals can be reported with GRS, but because of the fact that these were used to generate the navigation + /// solution they should be recomputed using the new solution in order to reflect the residuals for the position solution in + /// the GGA or GNS sentence. + /// + /// + /// The MODE field should indicate which computation method was used. An integrity process that uses these + /// range residuals would also require GGA or GNS, GSA, and GSV sentences to be sent. + /// + /// + /// If only GPS, or GLONASS, or Galileo, or BDS, or QZSS, or NavIC (IRNSS)is used for the reported position + /// solution, the talker ID is GP, GL, GA, GB, GQ, GI respectively and the range residuals pertain to the individual + /// system. + /// + /// + /// If GPS, GLONASS, Galileo, BDS, QZSS, NavIC (IRNSS) are combined to obtain the position solution multiple + /// GRS sentences are produced, one with the GPS satellites, another with the GLONASS satellites, etc. Each of these + /// GRS sentences shall have talker ID “GN”, to indicate that the satellites are used in a combined solution. The GNSS + /// System ID data field identifies the specific satellite system. It is important to distinguish the residuals from those that + /// would be produced by a GPS-only, GLONASS-only, etc. position solution. In general, the residuals for a combined + /// solution will be different from the residual for a GPS-only, GLONASS-only, etc. solution. + /// + /// + /// When multiple GRS sentences are necessary, use of the NMEA TAG Block structure (§ 7) and the TAG Block + /// Sentence-grouping Parameter (§ 7.9.3) reliably links the related sentences together over any transport medium. + /// + /// + /// When GRS sentences are provided with related GSA and/or GSV sentences, use of the NMEA TAG Block structure + /// (§ 7) and the TAG Block Sentence-grouping Parameter (§ 7.9.3) reliably links the related (different sentence + /// formatters) sentences together over any transport medium. + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")] + [NmeaMessageType("--GRS")] + public class Grs : NmeaMessage, ITimestampedMessage + { + /// + /// Determines the way the residuals were calculated. + /// + public enum GrsMode + { + /// + /// Residuals were used to calculate the position given in the matching GGA or GNS sentence + /// + UsedForPosition, + /// + /// Residuals were recomputed after the GGA or GNS position was computed + /// + RecomputedFromPosition + } + + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Grs (string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 8) + throw new ArgumentException("Invalid Grs", "message"); + FixTime = StringToTimeSpan(message[0]); + Mode = message[1] == "1" ? GrsMode.RecomputedFromPosition : GrsMode.UsedForPosition; + double[] residuals = new double[message.Length - 2]; + for (int i = 2; i < message.Length; i++) + { + residuals[i-2] = NmeaMessage.StringToDouble(message[i]); + } + Residuals = residuals; + } + + /// + /// UTC time of the GGA or GNS fix associated with this sentence + /// + public TimeSpan FixTime { get; } + + /// + /// Residual calculation mode + /// + public GrsMode Mode { get; } + + TimeSpan ITimestampedMessage.Timestamp => FixTime; + + /// + /// Range residuals in meters for satellites used in the navigation solution + /// + /// + /// + /// Order must match order of the satellite ID3 numbers in GSA. When GRS is used GSA and GSV are generally required + /// + /// + /// Notes: + ///
    + ///
  • If the range residual exceeds +99.9 meters, then the decimal part is dropped, resulting in an integer (-103.7 becomes -103). + /// The maximum value for this field is +999.
  • + ///
  • The sense or sign of the range residual is determined by the order of parameters used in the calculation. The + /// expected order is as follows: range residual = calculated range - measured range.
  • + ///
  • When multiple GRS sentences are being sent then their order of transmission must match the order of + /// corresponding GSA sentences.Listeners shall keep track of pairs of GSA and GRS sentences and discard data + /// if pairs are incomplete.
  • + ///
+ ///
+ ///
+ public double[] Residuals { get; } + } +} \ No newline at end of file diff --git a/src/NmeaParser/Nmea/Vlw.cs b/src/NmeaParser/Nmea/Vlw.cs new file mode 100644 index 0000000..a0b2c5d --- /dev/null +++ b/src/NmeaParser/Nmea/Vlw.cs @@ -0,0 +1,56 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System; + +namespace NmeaParser.Messages +{ + /// + /// Dual Ground/Water Distance + /// + /// + /// The distance traveled, relative to the water and over the ground. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")] + [NmeaMessageType("--VLW")] + public class Vlw : NmeaMessage + { + /// + /// Initializes a new instance of the class. + /// + /// The message type + /// The NMEA message values. + public Vlw (string type, string[] message) : base(type, message) + { + if (message == null || message.Length < 7) + throw new ArgumentException("Invalid VLW", "message"); + WaterDistanceCumulative = NmeaMessage.StringToDouble(message[0]); + WaterDistanceSinceReset = NmeaMessage.StringToDouble(message[2]); + GroundDistanceCumulative = NmeaMessage.StringToDouble(message[4]); + GroundDistanceSinceReset = NmeaMessage.StringToDouble(message[6]); + } + + /// Total cumulative water distance, nautical miles + public double WaterDistanceCumulative { get; } + + /// Water distance since reset, nautical miles + public double WaterDistanceSinceReset { get; } + + /// Total cumulative ground distance, nautical miles + public double GroundDistanceCumulative { get; } + + /// Ground distance since reset, nautical miles + public double GroundDistanceSinceReset { get; } + } +} \ No newline at end of file