LCOV - code coverage report
Current view: top level - AP_GPS - AP_GPS.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 93 122 76.2 %
Date: 2026-09-09 11:02:08 Functions: 47 52 90.4 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : #pragma once
      16             : 
      17             : #include "AP_GPS_config.h"
      18             : #include "AP_GPS_FixType.h"
      19             : 
      20             : #if AP_GPS_ENABLED
      21             : 
      22             : #include <AP_HAL/AP_HAL.h>
      23             : #include <inttypes.h>
      24             : #include <AP_Common/AP_Common.h>
      25             : #include <AP_Common/Location.h>
      26             : #include <AP_Param/AP_Param.h>
      27             : #include "GPS_detect_state.h"
      28             : #include <AP_Math/AP_Math.h>
      29             : #include <AP_MSP/msp.h>
      30             : #include <AP_ExternalAHRS/AP_ExternalAHRS.h>
      31             : #include <SITL/SIM_GPS.h>
      32             : #include <GCS_MAVLink/GCS_MAVLink.h>
      33             : 
      34             : #define GPS_UNKNOWN_DOP UINT16_MAX // set unknown DOP's to maximum value, which is also correct for MAVLink
      35             : 
      36             : // the number of GPS leap seconds - copied into SIM_GPS.cpp
      37             : #define GPS_LEAPSECONDS_MILLIS 18000ULL
      38             : 
      39             : #define UNIX_OFFSET_MSEC (17000ULL * 86400ULL + 52ULL * 10ULL * AP_MSEC_PER_WEEK - GPS_LEAPSECONDS_MILLIS)
      40             : 
      41             : #if GPS_MOVING_BASELINE
      42             : #include "MovingBase.h"
      43             : #endif // GPS_MOVING_BASELINE
      44             : 
      45             : class AP_GPS_Backend;
      46             : class RTCM3_Parser;
      47             : 
      48             : /// @class AP_GPS
      49             : /// GPS driver main class
      50             : class AP_GPS
      51             : {
      52             :     friend class AP_GPS_Blended;
      53             :     friend class AP_GPS_ERB;
      54             :     friend class AP_GPS_GSOF;
      55             :     friend class AP_GPS_MAV;
      56             :     friend class AP_GPS_MSP;
      57             :     friend class AP_GPS_ExternalAHRS;
      58             :     friend class AP_GPS_NMEA;
      59             :     friend class AP_GPS_NOVA;
      60             :     friend class AP_GPS_PX4;
      61             :     friend class AP_GPS_SBF;
      62             :     friend class AP_GPS_SBP;
      63             :     friend class AP_GPS_SBP2;
      64             :     friend class AP_GPS_SIRF;
      65             :     friend class AP_GPS_UBLOX;
      66             :     friend class AP_GPS_Backend;
      67             :     friend class AP_GPS_DroneCAN;
      68             :     friend class AP_GPS_UBLOX_CFGv2;
      69             : 
      70             : public:
      71             :     AP_GPS();
      72             : 
      73             :     /* Do not allow copies */
      74             :     CLASS_NO_COPY(AP_GPS);
      75             : 
      76   478764967 :     static AP_GPS *get_singleton() {
      77   478764967 :         return _singleton;
      78             :     }
      79             : 
      80             :     // allow threads to lock against GPS update
      81        4323 :     HAL_Semaphore &get_semaphore(void) {
      82        4323 :         return rsem;
      83             :     }
      84             :     
      85             :     // GPS driver types
      86             :     enum GPS_Type {
      87             :         GPS_TYPE_NONE  = 0,
      88             :         GPS_TYPE_AUTO  = 1,
      89             :         GPS_TYPE_UBLOX = 2,
      90             :         // GPS_TYPE_MTK   = 3,  // driver removed
      91             :         // GPS_TYPE_MTK19 = 4,  // driver removed
      92             :         GPS_TYPE_NMEA  = 5,
      93             :         GPS_TYPE_SIRF  = 6,
      94             :         GPS_TYPE_HIL   = 7,
      95             :         GPS_TYPE_SBP   = 8,
      96             :         GPS_TYPE_UAVCAN = 9,
      97             :         GPS_TYPE_SBF   = 10,
      98             :         GPS_TYPE_GSOF  = 11,
      99             :         GPS_TYPE_ERB = 13,
     100             :         GPS_TYPE_MAV = 14,
     101             :         GPS_TYPE_NOVA = 15,
     102             :         GPS_TYPE_HEMI = 16, // hemisphere NMEA
     103             :         GPS_TYPE_UBLOX_RTK_BASE = 17,
     104             :         GPS_TYPE_UBLOX_RTK_ROVER = 18,
     105             :         GPS_TYPE_MSP = 19,
     106             :         GPS_TYPE_ALLYSTAR = 20, // AllyStar NMEA
     107             :         GPS_TYPE_EXTERNAL_AHRS = 21,
     108             :         GPS_TYPE_UAVCAN_RTK_BASE = 22,
     109             :         GPS_TYPE_UAVCAN_RTK_ROVER = 23,
     110             :         GPS_TYPE_UNICORE_NMEA = 24,
     111             :         GPS_TYPE_UNICORE_MOVINGBASE_NMEA = 25,
     112             :         GPS_TYPE_SBF_DUAL_ANTENNA = 26,
     113             : #if AP_SIM_GPS_ENABLED
     114             :         GPS_TYPE_SITL = 100,
     115             : #endif
     116             :     };
     117             : 
     118             :     // convenience methods for working out what general type an instance is:
     119             :     bool is_rtk_base(uint8_t instance) const;
     120             :     bool is_rtk_rover(uint8_t instance) const;
     121             : 
     122             :     // return the instance whose moving baseline rover solution provides the
     123             :     // yaw reported for this instance by gps_yaw_deg
     124             :     uint8_t yaw_source_instance(uint8_t instance) const;
     125             : 
     126             :     // params for an instance:
     127             :     class Params {
     128             :     public:
     129             :         // Constructor
     130             :         Params(void);
     131             : 
     132             :         AP_Enum<GPS_Type> type;
     133             :         AP_Int16 gnss_mode;
     134             :         AP_Int16 rate_ms;   // this parameter should always be accessed using get_rate_ms()
     135             :         AP_Vector3f antenna_offset;
     136             :         AP_Int16 delay_ms;
     137             :         AP_Int8  com_port;
     138             : #if HAL_ENABLE_DRONECAN_DRIVERS
     139             :         AP_Int32 node_id;
     140             :         AP_Int32 override_node_id;
     141             : #endif
     142             : #if GPS_MOVING_BASELINE
     143             :         MovingBase mb_params;
     144             : #endif // GPS_MOVING_BASELINE
     145             : 
     146             :         static const struct AP_Param::GroupInfo var_info[];
     147             :     };
     148             : 
     149             :     // Aliases for AP_GPS_FixType values, for backwards compatibility with scripting
     150             :     static constexpr uint8_t NO_GPS                  = (uint8_t)AP_GPS_FixType::NO_GPS;
     151             :     static constexpr uint8_t NO_FIX                  = (uint8_t)AP_GPS_FixType::NONE;
     152             :     static constexpr uint8_t GPS_OK_FIX_2D           = (uint8_t)AP_GPS_FixType::FIX_2D;
     153             :     static constexpr uint8_t GPS_OK_FIX_3D           = (uint8_t)AP_GPS_FixType::FIX_3D;
     154             :     static constexpr uint8_t GPS_OK_FIX_3D_DGPS      = (uint8_t)AP_GPS_FixType::DGPS;
     155             :     static constexpr uint8_t GPS_OK_FIX_3D_RTK_FLOAT = (uint8_t)AP_GPS_FixType::RTK_FLOAT;
     156             :     static constexpr uint8_t GPS_OK_FIX_3D_RTK_FIXED = (uint8_t)AP_GPS_FixType::RTK_FIXED;
     157             :     static constexpr uint8_t GPS_OK_FIX_TYPE_STATIC = (uint8_t)AP_GPS_FixType::STATIC;
     158             :     static constexpr uint8_t GPS_OK_FIX_TYPE_PPP =    (uint8_t)AP_GPS_FixType::PPP;
     159             : 
     160             :     // GPS navigation engine settings. Not all GPS receivers support
     161             :     // this
     162             :     enum GPS_Engine_Setting {
     163             :         GPS_ENGINE_NONE        = -1,
     164             :         GPS_ENGINE_PORTABLE    = 0,
     165             :         GPS_ENGINE_STATIONARY  = 2,
     166             :         GPS_ENGINE_PEDESTRIAN  = 3,
     167             :         GPS_ENGINE_AUTOMOTIVE  = 4,
     168             :         GPS_ENGINE_SEA         = 5,
     169             :         GPS_ENGINE_AIRBORNE_1G = 6,
     170             :         GPS_ENGINE_AIRBORNE_2G = 7,
     171             :         GPS_ENGINE_AIRBORNE_4G = 8
     172             :     };
     173             : 
     174             :     // role for auto-config
     175             :     enum GPS_Role {
     176             :         GPS_ROLE_NORMAL,
     177             :         GPS_ROLE_MB_BASE,
     178             :         GPS_ROLE_MB_ROVER,
     179             :     };
     180             : 
     181             :     // GPS Covariance Types matching ROS2 sensor_msgs/msg/NavSatFix
     182             :     enum class CovarianceType : uint8_t {
     183             :         UNKNOWN = 0,  ///< The GPS does not support any accuracy metrics
     184             :         APPROXIMATED = 1,  ///< The accuracy is approximated through metrics such as HDOP/VDOP
     185             :         DIAGONAL_KNOWN = 2, ///< The diagonal (east, north, up) components of covariance are reported by the GPS
     186             :         KNOWN = 3, ///< The full covariance array is reported by the GPS
     187             :     };
     188             : 
     189             :     /*
     190             :       The GPS_State structure is filled in by the backend driver as it
     191             :       parses each message from the GPS.
     192             :      */
     193             :     struct GPS_State {
     194             :         uint8_t instance; // the instance number of this GPS
     195             : 
     196             :         // all the following fields must all be filled by the backend driver
     197             :         AP_GPS_FixType status;              ///< driver fix status
     198             :         uint32_t time_week_ms;              ///< GPS time (milliseconds from start of GPS week)
     199             :         uint16_t time_week;                 ///< GPS week number
     200             :         Location location;                  ///< last fix location
     201             :         float ground_speed;                 ///< ground speed in m/s
     202             :         float ground_course;                ///< ground course in degrees, wrapped 0-360
     203             :         float gps_yaw;                      ///< GPS derived yaw information, if available (degrees)
     204             :         uint32_t gps_yaw_time_ms;           ///< timestamp of last GPS yaw reading
     205             :         bool  gps_yaw_configured;           ///< GPS is configured to provide yaw
     206             :         uint16_t hdop;                      ///< horizontal dilution of precision, scaled by a factor of 100 (155 means the HDOP value is 1.55)
     207             :         uint16_t vdop;                      ///< vertical dilution of precision, scaled by a factor of 100 (155 means the VDOP value is 1.55)
     208             :         uint8_t num_sats;                   ///< Number of visible satellites
     209             :         Vector3f velocity;                  ///< 3D velocity in m/s, in NED format
     210             :         float speed_accuracy;               ///< 3D velocity RMS accuracy estimate in m/s
     211             :         float horizontal_accuracy;          ///< horizontal RMS accuracy estimate in m
     212             :         float vertical_accuracy;            ///< vertical RMS accuracy estimate in m
     213             :         float gps_yaw_accuracy;           ///< heading accuracy of the GPS in degrees
     214             :         bool have_vertical_velocity;      ///< does GPS give vertical velocity? Set to true only once available.
     215             :         bool have_speed_accuracy;         ///< does GPS give speed accuracy? Set to true only once available.
     216             :         bool have_horizontal_accuracy;    ///< does GPS give horizontal position accuracy? Set to true only once available.
     217             :         bool have_vertical_accuracy;      ///< does GPS give vertical position accuracy? Set to true only once available.
     218             :         bool have_gps_yaw;                ///< does GPS give yaw? Set to true only once available.
     219             :         bool have_gps_yaw_accuracy;       ///< does the GPS give a heading accuracy estimate? Set to true only once available
     220             :         float undulation;                   //<height that WGS84 is above AMSL at the current location
     221             :         bool have_undulation;               ///<do we have a value for the undulation
     222             :         uint32_t last_gps_time_ms;          ///< the system time we got the last GPS timestamp, milliseconds
     223             :         bool announced_detection;           ///< true once we have announced GPS has been seen to the user
     224             :         uint64_t last_corrected_gps_time_us;///< the system time we got the last corrected GPS timestamp, microseconds
     225             :         bool corrected_timestamp_updated;  ///< true if the corrected timestamp has been updated
     226             :         uint32_t lagged_sample_count;       ///< number of samples with 50ms more lag than expected
     227             : 
     228             :         // all the following fields must only all be filled by RTK capable backend drivers
     229             :         uint32_t rtk_time_week_ms;         ///< GPS Time of Week of last baseline in milliseconds
     230             :         uint16_t rtk_week_number;          ///< GPS Week Number of last baseline
     231             :         uint32_t rtk_age_ms;               ///< GPS age of last baseline correction in milliseconds  (0 when no corrections, 0xFFFFFFFF indicates overflow)
     232             :         uint8_t  rtk_num_sats;             ///< Current number of satellites used for RTK calculation
     233             :         uint8_t  rtk_baseline_coords_type; ///< Coordinate system of baseline. 0 == ECEF, 1 == NED
     234             :         int32_t  rtk_baseline_x_mm;        ///< Current baseline in ECEF x or NED north component in mm
     235             :         int32_t  rtk_baseline_y_mm;        ///< Current baseline in ECEF y or NED east component in mm
     236             :         int32_t  rtk_baseline_z_mm;        ///< Current baseline in ECEF z or NED down component in mm
     237             :         uint32_t rtk_accuracy;             ///< Current estimate of 3D baseline accuracy (receiver dependent, typical 0 to 9999)
     238             :         int32_t  rtk_iar_num_hypotheses;   ///< Current number of integer ambiguity hypotheses
     239             :         
     240             :         // UBX Relative Position and Heading message information
     241             :         float relPosHeading;               ///< Reported Heading in degrees
     242             :         float relPosLength;                ///< Reported Position horizontal distance in meters
     243             :         float relPosD;                     ///< Reported Vertical distance in meters
     244             :         float accHeading;                  ///< Reported Heading Accuracy in degrees
     245             :         uint32_t relposheading_ts;        ///< True if new data has been received since last time it was false
     246             : 
     247             : #if AP_GPS_MB_YAW_OFFSET_ENABLED
     248             :         // body-frame antenna offset used to calculate gps_yaw from a moving
     249             :         // baseline, zero when gps_yaw is not derived from a moving baseline.
     250             :         // gps_yaw is calculated assuming this offset is horizontal, so
     251             :         // consumers with an attitude estimate can use this offset to correct
     252             :         // gps_yaw for vehicle roll and pitch
     253             :         Vector3f mb_yaw_offset;
     254             : #endif
     255             :     };
     256             : 
     257             :     /// Startup initialisation.
     258             :     void init();
     259             : 
     260             :     // ethod for APPPeriph to set the default type for the first GPS instance:
     261             :     void set_default_type_for_gps1(uint8_t default_type) {
     262             :         params[0].type.set_default(default_type);
     263             :     }
     264             : 
     265             :     /// Update GPS state based on possible bytes received from the module.
     266             :     /// This routine must be called periodically (typically at 10Hz or
     267             :     /// more) to process incoming data.
     268             :     void update(void);
     269             : 
     270             :     // Pass mavlink data to message handlers (for MAV type)
     271             :     void handle_msg(mavlink_channel_t chan, const mavlink_message_t &msg);
     272             : #if HAL_MSP_GPS_ENABLED
     273             :     void handle_msp(const MSP::msp_gps_data_message_t &pkt);
     274             : #endif
     275             : #if AP_EXTERNAL_AHRS_ENABLED
     276             :     // Retrieve the first instance ID that is configured as type GPS_TYPE_EXTERNAL_AHRS.
     277             :     // Can be used by external AHRS systems that only report one GPS to get the instance ID.
     278             :     // Returns true if an instance was found, false otherwise.
     279             :     bool get_first_external_instance(uint8_t& instance) const WARN_IF_UNUSED;
     280             :     void handle_external(const AP_ExternalAHRS::gps_data_message_t &pkt, const uint8_t instance);
     281             : #endif
     282             : 
     283             :     // Accessor functions
     284             : 
     285             :     // return number of active GPS sensors. Note that if the first GPS
     286             :     // is not present but the 2nd is then we return 2. Note that a blended
     287             :     // GPS solution is treated as an additional sensor.
     288             :     uint8_t num_sensors(void) const;
     289             : 
     290             :     // Return the index of the primary sensor which is the index of the sensor contributing to
     291             :     // the output. A blended solution is available as an additional instance
     292    41845713 :     uint8_t primary_sensor(void) const {
     293    41845713 :         return primary_instance;
     294             :     }
     295             : 
     296             :     /// Query GPS status
     297   391130159 :     AP_GPS_FixType status(uint8_t instance) const {
     298   391130159 :         if (_force_disable_gps && state[instance].status > AP_GPS_FixType::NONE) {
     299       12461 :             return AP_GPS_FixType::NONE;
     300             :         }
     301   391117698 :         return state[instance].status;
     302             :     }
     303   265817971 :     AP_GPS_FixType status(void) const {
     304   265817971 :         return status(primary_instance);
     305             :     }
     306             : 
     307             :     // return a single human-presentable character representing the
     308             :     // fix type.  For space-constrained human-readable displays
     309           0 :     char status_onechar(void) const {
     310           0 :         switch (status()) {
     311           0 :         case AP_GPS_FixType::NO_GPS:
     312           0 :             return ' ';
     313           0 :         case AP_GPS_FixType::NONE:
     314           0 :             return '-';
     315           0 :         case AP_GPS_FixType::FIX_2D:
     316           0 :             return '2';
     317           0 :         case AP_GPS_FixType::FIX_3D:
     318           0 :             return '3';
     319           0 :         case AP_GPS_FixType::DGPS:
     320           0 :             return '4';
     321           0 :         case AP_GPS_FixType::RTK_FLOAT:
     322           0 :             return '5';
     323           0 :         case AP_GPS_FixType::RTK_FIXED:
     324           0 :             return '6';
     325           0 :         case AP_GPS_FixType::STATIC:
     326           0 :             return '7';
     327           0 :         case AP_GPS_FixType::PPP:
     328           0 :             return '8';
     329             :         }
     330             :         // should never reach here; compiler flags guarantees this.
     331           0 :         return '?';
     332             :     }
     333             : 
     334             :     // Query the highest status this GPS supports (always reports FIX_3D for the blended GPS)
     335             :     AP_GPS_FixType highest_supported_status(uint8_t instance) const WARN_IF_UNUSED;
     336             : 
     337             :     // location of last fix
     338   126812793 :     const Location &location(uint8_t instance) const {
     339   126812793 :         return state[instance].location;
     340             :     }
     341     1532558 :     const Location &location() const {
     342     1532558 :         return location(primary_instance);
     343             :     }
     344             : 
     345             :     // get the difference between WGS84 and AMSL. A positive value means
     346             :     // the AMSL height is higher than WGS84 ellipsoid height
     347             :     bool get_undulation(uint8_t instance, float &undulation) const;
     348             : 
     349             :     // get the difference between WGS84 and AMSL. A positive value means
     350             :     // the AMSL height is higher than WGS84 ellipsoid height
     351          13 :     bool get_undulation(float &undulation) const {
     352          13 :         return get_undulation(primary_instance, undulation);
     353             :     }
     354             : 
     355             :     // report speed accuracy
     356             :     bool speed_accuracy(uint8_t instance, float &sacc) const;
     357     1306596 :     bool speed_accuracy(float &sacc) const {
     358     1306596 :         return speed_accuracy(primary_instance, sacc);
     359             :     }
     360             : 
     361             :     bool horizontal_accuracy(uint8_t instance, float &hacc) const;
     362     1306596 :     bool horizontal_accuracy(float &hacc) const {
     363     1306596 :         return horizontal_accuracy(primary_instance, hacc);
     364             :     }
     365             : 
     366             :     bool vertical_accuracy(uint8_t instance, float &vacc) const;
     367     1306596 :     bool vertical_accuracy(float &vacc) const {
     368     1306596 :         return vertical_accuracy(primary_instance, vacc);
     369             :     }
     370             : 
     371             :     CovarianceType position_covariance(const uint8_t instance, Matrix3f& cov) const WARN_IF_UNUSED;
     372             : 
     373             :     // 3D velocity in NED format
     374   202618594 :     const Vector3f &velocity(uint8_t instance) const {
     375   202618594 :         return state[instance].velocity;
     376             :     }
     377    78460363 :     const Vector3f &velocity() const {
     378    78460363 :         return velocity(primary_instance);
     379             :     }
     380             : 
     381             :     // ground speed in m/s
     382    46000803 :     float ground_speed(uint8_t instance) const {
     383    46000803 :         return state[instance].ground_speed;
     384             :     }
     385    44189463 :     float ground_speed() const {
     386    44189463 :         return ground_speed(primary_instance);
     387             :     }
     388             : 
     389             :     // ground course in degrees
     390    43676418 :     float ground_course(uint8_t instance) const {
     391    43676418 :         return state[instance].ground_course;
     392             :     }
     393    41853492 :     float ground_course() const {
     394    41853492 :         return ground_course(primary_instance);
     395             :     }
     396             :     // ground course in centi-degrees
     397       11591 :     int32_t ground_course_cd(uint8_t instance) const {
     398       11591 :         return ground_course(instance) * 100;
     399             :     }
     400       11591 :     int32_t ground_course_cd() const {
     401       11591 :         return ground_course_cd(primary_instance);
     402             :     }
     403             : 
     404             :     // yaw in degrees if available
     405             :     bool gps_yaw_deg(uint8_t instance, float &yaw_deg, float &accuracy_deg, uint32_t &time_ms) const;
     406           0 :     bool gps_yaw_deg(float &yaw_deg, float &accuracy_deg, uint32_t &time_ms) const {
     407           0 :         return gps_yaw_deg(primary_instance, yaw_deg, accuracy_deg, time_ms);
     408             :     }
     409             : 
     410             :     // number of locked satellites
     411   164717320 :     uint8_t num_sats(uint8_t instance) const {
     412   164717320 :         return state[instance].num_sats;
     413             :     }
     414    39437131 :     uint8_t num_sats() const {
     415    39437131 :         return num_sats(primary_instance);
     416             :     }
     417             : 
     418             :     // GPS time of week in milliseconds
     419      689442 :     uint32_t time_week_ms(uint8_t instance) const {
     420      689442 :         return state[instance].time_week_ms;
     421             :     }
     422          66 :     uint32_t time_week_ms() const {
     423          66 :         return time_week_ms(primary_instance);
     424             :     }
     425             : 
     426             :     // GPS week
     427      689442 :     uint16_t time_week(uint8_t instance) const {
     428      689442 :         return state[instance].time_week;
     429             :     }
     430          66 :     uint16_t time_week() const {
     431          66 :         return time_week(primary_instance);
     432             :     }
     433             : 
     434             :     // horizontal dilution of precision
     435   125283045 :     uint16_t get_hdop(uint8_t instance) const {
     436   125283045 :         return state[instance].hdop;
     437             :     }
     438        2856 :     uint16_t get_hdop() const {
     439        2856 :         return get_hdop(primary_instance);
     440             :     }
     441             : 
     442             :     // vertical dilution of precision
     443     1813314 :     uint16_t get_vdop(uint8_t instance) const {
     444     1813314 :         return state[instance].vdop;
     445             :     }
     446        1980 :     uint16_t get_vdop() const {
     447        1980 :         return get_vdop(primary_instance);
     448             :     }
     449             : 
     450             :     // the time we got our last fix in system milliseconds. This is
     451             :     // used when calculating how far we might have moved since that fix
     452    41597038 :     uint32_t last_fix_time_ms(uint8_t instance) const {
     453    41597038 :         return timing[instance].last_fix_time_ms;
     454             :     }
     455    40475080 :     uint32_t last_fix_time_ms(void) const {
     456    40475080 :         return last_fix_time_ms(primary_instance);
     457             :     }
     458             : 
     459             :     // the time we last processed a message in milliseconds. This is
     460             :     // used to indicate that we have new GPS data to process
     461   163129162 :     uint32_t last_message_time_ms(uint8_t instance) const {
     462   163129162 :         return timing[instance].last_message_time_ms;
     463             :     }
     464    38970931 :     uint32_t last_message_time_ms(void) const {
     465    38970931 :         return last_message_time_ms(primary_instance);
     466             :     }
     467             : 
     468             :     // system time delta between the last two reported positions
     469      689376 :     uint16_t last_message_delta_time_ms(uint8_t instance) const {
     470      689376 :         return timing[instance].delta_time_ms;
     471             :     }
     472             :     uint16_t last_message_delta_time_ms(void) const {
     473             :         return last_message_delta_time_ms(primary_instance);
     474             :     }
     475             : 
     476             :     // return true if the GPS supports vertical velocity values
     477   124158233 :     bool have_vertical_velocity(uint8_t instance) const {
     478   124158233 :         return state[instance].have_vertical_velocity;
     479             :     }
     480           2 :     bool have_vertical_velocity(void) const {
     481           2 :         return have_vertical_velocity(primary_instance);
     482             :     }
     483             : 
     484             :     // return true if the GPS currently has yaw available
     485   124160971 :     bool have_gps_yaw(uint8_t instance) const {
     486   124160971 :         return !_force_disable_gps_yaw && state[instance].have_gps_yaw;
     487             :     }
     488           0 :     bool have_gps_yaw(void) const {
     489           0 :         return have_gps_yaw(primary_instance);
     490             :     }
     491             : 
     492             :     // return true if the GPS is configured to provide yaw. This will
     493             :     // be true if we expect the GPS to provide yaw, even if it
     494             :     // currently is not able to provide yaw
     495     1121958 :     bool have_gps_yaw_configured(uint8_t instance) const {
     496     1121958 :         return state[instance].gps_yaw_configured;
     497             :     }
     498             :     
     499             :     // the expected lag (in seconds) in the position and velocity readings from the gps
     500             :     // return true if the GPS hardware configuration is known or the lag parameter has been set manually
     501             :     bool get_lag(uint8_t instance, float &lag_sec) const;
     502    38475091 :     bool get_lag(float &lag_sec) const {
     503    38475091 :         return get_lag(primary_instance, lag_sec);
     504             :     }
     505             : 
     506             :     // return a 3D vector defining the offset of the GPS antenna in meters relative to the body frame origin
     507             :     const Vector3f &get_antenna_offset(uint8_t instance) const;
     508             : 
     509             : #if AP_GPS_MB_YAW_OFFSET_ENABLED
     510             :     // return the body-frame moving baseline antenna offset used to calculate
     511             :     // the yaw returned by gps_yaw_deg for this instance, zero when that yaw
     512             :     // is not derived from a moving baseline
     513             :     const Vector3f &get_mb_yaw_offset(uint8_t instance) const;
     514             : #endif
     515             : 
     516             :     // lock out a GPS port, allowing another application to use the port
     517             :     void lock_port(uint8_t instance, bool locked);
     518             : 
     519             :     //MAVLink Status Sending
     520             :     void send_mavlink_gps_raw(mavlink_channel_t chan);
     521             :     void send_mavlink_gps2_raw(mavlink_channel_t chan);
     522             : 
     523             :     void send_mavlink_gps_rtk(mavlink_channel_t chan, uint8_t inst);
     524             : 
     525             :     // Returns true if there is an unconfigured GPS, and provides the instance number of the first non configured GPS
     526             :     bool first_unconfigured_gps(uint8_t &instance) const WARN_IF_UNUSED;
     527             :     void broadcast_first_configuration_failure_reason(void) const;
     528             : 
     529             :     // pre-arm check that all GPSs are close to each other.  farthest distance between GPSs (in meters) is returned
     530             :     bool all_consistent(float &distance) const;
     531             : 
     532             :     // handle sending of initialisation strings to the GPS - only used by backends
     533             :     void send_blob_start(uint8_t instance);
     534             :     void send_blob_start(uint8_t instance, const char *_blob, uint16_t size);
     535             :     void send_blob_update(uint8_t instance);
     536             : 
     537             :     // return last fix time since the 1/1/1970 in microseconds
     538             :     uint64_t time_epoch_usec(uint8_t instance) const;
     539     1306662 :     uint64_t time_epoch_usec(void) const {
     540     1306662 :         return time_epoch_usec(primary_instance);
     541             :     }
     542             : 
     543             :     uint64_t last_message_epoch_usec(uint8_t instance) const;
     544             :     uint64_t last_message_epoch_usec() const {
     545             :         return last_message_epoch_usec(primary_instance);
     546             :     }
     547             : 
     548             :     // convert GPS week and millis to unix epoch in ms
     549             :     static uint64_t istate_time_to_epoch_ms(uint16_t gps_week, uint32_t gps_ms);
     550             : 
     551             :     static const struct AP_Param::GroupInfo var_info[];
     552             : 
     553             : #if HAL_LOGGING_ENABLED
     554             :     void Write_AP_Logger_Log_Startup_messages();
     555             : #endif
     556             : 
     557             :     // indicate which bit in LOG_BITMASK indicates gps logging enabled
     558        2092 :     void set_log_gps_bit(uint32_t bit) { _log_gps_bit = bit; }
     559             : 
     560             :     // report if the gps is healthy (this is defined as existing, an update at a rate greater than 4Hz,
     561             :     // as well as any driver specific behaviour)
     562             :     bool is_healthy(uint8_t instance) const;
     563     1121120 :     bool is_healthy(void) const { return is_healthy(primary_instance); }
     564             : 
     565             :     // returns true if all GPS instances have passed all final arming checks/state changes
     566             :     bool prepare_for_arming(void);
     567             : 
     568             :     // returns true if all GPS backend drivers are OK with the concept
     569             :     // of the vehicle arming.  this is for backends to be able to
     570             :     // spout pre arm error messages
     571             :     bool pre_arm_checks(char failure_msg[], uint16_t failure_msg_len);
     572             : 
     573             :     // returns false if any GPS drivers are not performing their logging appropriately
     574             :     bool logging_failed(void) const;
     575             : 
     576     1121120 :     bool logging_present(void) const { return _raw_data != 0; }
     577     2242240 :     bool logging_enabled(void) const { return _raw_data != 0; }
     578             : 
     579             :     // used to disable GPS for GPS failure testing in flight
     580           6 :     void force_disable(bool disable) {
     581           6 :         _force_disable_gps = disable;
     582           6 :     }
     583             : 
     584             :     // used to disable GPS yaw for GPS failure testing in flight
     585           0 :     void set_force_disable_yaw(bool disable) {
     586           0 :         _force_disable_gps_yaw = disable;
     587           0 :     }
     588             : 
     589             :     // handle possibly fragmented RTCM injection data
     590             :     void handle_gps_rtcm_fragment(uint8_t flags, const uint8_t *data, uint8_t len);
     591             : 
     592             :     // get configured type by instance
     593   288853634 :     GPS_Type get_type(uint8_t instance) const {
     594   288853634 :         return instance>=ARRAY_SIZE(params) ? GPS_Type::GPS_TYPE_NONE : params[instance].type;
     595             :     }
     596             : 
     597             :     // get iTOW, if supported, zero otherwie
     598             :     uint32_t get_itow(uint8_t instance) const;
     599             : 
     600             :     bool get_error_codes(uint8_t instance, uint32_t &error_codes) const;
     601           0 :     bool get_error_codes(uint32_t &error_codes) const { return get_error_codes(primary_instance, error_codes); }
     602             : 
     603             :     enum class SBAS_Mode : int8_t {
     604             :         Disabled = 0,
     605             :         Enabled = 1,
     606             :         DoNotChange = 2,
     607             :     };
     608             : 
     609             : #if GPS_MOVING_BASELINE
     610             :     // methods used by UAVCAN GPS driver and AP_Periph for moving baseline
     611             :     void inject_MBL_data(uint8_t* data, uint16_t length);
     612             :     bool get_RelPosHeading(uint32_t &timestamp, float &relPosHeading, float &relPosLength, float &relPosD, float &accHeading) WARN_IF_UNUSED;
     613             :     bool get_RTCMV3(const uint8_t *&bytes, uint16_t &len);
     614             :     void clear_RTCMV3();
     615             : #endif // GPS_MOVING_BASELINE
     616             : 
     617             : #if !AP_GPS_BLENDED_ENABLED
     618             :     uint8_t get_auto_switch_type() const { return _auto_switch; }
     619             : #endif
     620             : 
     621             :     // Inject a packet of raw binary to a GPS
     622             :     void inject_data(const uint8_t *data, uint16_t len);
     623             : 
     624             : protected:
     625             : 
     626             :     // configuration parameters
     627             :     Params params[GPS_MAX_INSTANCES];
     628             :     AP_Int8 _navfilter;
     629             :     AP_Int8 _auto_switch;
     630             :     AP_Int16 _sbp_logmask;
     631             :     AP_Int8 _inject_to;
     632             :     uint32_t _last_instance_swap_ms;
     633             :     AP_Enum<SBAS_Mode> _sbas_mode;
     634             :     AP_Int8 _min_elevation;
     635             :     AP_Int8 _raw_data;
     636             :     AP_Int8 _save_config;
     637             :     AP_Int8 _auto_config;
     638             :     AP_Int8 _blend_mask;
     639             :     AP_Int16 _driver_options;
     640             :     AP_Int8 _primary;
     641             : 
     642             :     uint32_t _log_gps_bit = -1;
     643             : 
     644             :     enum DriverOptions : int16_t {
     645             :         UBX_MBUseUart2    = (1U << 0U),
     646             :         SBF_UseBaseForYaw = (1U << 1U),
     647             :         UBX_Use115200     = (1U << 2U),
     648             :         UAVCAN_MBUseDedicatedBus  = (1 << 3U),
     649             :         HeightEllipsoid   = (1U << 4),
     650             :         GPSL5HealthOverride = (1U << 5),
     651             :         AlwaysRTCMDecode = (1U << 6),
     652             :         DisableRTCMDecode = (1U << 7),
     653             :         ForceUBXConfigV2 = (1U << 8U)
     654             :     };
     655             : 
     656             :     // check if an option is set
     657    50952083 :     bool option_set(const DriverOptions option) const {
     658    50952083 :         return (uint16_t(_driver_options.get()) & uint16_t(option)) != 0;
     659             :     }
     660             : 
     661             : private:
     662             :     static AP_GPS *_singleton;
     663             :     HAL_Semaphore rsem;
     664             : 
     665             :     // returns the desired gps update rate in milliseconds
     666             :     // this does not provide any guarantee that the GPS is updating at the requested
     667             :     // rate it is simply a helper for use in the backends for determining what rate
     668             :     // they should be configuring the GPS to run at
     669             :     uint16_t get_rate_ms(uint8_t instance) const;
     670             : 
     671             :     struct GPS_timing {
     672             :         // the time we got our last fix in system milliseconds
     673             :         uint32_t last_fix_time_ms;
     674             : 
     675             :         // the time we got our last message in system milliseconds
     676             :         uint32_t last_message_time_ms;
     677             : 
     678             :         // delta time between the last pair of GPS updates in system milliseconds
     679             :         uint16_t delta_time_ms;
     680             : 
     681             :         // count of delayed frames
     682             :         uint8_t delayed_count;
     683             : 
     684             :         // the average time delta
     685             :         float average_delta_ms;
     686             :     };
     687             :     // Note allowance for an additional instance to contain blended data
     688             :     GPS_timing timing[GPS_MAX_INSTANCES];
     689             :     GPS_State state[GPS_MAX_INSTANCES];
     690             :     AP_GPS_Backend *drivers[GPS_MAX_INSTANCES];
     691             :     AP_HAL::UARTDriver *_port[GPS_MAX_RECEIVERS];
     692             : 
     693             :     /// primary GPS instance
     694             :     uint8_t primary_instance;
     695             : 
     696             :     /// number of GPS instances present
     697             :     uint8_t num_instances;
     698             : 
     699             :     // which ports are locked
     700             :     uint8_t locked_ports;
     701             : 
     702             :     // state of auto-detection process, per instance
     703             :     struct detect_state {
     704             :         uint32_t last_baud_change_ms;
     705             :         uint8_t current_baud;
     706             :         uint32_t probe_baud;
     707             :         bool auto_detected_baud;
     708             : #if AP_GPS_UBLOX_ENABLED
     709             :         struct UBLOX_detect_state ublox_detect_state;
     710             : #endif
     711             : #if AP_GPS_SIRF_ENABLED
     712             :         struct SIRF_detect_state sirf_detect_state;
     713             : #endif
     714             : #if AP_GPS_NMEA_ENABLED
     715             :         struct NMEA_detect_state nmea_detect_state;
     716             : #endif
     717             : #if AP_GPS_SBP_ENABLED
     718             :         struct SBP_detect_state sbp_detect_state;
     719             : #endif
     720             : #if AP_GPS_SBP2_ENABLED
     721             :         struct SBP2_detect_state sbp2_detect_state;
     722             : #endif
     723             : #if AP_GPS_ERB_ENABLED
     724             :         struct ERB_detect_state erb_detect_state;
     725             : #endif
     726             :     } detect_state[GPS_MAX_RECEIVERS];
     727             : 
     728             :     struct {
     729             :         const char *blob;
     730             :         uint16_t remaining;
     731             :     } initblob_state[GPS_MAX_RECEIVERS];
     732             : 
     733             :     static const uint32_t  _baudrates[];
     734             :     static const char _initialisation_blob[];
     735             :     static const char _initialisation_raw_blob[];
     736             : 
     737             :     void detect_instance(uint8_t instance);
     738             :     // run detection step for one GPS instance. If this finds a GPS then it
     739             :     // will return it - otherwise nullptr
     740             :     AP_GPS_Backend *_detect_instance(uint8_t instance);
     741             : 
     742             :     void update_instance(uint8_t instance);
     743             : 
     744             :     // fold timing[instance].delta_time_ms into the delayed-frame counters
     745             :     // used by is_healthy(). Only called when that delta is a real
     746             :     // measurement of the interval between two messages
     747             :     void update_frame_timing_health(uint8_t instance);
     748             : 
     749             :     /*
     750             :       buffer for re-assembling RTCM data for GPS injection.
     751             :       The 8 bit flags field in GPS_RTCM_DATA is interpreted as:
     752             :               1 bit for "is fragmented"
     753             :               2 bits for fragment number
     754             :               5 bits for sequence number
     755             : 
     756             :       The rtcm_buffer is allocated on first use. Once a block of data
     757             :       is successfully reassembled it is injected into all active GPS
     758             :       backends. This assumes we don't want more than 4*180=720 bytes
     759             :       in a RTCM data block
     760             :      */
     761             :     struct rtcm_buffer {
     762             :         uint8_t fragments_received;
     763             :         uint8_t sequence;
     764             :         uint8_t fragment_count;
     765             :         uint16_t total_length;
     766             :         uint8_t buffer[MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN*4];
     767             :     } *rtcm_buffer;
     768             : 
     769             :     struct {
     770             :         uint16_t fragments_used;
     771             :         uint16_t fragments_discarded;
     772             :     } rtcm_stats;
     773             : 
     774             :     // re-assemble GPS_RTCM_DATA message
     775             :     void handle_gps_rtcm_data(mavlink_channel_t chan, const mavlink_message_t &msg);
     776             :     void handle_gps_inject(const mavlink_message_t &msg);
     777             : 
     778             :     //Inject a packet of raw binary to a GPS
     779             :     void inject_data(uint8_t instance, const uint8_t *data, uint16_t len);
     780             : 
     781             : #if AP_GPS_BLENDED_ENABLED
     782             :     bool _output_is_blended; // true when a blended GPS solution being output
     783             : #endif
     784             : 
     785             :     bool should_log() const;
     786             : 
     787             :     bool needs_uart(GPS_Type type) const;
     788             : 
     789             : #if GPS_MAX_RECEIVERS > 1
     790             :     /// Update primary instance
     791             :     void update_primary(void);
     792             : #endif
     793             : 
     794             :     // helper function for mavlink gps yaw
     795             :     uint16_t gps_yaw_cdeg(uint8_t instance) const;
     796             : 
     797             :     // Auto configure types
     798             :     enum GPS_AUTO_CONFIG {
     799             :         GPS_AUTO_CONFIG_DISABLE = 0,
     800             :         GPS_AUTO_CONFIG_ENABLE_SERIAL_ONLY  = 1,
     801             :         GPS_AUTO_CONFIG_ENABLE_ALL = 2,
     802             :         GPS_AUTO_CLEAR_CONFIG_UBLOX_SERIAL_ONLY = 3,  // then acts like GPS_AUTO_CONFIG_ENABLE_SERIAL_ONLY
     803             :     };
     804             : 
     805             :     enum class GPSAutoSwitch {
     806             :         NONE        = 0,
     807             :         USE_BEST    = 1,
     808             :         BLEND       = 2,
     809             :         //USE_SECOND  = 3, deprecated for new primary param
     810             :         USE_PRIMARY_IF_3D_FIX = 4,
     811             :     };
     812             : 
     813             :     // used for flight testing with GPS loss
     814             :     bool _force_disable_gps;
     815             : 
     816             :     // used for flight testing with GPS yaw loss
     817             :     bool _force_disable_gps_yaw;
     818             : 
     819             :     // logging support
     820             :     void Write_GPS(uint8_t instance);
     821             : 
     822             : #if AP_GPS_RTCM_DECODE_ENABLED
     823             :     /*
     824             :       per mavlink channel RTCM decoder, enabled with RTCM decode
     825             :        option in GPS_DRV_OPTIONS
     826             :     */
     827             :     struct {
     828             :         RTCM3_Parser *parsers[MAVLINK_COMM_NUM_BUFFERS];
     829             :         uint32_t sent_crc[32];
     830             :         uint8_t sent_idx;
     831             :         uint16_t seen_mav_channels;
     832             :     } rtcm;
     833             :     bool parse_rtcm_injection(mavlink_channel_t chan, const mavlink_gps_rtcm_data_t &pkt);
     834             : #endif
     835             : 
     836             :     void convert_parameters();
     837             : };
     838             : 
     839             : namespace AP {
     840             :     AP_GPS &gps();
     841             : };
     842             : 
     843             : #endif  // AP_GPS_ENABLED

Generated by: LCOV version 1.14