4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifndef XCSOAR_NMEA_INFO_H
25 #define XCSOAR_NMEA_INFO_H
27 #include "NMEA/Validity.hpp"
28 #include "NMEA/ExternalSettings.hpp"
29 #include "NMEA/Acceleration.hpp"
30 #include "NMEA/Attitude.hpp"
31 #include "SwitchState.hpp"
32 #include "Time/BrokenDateTime.hpp"
33 #include "Geo/GeoPoint.hpp"
34 #include "Atmosphere/Pressure.hpp"
35 #include "DeviceInfo.hpp"
36 #include "FLARM/Data.hpp"
37 #include "Geo/SpeedVector.hpp"
39 #include <type_traits>
41 enum class FixQuality
: uint8_t {
58 static constexpr unsigned MAXSATELLITES
= 12;
67 FixQuality fix_quality
;
68 Validity fix_quality_available
;
71 * Number of satellites used for gps fix. -1 means "unknown".
74 Validity satellites_used_available
;
76 /** GPS Satellite ids */
77 int satellite_ids
[MAXSATELLITES
];
78 Validity satellite_ids_available
;
80 /** Horizontal dilution of precision */
84 * Is the fix real? (no replay, no simulator)
88 /** Is XCSoar in replay mode? */
92 * Did the simulator provide the GPS position?
98 * Was this fix obtained from an Android InternalGPS device? If
99 * yes, then link timeout detection is disabled, because we get
100 * notifications from Android when the GPS gets disconnected.
102 bool android_internal_gps
;
106 void Expire(fixed now
);
110 * A struct that holds all the parsed data read from the connected devices
114 * A monotonic wall clock time, in seconds, with an undefined
115 * reference. This may get updated even if the device doesn't send
116 * any data. It is used to update and check the #Validity
117 * attributes in this struct.
122 * Is the device alive? This attribute gets updated each time a
123 * NMEA line was successfully parsed.
129 AccelerationState acceleration
;
131 AttitudeState attitude
;
133 Validity location_available
;
135 /** location of aircraft */
138 Validity track_available
;
140 /** track angle in degrees true */
148 * Did #TrueAirspeed and/or #IndicatedAirspeed come from an
149 * instrument? If false, then it was calculated (from ground speed
154 Validity ground_speed_available
;
157 * Is air speed information available?
158 * If not, will be estimated from ground speed and wind estimate
159 * @see TrueAirspeed in Aircraft
161 Validity airspeed_available
;
164 * Speed over ground in m/s
166 * @see IndicatedAirspeed
171 * True air speed (m/s)
173 * @see IndicatedAirspeed
178 * Indicated air speed (m/s)
181 * @see AirDensityRatio
183 fixed indicated_airspeed
;
189 Validity gps_altitude_available
;
191 /** GPS altitude AMSL (m) */
195 * Static pressure value [Pa].
197 AtmosphericPressure static_pressure
;
198 Validity static_pressure_available
;
201 * Pitot pressure value [Pa].
203 AtmosphericPressure pitot_pressure
;
204 Validity pitot_pressure_available
;
207 * Dynamic pressure value = pitot_pressure - static_pressure [Pa].
208 * Use only to compute indicated airspeed.
210 AtmosphericPressure dyn_pressure
;
211 Validity dyn_pressure_available
;
214 * Generic sensor calibration data for linear sensors.
215 * Used by some sensors e.g.:
216 * 1) pitot pressure offset relative to static_pressure [hPa].
217 * 2) outside air temperature sensor
218 * 3) battery voltage measurement
220 fixed sensor_calibration_offset
;
221 fixed sensor_calibration_factor
; // 0 is not a valid factor.
222 Validity sensor_calibration_available
;
225 * Is a barometric altitude available?
228 Validity baro_altitude_available
;
231 * Barometric altitude (if available)
232 * @see BaroAltitudeAvailable
238 * Pressure altitude, which is the BaroAltitude with QNH=1013.25 as reference (if available)
239 * @see BaroAltitudeAvailable
242 fixed pressure_altitude
;
243 Validity pressure_altitude_available
;
246 * Is the barometric altitude given by a "weak" source? This is
247 * used to clear the PGRMZ barometric altitude when a FLARM is
248 * detected, to switch from barometric altitude to pressure
251 bool baro_altitude_weak
;
254 * Is the pressure altitude given by a "weak" source? This is used
255 * to choose vendor-specific NMEA sentences over a semi-generic one
256 * like PGRMZ. Needed when Vega is improperly muxed with FLARM, to
257 * use Vega's pressure altitude instead of alternating between both.
259 bool pressure_altitude_weak
;
266 * Did the device provide a time value?
268 Validity time_available
;
271 * Global time (seconds after UTC midnight)
275 /** GPS date and time (UTC) */
276 BrokenDateTime date_time_utc
;
279 * Is the BrokenDate part of #date_time_utc available?
288 * Is an external gross, non-compensated, vertical speed vario signal present?
291 Validity noncomp_vario_available
;
294 * Is an external total energy vario signal available?
295 * @see TotalEnergyVario
297 Validity total_energy_vario_available
;
300 * Is an external netto vario signal available?
303 Validity netto_vario_available
;
306 * Gross, non-compensated aircraft vertical speed (m/s, up positive)
307 * @see NoncompVarioAvailable
312 * Rate of change of total energy of aircraft (m/s, up positive)
313 * @see TotalEnergyVarioAvailable
315 fixed total_energy_vario
;
318 * Vertical speed of air mass (m/s, up positive)
319 * @see NettoVarioAvailable
328 * Settings received from external devices.
330 ExternalSettings settings
;
337 * Is external wind information available?
338 * @see ExternalWindSpeed
339 * @see ExternalWindDirection
341 Validity external_wind_available
;
344 * The wind read from the device. If ExternalWindAvailable is
345 * false, then this value is undefined.
347 SpeedVector external_wind
;
350 * Is temperature information available?
351 * @see OutsideAirTemperature
353 bool temperature_available
;
355 * Temperature of outside air (if available)
356 * @see TemperatureAvailable
361 * Is humidity information available?
362 * @see RelativeHumidity
364 bool humidity_available
;
366 * Humidity of outside air (if available)
367 * @see HumidityAvailable
375 Validity engine_noise_level_available
;
376 unsigned engine_noise_level
;
378 Validity voltage_available
;
380 /** Battery supply voltage information (if available) */
383 Validity battery_level_available
;
385 /** Battery supply information in percent (0.0 - 100.0; if available) */
388 /** Switch state of the user inputs */
389 SwitchState switch_state
;
392 Validity stall_ratio_available
;
397 * Information about the "secondary" device, e.g. the GPS connected
398 * "behind" the LXNAV V7.
400 DeviceInfo secondary_device
;
407 bool HasTimeAdvancedSince(const NMEAInfo
&last
) const {
408 return time_available
&& last
.time_available
&& time
> last
.time
;
412 bool HasTimeRetreatedSince(const NMEAInfo
&last
) const {
413 return !last
.time_available
|| (time_available
&& time
< last
.time
);
417 * Returns a #BrokenDate referring to the given time stamp (all
418 * UTC). This object's #date_time_utc and #time attributes are used
419 * to calculate the date.
421 * @param other_time the time stamp (see attribute #time)
424 BrokenDateTime
GetDateTimeAt(fixed other_time
) const;
426 bool MovementDetected() const {
427 return ground_speed_available
&& ground_speed
> fixed(2);
431 * Sets a fake location, and marks it as "unavailable". This is
432 * used during startup to move the glider symbol to the home
435 void SetFakeLocation(const GeoPoint
&_location
, const fixed _altitude
) {
436 location
= _location
;
437 location_available
.Clear();
438 gps_altitude
= _altitude
;
439 gps_altitude_available
.Clear();
442 void ProvideTime(fixed time
);
443 void ProvideDate(const BrokenDate
&date
);
446 * Provide a "true" barometric altitude, but only use it if the
447 * previous altitude was not present or the same/lower priority.
449 void ProvideBaroAltitudeTrue(fixed value
) {
450 baro_altitude
= value
;
451 baro_altitude_weak
= false;
452 baro_altitude_available
.Update(clock
);
456 * Same as ProvideBaroAltitudeTrue(), but don't overwrite a "strong"
459 void ProvideWeakBaroAltitude(fixed value
) {
460 if (baro_altitude_available
&& !baro_altitude_weak
)
461 /* don't overwrite "strong" value */
464 baro_altitude
= value
;
465 baro_altitude_weak
= true;
466 baro_altitude_available
.Update(clock
);
470 * Clear the barometric altitude value if it is "weak".
472 void ClearWeakBaroAltitude() {
473 if (baro_altitude_available
&& baro_altitude_weak
)
474 baro_altitude_available
.Clear();
478 * Provide pressure altitude above 1013 hPa, but only use it if
479 * the previous altitude was not present or the same/lower priority.
481 void ProvidePressureAltitude(fixed value
) {
482 pressure_altitude
= value
;
483 pressure_altitude_weak
= false;
484 pressure_altitude_available
.Update(clock
);
488 * Same as ProvidePressureAltitude(), but don't overwrite a "strong"
491 void ProvideWeakPressureAltitude(fixed value
) {
492 if (pressure_altitude_available
&& !pressure_altitude_weak
)
493 /* don't overwrite "strong" value */
496 pressure_altitude
= value
;
497 pressure_altitude_weak
= true;
498 pressure_altitude_available
.Update(clock
);
502 * Clear the pressure altitude value if it is "weak".
504 void ClearWeakPressureAltitude() {
505 if (pressure_altitude_available
&& pressure_altitude_weak
)
506 pressure_altitude_available
.Clear();
510 * Provide barometric altitude from a static pressure sensor, but
511 * only use it if the previous altitude was not present or the
512 * same/lower priority.
514 void ProvideStaticPressure(AtmosphericPressure value
) {
515 static_pressure
= value
;
516 static_pressure_available
.Update(clock
);
520 * Provide dynamic pressure from a pitot tube.
521 * Use only to compute indicated airspeed when static pressure is known.
522 * When both pitot- and dynamic pressure are available use dynamic.
524 void ProvideDynamicPressure(AtmosphericPressure value
) {
525 dyn_pressure
= value
;
526 dyn_pressure_available
.Update(clock
);
530 * Used to compute indicated airspeed
531 * when static pressure is known.
532 * Value already includes calibration data.
534 void ProvidePitotPressure(AtmosphericPressure value
) {
535 pitot_pressure
= value
;
536 pitot_pressure_available
.Update(clock
);
540 * Used only as a config value that should be saved.
542 * Currently used for:
543 * battery voltage measurement (multiplier)
544 * offset between the pitot- and the static pressure sensor in hPa (zero).
547 void ProvideSensorCalibration(fixed value
, fixed offset
) {
548 sensor_calibration_factor
= value
;
549 sensor_calibration_offset
= offset
;
550 sensor_calibration_available
.Update(clock
);
554 * Returns the pressure altitude, and falls back to the barometric
555 * altitude or the GPS altitude. The "first" element is false if no
556 * altitude is available. The "second" element contains the
557 * altitude value [m] if "first" is true.
560 std::pair
<bool, fixed
> GetAnyAltitude() const {
561 return pressure_altitude_available
562 ? std::make_pair(true, pressure_altitude
)
563 : (baro_altitude_available
564 ? std::make_pair(true, baro_altitude
)
565 : (gps_altitude_available
566 ? std::make_pair(true, gps_altitude
)
567 : std::make_pair(false, fixed(0))));
571 * Set both true airspeed and indicated airspeed to this value
572 * [m/s]. This is used by device drivers when it is not documented
573 * whether the airspeed variable is TAS or IAS.
575 void ProvideBothAirspeeds(fixed as
) {
576 indicated_airspeed
= true_airspeed
= as
;
577 airspeed_available
.Update(clock
);
578 airspeed_real
= true;
582 * Set both true airspeed and indicated airspeed to two different
585 void ProvideBothAirspeeds(fixed ias
, fixed tas
) {
586 indicated_airspeed
= ias
;
588 airspeed_available
.Update(clock
);
589 airspeed_real
= true;
593 * Set the true airspeed [m/s] and derive the indicated airspeed
594 * from it, using the specified altitude [m].
596 void ProvideTrueAirspeedWithAltitude(fixed tas
, fixed altitude
);
599 * Set the indicated airspeed [m/s] and derive the true airspeed
600 * from it, using the specified altitude [m].
602 void ProvideIndicatedAirspeedWithAltitude(fixed ias
, fixed altitude
);
605 * Set the true airspeed [m/s] and derive the indicated airspeed
606 * from it, using the current altitude.
608 void ProvideTrueAirspeed(fixed tas
);
611 * Set the indicated airspeed [m/s] and derive the true airspeed
612 * from it, using the current altitude.
614 void ProvideIndicatedAirspeed(fixed ias
);
617 * Set the gross, non-compensated, plain-old vertical speed vario value [m/s].
619 void ProvideNoncompVario(fixed value
) {
620 noncomp_vario
= value
;
621 noncomp_vario_available
.Update(clock
);
625 * Set the barometric TE vario value [m/s].
627 void ProvideTotalEnergyVario(fixed value
) {
628 total_energy_vario
= value
;
629 total_energy_vario_available
.Update(clock
);
633 * Set the barometric netto vario value [m/s].
635 void ProvideNettoVario(fixed value
) {
637 netto_vario_available
.Update(clock
);
641 * Set the external wind value.
643 void ProvideExternalWind(const SpeedVector
&value
) {
644 external_wind
= value
;
645 external_wind_available
.Update(clock
);
649 * Clears all information, start with tabula rasa.
654 * Check the expiry time of the device connection with the wall
655 * clock time. This should be called from a periodic timer. The
656 * GPS time cannot be used here, because a disconnected device would
657 * not update its GPS time.
659 void ExpireWallClock();
662 * Check expiry times of all attributes which have a time stamp
663 * associated with them. This should be called after the GPS time
664 * stamp has been updated.
669 * Adds data from the specified object, unless already present in
672 * Note that this does not copy calculated values which are managed
673 * outside of the NMEA parser.
675 void Complement(const NMEAInfo
&add
);
678 static_assert(std::is_trivial
<NMEAInfo
>::value
, "type is not trivial");