LCOV - code coverage report
Current view: top level - AP_ADSB - AP_ADSB.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 27 33 81.8 %
Date: 2026-09-09 11:02:08 Functions: 12 15 80.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : /*
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation, either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : /*
      18             :     ADS-B RF based collision avoidance module
      19             :     https://en.wikipedia.org/wiki/Automatic_dependent_surveillance_%E2%80%93_broadcast
      20             : 
      21             :   Tom Pittenger, November 2015
      22             : */
      23             : 
      24             : #include "AP_ADSB_config.h"
      25             : 
      26             : #if HAL_ADSB_ENABLED
      27             : #include <AP_Common/AP_Common.h>
      28             : #include <AP_Param/AP_Param.h>
      29             : #include <AP_Common/Location.h>
      30             : #include <GCS_MAVLink/GCS_MAVLink.h>
      31             : #include <AP_GPS/AP_GPS_FixType.h>
      32             : 
      33             : #define ADSB_MAX_INSTANCES             1   // Maximum number of ADSB sensor instances available on this platform
      34             : 
      35             : #define ADSB_BITBASK_RF_CAPABILITIES_UAT_IN         (1 << 0)
      36             : #define ADSB_BITBASK_RF_CAPABILITIES_1090ES_IN      (1 << 1)
      37             : #define ADSB_BITBASK_RF_CAPABILITIES_UAT_OUT        (1 << 2)
      38             : #define ADSB_BITBASK_RF_CAPABILITIES_1090ES_OUT     (1 << 3)
      39             : 
      40             : class AP_ADSB_Backend;
      41             : 
      42             : class AP_ADSB {
      43             : public:
      44             :     friend class AP_ADSB_Backend;
      45             :     friend class AP_ADSB_MAVLink;
      46             :     friend class AP_ADSB_uAvionix_UCP;
      47             :     friend class AP_ADSB_Sagetech;
      48             :     friend class AP_ADSB_Sagetech_MXS;
      49             : 
      50             :     // constructor
      51             :     AP_ADSB();
      52             : 
      53             :     /* Do not allow copies */
      54             :     CLASS_NO_COPY(AP_ADSB);
      55             : 
      56             :     // get singleton instance
      57       66592 :     static AP_ADSB *get_singleton(void) {
      58       66592 :         return _singleton;
      59             :     }
      60             : 
      61             :     // ADSB driver types
      62             :     enum class Type {
      63             :         None                = 0,
      64             :         MAVLink             = 1,
      65             :         Sagetech            = 2,
      66             :         uAvionix_UCP        = 3,
      67             :         Sagetech_MXS        = 4,
      68             :     };
      69             : 
      70             :     struct adsb_vehicle_t {
      71             :         mavlink_adsb_vehicle_t info; // the whole mavlink struct with all the juicy details. sizeof() == 38
      72             :         uint32_t last_update_ms; // last time this was refreshed, allows timeouts
      73             :     };
      74             : 
      75             :     // enum for adsb optional features
      76             :     enum class AdsbOption {
      77             :         Ping200X_Send_GPS               = (1<<0),
      78             :         Squawk_7400_FS_RC               = (1<<1),
      79             :         Squawk_7400_FS_GCS              = (1<<2),
      80             :         SagteTech_MXS_External_Config   = (1<<3),
      81             :         Mode3_Only                      = (1<<4),
      82             :     };
      83             : 
      84             :     // for holding parameters
      85             :     static const struct AP_Param::GroupInfo var_info[];
      86             : 
      87             :     // periodic task that maintains vehicle_list
      88             :     void update(void);
      89             : 
      90             :     // a structure holding *this vehicle's* position-related information:
      91             :     enum class AltType {
      92             :         Barometric = 0,  // we use a specific model for this?
      93             :         WGS84 = 1,
      94             :     };
      95             :     struct Loc : Location {
      96             :         AltType loc_alt_type;  // more information on altitude in base class
      97             : 
      98             :         AP_GPS_FixType fix_type;
      99             :         uint64_t epoch_us;  // microseconds since 1970-01-01
     100             :         uint64_t epoch_from_rtc_us;  // microseconds since 1970-01-01
     101             :         bool have_epoch_from_rtc_us;
     102             :         uint8_t satellites;
     103             : 
     104             :         float horizontal_pos_accuracy;
     105             :         bool horizontal_pos_accuracy_is_valid;
     106             : 
     107             :         float vertical_pos_accuracy;
     108             :         bool vertical_pos_accuracy_is_valid;
     109             : 
     110             :         float horizontal_vel_accuracy;
     111             :         bool horizontal_vel_accuracy_is_valid;
     112             : 
     113             :         Vector3f vel_ned;
     114             : 
     115             :         float vertRateD;  // m/s down
     116             :         bool vertRateD_is_valid;
     117             : 
     118             :         // methods to make us look much like the AP::gps() singleton:
     119           9 :         AP_GPS_FixType status() const { return fix_type; }
     120           0 :         const Vector3f &velocity() const {
     121           0 :             return vel_ned;
     122             :         }
     123           0 :         uint64_t time_epoch_usec() const { return epoch_us; }
     124             : 
     125             :         bool speed_accuracy(float &sacc) const;
     126             :         bool horizontal_accuracy(float &hacc) const;
     127             :         bool vertical_accuracy(float &vacc) const;
     128             : 
     129           0 :         uint8_t num_sats() const { return satellites; }
     130             : 
     131             :         // methods to make us look like the AP::ahrs() singleton:
     132          20 :         const Vector2f &groundspeed_vector() const { return vel_ned.xy(); }
     133          11 :         bool get_vert_pos_rate_D(float &velocity) const {
     134          11 :             velocity = vertRateD;
     135          11 :             return vertRateD_is_valid;
     136             :         }
     137             : 
     138             :         // data from a pressure sensor:
     139             :         bool baro_is_healthy;
     140             :         float baro_alt_press_diff_sea_level;
     141             : 
     142             :     } _my_loc;
     143             : 
     144             :     // periodic task that maintains vehicle_list
     145             :     void update(const Loc &loc);
     146             : 
     147             :     // send ADSB_VEHICLE mavlink message, usually as a StreamRate
     148             :     void send_adsb_vehicle(mavlink_channel_t chan);
     149             : 
     150       54357 :     bool set_stall_speed_cm(const uint16_t stall_speed_cm) {
     151       54357 :         if (out_state.cfg.was_set_externally) {
     152           0 :             return false;
     153             :         }
     154       54357 :         out_state.cfg.stall_speed_cm = stall_speed_cm;
     155       54357 :         return true;
     156             :     }
     157             : 
     158       54357 :     bool set_max_speed(int16_t max_speed) {
     159       54357 :         if (out_state.cfg.was_set_externally) {
     160           0 :             return false;
     161             :         }
     162             :         // convert m/s to knots
     163       54357 :         out_state.cfg.maxAircraftSpeed_knots = (float)max_speed * M_PER_SEC_TO_KNOTS;
     164       54357 :         return true;
     165             :     }
     166             : 
     167        3196 :     void set_is_auto_mode(const bool is_in_auto_mode) { out_state.is_in_auto_mode = is_in_auto_mode; }
     168      348648 :     void set_is_flying(const bool is_flying) { out_state.is_flying = is_flying; }
     169             : 
     170             :     // extract a location out of a vehicle item
     171             :     Location get_location(const adsb_vehicle_t &vehicle) const;
     172             : 
     173             :     // ADSB is considered enabled if there are any configured backends
     174       52280 :     bool enabled() const {
     175       52295 :         for (uint8_t instance=0; instance<detected_num_instances; instance++) {
     176        2938 :             if (_type[instance] > 0) {
     177        2923 :                 return true;
     178             :             }
     179             :         }
     180       49357 :         return false;
     181             :     }
     182             : 
     183         281 :     bool init_failed() const {
     184         281 :         return _init_failed;
     185             :     }
     186             : 
     187           2 :     bool healthy() {
     188           2 :         return check_startup();
     189             :     }
     190             : 
     191             :     bool next_sample(adsb_vehicle_t &obstacle);
     192             : 
     193             :     // handle a adsb_vehicle_t from an external source
     194             :     void handle_adsb_vehicle(const adsb_vehicle_t &vehicle);
     195             : 
     196             :     // mavlink message handler
     197             :     void handle_message(const mavlink_channel_t chan, const mavlink_message_t &msg);
     198             : 
     199             :     void send_adsb_out_status(const mavlink_channel_t chan) const;
     200             : 
     201             :     // when true, a vehicle with that ICAO was found in database and the vehicle is populated.
     202             :     bool get_vehicle_by_ICAO(const uint32_t icao, adsb_vehicle_t &vehicle) const;
     203             : 
     204             :     uint32_t get_special_ICAO_target() const { return (uint32_t)_special_ICAO_target; };
     205             :     void set_special_ICAO_target(const uint32_t new_icao_target) { _special_ICAO_target.set((int32_t)new_icao_target); };
     206       16783 :     bool is_special_vehicle(uint32_t icao) const { return _special_ICAO_target != 0 && (_special_ICAO_target == (int32_t)icao); }
     207             : 
     208             :     // confirm a value is a valid callsign
     209             :     static bool is_valid_callsign(uint16_t octal) WARN_IF_UNUSED;
     210             : 
     211             :     static uint8_t convert_maxknots_to_enum(const float maxAircraftSpeed_knots);
     212             : 
     213             :     // Convert base 8 or 16 to decimal. Used to convert an octal/hexadecimal value
     214             :     // stored on a GCS as a string field in different format, but then transmitted
     215             :     // over mavlink as a float which is always a decimal.
     216             :     static uint32_t convert_base_to_decimal(const uint8_t baseIn, uint32_t inputNumber);
     217             : 
     218             :     // Trigger a Mode 3/A transponder IDENT. This should only be done when requested to do so by an Air Traffic Controller.
     219             :     // See wikipedia for IDENT explanation https://en.wikipedia.org/wiki/Transponder_(aeronautics)
     220             :     bool ident_start();
     221             : 
     222             :     AP_ADSB::Type get_type(uint8_t instance) const;
     223             : 
     224             : private:
     225             :     static AP_ADSB *_singleton;
     226             : 
     227             :     // initialize vehicle_list
     228             :     void init();
     229             : 
     230             :     // check to see if we are initialized (and possibly do initialization)
     231             :     bool check_startup();
     232             : 
     233             :     // compares current vector against vehicle_list to detect threats
     234             :     void determine_furthest_aircraft(void);
     235             : 
     236             :     // return index of given vehicle if ICAO_ADDRESS matches. return -1 if no match
     237             :     bool find_index(const adsb_vehicle_t &vehicle, uint16_t *index) const;
     238             : 
     239             :     // remove a vehicle from the list
     240             :     void delete_vehicle(const uint16_t index);
     241             : 
     242             :     void set_vehicle(const uint16_t index, const adsb_vehicle_t &vehicle);
     243             : 
     244             :     // Generates pseudorandom ICAO from gps time, lat, and lon
     245             :     uint32_t genICAO(const Location &loc) const;
     246             : 
     247             :     // set callsign: 8char string (plus null termination) then optionally append last 4 digits of icao
     248             :     void set_callsign(const char* str, const bool append_icao);
     249             : 
     250             :     // configure ADSB-out transceivers
     251             :     void handle_out_cfg(const mavlink_uavionix_adsb_out_cfg_t &packet);
     252             : 
     253             :     // control ADSB-out transcievers
     254             :     void handle_out_control(const mavlink_uavionix_adsb_out_control_t &packet);
     255             : 
     256             :     // mavlink handler
     257             :     void handle_transceiver_report(const mavlink_channel_t chan, const mavlink_uavionix_adsb_transceiver_health_report_t &packet);
     258             : 
     259             :     void detect_instance(uint8_t instance);
     260             : 
     261             :     AP_Int8 _type[ADSB_MAX_INSTANCES];
     262             : 
     263             :     bool _init_failed;
     264             : 
     265             :     // ADSB-IN state. Maintains list of external vehicles
     266             :     struct {
     267             :         // list management
     268             :         AP_Int16    list_size_param;
     269             :         uint16_t    list_size_allocated;
     270             :         adsb_vehicle_t *vehicle_list;
     271             :         uint16_t    vehicle_count;
     272             :         AP_Int32    list_radius;
     273             :         AP_Int16    list_altitude;
     274             : 
     275             :         // index of and distance to furthest vehicle in list
     276             :         uint16_t    furthest_vehicle_index;
     277             :         float       furthest_vehicle_distance;
     278             : 
     279             :         // streamrate stuff
     280             :         uint32_t    send_start_ms[MAVLINK_COMM_NUM_BUFFERS];
     281             :         uint16_t    send_index[MAVLINK_COMM_NUM_BUFFERS];
     282             :     } in_state;
     283             : 
     284             :     // ADSB-OUT state. Maintains export data
     285             :     struct {
     286             :         uint32_t    last_config_ms; // send once every 10s
     287             :         uint32_t    last_report_ms; // send at 5Hz
     288             :         int8_t      chan = -1; // channel that contains an ADS-b Transceiver. -1 means transceiver is not detected
     289             :         uint32_t    chan_last_ms;
     290             :         UAVIONIX_ADSB_RF_HEALTH status;     // transceiver status
     291             :         bool        is_flying;
     292             :         bool        is_in_auto_mode;
     293             : 
     294             :         // ADSB-OUT configuration
     295             :         struct {
     296             :             int32_t     ICAO_id;
     297             :             AP_Int32    ICAO_id_param;
     298             :             int32_t     ICAO_id_param_prev = -1; // assume we never send
     299             :             char        callsign[MAVLINK_MSG_UAVIONIX_ADSB_OUT_CFG_FIELD_CALLSIGN_LEN]; //Vehicle identifier (8 characters, null terminated, valid characters are A-Z, 0-9, " " only).
     300             :             AP_Int8     emitterType;
     301             :             AP_Int8     lengthWidth;  // Aircraft length and width encoding (table 2-35 of DO-282B)
     302             :             AP_Int8     gpsOffsetLat;
     303             :             AP_Int8     gpsOffsetLon;
     304             :             uint16_t    stall_speed_cm;
     305             :             AP_Int8     rfSelect;
     306             :             AP_Int16    squawk_octal_param;
     307             :             uint16_t    squawk_octal;
     308             :             float       maxAircraftSpeed_knots;
     309             :             AP_Int8     rf_capable;
     310             :             bool        was_set_externally;
     311             :         } cfg;
     312             : 
     313             :         struct {
     314             :             bool                          baroCrossChecked;
     315             :             uint8_t                       airGroundState;
     316             :             bool                          identActive;
     317             :             bool                          modeAEnabled;
     318             :             bool                          modeCEnabled;
     319             :             bool                          modeSEnabled;
     320             :             bool                          es1090TxEnabled;
     321             :             int32_t                       externalBaroAltitude_mm;
     322             :             uint16_t                      squawkCode;
     323             :             uint8_t                       emergencyState;
     324             :             uint8_t                       callsign[8];
     325             :             bool                          x_bit;
     326             :         } ctrl;
     327             : 
     328             :         mavlink_uavionix_adsb_out_status_t tx_status;
     329             :     } out_state;
     330             : 
     331             :     uint8_t detected_num_instances;
     332             : 
     333             :     // special ICAO of interest that ignored filters when != 0
     334             :     AP_Int32 _special_ICAO_target;
     335             : 
     336             :     AP_Int32 _options;
     337             : 
     338             :     static const uint8_t _max_samples = 30;
     339             :     ObjectBuffer<adsb_vehicle_t> _samples{_max_samples};
     340             : 
     341             :     void push_sample(const adsb_vehicle_t &vehicle);
     342             : 
     343             :     // logging
     344             :     void write_log(const adsb_vehicle_t &vehicle) const;
     345             :     enum class Logging {
     346             :         NONE            = 0,
     347             :         SPECIAL_ONLY    = 1,
     348             :         ALL             = 2
     349             :     };
     350             :     AP_Enum<Logging> _log;
     351             : 
     352             :     // reference to backend
     353             :     AP_ADSB_Backend *_backend[ADSB_MAX_INSTANCES];
     354             : };
     355             : 
     356             : namespace AP {
     357             :     AP_ADSB *ADSB();
     358             : };
     359             : 
     360             : #endif // HAL_ADSB_ENABLED

Generated by: LCOV version 1.14