123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635 |
- #include "AP_GPS.h"
- #include <AP_Common/AP_Common.h>
- #include <AP_HAL/AP_HAL.h>
- #include <AP_Math/AP_Math.h>
- #include <AP_Notify/AP_Notify.h>
- #include <GCS_MAVLink/GCS.h>
- #include <AP_BoardConfig/AP_BoardConfig.h>
- #include <AP_RTC/AP_RTC.h>
- #include <climits>
- #include "AP_GPS_NOVA.h"
- #include "AP_GPS_ERB.h"
- #include "AP_GPS_GSOF.h"
- #include "AP_GPS_MTK.h"
- #include "AP_GPS_MTK19.h"
- #include "AP_GPS_NMEA.h"
- #include "AP_GPS_SBF.h"
- #include "AP_GPS_SBP.h"
- #include "AP_GPS_SBP2.h"
- #include "AP_GPS_SIRF.h"
- #include "AP_GPS_UBLOX.h"
- #include "AP_GPS_MAV.h"
- #include "GPS_Backend.h"
- #if HAL_WITH_UAVCAN
- #include <AP_BoardConfig/AP_BoardConfig_CAN.h>
- #include <AP_UAVCAN/AP_UAVCAN.h>
- #include "AP_GPS_UAVCAN.h"
- #endif
- #include <AP_AHRS/AP_AHRS.h>
- #include <AP_Logger/AP_Logger.h>
- #define GPS_RTK_INJECT_TO_ALL 127
- #define GPS_MAX_RATE_MS 200
- #define GPS_BAUD_TIME_MS 1200
- #define GPS_TIMEOUT_MS 4000u
- #define BLEND_MASK_USE_HPOS_ACC 1
- #define BLEND_MASK_USE_VPOS_ACC 2
- #define BLEND_MASK_USE_SPD_ACC 4
- #define BLEND_COUNTER_FAILURE_INCREMENT 10
- extern const AP_HAL::HAL &hal;
- const uint32_t AP_GPS::_baudrates[] = {9600U, 115200U, 4800U, 19200U, 38400U, 57600U, 230400U};
- const char AP_GPS::_initialisation_blob[] = UBLOX_SET_BINARY MTK_SET_BINARY SIRF_SET_BINARY;
- AP_GPS *AP_GPS::_singleton;
- const AP_Param::GroupInfo AP_GPS::var_info[] = {
-
-
-
-
-
-
- AP_GROUPINFO("TYPE", 0, AP_GPS, _type[0], HAL_GPS_TYPE_DEFAULT),
- #if GPS_MAX_RECEIVERS > 1
-
-
-
-
-
-
- AP_GROUPINFO("TYPE2", 1, AP_GPS, _type[1], 0),
- #endif
-
-
-
-
-
- AP_GROUPINFO("NAVFILTER", 2, AP_GPS, _navfilter, GPS_ENGINE_AIRBORNE_4G),
- #if GPS_MAX_RECEIVERS > 1
-
-
-
-
-
- AP_GROUPINFO("AUTO_SWITCH", 3, AP_GPS, _auto_switch, 1),
- #endif
-
-
-
-
-
-
- AP_GROUPINFO("MIN_DGPS", 4, AP_GPS, _min_dgps, 100),
-
-
-
-
-
- AP_GROUPINFO("SBAS_MODE", 5, AP_GPS, _sbas_mode, 2),
-
-
-
-
-
-
- AP_GROUPINFO("MIN_ELEV", 6, AP_GPS, _min_elevation, -100),
-
-
-
-
-
- AP_GROUPINFO("INJECT_TO", 7, AP_GPS, _inject_to, GPS_RTK_INJECT_TO_ALL),
-
-
-
-
-
- AP_GROUPINFO("SBP_LOGMASK", 8, AP_GPS, _sbp_logmask, -256),
-
-
-
-
-
-
- AP_GROUPINFO("RAW_DATA", 9, AP_GPS, _raw_data, 0),
-
-
-
-
-
-
- AP_GROUPINFO("GNSS_MODE", 10, AP_GPS, _gnss_mode[0], 0),
-
-
-
-
-
- AP_GROUPINFO("SAVE_CFG", 11, AP_GPS, _save_config, 2),
- #if GPS_MAX_RECEIVERS > 1
-
-
-
-
-
-
- AP_GROUPINFO("GNSS_MODE2", 12, AP_GPS, _gnss_mode[1], 0),
- #endif
-
-
-
-
-
- AP_GROUPINFO("AUTO_CONFIG", 13, AP_GPS, _auto_config, 1),
-
-
-
-
-
-
-
- AP_GROUPINFO("RATE_MS", 14, AP_GPS, _rate_ms[0], 200),
- #if GPS_MAX_RECEIVERS > 1
-
-
-
-
-
-
-
- AP_GROUPINFO("RATE_MS2", 15, AP_GPS, _rate_ms[1], 200),
- #endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AP_GROUPINFO("POS1", 16, AP_GPS, _antenna_offset[0], 0.0f),
-
-
-
-
-
-
-
-
-
-
-
-
- #if GPS_MAX_RECEIVERS > 1
-
-
-
-
-
-
- AP_GROUPINFO("POS2", 17, AP_GPS, _antenna_offset[1], 0.0f),
- #endif
-
-
-
-
-
-
-
- AP_GROUPINFO("DELAY_MS", 18, AP_GPS, _delay_ms[0], 0),
- #if GPS_MAX_RECEIVERS > 1
-
-
-
-
-
-
-
- AP_GROUPINFO("DELAY_MS2", 19, AP_GPS, _delay_ms[1], 0),
- #endif
- #if defined(GPS_BLENDED_INSTANCE)
-
-
-
-
-
- AP_GROUPINFO("BLEND_MASK", 20, AP_GPS, _blend_mask, 5),
-
-
-
-
-
-
- AP_GROUPINFO("BLEND_TC", 21, AP_GPS, _blend_tc, 10.0f),
- #endif
- AP_GROUPEND
- };
- AP_GPS::AP_GPS()
- {
- static_assert((sizeof(_initialisation_blob) * (CHAR_BIT + 2)) < (4800 * GPS_BAUD_TIME_MS * 1e-3),
- "GPS initilisation blob is too large to be completely sent before the baud rate changes");
- AP_Param::setup_object_defaults(this, var_info);
- if (_singleton != nullptr) {
- AP_HAL::panic("AP_GPS must be singleton");
- }
- _singleton = this;
- }
- void AP_GPS::init(const AP_SerialManager& serial_manager)
- {
- primary_instance = 0;
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- _port[i] = serial_manager.find_serial(AP_SerialManager::SerialProtocol_GPS, i);
- }
- _last_instance_swap_ms = 0;
-
- _omega_lpf = 1.0f / constrain_float(_blend_tc, 5.0f, 30.0f);
-
- for (uint8_t i = 0; i < GPS_MAX_INSTANCES; i++) {
- state[i].instance = i;
- }
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (_rate_ms[i] <= 0 || _rate_ms[i] > GPS_MAX_RATE_MS) {
- _rate_ms[i] = GPS_MAX_RATE_MS;
- }
- }
- }
- uint8_t AP_GPS::num_sensors(void) const
- {
- if (!_output_is_blended) {
- return num_instances;
- } else {
- return num_instances+1;
- }
- }
- bool AP_GPS::speed_accuracy(uint8_t instance, float &sacc) const
- {
- if (state[instance].have_speed_accuracy) {
- sacc = state[instance].speed_accuracy;
- return true;
- }
- return false;
- }
- bool AP_GPS::horizontal_accuracy(uint8_t instance, float &hacc) const
- {
- if (state[instance].have_horizontal_accuracy) {
- hacc = state[instance].horizontal_accuracy;
- return true;
- }
- return false;
- }
- bool AP_GPS::vertical_accuracy(uint8_t instance, float &vacc) const
- {
- if (state[instance].have_vertical_accuracy) {
- vacc = state[instance].vertical_accuracy;
- return true;
- }
- return false;
- }
- uint64_t AP_GPS::time_epoch_convert(uint16_t gps_week, uint32_t gps_ms)
- {
- uint64_t fix_time_ms = UNIX_OFFSET_MSEC + gps_week * AP_MSEC_PER_WEEK + gps_ms;
- return fix_time_ms;
- }
- uint64_t AP_GPS::time_epoch_usec(uint8_t instance) const
- {
- const GPS_State &istate = state[instance];
- if (istate.last_gps_time_ms == 0 || istate.time_week == 0) {
- return 0;
- }
- uint64_t fix_time_ms = time_epoch_convert(istate.time_week, istate.time_week_ms);
-
- return (fix_time_ms + (AP_HAL::millis() - istate.last_gps_time_ms)) * 1000ULL;
- }
- void AP_GPS::send_blob_start(uint8_t instance, const char *_blob, uint16_t size)
- {
- initblob_state[instance].blob = _blob;
- initblob_state[instance].remaining = size;
- }
- void AP_GPS::send_blob_update(uint8_t instance)
- {
-
- if (_port[instance] == nullptr) {
- return;
- }
-
- if (initblob_state[instance].remaining > 0) {
- int16_t space = _port[instance]->txspace();
- if (space > (int16_t)initblob_state[instance].remaining) {
- space = initblob_state[instance].remaining;
- }
- while (space > 0) {
- _port[instance]->write(*initblob_state[instance].blob);
- initblob_state[instance].blob++;
- space--;
- initblob_state[instance].remaining--;
- }
- }
- }
- void AP_GPS::detect_instance(uint8_t instance)
- {
- AP_GPS_Backend *new_gps = nullptr;
- struct detect_state *dstate = &detect_state[instance];
- const uint32_t now = AP_HAL::millis();
- state[instance].status = NO_GPS;
- state[instance].hdop = GPS_UNKNOWN_DOP;
- state[instance].vdop = GPS_UNKNOWN_DOP;
- switch (_type[instance]) {
-
-
- case GPS_TYPE_MAV:
- #ifndef HAL_BUILD_AP_PERIPH
- dstate->auto_detected_baud = false;
- new_gps = new AP_GPS_MAV(*this, state[instance], nullptr);
- goto found_gps;
- #endif
- break;
-
- case GPS_TYPE_UAVCAN:
- #if HAL_WITH_UAVCAN
- dstate->auto_detected_baud = false;
- new_gps = AP_GPS_UAVCAN::probe(*this, state[instance]);
- goto found_gps;
- #endif
- return;
- default:
- break;
- }
- if (_port[instance] == nullptr) {
-
- return;
- }
-
-
- dstate->auto_detected_baud = true;
- #ifndef HAL_BUILD_AP_PERIPH
- switch (_type[instance]) {
-
- case GPS_TYPE_SBF:
- new_gps = new AP_GPS_SBF(*this, state[instance], _port[instance]);
- break;
- case GPS_TYPE_GSOF:
- new_gps = new AP_GPS_GSOF(*this, state[instance], _port[instance]);
- break;
- case GPS_TYPE_NOVA:
- new_gps = new AP_GPS_NOVA(*this, state[instance], _port[instance]);
- break;
- default:
- break;
- }
- #endif
- if (now - dstate->last_baud_change_ms > GPS_BAUD_TIME_MS) {
-
-
-
- dstate->current_baud++;
- if (dstate->current_baud == ARRAY_SIZE(_baudrates)) {
- dstate->current_baud = 0;
- }
- uint32_t baudrate = _baudrates[dstate->current_baud];
- _port[instance]->begin(baudrate);
- _port[instance]->set_flow_control(AP_HAL::UARTDriver::FLOW_CONTROL_DISABLE);
- dstate->last_baud_change_ms = now;
- if (_auto_config == GPS_AUTO_CONFIG_ENABLE && new_gps == nullptr) {
- if (_type[instance] == GPS_TYPE_HEMI) {
- send_blob_start(instance, AP_GPS_NMEA_HEMISPHERE_INIT_STRING, strlen(AP_GPS_NMEA_HEMISPHERE_INIT_STRING));
- } else {
- send_blob_start(instance, _initialisation_blob, sizeof(_initialisation_blob));
- }
- }
- }
- if (_auto_config == GPS_AUTO_CONFIG_ENABLE && new_gps == nullptr) {
- send_blob_update(instance);
- }
- while (initblob_state[instance].remaining == 0 && _port[instance]->available() > 0
- && new_gps == nullptr) {
- uint8_t data = _port[instance]->read();
-
- if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_UBLOX) &&
- ((!_auto_config && _baudrates[dstate->current_baud] >= 38400) ||
- _baudrates[dstate->current_baud] == 115200) &&
- AP_GPS_UBLOX::_detect(dstate->ublox_detect_state, data)) {
- new_gps = new AP_GPS_UBLOX(*this, state[instance], _port[instance]);
- }
- #ifndef HAL_BUILD_AP_PERIPH
- #if !HAL_MINIMIZE_FEATURES
-
-
- else if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_MTK19) &&
- AP_GPS_MTK19::_detect(dstate->mtk19_detect_state, data)) {
- new_gps = new AP_GPS_MTK19(*this, state[instance], _port[instance]);
- } else if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_MTK) &&
- AP_GPS_MTK::_detect(dstate->mtk_detect_state, data)) {
- new_gps = new AP_GPS_MTK(*this, state[instance], _port[instance]);
- }
- #endif
- else if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_SBP) &&
- AP_GPS_SBP2::_detect(dstate->sbp2_detect_state, data)) {
- new_gps = new AP_GPS_SBP2(*this, state[instance], _port[instance]);
- }
- else if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_SBP) &&
- AP_GPS_SBP::_detect(dstate->sbp_detect_state, data)) {
- new_gps = new AP_GPS_SBP(*this, state[instance], _port[instance]);
- }
- #if !HAL_MINIMIZE_FEATURES
- else if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_SIRF) &&
- AP_GPS_SIRF::_detect(dstate->sirf_detect_state, data)) {
- new_gps = new AP_GPS_SIRF(*this, state[instance], _port[instance]);
- }
- #endif
- else if ((_type[instance] == GPS_TYPE_AUTO || _type[instance] == GPS_TYPE_ERB) &&
- AP_GPS_ERB::_detect(dstate->erb_detect_state, data)) {
- new_gps = new AP_GPS_ERB(*this, state[instance], _port[instance]);
- } else if ((_type[instance] == GPS_TYPE_NMEA ||
- _type[instance] == GPS_TYPE_HEMI) &&
- AP_GPS_NMEA::_detect(dstate->nmea_detect_state, data)) {
- new_gps = new AP_GPS_NMEA(*this, state[instance], _port[instance]);
- }
- #endif
- if (new_gps) {
- goto found_gps;
- }
- }
- found_gps:
- if (new_gps != nullptr) {
- state[instance].status = NO_FIX;
- drivers[instance] = new_gps;
- timing[instance].last_message_time_ms = now;
- timing[instance].delta_time_ms = GPS_TIMEOUT_MS;
- new_gps->broadcast_gps_type();
- }
- }
- AP_GPS::GPS_Status AP_GPS::highest_supported_status(uint8_t instance) const
- {
- if (instance < GPS_MAX_RECEIVERS && drivers[instance] != nullptr) {
- return drivers[instance]->highest_supported_status();
- }
- return AP_GPS::GPS_OK_FIX_3D;
- }
- bool AP_GPS::should_log() const
- {
- #ifndef HAL_BUILD_AP_PERIPH
- AP_Logger *logger = AP_Logger::get_singleton();
- if (logger == nullptr) {
- return false;
- }
- if (_log_gps_bit == (uint32_t)-1) {
- return false;
- }
- if (!logger->should_log(_log_gps_bit)) {
- return false;
- }
- return true;
- #else
- return false;
- #endif
- }
- void AP_GPS::update_instance(uint8_t instance)
- {
- if (_type[instance] == GPS_TYPE_HIL) {
-
- return;
- }
- if (_type[instance] == GPS_TYPE_NONE) {
-
- state[instance].status = NO_GPS;
- state[instance].hdop = GPS_UNKNOWN_DOP;
- state[instance].vdop = GPS_UNKNOWN_DOP;
- return;
- }
- if (locked_ports & (1U<<instance)) {
-
- return;
- }
- if (drivers[instance] == nullptr || state[instance].status == NO_GPS) {
-
-
- detect_instance(instance);
- return;
- }
- if (_auto_config == GPS_AUTO_CONFIG_ENABLE) {
- send_blob_update(instance);
- }
-
- bool result = drivers[instance]->read();
- uint32_t tnow = AP_HAL::millis();
-
-
-
- bool data_should_be_logged = false;
- if (!result) {
- if (tnow - timing[instance].last_message_time_ms > GPS_TIMEOUT_MS) {
- memset((void *)&state[instance], 0, sizeof(state[instance]));
- state[instance].instance = instance;
- state[instance].hdop = GPS_UNKNOWN_DOP;
- state[instance].vdop = GPS_UNKNOWN_DOP;
- timing[instance].last_message_time_ms = tnow;
- timing[instance].delta_time_ms = GPS_TIMEOUT_MS;
-
- if (_type[instance] == GPS_TYPE_MAV) {
- state[instance].status = NO_FIX;
- } else {
-
-
- delete drivers[instance];
- drivers[instance] = nullptr;
- state[instance].status = NO_GPS;
- }
-
-
- data_should_be_logged = true;
- }
- } else {
- if (state[instance].uart_timestamp_ms != 0) {
-
-
- tnow = state[instance].uart_timestamp_ms;
- state[instance].uart_timestamp_ms = 0;
- }
-
- timing[instance].delta_time_ms = tnow - timing[instance].last_message_time_ms;
- timing[instance].last_message_time_ms = tnow;
- if (state[instance].status >= GPS_OK_FIX_2D) {
- timing[instance].last_fix_time_ms = tnow;
- }
- data_should_be_logged = true;
- }
- #ifndef HAL_BUILD_AP_PERIPH
- if (data_should_be_logged &&
- (should_log() || AP::ahrs().have_ekf_logging())) {
- AP::logger().Write_GPS(instance);
- }
- if (state[instance].status >= GPS_OK_FIX_3D) {
- const uint64_t now = time_epoch_usec(instance);
- if (now != 0) {
- AP::rtc().set_utc_usec(now, AP_RTC::SOURCE_GPS);
- }
- }
- #else
- (void)data_should_be_logged;
- #endif
- }
- void AP_GPS::update(void)
- {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- update_instance(i);
- }
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status != NO_GPS) {
- num_instances = i+1;
- }
- }
- #if defined(GPS_BLENDED_INSTANCE)
-
- if (_auto_switch == 2) {
- _output_is_blended = calc_blend_weights();
-
- if (!_output_is_blended) {
- _blend_health_counter = MIN(_blend_health_counter+BLEND_COUNTER_FAILURE_INCREMENT, 100);
- } else if (_blend_health_counter > 0) {
- _blend_health_counter--;
- }
-
- if (_blend_health_counter >= 50) {
- _output_is_blended = false;
- }
- } else {
- _output_is_blended = false;
- _blend_health_counter = 0;
- }
- if (_output_is_blended) {
-
- calc_blended_state();
-
- primary_instance = GPS_BLENDED_INSTANCE;
- } else {
-
- uint32_t now = AP_HAL::millis();
- if (_auto_switch == 3) {
-
- primary_instance = 1;
- } else if (_auto_switch >= 1) {
-
- if (primary_instance == GPS_BLENDED_INSTANCE) {
- primary_instance = 0;
- for (uint8_t i=1; i<GPS_MAX_RECEIVERS; i++) {
-
- if ((state[i].status > state[primary_instance].status) ||
- ((state[i].status == state[primary_instance].status) && (state[i].num_sats > state[primary_instance].num_sats))) {
- primary_instance = i;
- _last_instance_swap_ms = now;
- }
- }
- } else {
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (i == primary_instance) {
- continue;
- }
- if (state[i].status > state[primary_instance].status) {
-
- primary_instance = i;
- _last_instance_swap_ms = now;
- continue;
- }
- bool another_gps_has_1_or_more_sats = (state[i].num_sats >= state[primary_instance].num_sats + 1);
- if (state[i].status == state[primary_instance].status && another_gps_has_1_or_more_sats) {
- bool another_gps_has_2_or_more_sats = (state[i].num_sats >= state[primary_instance].num_sats + 2);
- if ((another_gps_has_1_or_more_sats && (now - _last_instance_swap_ms) >= 20000) ||
- (another_gps_has_2_or_more_sats && (now - _last_instance_swap_ms) >= 5000)) {
-
-
-
-
-
- primary_instance = i;
- _last_instance_swap_ms = now;
- }
- }
- }
- }
- } else {
-
- primary_instance = 0;
- }
-
- state[GPS_BLENDED_INSTANCE] = state[primary_instance];
- _blended_antenna_offset = _antenna_offset[primary_instance];
- }
- #endif
- #ifndef HAL_BUILD_AP_PERIPH
-
- AP_Notify::flags.gps_status = state[primary_instance].status;
- AP_Notify::flags.gps_num_sats = state[primary_instance].num_sats;
- #endif
- }
- void AP_GPS::handle_gps_inject(const mavlink_message_t &msg)
- {
- mavlink_gps_inject_data_t packet;
- mavlink_msg_gps_inject_data_decode(&msg, &packet);
-
- inject_data(packet.data, packet.len);
- }
- void AP_GPS::handle_msg(const mavlink_message_t &msg)
- {
- switch (msg.msgid) {
- case MAVLINK_MSG_ID_GPS_RTCM_DATA:
-
- handle_gps_rtcm_data(msg);
- break;
- case MAVLINK_MSG_ID_GPS_INJECT_DATA:
- handle_gps_inject(msg);
- break;
- default: {
- uint8_t i;
- for (i=0; i<num_instances; i++) {
- if ((drivers[i] != nullptr) && (_type[i] != GPS_TYPE_NONE)) {
- drivers[i]->handle_msg(msg);
- }
- }
- break;
- }
- }
- }
- void AP_GPS::setHIL(uint8_t instance, GPS_Status _status, uint64_t time_epoch_ms,
- const Location &_location, const Vector3f &_velocity, uint8_t _num_sats,
- uint16_t hdop)
- {
- if (instance >= GPS_MAX_RECEIVERS) {
- return;
- }
- const uint32_t tnow = AP_HAL::millis();
- GPS_State &istate = state[instance];
- istate.status = _status;
- istate.location = _location;
- istate.velocity = _velocity;
- istate.ground_speed = norm(istate.velocity.x, istate.velocity.y);
- istate.ground_course = wrap_360(degrees(atan2f(istate.velocity.y, istate.velocity.x)));
- istate.hdop = hdop;
- istate.num_sats = _num_sats;
- istate.last_gps_time_ms = tnow;
- uint64_t gps_time_ms = time_epoch_ms - UNIX_OFFSET_MSEC;
- istate.time_week = gps_time_ms / AP_MSEC_PER_WEEK;
- istate.time_week_ms = gps_time_ms - istate.time_week * AP_MSEC_PER_WEEK;
- timing[instance].last_message_time_ms = tnow;
- timing[instance].last_fix_time_ms = tnow;
- _type[instance].set(GPS_TYPE_HIL);
- }
- void AP_GPS::setHIL_Accuracy(uint8_t instance, float vdop, float hacc, float vacc, float sacc, bool _have_vertical_velocity, uint32_t sample_ms)
- {
- if (instance >= GPS_MAX_RECEIVERS) {
- return;
- }
- GPS_State &istate = state[instance];
- istate.vdop = vdop * 100;
- istate.horizontal_accuracy = hacc;
- istate.vertical_accuracy = vacc;
- istate.speed_accuracy = sacc;
- istate.have_horizontal_accuracy = true;
- istate.have_vertical_accuracy = true;
- istate.have_speed_accuracy = true;
- istate.have_vertical_velocity |= _have_vertical_velocity;
- if (sample_ms != 0) {
- timing[instance].last_message_time_ms = sample_ms;
- timing[instance].last_fix_time_ms = sample_ms;
- }
- }
- void AP_GPS::lock_port(uint8_t instance, bool lock)
- {
- if (instance >= GPS_MAX_RECEIVERS) {
- return;
- }
- if (lock) {
- locked_ports |= (1U<<instance);
- } else {
- locked_ports &= ~(1U<<instance);
- }
- }
- void AP_GPS::inject_data(uint8_t *data, uint16_t len)
- {
-
- if (_inject_to == GPS_RTK_INJECT_TO_ALL) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- inject_data(i, data, len);
- }
- } else {
- inject_data(_inject_to, data, len);
- }
- }
- void AP_GPS::inject_data(uint8_t instance, uint8_t *data, uint16_t len)
- {
- if (instance < GPS_MAX_RECEIVERS && drivers[instance] != nullptr) {
- drivers[instance]->inject_data(data, len);
- }
- }
- void AP_GPS::send_mavlink_gps_raw(mavlink_channel_t chan)
- {
- static uint32_t last_send_time_ms[MAVLINK_COMM_NUM_BUFFERS];
- if (status(0) > AP_GPS::NO_GPS) {
-
- if (last_send_time_ms[chan] == last_message_time_ms(0)) {
- return;
- }
- last_send_time_ms[chan] = last_message_time_ms(0);
- } else {
-
- uint32_t now = AP_HAL::millis();
- if (now - last_send_time_ms[chan] < 1000) {
- return;
- }
- last_send_time_ms[chan] = now;
- }
- const Location &loc = location(0);
- float hacc = 0.0f;
- float vacc = 0.0f;
- float sacc = 0.0f;
- horizontal_accuracy(0, hacc);
- vertical_accuracy(0, vacc);
- speed_accuracy(0, sacc);
- mavlink_msg_gps_raw_int_send(
- chan,
- last_fix_time_ms(0)*(uint64_t)1000,
- status(0),
- loc.lat,
- loc.lng,
- loc.alt * 10UL,
- get_hdop(0),
- get_vdop(0),
- ground_speed(0)*100,
- ground_course(0)*100,
- num_sats(0),
- 0,
- hacc * 1000,
- vacc * 1000,
- sacc * 1000,
- 0);
- }
- #if GPS_MAX_RECEIVERS > 1
- void AP_GPS::send_mavlink_gps2_raw(mavlink_channel_t chan)
- {
- static uint32_t last_send_time_ms[MAVLINK_COMM_NUM_BUFFERS];
- if (num_instances < 2 || status(1) <= AP_GPS::NO_GPS) {
- return;
- }
-
- if (last_send_time_ms[chan] == last_message_time_ms(1)) {
- return;
- }
- last_send_time_ms[chan] = last_message_time_ms(1);
- const Location &loc = location(1);
- mavlink_msg_gps2_raw_send(
- chan,
- last_fix_time_ms(1)*(uint64_t)1000,
- status(1),
- loc.lat,
- loc.lng,
- loc.alt * 10UL,
- get_hdop(1),
- get_vdop(1),
- ground_speed(1)*100,
- ground_course(1)*100,
- num_sats(1),
- state[1].rtk_num_sats,
- state[1].rtk_age_ms);
- }
- #endif
- void AP_GPS::send_mavlink_gps_rtk(mavlink_channel_t chan, uint8_t inst)
- {
- if (inst >= GPS_MAX_RECEIVERS) {
- return;
- }
- if (drivers[inst] != nullptr && drivers[inst]->supports_mavlink_gps_rtk_message()) {
- drivers[inst]->send_mavlink_gps_rtk(chan);
- }
- }
- bool AP_GPS::first_unconfigured_gps(uint8_t &instance) const
- {
- for (int i = 0; i < GPS_MAX_RECEIVERS; i++) {
- if (_type[i] != GPS_TYPE_NONE && (drivers[i] == nullptr || !drivers[i]->is_configured())) {
- instance = i;
- return true;
- }
- }
- return false;
- }
- void AP_GPS::broadcast_first_configuration_failure_reason(void) const
- {
- uint8_t unconfigured;
- if (first_unconfigured_gps(unconfigured)) {
- if (drivers[unconfigured] == nullptr) {
- gcs().send_text(MAV_SEVERITY_INFO, "GPS %d: was not found", unconfigured + 1);
- } else {
- drivers[unconfigured]->broadcast_configuration_failure_reason();
- }
- }
- }
- bool AP_GPS::all_consistent(float &distance) const
- {
-
- if (num_instances <= 1 ||
- drivers[0] == nullptr || _type[0] == GPS_TYPE_NONE) {
- distance = 0;
- return true;
- }
-
- distance = state[0].location.get_distance_NED(state[1].location).length();
-
- return (distance < 50);
- }
- bool AP_GPS::blend_health_check() const
- {
- return (_blend_health_counter < 50);
- }
- void AP_GPS::handle_gps_rtcm_data(const mavlink_message_t &msg)
- {
- mavlink_gps_rtcm_data_t packet;
- mavlink_msg_gps_rtcm_data_decode(&msg, &packet);
- if (packet.len > MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN) {
-
- return;
- }
- if ((packet.flags & 1) == 0) {
-
- inject_data(packet.data, packet.len);
- return;
- }
-
- if (rtcm_buffer == nullptr) {
- rtcm_buffer = (struct rtcm_buffer *)calloc(1, sizeof(*rtcm_buffer));
- if (rtcm_buffer == nullptr) {
-
- return;
- }
- }
- uint8_t fragment = (packet.flags >> 1U) & 0x03;
- uint8_t sequence = (packet.flags >> 3U) & 0x1F;
-
- if (rtcm_buffer->fragments_received &&
- (rtcm_buffer->sequence != sequence ||
- (rtcm_buffer->fragments_received & (1U<<fragment)))) {
-
-
- memset(rtcm_buffer, 0, sizeof(*rtcm_buffer));
- }
-
- rtcm_buffer->sequence = sequence;
- rtcm_buffer->fragments_received |= (1U << fragment);
-
- memcpy(&rtcm_buffer->buffer[MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN*(uint16_t)fragment], packet.data, packet.len);
-
-
-
-
- if (packet.len < MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN) {
- rtcm_buffer->fragment_count = fragment+1;
- rtcm_buffer->total_length = (MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN*fragment) + packet.len;
- } else if (rtcm_buffer->fragments_received == 0x0F) {
-
- rtcm_buffer->fragment_count = 4;
- rtcm_buffer->total_length = MAVLINK_MSG_GPS_RTCM_DATA_FIELD_DATA_LEN*4;
- }
-
- if (rtcm_buffer->fragment_count != 0 &&
- rtcm_buffer->fragments_received == (1U << rtcm_buffer->fragment_count) - 1) {
-
- inject_data(rtcm_buffer->buffer, rtcm_buffer->total_length);
- memset(rtcm_buffer, 0, sizeof(*rtcm_buffer));
- }
- }
- void AP_GPS::Write_AP_Logger_Log_Startup_messages()
- {
- for (uint8_t instance=0; instance<num_instances; instance++) {
- if (drivers[instance] == nullptr || state[instance].status == NO_GPS) {
- continue;
- }
- drivers[instance]->Write_AP_Logger_Log_Startup_messages();
- }
- }
- bool AP_GPS::get_lag(uint8_t instance, float &lag_sec) const
- {
-
- lag_sec = 0.22f;
- if (instance >= GPS_MAX_INSTANCES) {
- return false;
- }
- #if defined(GPS_BLENDED_INSTANCE)
-
- if (instance == GPS_BLENDED_INSTANCE) {
- lag_sec = _blended_lag_sec;
-
- uint8_t inst;
- return first_unconfigured_gps(inst);
- }
- #endif
- if (_delay_ms[instance] > 0) {
-
- lag_sec = 0.001f * (float)_delay_ms[instance];
-
- return true;
- } else if (drivers[instance] == nullptr || state[instance].status == NO_GPS) {
-
- if (_type[instance] == GPS_TYPE_NONE) {
- lag_sec = 0.0f;
- return true;
- }
- return _type[instance] == GPS_TYPE_AUTO;
- } else {
-
- return drivers[instance]->get_lag(lag_sec);
- }
- }
- const Vector3f &AP_GPS::get_antenna_offset(uint8_t instance) const
- {
- if (instance >= GPS_MAX_INSTANCES) {
-
- return _antenna_offset[0];
- }
- #if defined(GPS_BLENDED_INSTANCE)
- if (instance == GPS_BLENDED_INSTANCE) {
-
- return _blended_antenna_offset;
- }
- #endif
- return _antenna_offset[instance];
- }
- uint16_t AP_GPS::get_rate_ms(uint8_t instance) const
- {
-
- if (instance >= num_instances || _rate_ms[instance] <= 0) {
- return GPS_MAX_RATE_MS;
- }
- return MIN(_rate_ms[instance], GPS_MAX_RATE_MS);
- }
- #if defined(GPS_BLENDED_INSTANCE)
- bool AP_GPS::calc_blend_weights(void)
- {
-
- memset(&_blend_weights, 0, sizeof(_blend_weights));
-
- if (state[0].status <= NO_FIX || state[1].status <= NO_FIX) {
- return false;
- }
-
- uint32_t max_ms = 0;
- uint32_t min_ms = -1;
- int16_t max_rate_ms = 0;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
-
- if (state[i].last_gps_time_ms > max_ms) {
- max_ms = state[i].last_gps_time_ms;
- }
- if ((state[i].last_gps_time_ms < min_ms) && (state[i].last_gps_time_ms > 0)) {
- min_ms = state[i].last_gps_time_ms;
- }
- if (get_rate_ms(i) > max_rate_ms) {
- max_rate_ms = get_rate_ms(i);
- }
- }
- if ((int32_t)(max_ms - min_ms) < (int32_t)(2 * max_rate_ms)) {
-
- state[GPS_BLENDED_INSTANCE].last_gps_time_ms = min_ms;
- } else {
-
- return false;
- }
-
- float speed_accuracy_sum_sq = 0.0f;
- if (_blend_mask & BLEND_MASK_USE_SPD_ACC) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status >= GPS_OK_FIX_3D) {
- if (state[i].have_speed_accuracy && state[i].speed_accuracy > 0.0f) {
- speed_accuracy_sum_sq += state[i].speed_accuracy * state[i].speed_accuracy;
- } else {
-
- speed_accuracy_sum_sq = 0.0f;
- break;
- }
- }
- }
- }
-
- float horizontal_accuracy_sum_sq = 0.0f;
- if (_blend_mask & BLEND_MASK_USE_HPOS_ACC) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status >= GPS_OK_FIX_2D) {
- if (state[i].have_horizontal_accuracy && state[i].horizontal_accuracy > 0.0f) {
- horizontal_accuracy_sum_sq += state[i].horizontal_accuracy * state[i].horizontal_accuracy;
- } else {
-
- horizontal_accuracy_sum_sq = 0.0f;
- break;
- }
- }
- }
- }
-
- float vertical_accuracy_sum_sq = 0.0f;
- if (_blend_mask & BLEND_MASK_USE_VPOS_ACC) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status >= GPS_OK_FIX_3D) {
- if (state[i].have_vertical_accuracy && state[i].vertical_accuracy > 0.0f) {
- vertical_accuracy_sum_sq += state[i].vertical_accuracy * state[i].vertical_accuracy;
- } else {
-
- vertical_accuracy_sum_sq = 0.0f;
- break;
- }
- }
- }
- }
-
- bool can_do_blending = (horizontal_accuracy_sum_sq > 0.0f || vertical_accuracy_sum_sq > 0.0f || speed_accuracy_sum_sq > 0.0f);
-
- if (!can_do_blending) {
- return false;
- }
- float sum_of_all_weights = 0.0f;
-
- float hpos_blend_weights[GPS_MAX_RECEIVERS] = {};
- if (horizontal_accuracy_sum_sq > 0.0f && (_blend_mask & BLEND_MASK_USE_HPOS_ACC)) {
-
- float sum_of_hpos_weights = 0.0f;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status >= GPS_OK_FIX_2D && state[i].horizontal_accuracy >= 0.001f) {
- hpos_blend_weights[i] = horizontal_accuracy_sum_sq / (state[i].horizontal_accuracy * state[i].horizontal_accuracy);
- sum_of_hpos_weights += hpos_blend_weights[i];
- }
- }
-
- if (sum_of_hpos_weights > 0.0f) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- hpos_blend_weights[i] = hpos_blend_weights[i] / sum_of_hpos_weights;
- }
- sum_of_all_weights += 1.0f;
- }
- }
-
- float vpos_blend_weights[GPS_MAX_RECEIVERS] = {};
- if (vertical_accuracy_sum_sq > 0.0f && (_blend_mask & BLEND_MASK_USE_VPOS_ACC)) {
-
- float sum_of_vpos_weights = 0.0f;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status >= GPS_OK_FIX_3D && state[i].vertical_accuracy >= 0.001f) {
- vpos_blend_weights[i] = vertical_accuracy_sum_sq / (state[i].vertical_accuracy * state[i].vertical_accuracy);
- sum_of_vpos_weights += vpos_blend_weights[i];
- }
- }
-
- if (sum_of_vpos_weights > 0.0f) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- vpos_blend_weights[i] = vpos_blend_weights[i] / sum_of_vpos_weights;
- }
- sum_of_all_weights += 1.0f;
- };
- }
-
- float spd_blend_weights[GPS_MAX_RECEIVERS] = {};
- if (speed_accuracy_sum_sq > 0.0f && (_blend_mask & BLEND_MASK_USE_SPD_ACC)) {
-
- float sum_of_spd_weights = 0.0f;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].status >= GPS_OK_FIX_3D && state[i].speed_accuracy >= 0.001f) {
- spd_blend_weights[i] = speed_accuracy_sum_sq / (state[i].speed_accuracy * state[i].speed_accuracy);
- sum_of_spd_weights += spd_blend_weights[i];
- }
- }
-
- if (sum_of_spd_weights > 0.0f) {
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- spd_blend_weights[i] = spd_blend_weights[i] / sum_of_spd_weights;
- }
- sum_of_all_weights += 1.0f;
- }
- }
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- _blend_weights[i] = (hpos_blend_weights[i] + vpos_blend_weights[i] + spd_blend_weights[i]) / sum_of_all_weights;
- }
- return true;
- }
- void AP_GPS::calc_blended_state(void)
- {
-
- state[GPS_BLENDED_INSTANCE].instance = GPS_BLENDED_INSTANCE;
- state[GPS_BLENDED_INSTANCE].status = NO_FIX;
- state[GPS_BLENDED_INSTANCE].time_week_ms = 0;
- state[GPS_BLENDED_INSTANCE].time_week = 0;
- state[GPS_BLENDED_INSTANCE].ground_speed = 0.0f;
- state[GPS_BLENDED_INSTANCE].ground_course = 0.0f;
- state[GPS_BLENDED_INSTANCE].hdop = GPS_UNKNOWN_DOP;
- state[GPS_BLENDED_INSTANCE].vdop = GPS_UNKNOWN_DOP;
- state[GPS_BLENDED_INSTANCE].num_sats = 0;
- state[GPS_BLENDED_INSTANCE].velocity.zero();
- state[GPS_BLENDED_INSTANCE].speed_accuracy = 1e6f;
- state[GPS_BLENDED_INSTANCE].horizontal_accuracy = 1e6f;
- state[GPS_BLENDED_INSTANCE].vertical_accuracy = 1e6f;
- state[GPS_BLENDED_INSTANCE].have_vertical_velocity = false;
- state[GPS_BLENDED_INSTANCE].have_speed_accuracy = false;
- state[GPS_BLENDED_INSTANCE].have_horizontal_accuracy = false;
- state[GPS_BLENDED_INSTANCE].have_vertical_accuracy = false;
- state[GPS_BLENDED_INSTANCE].location = {};
- _blended_antenna_offset.zero();
- _blended_lag_sec = 0;
- timing[GPS_BLENDED_INSTANCE].last_fix_time_ms = 0;
- timing[GPS_BLENDED_INSTANCE].last_message_time_ms = 0;
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
-
- if (state[i].status > state[GPS_BLENDED_INSTANCE].status) {
- state[GPS_BLENDED_INSTANCE].status = state[i].status;
- }
-
- state[GPS_BLENDED_INSTANCE].velocity += state[i].velocity * _blend_weights[i];
-
- if (state[i].have_horizontal_accuracy && state[i].horizontal_accuracy > 0.0f && state[i].horizontal_accuracy < state[GPS_BLENDED_INSTANCE].horizontal_accuracy) {
- state[GPS_BLENDED_INSTANCE].have_horizontal_accuracy = true;
- state[GPS_BLENDED_INSTANCE].horizontal_accuracy = state[i].horizontal_accuracy;
- }
- if (state[i].have_vertical_accuracy && state[i].vertical_accuracy > 0.0f && state[i].vertical_accuracy < state[GPS_BLENDED_INSTANCE].vertical_accuracy) {
- state[GPS_BLENDED_INSTANCE].have_vertical_accuracy = true;
- state[GPS_BLENDED_INSTANCE].vertical_accuracy = state[i].vertical_accuracy;
- }
- if (state[i].have_vertical_velocity) {
- state[GPS_BLENDED_INSTANCE].have_vertical_velocity = true;
- }
- if (state[i].have_speed_accuracy && state[i].speed_accuracy > 0.0f && state[i].speed_accuracy < state[GPS_BLENDED_INSTANCE].speed_accuracy) {
- state[GPS_BLENDED_INSTANCE].have_speed_accuracy = true;
- state[GPS_BLENDED_INSTANCE].speed_accuracy = state[i].speed_accuracy;
- }
- if (state[i].hdop > 0 && state[i].hdop < state[GPS_BLENDED_INSTANCE].hdop) {
- state[GPS_BLENDED_INSTANCE].hdop = state[i].hdop;
- }
- if (state[i].vdop > 0 && state[i].vdop < state[GPS_BLENDED_INSTANCE].vdop) {
- state[GPS_BLENDED_INSTANCE].vdop = state[i].vdop;
- }
- if (state[i].num_sats > 0 && state[i].num_sats > state[GPS_BLENDED_INSTANCE].num_sats) {
- state[GPS_BLENDED_INSTANCE].num_sats = state[i].num_sats;
- }
-
- Vector3f temp_antenna_offset = _antenna_offset[i];
- temp_antenna_offset *= _blend_weights[i];
- _blended_antenna_offset += temp_antenna_offset;
-
- if (timing[i].last_fix_time_ms > timing[GPS_BLENDED_INSTANCE].last_fix_time_ms) {
- timing[GPS_BLENDED_INSTANCE].last_fix_time_ms = timing[i].last_fix_time_ms;
- }
- if (timing[i].last_message_time_ms > timing[GPS_BLENDED_INSTANCE].last_message_time_ms) {
- timing[GPS_BLENDED_INSTANCE].last_message_time_ms = timing[i].last_message_time_ms;
- }
- }
-
-
- float best_weight = 0.0f;
- uint8_t best_index = 0;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (_blend_weights[i] > best_weight) {
- best_weight = _blend_weights[i];
- best_index = i;
- state[GPS_BLENDED_INSTANCE].location = state[i].location;
- }
- }
-
- Vector2f blended_NE_offset_m;
- float blended_alt_offset_cm = 0.0f;
- blended_NE_offset_m.zero();
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (_blend_weights[i] > 0.0f && i != best_index) {
- blended_NE_offset_m += state[GPS_BLENDED_INSTANCE].location.get_distance_NE(state[i].location) * _blend_weights[i];
- blended_alt_offset_cm += (float)(state[i].location.alt - state[GPS_BLENDED_INSTANCE].location.alt) * _blend_weights[i];
- }
- }
-
- state[GPS_BLENDED_INSTANCE].location.offset(blended_NE_offset_m.x, blended_NE_offset_m.y);
- state[GPS_BLENDED_INSTANCE].location.alt += (int)blended_alt_offset_cm;
-
- state[GPS_BLENDED_INSTANCE].ground_speed = norm(state[GPS_BLENDED_INSTANCE].velocity.x, state[GPS_BLENDED_INSTANCE].velocity.y);
- state[GPS_BLENDED_INSTANCE].ground_course = wrap_360(degrees(atan2f(state[GPS_BLENDED_INSTANCE].velocity.y, state[GPS_BLENDED_INSTANCE].velocity.x)));
-
-
-
- float alpha[GPS_MAX_RECEIVERS] = {};
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (state[i].last_gps_time_ms - _last_time_updated[i] > 0) {
- float min_alpha = constrain_float(_omega_lpf * 0.001f * (float)(state[i].last_gps_time_ms - _last_time_updated[i]), 0.0f, 1.0f);
- if (_blend_weights[i] > min_alpha) {
- alpha[i] = min_alpha / _blend_weights[i];
- } else {
- alpha[i] = 1.0f;
- }
- _last_time_updated[i] = state[i].last_gps_time_ms;
- }
- }
-
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- _NE_pos_offset_m[i] = state[i].location.get_distance_NE(state[GPS_BLENDED_INSTANCE].location) * alpha[i] + _NE_pos_offset_m[i] * (1.0f - alpha[i]);
- _hgt_offset_cm[i] = (float)(state[GPS_BLENDED_INSTANCE].location.alt - state[i].location.alt) * alpha[i] + _hgt_offset_cm[i] * (1.0f - alpha[i]);
- }
-
- Location corrected_location[GPS_MAX_RECEIVERS];
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- corrected_location[i] = state[i].location;
- corrected_location[i].offset(_NE_pos_offset_m[i].x, _NE_pos_offset_m[i].y);
- corrected_location[i].alt += (int)(_hgt_offset_cm[i]);
- }
-
-
-
- uint8_t last_week_instance = 0;
- bool weeks_consistent = true;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (last_week_instance == 0 && _blend_weights[i] > 0) {
-
- last_week_instance = state[i].time_week;
- } else if (last_week_instance != 0 && _blend_weights[i] > 0 && last_week_instance != state[i].time_week) {
-
- weeks_consistent = false;
- }
- }
-
- if (!weeks_consistent) {
-
- state[GPS_BLENDED_INSTANCE].time_week = state[best_index].time_week;
- state[GPS_BLENDED_INSTANCE].time_week_ms = state[best_index].time_week_ms;
- } else {
-
- state[GPS_BLENDED_INSTANCE].time_week = state[best_index].time_week;
-
- double temp_time_0 = 0.0;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (_blend_weights[i] > 0.0f) {
- temp_time_0 += (double)state[i].time_week_ms * (double)_blend_weights[i];
- }
- }
- state[GPS_BLENDED_INSTANCE].time_week_ms = (uint32_t)temp_time_0;
- }
-
- double temp_time_1 = 0.0;
- double temp_time_2 = 0.0;
- for (uint8_t i=0; i<GPS_MAX_RECEIVERS; i++) {
- if (_blend_weights[i] > 0.0f) {
- temp_time_1 += (double)timing[i].last_fix_time_ms * (double) _blend_weights[i];
- temp_time_2 += (double)timing[i].last_message_time_ms * (double)_blend_weights[i];
- float gps_lag_sec = 0;
- get_lag(i, gps_lag_sec);
- _blended_lag_sec += gps_lag_sec * _blend_weights[i];
- }
- }
- timing[GPS_BLENDED_INSTANCE].last_fix_time_ms = (uint32_t)temp_time_1;
- timing[GPS_BLENDED_INSTANCE].last_message_time_ms = (uint32_t)temp_time_2;
- }
- #endif
- bool AP_GPS::is_healthy(uint8_t instance) const
- {
- if (instance >= GPS_MAX_INSTANCES) {
- return false;
- }
- const uint16_t gps_max_delta_ms = 245;
- bool last_msg_valid = last_message_delta_time_ms(instance) < gps_max_delta_ms;
- #if defined(GPS_BLENDED_INSTANCE)
- if (instance == GPS_BLENDED_INSTANCE) {
- return last_msg_valid && blend_health_check();
- }
- #endif
- return last_msg_valid &&
- drivers[instance] != nullptr &&
- drivers[instance]->is_healthy();
- }
- bool AP_GPS::prepare_for_arming(void) {
- bool all_passed = true;
- for (uint8_t i = 0; i < GPS_MAX_RECEIVERS; i++) {
- if (drivers[i] != nullptr) {
- all_passed &= drivers[i]->prepare_for_arming();
- }
- }
- return all_passed;
- }
- namespace AP {
- AP_GPS &gps()
- {
- return *AP_GPS::get_singleton();
- }
- };
|