bool AP_GPS_UBLOX::_parse_gps(void) { if (_class == CLASS_ACK) { Debug("ACK %u", (unsigned)_msg_id); return false; } if (_class == CLASS_CFG && _msg_id == MSG_CFG_NAV_SETTINGS) { Debug("Got settings %u min_elev %d drLimit %u\n", (unsigned)_buffer.nav_settings.dynModel, (int)_buffer.nav_settings.minElev, (unsigned)_buffer.nav_settings.drLimit); _buffer.nav_settings.mask = 0; if (gps._navfilter != AP_GPS::GPS_ENGINE_NONE && _buffer.nav_settings.dynModel != gps._navfilter) { // we've received the current nav settings, change the engine // settings and send them back Debug("Changing engine setting from %u to %u\n", (unsigned)_buffer.nav_settings.dynModel, (unsigned)gps._navfilter); _buffer.nav_settings.dynModel = gps._navfilter; _buffer.nav_settings.mask |= 1; } if (gps._min_elevation != -100 && _buffer.nav_settings.minElev != gps._min_elevation) { Debug("Changing min elevation to %d\n", (int)gps._min_elevation); _buffer.nav_settings.minElev = gps._min_elevation; _buffer.nav_settings.mask |= 2; } if (_buffer.nav_settings.mask != 0) { _send_message(CLASS_CFG, MSG_CFG_NAV_SETTINGS, &_buffer.nav_settings, sizeof(_buffer.nav_settings)); } return false; } #if UBLOX_GNSS_SETTINGS if (_class == CLASS_CFG && _msg_id == MSG_CFG_GNSS && gps._gnss_mode != 0) { uint8_t gnssCount = 0; Debug("Got GNSS Settings %u %u %u %u:\n", (unsigned)_buffer.gnss.msgVer, (unsigned)_buffer.gnss.numTrkChHw, (unsigned)_buffer.gnss.numTrkChUse, (unsigned)_buffer.gnss.numConfigBlocks); #if UBLOX_DEBUG for(int i = 0; i < _buffer.gnss.numConfigBlocks; i++) { Debug(" %u %u %u 0x%08x\n", (unsigned)_buffer.gnss.configBlock[i].gnssId, (unsigned)_buffer.gnss.configBlock[i].resTrkCh, (unsigned)_buffer.gnss.configBlock[i].maxTrkCh, (unsigned)_buffer.gnss.configBlock[i].flags); } #endif for(int i = 0; i < UBLOX_MAX_GNSS_CONFIG_BLOCKS; i++) { if((gps._gnss_mode & (1 << i)) && i != GNSS_SBAS) { gnssCount++; } } for(int i = 0; i < _buffer.gnss.numConfigBlocks; i++) { // Reserve an equal portion of channels for all enabled systems if(gps._gnss_mode & (1 << _buffer.gnss.configBlock[i].gnssId)) { if(GNSS_SBAS !=_buffer.gnss.configBlock[i].gnssId) { _buffer.gnss.configBlock[i].resTrkCh = (_buffer.gnss.numTrkChHw - 3) / (gnssCount * 2); _buffer.gnss.configBlock[i].maxTrkCh = _buffer.gnss.numTrkChHw; } else { _buffer.gnss.configBlock[i].resTrkCh = 1; _buffer.gnss.configBlock[i].maxTrkCh = 3; } _buffer.gnss.configBlock[i].flags = _buffer.gnss.configBlock[i].flags | 0x00000001; } else { _buffer.gnss.configBlock[i].resTrkCh = 0; _buffer.gnss.configBlock[i].maxTrkCh = 0; _buffer.gnss.configBlock[i].flags = _buffer.gnss.configBlock[i].flags & 0xFFFFFFFE; } } _send_message(CLASS_CFG, MSG_CFG_GNSS, &_buffer.gnss, 4 + (8 * _buffer.gnss.numConfigBlocks)); return false; } #endif if (_class == CLASS_CFG && _msg_id == MSG_CFG_SBAS && gps._sbas_mode != 2) { Debug("Got SBAS settings %u %u %u 0x%x 0x%x\n", (unsigned)_buffer.sbas.mode, (unsigned)_buffer.sbas.usage, (unsigned)_buffer.sbas.maxSBAS, (unsigned)_buffer.sbas.scanmode2, (unsigned)_buffer.sbas.scanmode1); if (_buffer.sbas.mode != gps._sbas_mode) { _buffer.sbas.mode = gps._sbas_mode; _send_message(CLASS_CFG, MSG_CFG_SBAS, &_buffer.sbas, sizeof(_buffer.sbas)); } } #if UBLOX_HW_LOGGING if (_class == CLASS_MON) { if (_msg_id == MSG_MON_HW) { if (_payload_length == 60 || _payload_length == 68) { log_mon_hw(); } } else if (_msg_id == MSG_MON_HW2) { if (_payload_length == 28) { log_mon_hw2(); } } else { unexpected_message(); } return false; } #endif // UBLOX_HW_LOGGING #if UBLOX_RXM_RAW_LOGGING if (_class == CLASS_RXM && _msg_id == MSG_RXM_RAW && gps._raw_data != 0) { log_rxm_raw(_buffer.rxm_raw); return false; } else if (_class == CLASS_RXM && _msg_id == MSG_RXM_RAWX && gps._raw_data != 0) { log_rxm_rawx(_buffer.rxm_rawx); return false; } #endif // UBLOX_RXM_RAW_LOGGING if (_class != CLASS_NAV) { unexpected_message(); return false; } switch (_msg_id) { case MSG_POSLLH: Debug("MSG_POSLLH next_fix=%u", next_fix); _last_pos_time = _buffer.posllh.time; state.location.lng = _buffer.posllh.longitude; state.location.lat = _buffer.posllh.latitude; state.location.alt = _buffer.posllh.altitude_msl / 10; state.status = next_fix; _new_position = true; #if UBLOX_FAKE_3DLOCK state.location.lng = 1491652300L; state.location.lat = -353632610L; state.location.alt = 58400; #endif state.horizontal_accuracy = _buffer.posllh.horizontal_accuracy*1.0e-3f; state.vertical_accuracy = _buffer.posllh.vertical_accuracy*1.0e-3f; state.have_horizontal_accuracy = true; state.have_vertical_accuracy = true; break; case MSG_STATUS: Debug("MSG_STATUS fix_status=%u fix_type=%u", _buffer.status.fix_status, _buffer.status.fix_type); if (_buffer.status.fix_status & NAV_STATUS_FIX_VALID) { if( (_buffer.status.fix_type == AP_GPS_UBLOX::FIX_3D) && (_buffer.status.fix_status & AP_GPS_UBLOX::NAV_STATUS_DGPS_USED)) { next_fix = AP_GPS::GPS_OK_FIX_3D_DGPS; }else if( _buffer.status.fix_type == AP_GPS_UBLOX::FIX_3D) { next_fix = AP_GPS::GPS_OK_FIX_3D; }else if (_buffer.status.fix_type == AP_GPS_UBLOX::FIX_2D) { next_fix = AP_GPS::GPS_OK_FIX_2D; }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } #if UBLOX_FAKE_3DLOCK state.status = AP_GPS::GPS_OK_FIX_3D; next_fix = state.status; #endif break; case MSG_DOP: Debug("MSG_DOP"); noReceivedHdop = false; state.hdop = _buffer.dop.hDOP; #if UBLOX_FAKE_3DLOCK state.hdop = 130; #endif break; case MSG_SOL: Debug("MSG_SOL fix_status=%u fix_type=%u", _buffer.solution.fix_status, _buffer.solution.fix_type); if (_buffer.solution.fix_status & NAV_STATUS_FIX_VALID) { if( (_buffer.solution.fix_type == AP_GPS_UBLOX::FIX_3D) && (_buffer.solution.fix_status & AP_GPS_UBLOX::NAV_STATUS_DGPS_USED)) { next_fix = AP_GPS::GPS_OK_FIX_3D_DGPS; }else if( _buffer.solution.fix_type == AP_GPS_UBLOX::FIX_3D) { next_fix = AP_GPS::GPS_OK_FIX_3D; }else if (_buffer.solution.fix_type == AP_GPS_UBLOX::FIX_2D) { next_fix = AP_GPS::GPS_OK_FIX_2D; }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } if(noReceivedHdop) { state.hdop = _buffer.solution.position_DOP; } state.num_sats = _buffer.solution.satellites; if (next_fix >= AP_GPS::GPS_OK_FIX_2D) { state.last_gps_time_ms = hal.scheduler->millis(); if (state.time_week == _buffer.solution.week && state.time_week_ms + 200 == _buffer.solution.time) { // we got a 5Hz update. This relies on the way // that uBlox gives timestamps that are always // multiples of 200 for 5Hz _last_5hz_time = state.last_gps_time_ms; } state.time_week_ms = _buffer.solution.time; state.time_week = _buffer.solution.week; } #if UBLOX_FAKE_3DLOCK next_fix = state.status; state.num_sats = 10; state.time_week = 1721; state.time_week_ms = hal.scheduler->millis() + 3*60*60*1000 + 37000; state.last_gps_time_ms = hal.scheduler->millis(); #endif break; case MSG_VELNED: Debug("MSG_VELNED"); _last_vel_time = _buffer.velned.time; state.ground_speed = _buffer.velned.speed_2d*0.01f; // m/s state.ground_course_cd = _buffer.velned.heading_2d / 1000; // Heading 2D deg * 100000 rescaled to deg * 100 state.have_vertical_velocity = true; state.velocity.x = _buffer.velned.ned_north * 0.01f; state.velocity.y = _buffer.velned.ned_east * 0.01f; state.velocity.z = _buffer.velned.ned_down * 0.01f; state.have_speed_accuracy = true; state.speed_accuracy = _buffer.velned.speed_accuracy*0.01f; _new_speed = true; break; #if UBLOX_VERSION_AUTODETECTION case MSG_NAV_SVINFO: { Debug("MSG_NAV_SVINFO\n"); static const uint8_t HardwareGenerationMask = 0x07; uint8_t hardware_generation = _buffer.svinfo_header.globalFlags & HardwareGenerationMask; switch (hardware_generation) { case UBLOX_5: case UBLOX_6: /*speed already configured */; break; case UBLOX_7: case UBLOX_M8: port->begin(4000000U); Debug("Changed speed to 5Mhzfor SPI-driven UBlox\n"); break; default: hal.console->printf("Wrong Ublox' Hardware Version%u\n", hardware_generation); break; }; /* We don't need that anymore */ _configure_message_rate(CLASS_NAV, MSG_NAV_SVINFO, 0); break; } #endif default: Debug("Unexpected NAV message 0x%02x", (unsigned)_msg_id); if (++_disable_counter == 0) { Debug("Disabling NAV message 0x%02x", (unsigned)_msg_id); _configure_message_rate(CLASS_NAV, _msg_id, 0); } return false; } // we only return true when we get new position and speed data // this ensures we don't use stale data if (_new_position && _new_speed && _last_vel_time == _last_pos_time) { _new_speed = _new_position = false; _fix_count++; if ((hal.scheduler->millis() - _last_5hz_time) > 15000U && !need_rate_update) { // the GPS is running slow. It possibly browned out and // restarted with incorrect parameters. We will slowly // send out new parameters to fix it need_rate_update = true; rate_update_step = 0; _last_5hz_time = hal.scheduler->millis(); } if (_fix_count == 50 && gps._sbas_mode != 2) { // ask for SBAS settings every 20 seconds Debug("Asking for SBAS setting\n"); _send_message(CLASS_CFG, MSG_CFG_SBAS, NULL, 0); } if (_fix_count == 100) { // ask for nav settings every 20 seconds Debug("Asking for engine setting\n"); _send_message(CLASS_CFG, MSG_CFG_NAV_SETTINGS, NULL, 0); _fix_count = 0; } #if UBLOX_HW_LOGGING log_accuracy(); #endif //UBLOX_HW_LOGGING return true; } return false; }
bool AP_GPS_UBLOX::_parse_gps(void) { if (_class == CLASS_ACK) { Debug("ACK %u", (unsigned)_msg_id); if(_msg_id == MSG_ACK_ACK) { switch(_buffer.ack.clsID) { case CLASS_CFG: switch(_buffer.ack.msgID) { case MSG_CFG_CFG: _cfg_saved = true; _cfg_needs_save = false; break; case MSG_CFG_GNSS: _unconfigured_messages &= ~CONFIG_GNSS; break; case MSG_CFG_MSG: // There is no way to know what MSG config was ack'ed, assume it was the last // one requested. To verify it rerequest the last config we sent. If we miss // the actual ack we will catch it next time through the poll loop, but that // will be a good chunk of time later. break; case MSG_CFG_NAV_SETTINGS: _unconfigured_messages &= ~CONFIG_NAV_SETTINGS; break; case MSG_CFG_RATE: // The GPS will ACK a update rate that is invalid. in order to detect this // only accept the rate as configured by reading the settings back and // validating that they all match the target values break; case MSG_CFG_SBAS: _unconfigured_messages &= ~CONFIG_SBAS; break; } break; case CLASS_MON: switch(_buffer.ack.msgID) { case MSG_MON_HW: _unconfigured_messages &= ~CONFIG_RATE_MON_HW; break; case MSG_MON_HW2: _unconfigured_messages &= ~CONFIG_RATE_MON_HW2; break; } } } return false; } if (_class == CLASS_CFG) { switch(_msg_id) { case MSG_CFG_NAV_SETTINGS: Debug("Got settings %u min_elev %d drLimit %u\n", (unsigned)_buffer.nav_settings.dynModel, (int)_buffer.nav_settings.minElev, (unsigned)_buffer.nav_settings.drLimit); _buffer.nav_settings.mask = 0; if (gps._navfilter != AP_GPS::GPS_ENGINE_NONE && _buffer.nav_settings.dynModel != gps._navfilter) { // we've received the current nav settings, change the engine // settings and send them back Debug("Changing engine setting from %u to %u\n", (unsigned)_buffer.nav_settings.dynModel, (unsigned)gps._navfilter); _buffer.nav_settings.dynModel = gps._navfilter; _buffer.nav_settings.mask |= 1; } if (gps._min_elevation != -100 && _buffer.nav_settings.minElev != gps._min_elevation) { Debug("Changing min elevation to %d\n", (int)gps._min_elevation); _buffer.nav_settings.minElev = gps._min_elevation; _buffer.nav_settings.mask |= 2; } if (_buffer.nav_settings.mask != 0) { _send_message(CLASS_CFG, MSG_CFG_NAV_SETTINGS, &_buffer.nav_settings, sizeof(_buffer.nav_settings)); _unconfigured_messages |= CONFIG_NAV_SETTINGS; _cfg_needs_save = true; } else { _unconfigured_messages &= ~CONFIG_NAV_SETTINGS; } return false; #if UBLOX_GNSS_SETTINGS case MSG_CFG_GNSS: if (gps._gnss_mode[state.instance] != 0) { struct ubx_cfg_gnss start_gnss = _buffer.gnss; uint8_t gnssCount = 0; Debug("Got GNSS Settings %u %u %u %u:\n", (unsigned)_buffer.gnss.msgVer, (unsigned)_buffer.gnss.numTrkChHw, (unsigned)_buffer.gnss.numTrkChUse, (unsigned)_buffer.gnss.numConfigBlocks); #if UBLOX_DEBUGGING for(int i = 0; i < _buffer.gnss.numConfigBlocks; i++) { Debug(" %u %u %u 0x%08x\n", (unsigned)_buffer.gnss.configBlock[i].gnssId, (unsigned)_buffer.gnss.configBlock[i].resTrkCh, (unsigned)_buffer.gnss.configBlock[i].maxTrkCh, (unsigned)_buffer.gnss.configBlock[i].flags); } #endif for(int i = 0; i < UBLOX_MAX_GNSS_CONFIG_BLOCKS; i++) { if((gps._gnss_mode[state.instance] & (1 << i)) && i != GNSS_SBAS) { gnssCount++; } } for(int i = 0; i < _buffer.gnss.numConfigBlocks; i++) { // Reserve an equal portion of channels for all enabled systems if(gps._gnss_mode[state.instance] & (1 << _buffer.gnss.configBlock[i].gnssId)) { if(GNSS_SBAS !=_buffer.gnss.configBlock[i].gnssId) { _buffer.gnss.configBlock[i].resTrkCh = (_buffer.gnss.numTrkChHw - 3) / (gnssCount * 2); _buffer.gnss.configBlock[i].maxTrkCh = _buffer.gnss.numTrkChHw; } else { _buffer.gnss.configBlock[i].resTrkCh = 1; _buffer.gnss.configBlock[i].maxTrkCh = 3; } _buffer.gnss.configBlock[i].flags = _buffer.gnss.configBlock[i].flags | 0x00000001; } else { _buffer.gnss.configBlock[i].resTrkCh = 0; _buffer.gnss.configBlock[i].maxTrkCh = 0; _buffer.gnss.configBlock[i].flags = _buffer.gnss.configBlock[i].flags & 0xFFFFFFFE; } } if (!memcmp(&start_gnss, &_buffer.gnss, sizeof(start_gnss))) { _send_message(CLASS_CFG, MSG_CFG_GNSS, &_buffer.gnss, 4 + (8 * _buffer.gnss.numConfigBlocks)); _unconfigured_messages |= CONFIG_GNSS; _cfg_needs_save = true; } else { _unconfigured_messages &= ~CONFIG_GNSS; } } else { _unconfigured_messages &= ~CONFIG_GNSS; } return false; #endif case MSG_CFG_SBAS: if (gps._sbas_mode != 2) { Debug("Got SBAS settings %u %u %u 0x%x 0x%x\n", (unsigned)_buffer.sbas.mode, (unsigned)_buffer.sbas.usage, (unsigned)_buffer.sbas.maxSBAS, (unsigned)_buffer.sbas.scanmode2, (unsigned)_buffer.sbas.scanmode1); if (_buffer.sbas.mode != gps._sbas_mode) { _buffer.sbas.mode = gps._sbas_mode; _send_message(CLASS_CFG, MSG_CFG_SBAS, &_buffer.sbas, sizeof(_buffer.sbas)); _unconfigured_messages |= CONFIG_SBAS; _cfg_needs_save = true; } else { _unconfigured_messages &= ~CONFIG_SBAS; } } else { _unconfigured_messages &= ~CONFIG_SBAS; } return false; case MSG_CFG_MSG: if(_payload_length == sizeof(ubx_cfg_msg_rate_6)) { // can't verify the setting without knowing the port // request the port again if(_ublox_port >= UBLOX_MAX_PORTS) { _request_port(); return false; } _verify_rate(_buffer.msg_rate_6.msg_class, _buffer.msg_rate_6.msg_id, _buffer.msg_rate_6.rates[_ublox_port]); } else { _verify_rate(_buffer.msg_rate.msg_class, _buffer.msg_rate.msg_id, _buffer.msg_rate.rate); } return false; case MSG_CFG_PRT: _ublox_port = _buffer.prt.portID; return false; case MSG_CFG_RATE: if(_buffer.nav_rate.measure_rate_ms != gps._rate_ms[state.instance] || _buffer.nav_rate.nav_rate != 1 || _buffer.nav_rate.timeref != 0) { _configure_rate(); _unconfigured_messages |= CONFIG_RATE_NAV; _cfg_needs_save = true; } else { _unconfigured_messages &= ~CONFIG_RATE_NAV; } return false; } } if (_class == CLASS_MON) { switch(_msg_id) { case MSG_MON_HW: if (_payload_length == 60 || _payload_length == 68) { log_mon_hw(); } break; case MSG_MON_HW2: if (_payload_length == 28) { log_mon_hw2(); } break; case MSG_MON_VER: _have_version = true; GCS_MAVLINK::send_statustext_all(MAV_SEVERITY_INFO, "u-blox %d HW: %s SW: %s", state.instance, _buffer.mon_ver.hwVersion, _buffer.mon_ver.swVersion); break; default: unexpected_message(); } return false; } #if UBLOX_RXM_RAW_LOGGING if (_class == CLASS_RXM && _msg_id == MSG_RXM_RAW && gps._raw_data != 0) { log_rxm_raw(_buffer.rxm_raw); return false; } else if (_class == CLASS_RXM && _msg_id == MSG_RXM_RAWX && gps._raw_data != 0) { log_rxm_rawx(_buffer.rxm_rawx); return false; } #endif // UBLOX_RXM_RAW_LOGGING if (_class != CLASS_NAV) { unexpected_message(); return false; } switch (_msg_id) { case MSG_POSLLH: Debug("MSG_POSLLH next_fix=%u", next_fix); _last_pos_time = _buffer.posllh.time; state.location.lng = _buffer.posllh.longitude; state.location.lat = _buffer.posllh.latitude; state.location.alt = _buffer.posllh.altitude_msl / 10; state.status = next_fix; _new_position = true; state.horizontal_accuracy = _buffer.posllh.horizontal_accuracy*1.0e-3f; state.vertical_accuracy = _buffer.posllh.vertical_accuracy*1.0e-3f; state.have_horizontal_accuracy = true; state.have_vertical_accuracy = true; #if UBLOX_FAKE_3DLOCK state.location.lng = 1491652300L; state.location.lat = -353632610L; state.location.alt = 58400; state.vertical_accuracy = 0; state.horizontal_accuracy = 0; #endif break; case MSG_STATUS: Debug("MSG_STATUS fix_status=%u fix_type=%u", _buffer.status.fix_status, _buffer.status.fix_type); if (_buffer.status.fix_status & NAV_STATUS_FIX_VALID) { if( (_buffer.status.fix_type == AP_GPS_UBLOX::FIX_3D) && (_buffer.status.fix_status & AP_GPS_UBLOX::NAV_STATUS_DGPS_USED)) { next_fix = AP_GPS::GPS_OK_FIX_3D_DGPS; }else if( _buffer.status.fix_type == AP_GPS_UBLOX::FIX_3D) { next_fix = AP_GPS::GPS_OK_FIX_3D; }else if (_buffer.status.fix_type == AP_GPS_UBLOX::FIX_2D) { next_fix = AP_GPS::GPS_OK_FIX_2D; }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } #if UBLOX_FAKE_3DLOCK state.status = AP_GPS::GPS_OK_FIX_3D; next_fix = state.status; #endif break; case MSG_DOP: Debug("MSG_DOP"); noReceivedHdop = false; state.hdop = _buffer.dop.hDOP; state.vdop = _buffer.dop.vDOP; #if UBLOX_FAKE_3DLOCK state.hdop = 130; state.hdop = 170; #endif break; case MSG_SOL: Debug("MSG_SOL fix_status=%u fix_type=%u", _buffer.solution.fix_status, _buffer.solution.fix_type); if (_buffer.solution.fix_status & NAV_STATUS_FIX_VALID) { if( (_buffer.solution.fix_type == AP_GPS_UBLOX::FIX_3D) && (_buffer.solution.fix_status & AP_GPS_UBLOX::NAV_STATUS_DGPS_USED)) { next_fix = AP_GPS::GPS_OK_FIX_3D_DGPS; }else if( _buffer.solution.fix_type == AP_GPS_UBLOX::FIX_3D) { next_fix = AP_GPS::GPS_OK_FIX_3D; }else if (_buffer.solution.fix_type == AP_GPS_UBLOX::FIX_2D) { next_fix = AP_GPS::GPS_OK_FIX_2D; }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } }else{ next_fix = AP_GPS::NO_FIX; state.status = AP_GPS::NO_FIX; } if(noReceivedHdop) { state.hdop = _buffer.solution.position_DOP; } state.num_sats = _buffer.solution.satellites; if (next_fix >= AP_GPS::GPS_OK_FIX_2D) { state.last_gps_time_ms = AP_HAL::millis(); state.time_week_ms = _buffer.solution.time; state.time_week = _buffer.solution.week; } #if UBLOX_FAKE_3DLOCK next_fix = state.status; state.num_sats = 10; state.time_week = 1721; state.time_week_ms = AP_HAL::millis() + 3*60*60*1000 + 37000; state.last_gps_time_ms = AP_HAL::millis(); state.hdop = 130; #endif break; case MSG_VELNED: Debug("MSG_VELNED"); _last_vel_time = _buffer.velned.time; state.ground_speed = _buffer.velned.speed_2d*0.01f; // m/s state.ground_course = wrap_360(_buffer.velned.heading_2d * 1.0e-5f); // Heading 2D deg * 100000 state.have_vertical_velocity = true; state.velocity.x = _buffer.velned.ned_north * 0.01f; state.velocity.y = _buffer.velned.ned_east * 0.01f; state.velocity.z = _buffer.velned.ned_down * 0.01f; state.ground_course = wrap_360(degrees(atan2f(state.velocity.y, state.velocity.x))); state.ground_speed = norm(state.velocity.y, state.velocity.x); state.have_speed_accuracy = true; state.speed_accuracy = _buffer.velned.speed_accuracy*0.01f; #if UBLOX_FAKE_3DLOCK state.speed_accuracy = 0; #endif _new_speed = true; break; case MSG_NAV_SVINFO: { Debug("MSG_NAV_SVINFO\n"); static const uint8_t HardwareGenerationMask = 0x07; _hardware_generation = _buffer.svinfo_header.globalFlags & HardwareGenerationMask; switch (_hardware_generation) { case UBLOX_5: case UBLOX_6: // only 7 and newer support CONFIG_GNSS _unconfigured_messages &= ~CONFIG_GNSS; break; case UBLOX_7: case UBLOX_M8: #if UBLOX_SPEED_CHANGE port->begin(4000000U); Debug("Changed speed to 4Mhz for SPI-driven UBlox\n"); #endif break; default: hal.console->printf("Wrong Ublox Hardware Version%u\n", _hardware_generation); break; }; _unconfigured_messages &= ~CONFIG_VERSION; /* We don't need that anymore */ _configure_message_rate(CLASS_NAV, MSG_NAV_SVINFO, 0); break; } default: Debug("Unexpected NAV message 0x%02x", (unsigned)_msg_id); if (++_disable_counter == 0) { Debug("Disabling NAV message 0x%02x", (unsigned)_msg_id); _configure_message_rate(CLASS_NAV, _msg_id, 0); } return false; } // we only return true when we get new position and speed data // this ensures we don't use stale data if (_new_position && _new_speed && _last_vel_time == _last_pos_time) { _new_speed = _new_position = false; return true; } return false; }