Added DTM, GBS, GRS and VLW message types

This commit is contained in:
Morten Nielsen 2020-07-29 12:15:43 -07:00
parent 2fb8c32271
commit eb61c55302
4 changed files with 474 additions and 0 deletions

149
src/NmeaParser/Nmea/Dtm.cs Normal file
View file

@ -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
{
/// <summary>
/// Local geodetic datum and datum offsets from a reference datum.
/// </summary>
/// <remarks>
/// <para>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.</para>
/// <para>
/// The datum sentence should be transmitted immediately prior to every positional sentence (e.g., <c>GLL</c>,
/// <c>BWC</c>, <c>WPL</c>) that is referenced to a datum other than WGS84, which is the datum recommended by IMO.
/// </para>
/// <para>
/// For all datums the DTM sentence should be transmitted prior to any datum change and periodically at
/// intervals of not greater than 30 seconds.
/// </para>
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")]
[NmeaMessageType("--DTM")]
public class Dtm : NmeaMessage
{
/// <summary>
/// Initializes a new instance of the <see cref="Gll"/> class.
/// </summary>
/// <param name="type">The message type</param>
/// <param name="message">The NMEA message values.</param>
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];
}
/// <summary>
/// Local datum code
/// </summary>
/// <remarks>
/// <para>Three character alpha code for local datum. If not one of the listed earth-centered datums, or <c>999</c>
/// for user defined datum, use IHO datum code from International Hydrographic Organization Publication S-60
/// Appendices B and C. String.Empty if unknown.</para>
/// <para>
/// Users should be aware that chart transformations based on IHO S60 parameters may result in significant
/// positional errors when applied to chart data.
/// </para>
/// <para>
/// Common known datum codes are:
/// <table>
/// <tr>
/// <th>Code</th>
/// <th>Datum</th>
/// </tr>
/// <tr><td><c>W84</c></td><td>WGS 84</td></tr>
/// <tr><td><c>W72</c></td><td>WGS 72</td></tr>
/// <tr><td><c>S85</c></td><td>SGS 85</td></tr>
/// <tr><td><c>P90</c></td><td>PE 90</td></tr>
/// <tr><td><c>999</c></td><td>User Defined</td></tr>
/// <tr><td><c>Others</c></td><td>IHO Datum Code</td></tr>
/// </table>
/// </para>
/// </remarks>
public string LocalDatumCode { get; }
/// <summary>
/// Local datum subdivision code.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public char? LocalDatumSubdivisionCode { get; }
/// <summary>
/// Latitude Offset, decimal degrees
/// </summary>
/// <remarks>
/// 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:
/// <c>P_local_datum = P_ref_datum + offset</c>
/// </remarks>
public double LatitudeOffset { get; }
/// <summary>
/// Longitude Offset in minutes
/// </summary>
/// <remarks>
/// 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:
/// <c>P_local_datum = P_ref_datum + offset</c>
/// </remarks>
public double LongitudeOffset { get; }
/// <summary>
/// Altitude Offset in minutes
/// </summary>
/// <remarks>
/// 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:
/// <c>P_local_datum = P_ref_datum + offset</c>
/// </remarks>
public double AltitudeOffset { get; }
/// <summary>
/// Reference datum code
/// </summary>
/// <remarks>
/// <para>
/// Common known datum codes are:
/// <table>
/// <tr>
/// <th>Code</th>
/// <th>Datum</th>
/// </tr>
/// <tr><td><c>W84</c></td><td>WGS 84</td></tr>
/// <tr><td><c>W72</c></td><td>WGS 72</td></tr>
/// <tr><td><c>S85</c></td><td>SGS 85</td></tr>
/// <tr><td><c>P90</c></td><td>PE 90</td></tr>
/// </table>
/// </para>
/// </remarks>
public string ReferenceDatumCode { get; }
}
}

135
src/NmeaParser/Nmea/Gbs.cs Normal file
View file

@ -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
{
/// <summary>
/// GNSS Satellite Fault Detection
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")]
[NmeaMessageType("--GBS")]
public class Gbs : NmeaMessage, ITimestampedMessage
{
/// <summary>
/// Initializes a new instance of the <see cref="Gbs"/> class.
/// </summary>
/// <param name="type">The message type</param>
/// <param name="message">The NMEA message values.</param>
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]);
}
/// <summary>
/// UTC time of the GGA or GNS fix associated with this sentence.
/// </summary>
public TimeSpan FixTime { get; }
TimeSpan ITimestampedMessage.Timestamp => FixTime;
/// <summary>
/// Expected Error in latitude
/// </summary>
/// <remarks>
/// Expected error in meters due to bias, with noise = 0
/// </remarks>
public double LatitudeError { get; }
/// <summary>
/// Expected Error in longitude
/// </summary>
/// <remarks>
/// Expected error in meters due to bias, with noise = 0
/// </remarks>
public double LongitudeError { get; }
/// <summary>
/// Expected Error in altitude
/// </summary>
/// <remarks>
/// Expected error in meters due to bias, with noise = 0
/// </remarks>
public double AltitudeError { get; }
/// <summary>
/// ID number of most likely failed satellite
/// </summary>
/// <remarks>
/// <para>
/// 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:
/// <ul>
/// <li>a) GPS satellites are identified by their PRN numbers, which range from 1 to 32.</li>
/// <li>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.</li>
/// <li>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.
/// </li>
/// <li>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</li>
/// </ul>
/// </para>
///
/// </remarks>
public int? SatelliteId { get; }
/// <summary>
/// Probability of missed detection for most likely failed satellite
/// </summary>
public double MissedDetectionProbability { get; }
/// <summary>
/// Estimate of bias in meters on most likely failed satellite
/// </summary>
public double BiasEstimate { get; }
/// <summary>
/// Standard deviation of bias estimate
/// </summary>
public double StandardDeviation { get; }
}
}

134
src/NmeaParser/Nmea/Grs.cs Normal file
View file

@ -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
{
/// <summary>
/// GNSS Range Residuals
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// <para>
/// 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.
/// </para>
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")]
[NmeaMessageType("--GRS")]
public class Grs : NmeaMessage, ITimestampedMessage
{
/// <summary>
/// Determines the way the <see cref="Grs"/> residuals were calculated.
/// </summary>
public enum GrsMode
{
/// <summary>
/// Residuals were used to calculate the position given in the matching GGA or GNS sentence
/// </summary>
UsedForPosition,
/// <summary>
/// Residuals were recomputed after the GGA or GNS position was computed
/// </summary>
RecomputedFromPosition
}
/// <summary>
/// Initializes a new instance of the <see cref="Gbs"/> class.
/// </summary>
/// <param name="type">The message type</param>
/// <param name="message">The NMEA message values.</param>
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;
}
/// <summary>
/// UTC time of the GGA or GNS fix associated with this sentence
/// </summary>
public TimeSpan FixTime { get; }
/// <summary>
/// Residual calculation mode
/// </summary>
public GrsMode Mode { get; }
TimeSpan ITimestampedMessage.Timestamp => FixTime;
/// <summary>
/// Range residuals in meters for satellites used in the navigation solution
/// </summary>
/// <remarks>
/// <para>
/// Order must match order of the satellite ID3 numbers in GSA. When GRS is used GSA and GSV are generally required
/// </para>
/// <para>
/// Notes:
/// <ul>
/// <li>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.</li>
/// <li>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.</li>
/// <li>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.</li>
/// </ul>
/// </para>
/// </remarks>
public double[] Residuals { get; }
}
}

View file

@ -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
{
/// <summary>
/// Dual Ground/Water Distance
/// </summary>
/// <remarks>
/// The distance traveled, relative to the water and over the ground.
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dtm")]
[NmeaMessageType("--VLW")]
public class Vlw : NmeaMessage
{
/// <summary>
/// Initializes a new instance of the <see cref="Vlw"/> class.
/// </summary>
/// <param name="type">The message type</param>
/// <param name="message">The NMEA message values.</param>
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]);
}
/// <summary>Total cumulative water distance, nautical miles</summary>
public double WaterDistanceCumulative { get; }
/// <summary>Water distance since reset, nautical miles</summary>
public double WaterDistanceSinceReset { get; }
/// <summary>Total cumulative ground distance, nautical miles</summary>
public double GroundDistanceCumulative { get; }
/// <summary>Ground distance since reset, nautical miles</summary>
public double GroundDistanceSinceReset { get; }
}
}