solution.h
Go to the documentation of this file.
1 /**************************************************************************/ /**
2  * @brief Platform position/attitude solution messages.
3  * @file
4  ******************************************************************************/
5 
6 #pragma once
7 
10 
11 namespace point_one {
12 namespace fusion_engine {
13 namespace messages {
14 
15 // Enforce 4-byte alignment and packing of all data structures and values.
16 // Floating point values are aligned on platforms that require it. This is done
17 // with a combination of setting struct attributes, and manual alignment
18 // within the definitions. See the "Message Packing" section of the README.
19 #pragma pack(push, 1)
20 
21 /**
22  * @defgroup solution_messages Navigation Solution Message Definitions
23  * @brief Output messages containing position, navigation, and time results.
24  * @ingroup messages
25  *
26  * See also @ref messages.
27  */
28 
29 /**
30  * @brief Platform pose solution: position, velocity, attitude (@ref
31  * MessageType::POSE, version 1.2).
32  * @ingroup solution_messages
33  *
34  * @note
35  * All data is timestamped using Point One (P1) time, which is a monotonic
36  * timestamp referenced to the start of the device. Corresponding messages (@ref
37  * GNSSInfoMessage, @ref GNSSSatelliteMessage, etc.) may be associated using
38  * their @ref p1_time values.
39  */
41  static constexpr MessageType MESSAGE_TYPE = MessageType::POSE;
42  static constexpr uint8_t MESSAGE_VERSION = 2;
43  static constexpr int16_t INVALID_UNDULATION = INT16_MIN;
44 
45  /** Set if the device is stationary. */
46  static constexpr uint8_t FLAG_STATIONARY = 0x01;
47 
48  /** The time of the message, in P1 time (beginning at power-on). */
50 
51  /** The GPS time of the message, if available, referenced to 1980/1/6. */
53 
54  /** The type of this position solution. */
56 
57  /**
58  * A bitmask of flags associated with the pose data.
59  *
60  * Added in @ref PoseMessage version 1.2.
61  */
62  uint8_t flags = 0x0;
63 
64  /**
65  * The geoid undulation at at the current location (i.e., the difference
66  * between the WGS-84 ellipsoid and the geoid).
67  *
68  * Height above the ellipsoid can be converted to a corresponding height above
69  * the geoid (orthometric height or height above mean sea level (MSL)) as
70  * follows:
71  *
72  * @f[
73  * h_{orthometric} = h_{ellipsoid} - undulation
74  * @f]
75  *
76  * Stored in units of 0.01 meters: `undulation_m = undulation_cm * 0.01`. Set
77  * to `-32768` if invalid.
78  *
79  * Added in @ref PoseMessage version 1.1.
80  */
81  int16_t undulation_cm = INVALID_UNDULATION;
82 
83  /**
84  * The geodetic latitude, longitude, and altitude (in degrees/degrees/meters),
85  * expressed using the WGS-84 reference ellipsoid.
86  *
87  * @section p1_fe_pose_datum Datum/Epoch Considerations
88  * When comparing two positions, it is very important to make sure they are
89  * compared using the same geodetic datum, defined at the same time (epoch).
90  * Failing to do so can cause very large unexpected differences since the
91  * ground moves in various directions over time due to motion of tectonic
92  * plates.
93  *
94  * For example, the coordinates for a point on the ground in San Francisco
95  * expressed in the ITRF14 datum may differ by multiple meters from the
96  * coordinates for the same point expressed the NAD83 datum. Similarly, the
97  * coordinates for that location expressed in the ITRF14 2017.0 epoch
98  * (January 1, 2017) may differ by 12 cm or more when expressed using the
99  * ITRF14 2021.0 epoch (January 1, 2021).
100  *
101  * The datum and epoch to which the position reported in this message is
102  * aligned depends on the current @ref solution_type.
103  * - @ref SolutionType::AutonomousGPS / @ref SolutionType::DGPS /
104  * @ref SolutionType::PPP - Standalone solutions (i.e., no differential
105  * corrections) are aligned to the WGS-84 datum as broadcast live by GPS
106  * (aligns closely with the ITRF08/14 datums).
107  * - @ref SolutionType::RTKFloat / @ref SolutionType::RTKFixed - When
108  * differential corrections are applied, the reference datum and epoch are
109  * defined by the corrections provider. Point One's Polaris Corrections
110  * Service produces corrections using the ITRF14 datum. See
111  * https://pointonenav.com/polaris for more details.
112  * - @ref SolutionType::Integrate - When the INS is dead reckoning in the
113  * absence of GNSS, vision, or other measurements anchored in absolute world
114  * coordinates, the position solution is defined in the same datum/epoch
115  * specified by the previous solution type (e.g., WGS-84 if previously
116  * standalone GNSS, i.e., @ref SolutionType::AutonomousGPS).
117  */
118  double lla_deg[3] = {NAN, NAN, NAN};
119 
120  /**
121  * The position standard deviation (in meters), resolved with respect to the
122  * local ENU tangent plane: east, north, up.
123  */
124  float position_std_enu_m[3] = {NAN, NAN, NAN};
125 
126  /**
127  * The platform attitude (in degrees), if known, described as intrinsic
128  * Euler-321 angles (yaw, pitch, roll) with respect to the local ENU tangent
129  * plane. Set to `NAN` if attitude is not available.
130  *
131  * @note
132  * The platform body axes are defined as +x forward, +y left, and +z up. A
133  * positive yaw is a left turn, positive pitch points the nose of the vehicle
134  * down, and positive roll is a roll toward the right. Yaw is measured from
135  * east in a counter-clockwise direction. For example, north is +90 degrees
136  * (i.e., `heading = 90.0 - ypr_deg[0]`).
137  */
138  double ypr_deg[3] = {NAN, NAN, NAN};
139 
140  /**
141  * The attitude standard deviation (in degrees): yaw, pitch, roll.
142  */
143  float ypr_std_deg[3] = {NAN, NAN, NAN};
144 
145  /**
146  * The platform velocity (in meters/second), resolved in the body frame. Set
147  * to `NAN` if attitude is not available for the body frame transformation.
148  */
149  double velocity_body_mps[3] = {NAN, NAN, NAN};
150 
151  /**
152  * The velocity standard deviation (in meters/second), resolved in the body
153  * frame.
154  */
155  float velocity_std_body_mps[3] = {NAN, NAN, NAN};
156 
157  /** The estimated aggregate 3D protection level (in meters). */
158  float aggregate_protection_level_m = NAN;
159  /** The estimated 2D horizontal protection level (in meters). */
160  float horizontal_protection_level_m = NAN;
161  /** The estimated vertical protection level (in meters). */
162  float vertical_protection_level_m = NAN;
163 };
164 
165 /**
166  * @brief Auxiliary platform pose information (@ref MessageType::POSE_AUX,
167  * version 1.0).
168  * @ingroup solution_messages
169  */
171  static constexpr MessageType MESSAGE_TYPE = MessageType::POSE_AUX;
172  static constexpr uint8_t MESSAGE_VERSION = 0;
173 
174  /** The time of the message, in P1 time (beginning at power-on). */
176 
177  /**
178  * The position standard deviation (in meters), resolved in the body frame.
179  * Set to `NAN` if attitude is not available for the body frame
180  * transformation.
181  */
182  float position_std_body_m[3] = {NAN, NAN, NAN};
183 
184  /**
185  * The 3x3 position covariance matrix (in m^2), resolved in the local ENU
186  * frame. Values are stored in row-major order.
187  */
188  double position_cov_enu_m2[9] = {NAN};
189 
190  /**
191  * The platform body orientation with respect to the local ENU frame,
192  * represented as a quaternion with the scalar component last (x, y, z, w).
193  */
194  double attitude_quaternion[4] = {NAN, NAN, NAN, NAN};
195 
196  /**
197  * The platform velocity (in meters/second), resolved in the local ENU frame.
198  */
199  double velocity_enu_mps[3] = {NAN, NAN, NAN};
200 
201  /**
202  * The velocity standard deviation (in meters/second), resolved in the local
203  * ENU frame.
204  */
205  float velocity_std_enu_mps[3] = {NAN, NAN, NAN};
206 };
207 
208 /**
209  * @brief Information about the GNSS data used in the @ref PoseMessage with the
210  * corresponding timestamp (@ref MessageType::GNSS_INFO, version 1.1).
211  * @ingroup solution_messages
212  *
213  * @note
214  * The deprecated `last_differential_time` field was removed in version 1.1 of
215  * this message, and was replaced by the new @ref leap_second, @ref num_svs,
216  * @ref corrections_age, and @ref baseline_distance fields. Attempting to use
217  * those fields on version 0 messages will result in undefined behavior.
218  */
220  static constexpr MessageType MESSAGE_TYPE = MessageType::GNSS_INFO;
221  static constexpr uint8_t MESSAGE_VERSION = 1;
222 
223  static constexpr uint16_t INVALID_LEAP_SECOND = 0xFF;
224  static constexpr uint16_t INVALID_AGE = 0xFFFF;
225  static constexpr uint16_t INVALID_DISTANCE = 0xFFFF;
226  static constexpr uint32_t INVALID_REFERENCE_STATION = 0xFFFFFFFF;
227 
228  /** The time of the message, in P1 time (beginning at power-on). */
230 
231  /** The GPS time of the message, if available, referenced to 1980/1/6. */
233 
234  /**
235  * The current UTC leap second (offset between UTC and GPS time), if known.
236  * Set to 0xFF if invalid.
237  *
238  * Added in message version 1.
239  */
240  uint8_t leap_second = INVALID_LEAP_SECOND;
241 
242  /** The number of satellites used in the current position solution. */
243  uint8_t num_svs = 0;
244 
245  uint8_t reserved[2];
246 
247  /**
248  * The age of the most recently received GNSS corrections data (in 0.1
249  * seconds). Set to 0xFFFF if invalid.
250  *
251  * Added in message version 1.
252  */
253  uint16_t corrections_age = INVALID_AGE;
254 
255  /**
256  * The distance between the device and the GNSS corrections base station.
257  * Stored in units of 10 meters:
258  * `baseline_distance_m = baseline_distance * 10`. Set to 0xFFFF if invalid.
259  *
260  * Added in message version 1.
261  */
262  uint16_t baseline_distance = INVALID_DISTANCE;
263 
264  /**
265  * The ID of the GNSS corrections base station, if used. Set to 0xFFFFFFFF if
266  * invalid.
267  */
268  uint32_t reference_station_id = INVALID_REFERENCE_STATION;
269 
270  /** The geometric dilution of precision (GDOP). */
271  float gdop = NAN;
272  /** The position dilution of precision (PDOP). */
273  float pdop = NAN;
274  /** The horizontal dilution of precision (HDOP). */
275  float hdop = NAN;
276  /** The vertical dilution of precision (VDOP). */
277  float vdop = NAN;
278 
279  /** GPS time alignment standard deviation (in seconds). */
280  float gps_time_std_sec = NAN;
281 };
282 
283 /**
284  * @brief Information about the individual satellites used in the @ref
285  * PoseMessage and @ref GNSSInfoMessage with the corresponding timestamp
286  * (@ref MessageType::GNSS_SATELLITE, version 1.0).
287  * @ingroup solution_messages
288  *
289  * This message is followed by `N` @ref SatelliteInfo objects, where `N` is
290  * equal to @ref num_satellites. For example, a message with two satellites
291  * would be serialized as:
292  *
293  * ```
294  * {MessageHeader, GNSSSatelliteMessage, SatelliteInfo, SatelliteInfo, ...}
295  * ```
296  */
298  static constexpr MessageType MESSAGE_TYPE = MessageType::GNSS_SATELLITE;
299  static constexpr uint8_t MESSAGE_VERSION = 0;
300 
301  /** The time of the message, in P1 time (beginning at power-on). */
303 
304  /** The GPS time of the message, if available, referenced to 1980/1/6. */
306 
307  /** The number of known satellites. */
308  uint16_t num_satellites = 0;
309 
310  uint8_t reserved[2] = {0};
311 };
312 
313 /**
314  * @brief Information about an individual satellite (see @ref
315  * GNSSSatelliteMessage).
316  *
317  * For satellites where @ref usage is 0, the satellite may either be currently
318  * tracked by the receiver but not used for navigation, or may just be expected
319  * according to available ephemeris data.
320  */
322  /**
323  * @defgroup satellite_usage Bit definitions for the satellite usage bitmask
324  * (@ref SatelliteInfo::usage).
325  * @{
326  */
327  static constexpr uint8_t SATELLITE_USED = 0x01;
328  /** @} */
329 
330  static constexpr int16_t INVALID_CN0 = 0;
331 
332  /** The GNSS system to which this satellite belongs. */
334 
335  /** The satellite's PRN (or slot number for GLONASS). */
336  uint8_t prn = 0;
337 
338  /**
339  * A bitmask specifying how this satellite was used in the position solution.
340  * Set to 0 if the satellite was not used. See @ref satellite_usage.
341  */
342  uint8_t usage = 0;
343 
344  /**
345  * The carrier-to-noise density ratio (C/N0) for the L1 signal on the
346  * satellite.
347  *
348  * Stored in units of 0.25 dB-Hz: `cn0_dbhz = cn0 * 0.25`. Set to 0 if
349  * invalid. The range of this field is 0.25-63.75 dB-Hz. Values outside of
350  * this range will be clipped to the min/max values.
351  *
352  * @note
353  * If the satellite is not tracking L1 (or the L1-equivalent for other
354  * constellations, e.g., G1 for GLONASS) but another frequency is being used,
355  * that signal's C/N0 value will be reported.
356  *
357  * Added in @ref GNSSSatelliteMessage version 1.1.
358  */
359  uint8_t cn0 = INVALID_CN0;
360 
361  /** The azimuth of the satellite (in degrees). */
362  float azimuth_deg = NAN;
363 
364  /** The elevation of the satellite (in degrees). */
365  float elevation_deg = NAN;
366 };
367 
368 /**
369  * @brief The stages of the device calibration process.
370  * @ingroup solution_messages
371  */
372 enum class CalibrationStage : uint8_t {
373  UNKNOWN = 0, ///< Calibration stage not known.
374  MOUNTING_ANGLE = 1, ///< Estimating IMU mounting angles.
375  DONE = 255, ///< Calibration complete.
376 };
377 
378 /**
379  * @brief Get a human-friendly string name for the specified @ref
380  * CalibrationStage.
381  *
382  * @param val The enum to get the string name for.
383  *
384  * @return The corresponding string name.
385  */
387  switch (val) {
389  return "Unknown";
391  return "IMU Mounting Angles";
393  return "Done";
394  default:
395  return "Unrecognized";
396  }
397 }
398 
399 /**
400  * @brief @ref CalibrationStage stream operator.
401  */
403  stream << to_string(val) << " (" << (int)val << ")";
404  return stream;
405 }
406 
407 /**
408  * @brief Device calibration status update. (@ref
409  * MessageType::CALIBRATION_STATUS, version 1.1).
410  * @brief
411  * @ingroup solution_messages
412  */
414  static constexpr MessageType MESSAGE_TYPE = MessageType::CALIBRATION_STATUS;
415  static constexpr uint8_t MESSAGE_VERSION = 1;
416 
417  /** The most recent P1 time, if available. */
419 
420  /**
421  * @name Calibration State Data
422  * @{
423  */
424 
425  /** The current calibration stage. */
427 
428  uint8_t reserved1[3] = {0};
429 
430  /** The IMU yaw, pitch, and roll mounting angle offsets (in degrees). */
431  float ypr_deg[3] = {NAN, NAN, NAN};
432 
433  /**
434  * The IMU yaw, pitch, and roll mounting angle standard deviations (in
435  * degrees).
436  */
437  float ypr_std_dev_deg[3] = {NAN, NAN, NAN};
438 
439  /** The accumulated calibration travel distance (in meters). */
440  float travel_distance_m = 0.0;
441 
442  uint8_t reserved2[24] = {0};
443 
444  /** @} */
445 
446  /**
447  * @name Calibration Process Status
448  * @{
449  */
450 
451  /**
452  * Set to 1 once the navigation engine state is validated after
453  * initialization.
454  */
455  uint8_t state_verified{0};
456 
457  uint8_t reserved3[3] = {0};
458 
459  /**
460  * The completion percentage for gyro bias estimation, stored with a
461  * scale factor of 0.5% (0-200).
462  */
463  uint8_t gyro_bias_percent_complete = 0;
464 
465  /**
466  * The completion percentage for accelerometer bias estimation, stored with a
467  * scale factor of 0.5% (0-200).
468  */
469  uint8_t accel_bias_percent_complete = 0;
470 
471  /**
472  * The completion percentage for IMU mounting angle estimation, stored with a
473  * scale factor of 0.5% (0-200).
474  */
475  uint8_t mounting_angle_percent_complete = 0;
476 
477  uint8_t reserved4[5] = {0};
478 
479  /** @} */
480 
481  /**
482  * @name Calibration Thresholds
483  * @{
484  */
485 
486  /**
487  * The minimum accumulated calibration travel distance needed to complete
488  * mounting angle calibration.
489  */
490  float min_travel_distance_m = NAN;
491 
492  /**
493  * The max threshold for each of the YPR mounting angle states (in degrees),
494  * above which calibration is incomplete.
495  */
496  float mounting_angle_max_std_dev_deg[3] = {NAN, NAN, NAN};
497 
498  /** @} */
499 };
500 
501 /**
502  * @brief Relative ENU position to base station (@ref
503  * MessageType::RELATIVE_ENU_POSITION, version 1.1).
504  * @ingroup solution_messages
505  *
506  * @note
507  * This message represents the relationship between the navigation engine's
508  * position solution and a nearby RTK base station. It is not used to convey
509  * unfiltered vehicle body orientation measurements generated using multiple
510  * GNSS antennas. See @ref GNSSAttitudeOutput instead.
511  */
513  static constexpr MessageType MESSAGE_TYPE =
515  static constexpr uint8_t MESSAGE_VERSION = 1;
516 
517  static constexpr uint32_t INVALID_REFERENCE_STATION = 0xFFFFFFFF;
518 
519  /** The time of the message, in P1 time (beginning at power-on). */
521 
522  /** The GPS time of the message, if available, referenced to 1980/1/6. */
524 
525  /** The type of this position solution. */
527 
528  uint8_t reserved[3] = {0};
529 
530  /** The ID of the differential base station. */
531  uint32_t reference_station_id = INVALID_REFERENCE_STATION;
532 
533  /**
534  * The relative position (in meters), resolved in the local ENU frame.
535  *
536  * @note
537  * If a differential solution to the base station is not available, these
538  * values will be `NAN`.
539  */
540  double relative_position_enu_m[3] = {NAN, NAN, NAN};
541 
542  /**
543  * The position standard deviation (in meters), resolved with respect to the
544  * local ENU tangent plane: east, north, up.
545  *
546  * @note
547  * If a differential solution to the base station is not available, these
548  * values will be `NAN`.
549  */
550  float position_std_enu_m[3] = {NAN, NAN, NAN};
551 };
552 
553 #pragma pack(pop)
554 
555 } // namespace messages
556 } // namespace fusion_engine
557 } // namespace point_one
@ POSE_AUX
PoseAuxMessage
MessageType
Identifiers for the defined output message types.
Definition: defs.h:34
Library portability helper definitions.
SolutionType
Navigation solution type definitions.
Definition: defs.h:503
@ UNKNOWN
Timestamp p1_time
The time of the message, in P1 time (beginning at power-on).
Definition: solution.h:302
P1_CONSTEXPR_FUNC const char * to_string(ConfigType type)
Get a human-friendly string name for the specified ConfigType.
@ MOUNTING_ANGLE
Estimating IMU mounting angles.
#define P1_ALIGNAS(N)
Definition: portability.h:57
Device calibration status update.
Definition: solution.h:413
@ DONE
Calibration complete.
@ GNSS_INFO
GNSSInfoMessage
Timestamp p1_time
The time of the message, in P1 time (beginning at power-on).
Definition: solution.h:49
@ CALIBRATION_STATUS
CalibrationStatusMessage
@ GNSS_SATELLITE
GNSSSatelliteMessage
The base class for all message payloads.
Definition: defs.h:687
Information about an individual satellite (see GNSSSatelliteMessage).
Definition: solution.h:321
Timestamp p1_time
The time of the message, in P1 time (beginning at power-on).
Definition: solution.h:520
@ POSE
PoseMessage
@ Invalid
Invalid, no position available.
GNSS signal and frequency type definitions.
Definition: logging.h:38
Auxiliary platform pose information (MessageType::POSE_AUX, version 1.0).
Definition: solution.h:170
Timestamp p1_time
The time of the message, in P1 time (beginning at power-on).
Definition: solution.h:175
Timestamp gps_time
The GPS time of the message, if available, referenced to 1980/1/6.
Definition: solution.h:232
std::ostream p1_ostream
Definition: portability.h:75
Timestamp gps_time
The GPS time of the message, if available, referenced to 1980/1/6.
Definition: solution.h:305
p1_ostream & operator<<(p1_ostream &stream, ConfigType type)
ConfigType stream operator.
CalibrationStage
The stages of the device calibration process.
Definition: solution.h:372
#define P1_CONSTEXPR_FUNC
Definition: portability.h:105
Platform pose solution: position, velocity, attitude (MessageType::POSE, version 1....
Definition: solution.h:40
SatelliteType
System/constellation type definitions.
Definition: signal_defs.h:27
Timestamp gps_time
The GPS time of the message, if available, referenced to 1980/1/6.
Definition: solution.h:52
Timestamp p1_time
The most recent P1 time, if available.
Definition: solution.h:418
@ RELATIVE_ENU_POSITION
RelativeENUPositionMessage
Information about the GNSS data used in the PoseMessage with the corresponding timestamp (MessageType...
Definition: solution.h:219
@ UNKNOWN
Calibration stage not known.
Relative ENU position to base station (MessageType::RELATIVE_ENU_POSITION, version 1....
Definition: solution.h:512
Point One FusionEngine output message common definitions.
Information about the individual satellites used in the PoseMessage and GNSSInfoMessage with the corr...
Definition: solution.h:297
Generic timestamp representation.
Definition: defs.h:588
SolutionType solution_type
The type of this position solution.
Definition: solution.h:55
Timestamp gps_time
The GPS time of the message, if available, referenced to 1980/1/6.
Definition: solution.h:523
Timestamp p1_time
The time of the message, in P1 time (beginning at power-on).
Definition: solution.h:229