diff --git a/libraries/AP_AHRS/AP_AHRS.cpp b/libraries/AP_AHRS/AP_AHRS.cpp index 623df872375..ad5c1a0a10f 100644 --- a/libraries/AP_AHRS/AP_AHRS.cpp +++ b/libraries/AP_AHRS/AP_AHRS.cpp @@ -272,7 +272,7 @@ void AP_AHRS::init() #if !HAL_NAVEKF2_AVAILABLE && HAL_NAVEKF3_AVAILABLE if (_ekf_type.get() == 2) { _ekf_type.set(EKFType::THREE); - EKF3.set_enable(true); + ekf3.EKF3.set_enable(true); } #elif !HAL_NAVEKF3_AVAILABLE && HAL_NAVEKF2_AVAILABLE if (_ekf_type.get() == 3) { @@ -284,7 +284,7 @@ void AP_AHRS::init() #if HAL_NAVEKF2_AVAILABLE && HAL_NAVEKF3_AVAILABLE // a special case to catch users who had AHRS_EKF_TYPE=2 saved and // updated to a version where EK2_ENABLE=0 - if (_ekf_type.get() == 2 && !EKF2.get_enable() && EKF3.get_enable()) { + if (_ekf_type.get() == 2 && !EKF2.get_enable() && ekf3.EK3.get_enable()) { _ekf_type.set(EKFType::THREE); } #endif @@ -385,7 +385,7 @@ void AP_AHRS::reset_gyro_drift(void) EKF2.resetGyroBias(); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.resetGyroBias(); + ekf3.reset_gyro_drift(); #endif } @@ -716,7 +716,7 @@ void AP_AHRS::update_EKF2(void) if (EKF2.getOriginLLH(new_origin)) { done_common_origin = true; #if HAL_NAVEKF3_AVAILABLE - EKF3.setOriginLLH(new_origin); + ekf3.set_origin(new_origin); #endif #if AP_AHRS_EXTERNAL_ENABLED external.set_origin(new_origin); @@ -730,7 +730,7 @@ void AP_AHRS::update_EKF2(void) #if HAL_NAVEKF3_AVAILABLE void AP_AHRS::update_EKF3(void) { - if (!_ekf3_started) { + if (!ekf3.started) { // wait 1 second for DCM to output a valid tilt error estimate if (start_time_ms == 0) { start_time_ms = AP_HAL::millis(); @@ -747,49 +747,19 @@ void AP_AHRS::update_EKF3(void) } #endif if (AP_HAL::millis() - start_time_ms > startup_delay_ms) { - _ekf3_started = EKF3.InitialiseFilter(); + ekf3.started = ekf3.EKF3.InitialiseFilter(); } } - if (_ekf3_started) { - EKF3.UpdateFilter(); + if (ekf3.started) { + ekf3.update(); + ekf3_estimates = {}; + ekf3.get_results(ekf3_estimates); if (_active_EKF_type() == EKFType::THREE) { - Vector3f eulers; - EKF3.getRotationBodyToNED(state.dcm_matrix); - EKF3.getEulerAngles(eulers); - roll = eulers.x; - pitch = eulers.y; - yaw = eulers.z; - update_cd_values(); - update_trig(); - - const AP_InertialSensor &_ins = AP::ins(); - - // Use the primary EKF to select the primary gyro - const int8_t primary_imu = EKF3.getPrimaryCoreIMUIndex(); - const uint8_t primary_gyro = primary_imu>=0?primary_imu:_ins.get_first_usable_gyro(); - const uint8_t primary_accel = primary_imu>=0?primary_imu:_ins.get_first_usable_accel(); - - // get gyro bias for primary EKF and change sign to give gyro drift - // Note sign convention used by EKF is bias = measurement - truth - Vector3f drift; - EKF3.getGyroBias(-1, drift); - state.gyro_drift = -drift; - - // use the same IMU as the primary EKF and correct for gyro drift - state.gyro_estimate = _ins.get_gyro(primary_gyro) + state.gyro_drift; - - // get 3-axis accel bias estimates for active EKF (this is usually for the primary IMU) - Vector3f &abias = state.accel_bias; - EKF3.getAccelBias(-1,abias); - - // use the primary IMU for accel earth frame - Vector3f accel = _ins.get_accel(primary_accel); - accel -= abias; - state.accel_ef = state.dcm_matrix * get_rotation_autopilot_body_to_vehicle_body() * accel; + copy_estimates_from_backend_estimates(ekf3_estimates); nav_filter_status filt_state; - EKF3.getFilterStatus(filt_state); + ekf3.get_filter_status(filt_state); update_notify_from_filter_status(filt_state); } /* @@ -797,7 +767,7 @@ void AP_AHRS::update_EKF3(void) */ if (!done_common_origin) { Location new_origin; - if (EKF3.getOriginLLH(new_origin)) { + if (ekf3.get_origin(new_origin)) { done_common_origin = true; #if HAL_NAVEKF2_AVAILABLE EKF2.setOriginLLH(new_origin); @@ -832,7 +802,7 @@ void AP_AHRS::update_external(void) EKF2.setOriginLLH(new_origin); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.setOriginLLH(new_origin); + ekf3.set_origin(new_origin); #endif } } @@ -861,9 +831,7 @@ void AP_AHRS::reset() } #endif #if HAL_NAVEKF3_AVAILABLE - if (_ekf3_started) { - _ekf3_started = EKF3.InitialiseFilter(); - } + ekf3.reset(); #endif } @@ -885,7 +853,7 @@ bool AP_AHRS::_get_location(Location &loc) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - if (EKF3.getLLH(loc)) { + if (ekf3_estimates.get_location(loc)) { return true; } break; @@ -951,7 +919,7 @@ bool AP_AHRS::_wind_estimate(Vector3f &wind) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getWind(wind); + return ekf3.wind_estimate(wind); #endif #if AP_AHRS_EXTERNAL_ENABLED @@ -1081,7 +1049,7 @@ bool AP_AHRS::_airspeed_EAS(float &airspeed_ret, AirspeedEstimateType &airspeed_ #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - have_wind = EKF3.getWind(wind_vel); + have_wind = ekf3.wind_estimate(wind_vel); break; #endif @@ -1168,7 +1136,7 @@ bool AP_AHRS::_airspeed_TAS(Vector3f &vec) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getAirSpdVec(vec); + return ekf3.EKF3.getAirSpdVec(vec); #endif #if AP_AHRS_SIM_ENABLED @@ -1200,7 +1168,7 @@ bool AP_AHRS::airspeed_health_data(uint8_t instance, float &innovation, float &i #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getAirSpdHealthData(instance, innovation, innovationVariance, age_ms); + return ekf3.EKF3.getAirSpdHealthData(instance, innovation, innovationVariance, age_ms); #endif #if AP_AHRS_SIM_ENABLED @@ -1231,7 +1199,7 @@ bool AP_AHRS::use_compass(void) #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.use_compass(); + return ekf3.use_compass(); #endif #if AP_AHRS_SIM_ENABLED @@ -1279,11 +1247,8 @@ bool AP_AHRS::_get_quaternion_for_ekf_type(Quaternion &quat, EKFType type) const #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - if (!_ekf3_started) { - return false; - } - EKF3.getQuaternion(quat); - break; + quat = ekf3_estimates.quaternion; + return ekf3_estimates.attitude_valid; #endif #if AP_AHRS_SIM_ENABLED case EKFType::SIM: @@ -1338,8 +1303,10 @@ bool AP_AHRS::_get_secondary_attitude(Vector3f &eulers) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: // EKF3 is secondary - EKF3.getEulerAngles(eulers); - return _ekf3_started; + eulers[0] = ekf3_estimates.roll_rad; + eulers[1] = ekf3_estimates.pitch_rad; + eulers[2] = ekf3_estimates.yaw_rad; + return ekf3_estimates.attitude_valid; #endif #if AP_AHRS_SIM_ENABLED @@ -1407,8 +1374,8 @@ bool AP_AHRS::_get_secondary_position(Location &loc) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: // EKF3 is secondary - EKF3.getLLH(loc); - return _ekf3_started; + ekf3_estimates.get_location(loc); + return ekf3.started; #endif #if AP_AHRS_SIM_ENABLED @@ -1446,11 +1413,8 @@ Vector2f AP_AHRS::_groundspeed_vector(void) #endif #if HAL_NAVEKF3_AVAILABLE - case EKFType::THREE: { - Vector3f vec; - EKF3.getVelNED(vec); - return vec.xy(); - } + case EKFType::THREE: + return ekf3.groundspeed_vector(); #endif #if AP_AHRS_SIM_ENABLED @@ -1481,7 +1445,7 @@ bool AP_AHRS::set_origin(const Location &loc) const bool ret2 = EKF2.setOriginLLH(loc); #endif #if HAL_NAVEKF3_AVAILABLE - const bool ret3 = EKF3.setOriginLLH(loc); + const bool ret3 = ekf3.set_origin(loc); #endif #if AP_AHRS_EXTERNAL_ENABLED const bool ret_ext = external.set_origin(loc); @@ -1574,7 +1538,7 @@ void AP_AHRS::use_recorded_origin_maybe() bool AP_AHRS::handle_external_position_estimate(const Location &loc, float pos_accuracy, uint32_t timestamp_ms) { #if HAL_NAVEKF3_AVAILABLE - return EKF3.setLatLng(loc, pos_accuracy, timestamp_ms); + return ekf3.EKF3.setLatLng(loc, pos_accuracy, timestamp_ms); #endif return false; } @@ -1606,8 +1570,7 @@ bool AP_AHRS::_get_velocity_NED(Vector3f &vec) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.getVelNED(vec); - return true; + return ekf3_estimates.get_velocity_NED(vec); #endif #if AP_AHRS_SIM_ENABLED @@ -1641,7 +1604,7 @@ bool AP_AHRS::get_mag_field_NED(Vector3f &vec) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.getMagNED(vec); + ekf3.EKF3.getMagNED(vec); return true; #endif @@ -1673,7 +1636,7 @@ bool AP_AHRS::get_mag_field_correction(Vector3f &vec) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.getMagXYZ(vec); + ekf3.EKF3.getMagXYZ(vec); return true; #endif @@ -1720,8 +1683,7 @@ bool AP_AHRS::get_vert_pos_rate_D(float &velocity) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - velocity = EKF3.getPosDownDerivative(); - return true; + return ekf3_estimates.get_vert_pos_rate_D(velocity); #endif #if AP_AHRS_SIM_ENABLED @@ -1752,7 +1714,7 @@ bool AP_AHRS::get_hagl(float &height) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getHAGL(height); + return ekf3.get_hagl(height); #endif #if AP_AHRS_SIM_ENABLED @@ -1798,7 +1760,7 @@ bool AP_AHRS::get_relative_position_NED_origin(Vector3p &vec) const case EKFType::THREE: { Vector2p posNE; postype_t posD; - if (EKF3.getPosNE(posNE) && EKF3.getPosD(posD)) { + if (ekf3.EKF3.getPosNE(posNE) && ekf3.EKF3.getPosD(posD)) { // position is valid vec.x = posNE.x; vec.y = posNE.y; @@ -1866,7 +1828,7 @@ bool AP_AHRS::get_relative_position_NE_origin(Vector2p &posNE) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: { - bool position_is_valid = EKF3.getPosNE(posNE); + bool position_is_valid = ekf3.EKF3.getPosNE(posNE); return position_is_valid; } #endif @@ -1932,7 +1894,7 @@ bool AP_AHRS::get_relative_position_D_origin(postype_t &posD) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: { - bool position_is_valid = EKF3.getPosD(posD); + bool position_is_valid = ekf3.EKF3.getPosD(posD); return position_is_valid; } #endif @@ -2073,16 +2035,16 @@ AP_AHRS::EKFType AP_AHRS::_active_EKF_type(void) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: { // do we have an EKF3 yet? - if (!_ekf3_started) { + if (!ekf3.started) { return fallback_active_EKF_type(); } if (always_use_EKF()) { uint16_t ekf3_faults; - EKF3.getFilterFaults(ekf3_faults); + ekf3.EKF3.getFilterFaults(ekf3_faults); if (ekf3_faults == 0) { ret = EKFType::THREE; } - } else if (EKF3.healthy()) { + } else if (ekf3.healthy()) { ret = EKFType::THREE; } break; @@ -2119,8 +2081,8 @@ AP_AHRS::EKFType AP_AHRS::_active_EKF_type(void) const #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.getFilterStatus(filt_state); - should_use_gps = EKF3.configuredToUseGPSForPosXY(); + ekf3.get_filter_status(filt_state); + should_use_gps = ekf3.EKF3.configuredToUseGPSForPosXY(); break; #endif #if AP_AHRS_SIM_ENABLED @@ -2213,7 +2175,7 @@ AP_AHRS::EKFType AP_AHRS::fallback_active_EKF_type(void) const #endif #if HAL_NAVEKF3_AVAILABLE - if (_ekf3_started) { + if (ekf3.started) { return EKFType::THREE; } #endif @@ -2322,9 +2284,8 @@ bool AP_AHRS::healthy(void) const #endif #if HAL_NAVEKF3_AVAILABLE - case EKFType::THREE: { - bool ret = _ekf3_started && EKF3.healthy(); - if (!ret) { + case EKFType::THREE: + if (!ekf3.healthy()) { return false; } if ((_vehicle_class == VehicleClass::FIXED_WING || @@ -2335,7 +2296,6 @@ bool AP_AHRS::healthy(void) const return false; } return true; - } #endif #if AP_AHRS_SIM_ENABLED @@ -2411,11 +2371,7 @@ bool AP_AHRS::pre_arm_check(bool requires_position, char *failure_msg, uint8_t f #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - if (!_ekf3_started) { - hal.util->snprintf(failure_msg, failure_msg_len, "EKF3 not started"); - return false; - } - return EKF3.pre_arm_check(requires_position, failure_msg, failure_msg_len) && ret; + return ekf3.pre_arm_check(requires_position, failure_msg, failure_msg_len) && ret; #endif } @@ -2442,7 +2398,7 @@ bool AP_AHRS::initialised(void) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: // initialisation complete 10sec after ekf has started - return (_ekf3_started && (AP_HAL::millis() - start_time_ms > AP_AHRS_NAVEKF_SETTLE_TIME_MS)); + return (ekf3.started && (AP_HAL::millis() - start_time_ms > AP_AHRS_NAVEKF_SETTLE_TIME_MS)); #endif #if AP_AHRS_SIM_ENABLED @@ -2474,7 +2430,7 @@ bool AP_AHRS::get_filter_status(nav_filter_status &status) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.getFilterStatus(status); + ekf3.get_filter_status(status); return true; #endif @@ -2498,7 +2454,7 @@ void AP_AHRS::writeOptFlowMeas(const uint8_t rawFlowQuality, const Vector2f &ra EKF2.writeOptFlowMeas(rawFlowQuality, rawFlowRates, rawGyroRates, msecFlowMeas, posOffset, heightOverride); #endif #if EK3_FEATURE_OPTFLOW_FUSION - EKF3.writeOptFlowMeas(rawFlowQuality, rawFlowRates, rawGyroRates, msecFlowMeas, posOffset, heightOverride); + ekf3.EKF3.writeOptFlowMeas(rawFlowQuality, rawFlowRates, rawGyroRates, msecFlowMeas, posOffset, heightOverride); #endif } @@ -2506,7 +2462,7 @@ void AP_AHRS::writeOptFlowMeas(const uint8_t rawFlowQuality, const Vector2f &ra bool AP_AHRS::getOptFlowSample(uint32_t& timeStamp_ms, Vector2f& flowRate, Vector2f& bodyRate, Vector2f& losPred) const { #if EK3_FEATURE_OPTFLOW_FUSION - return EKF3.getOptFlowSample(timeStamp_ms, flowRate, bodyRate, losPred); + return ekf3.EKF3.getOptFlowSample(timeStamp_ms, flowRate, bodyRate, losPred); #endif return false; } @@ -2515,7 +2471,7 @@ bool AP_AHRS::getOptFlowSample(uint32_t& timeStamp_ms, Vector2f& flowRate, Vecto void AP_AHRS::writeBodyFrameOdom(float quality, const Vector3f &delPos, const Vector3f &delAng, float delTime, uint32_t timeStamp_ms, uint16_t delay_ms, const Vector3f &posOffset) { #if HAL_NAVEKF3_AVAILABLE - EKF3.writeBodyFrameOdom(quality, delPos, delAng, delTime, timeStamp_ms, delay_ms, posOffset); + ekf3.EKF3.writeBodyFrameOdom(quality, delPos, delAng, delTime, timeStamp_ms, delay_ms, posOffset); #endif } @@ -2526,7 +2482,7 @@ void AP_AHRS::writeExtNavData(const Vector3f &pos, const Quaternion &quat, float EKF2.writeExtNavData(pos, quat, posErr, angErr, timeStamp_ms, delay_ms, resetTime_ms); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.writeExtNavData(pos, quat, posErr, angErr, timeStamp_ms, delay_ms, resetTime_ms); + ekf3.EKF3.writeExtNavData(pos, quat, posErr, angErr, timeStamp_ms, delay_ms, resetTime_ms); #endif } @@ -2537,7 +2493,7 @@ void AP_AHRS::writeDefaultAirSpeed(float airspeed, float uncertainty) EKF2.writeDefaultAirSpeed(airspeed); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.writeDefaultAirSpeed(airspeed, uncertainty); + ekf3.EKF3.writeDefaultAirSpeed(airspeed, uncertainty); #endif } @@ -2548,7 +2504,7 @@ void AP_AHRS::writeExtNavVelData(const Vector3f &vel, float err, uint32_t timeSt EKF2.writeExtNavVelData(vel, err, timeStamp_ms, delay_ms); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.writeExtNavVelData(vel, err, timeStamp_ms, delay_ms); + ekf3.EKF3.writeExtNavVelData(vel, err, timeStamp_ms, delay_ms); #endif } @@ -2586,7 +2542,7 @@ void AP_AHRS::getControlLimits(float &ekfGndSpdLimit, float &ekfNavVelGainScaler #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.getEkfControlLimits(ekfGndSpdLimit,ekfNavVelGainScaler); + ekf3.get_control_limits(ekfGndSpdLimit,ekfNavVelGainScaler); break; #endif @@ -2636,7 +2592,7 @@ bool AP_AHRS::getMagOffsets(uint8_t mag_idx, Vector3f &magOffsets) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getMagOffsets(mag_idx, magOffsets); + return ekf3.EKF3.getMagOffsets(mag_idx, magOffsets); #endif #if AP_AHRS_SIM_ENABLED @@ -2671,8 +2627,8 @@ void AP_AHRS::_getCorrectedDeltaVelocityNED(Vector3f& ret, float& dt) const #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - imu_idx = EKF3.getPrimaryCoreIMUIndex(); - EKF3.getAccelBias(-1,accel_bias); + imu_idx = ekf3.EKF3.getPrimaryCoreIMUIndex(); + accel_bias = ekf3_estimates.accel_bias; break; #endif #if AP_AHRS_SIM_ENABLED @@ -2740,9 +2696,9 @@ bool AP_AHRS::attitudes_consistent(char *failure_msg, const uint8_t failure_msg_ #if HAL_NAVEKF3_AVAILABLE // check primary vs ekf3 if (configured_ekf_type() == EKFType::THREE || active_EKF_type() == EKFType::THREE) { - for (uint8_t i = 0; i < EKF3.activeCores(); i++) { + for (uint8_t i = 0; i < ekf3.EKF3.activeCores(); i++) { Quaternion ekf3_quat; - EKF3.getQuaternionBodyToNED(i, ekf3_quat); + ekf3.EKF3.getQuaternionBodyToNED(i, ekf3_quat); // check roll and pitch difference const float rp_diff_rad = primary_quat.roll_pitch_difference(ekf3_quat); @@ -2760,7 +2716,7 @@ bool AP_AHRS::attitudes_consistent(char *failure_msg, const uint8_t failure_msg_ return false; } } - total_ekf_cores += EKF3.activeCores(); + total_ekf_cores += ekf3.EKF3.activeCores(); } #endif @@ -2781,7 +2737,7 @@ bool AP_AHRS::attitudes_consistent(char *failure_msg, const uint8_t failure_msg_ // and if not using an external yaw source (DCM does not support external yaw sources) bool using_noncompass_for_yaw = false; #if HAL_NAVEKF3_AVAILABLE - using_noncompass_for_yaw = (configured_ekf_type() == EKFType::THREE) && EKF3.using_noncompass_for_yaw(); + using_noncompass_for_yaw = (configured_ekf_type() == EKFType::THREE) && ekf3.EKF3.using_noncompass_for_yaw(); #endif if (!always_use_EKF() && !using_noncompass_for_yaw) { Vector3f angle_diff; @@ -2816,7 +2772,7 @@ uint32_t AP_AHRS::getLastYawResetAngle(float &yawAng) #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getLastYawResetAngle(yawAng); + return ekf3.getLastYawResetAngle(yawAng); #endif #if AP_AHRS_SIM_ENABLED @@ -2849,7 +2805,7 @@ uint32_t AP_AHRS::getLastPosNorthEastReset(Vector2f &pos) #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getLastPosNorthEastReset(pos); + return ekf3.getLastPosNorthEastReset(pos); #endif #if AP_AHRS_SIM_ENABLED @@ -2882,7 +2838,7 @@ uint32_t AP_AHRS::getLastVelNorthEastReset(Vector2f &vel) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getLastVelNorthEastReset(vel); + return ekf3.getLastVelNorthEastReset(vel); #endif #if AP_AHRS_SIM_ENABLED @@ -2915,7 +2871,7 @@ uint32_t AP_AHRS::getLastPosDownReset(float &posDelta) #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getLastPosDownReset(posDelta); + return ekf3.getLastPosDownReset(posDelta); #endif #if AP_AHRS_SIM_ENABLED @@ -2939,7 +2895,7 @@ void AP_AHRS::resetHeightDatum(void) WITH_SEMAPHORE(_rsem); #if HAL_NAVEKF3_AVAILABLE - EKF3.resetHeightDatum(); + ekf3.resetHeightDatum(); #endif #if HAL_NAVEKF2_AVAILABLE EKF2.resetHeightDatum(); @@ -2979,7 +2935,7 @@ void AP_AHRS::send_ekf_status_report(GCS_MAVLINK &link) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.send_status_report(link); + return ekf3.send_ekf_status_report(link); #endif } @@ -3001,7 +2957,7 @@ bool AP_AHRS::_get_origin(EKFType type, Location &ret) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getOriginLLH(ret); + return ekf3.get_origin(ret); #endif #if AP_AHRS_SIM_ENABLED @@ -3120,7 +3076,7 @@ bool AP_AHRS::get_hgt_ctrl_limit(float& limit) const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getHeightControlLimit(limit); + return ekf3.get_hgt_ctrl_limit(limit); #endif #if AP_AHRS_SIM_ENABLED @@ -3162,7 +3118,7 @@ void AP_AHRS::set_terrain_hgt_stable(bool stable) EKF2.setTerrainHgtStable(stable); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.setTerrainHgtStable(stable); + ekf3.set_terrain_hgt_stable(stable); #endif } @@ -3186,7 +3142,7 @@ bool AP_AHRS::get_innovations(Vector3f &velInnov, Vector3f &posInnov, Vector3f & #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: // use EKF to get innovations - return EKF3.getInnovations(velInnov, posInnov, magInnov, tasInnov, yawInnov); + return ekf3.get_innovations(velInnov, posInnov, magInnov, tasInnov, yawInnov); #endif #if AP_AHRS_SIM_ENABLED @@ -3209,7 +3165,7 @@ bool AP_AHRS::is_vibration_affected() const switch (configured_ekf_type()) { #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.isVibrationAffected(); + return ekf3.EKF3.isVibrationAffected(); #endif #if AP_AHRS_DCM_ENABLED case EKFType::DCM: @@ -3252,8 +3208,7 @@ bool AP_AHRS::get_variances(float &velVar, float &posVar, float &hgtVar, Vector3 #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: { // use EKF to get variance - Vector2f offset; - return EKF3.getVariances(velVar, posVar, hgtVar, magVar, tasVar, offset); + return ekf3.get_variances(velVar, posVar, hgtVar, magVar, tasVar); } #endif @@ -3304,7 +3259,7 @@ bool AP_AHRS::get_vel_innovations_and_variances_for_source(uint8_t source, Vecto #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: // use EKF to get variance - return EKF3.getVelInnovationsAndVariancesForSource((AP_NavEKF_Source::SourceXY)source, innovations, variances); + return ekf3.get_vel_innovations_and_variances_for_source(source, innovations, variances); #endif #if AP_AHRS_SIM_ENABLED @@ -3334,7 +3289,7 @@ uint8_t AP_AHRS::get_active_airspeed_index() const // we only have affinity for EKF3 as of now #if HAL_NAVEKF3_AVAILABLE if (active_EKF_type() == EKFType::THREE) { - uint8_t ret = EKF3.getActiveAirspeed(); + uint8_t ret = ekf3.EKF3.getActiveAirspeed(); if (ret != UINT8_MAX && airspeed->healthy(ret) && airspeed->use(ret)) { return ret; } @@ -3367,7 +3322,7 @@ uint8_t AP_AHRS::_get_primary_IMU_index() const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: // let EKF2 choose primary IMU - imu = EKF3.getPrimaryCoreIMUIndex(); + imu = ekf3.EKF3.getPrimaryCoreIMUIndex(); break; #endif #if AP_AHRS_SIM_ENABLED @@ -3412,7 +3367,7 @@ int8_t AP_AHRS::_get_primary_core_index() const #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.getPrimaryCoreIndex(); + return ekf3.EKF3.getPrimaryCoreIndex(); #endif } @@ -3460,7 +3415,7 @@ void AP_AHRS::check_lane_switch(void) #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.checkLaneSwitch(); + ekf3.EKF3.checkLaneSwitch(); break; #endif } @@ -3492,7 +3447,7 @@ void AP_AHRS::request_yaw_reset(void) #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - EKF3.requestYawReset(); + ekf3.request_yaw_reset(); break; #endif } @@ -3502,7 +3457,7 @@ void AP_AHRS::request_yaw_reset(void) void AP_AHRS::set_posvelyaw_source_set(AP_NavEKF_Source::SourceSetSelection source_set_idx) { #if HAL_NAVEKF3_AVAILABLE - EKF3.setPosVelYawSourceSet((uint8_t)source_set_idx); + ekf3.EKF3.setPosVelYawSourceSet((uint8_t)source_set_idx); #endif } @@ -3510,7 +3465,7 @@ void AP_AHRS::set_posvelyaw_source_set(AP_NavEKF_Source::SourceSetSelection sour uint8_t AP_AHRS::get_posvelyaw_source_set() const { #if HAL_NAVEKF3_AVAILABLE - return EKF3.get_active_source_set(); + return ekf3.EKF3.get_active_source_set(); #else return 0; #endif @@ -3522,7 +3477,7 @@ void AP_AHRS::Log_Write() EKF2.Log_Write(); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.Log_Write(); + ekf3.EKF3.Log_Write(); #endif Write_AHRS2(); @@ -3546,7 +3501,7 @@ bool AP_AHRS::using_noncompass_for_yaw(void) const #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.using_noncompass_for_yaw(); + return ekf3.EKF3.using_noncompass_for_yaw(); #endif #if AP_AHRS_SIM_ENABLED case EKFType::SIM: @@ -3573,7 +3528,7 @@ bool AP_AHRS::using_extnav_for_yaw(void) const #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.using_extnav_for_yaw(); + return ekf3.EKF3.using_extnav_for_yaw(); #endif #if AP_AHRS_SIM_ENABLED case EKFType::SIM: @@ -3602,7 +3557,7 @@ bool AP_AHRS::using_gps(void) const #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.using_gps(); + return ekf3.EKF3.using_gps(); #endif #if AP_AHRS_SIM_ENABLED case EKFType::SIM: @@ -3652,7 +3607,7 @@ void AP_AHRS::set_alt_measurement_noise(float noise) EKF2.set_baro_alt_noise(noise); #endif #if HAL_NAVEKF3_AVAILABLE - EKF3.set_baro_alt_noise(noise); + ekf3.EKF3.set_baro_alt_noise(noise); #endif } @@ -3667,14 +3622,14 @@ const EKFGSF_yaw *AP_AHRS::get_yaw_estimator(void) const #if AP_AHRS_DCM_ENABLED case EKFType::DCM: #if HAL_NAVEKF3_AVAILABLE - return EKF3.get_yawEstimator(); + return ekf3.EKF3.get_yawEstimator(); #else return nullptr; #endif #endif #if HAL_NAVEKF3_AVAILABLE case EKFType::THREE: - return EKF3.get_yawEstimator(); + return ekf3.EKF3.get_yawEstimator(); #endif #if AP_AHRS_SIM_ENABLED case EKFType::SIM: diff --git a/libraries/AP_AHRS/AP_AHRS.h b/libraries/AP_AHRS/AP_AHRS.h index 052145e49b2..3bed655b97d 100644 --- a/libraries/AP_AHRS/AP_AHRS.h +++ b/libraries/AP_AHRS/AP_AHRS.h @@ -27,7 +27,7 @@ #include "AP_AHRS_Backend.h" #include -#include +#include "AP_AHRS_NavEKF3.h" #include // definitions shared by inertial and ekf nav filters #include "AP_AHRS_DCM.h" @@ -74,6 +74,10 @@ public: return _singleton; } +#if AP_AHRS_NAVEKF3_ENABLED + AP_AHRS_NavEKF3 ekf3; +#endif + // periodically checks to see if we should update the AHRS // orientation (e.g. based on the AHRS_ORIENTATION parameter) // allow for runtime change of orientation @@ -473,7 +477,7 @@ public: #if AP_AHRS_DCM_ENABLED DCM = 0, #endif -#if HAL_NAVEKF3_AVAILABLE +#if AP_AHRS_NAVEKF3_ENABLED THREE = 3, #endif #if HAL_NAVEKF2_AVAILABLE @@ -500,9 +504,6 @@ public: #if HAL_NAVEKF2_AVAILABLE NavEKF2 EKF2; #endif -#if HAL_NAVEKF3_AVAILABLE - NavEKF3 EKF3; -#endif // for holding parameters static const struct AP_Param::GroupInfo var_info[]; @@ -818,7 +819,6 @@ private: bool _ekf2_started; #endif #if HAL_NAVEKF3_AVAILABLE - bool _ekf3_started; void update_EKF3(void); #endif @@ -1060,9 +1060,12 @@ private: AP_AHRS_DCM dcm{_kp_yaw, _kp, gps_gain, beta, _gps_use, _gps_minsats}; struct AP_AHRS_Backend::Estimates dcm_estimates; #endif +#if AP_AHRS_NAVEKF3_ENABLED + struct AP_AHRS_Backend::Estimates ekf3_estimates; +#endif #if AP_AHRS_SIM_ENABLED #if HAL_NAVEKF3_AVAILABLE - AP_AHRS_SIM sim{EKF3}; + AP_AHRS_SIM sim{ekf3.EKF3}; #else AP_AHRS_SIM sim; #endif diff --git a/libraries/AP_AHRS/AP_AHRS_NavEKF3.cpp b/libraries/AP_AHRS/AP_AHRS_NavEKF3.cpp new file mode 100644 index 00000000000..737e2f49fb9 --- /dev/null +++ b/libraries/AP_AHRS/AP_AHRS_NavEKF3.cpp @@ -0,0 +1,83 @@ +#include "AP_AHRS_config.h" + +#if AP_AHRS_NAVEKF3_ENABLED + +#include "AP_AHRS_NavEKF3.h" +#include +#include + +extern const AP_HAL::HAL& hal; + +void AP_AHRS_NavEKF3::get_results(AP_AHRS_Backend::Estimates &results) +{ + /* + * attitude estimates: + */ + EKF3.getRotationBodyToNED(results.dcm_matrix); + + Vector3f eulers; + EKF3.getEulerAngles(eulers); + results.roll_rad = eulers.x; + results.pitch_rad = eulers.y; + results.yaw_rad = eulers.z; + + EKF3.getQuaternion(results.quaternion); + results.quaternion.rotate(-AP::ahrs().get_trim()); + + results.attitude_valid = started; + + /* + * rotational rate estimates: + */ + const AP_InertialSensor &_ins = AP::ins(); + + // Use the primary EKF to select the primary gyro + const int8_t primary_imu = EKF3.getPrimaryCoreIMUIndex(); + const uint8_t primary_gyro = primary_imu>=0?primary_imu:_ins.get_first_usable_gyro(); + const uint8_t primary_accel = primary_imu>=0?primary_imu:_ins.get_first_usable_accel(); + + // get gyro bias for primary EKF and change sign to give gyro drift + // Note sign convention used by EKF is bias = measurement - truth + Vector3f drift; + EKF3.getGyroBias(-1, drift); + results.gyro_drift = -drift; + + // use the same IMU as the primary EKF and correct for gyro drift + results.gyro_estimate = _ins.get_gyro(primary_gyro) + results.gyro_drift; + + /* + * acceleration estimates + */ + // get 3-axis accel bias estimates for active EKF (this is usually + // for the primary IMU) + EKF3.getAccelBias(-1, results.accel_bias); + + // use the primary IMU for accel earth frame + Vector3f accel = _ins.get_accel(primary_accel); + accel -= results.accel_bias; + results.accel_ef = results.dcm_matrix * AP::ahrs().get_rotation_autopilot_body_to_vehicle_body() * accel; + + /* + * velocity estimates + */ + EKF3.getVelNED(results.velocity_NED); + results.velocity_NED_valid = true; + results.vert_pos_rate_D = EKF3.getPosDownDerivative(); + results.vert_pos_rate_D_valid = true; + + /* + * position estimates + */ + results.location_valid = EKF3.getLLH(results.location); +} + +bool AP_AHRS_NavEKF3::pre_arm_check(bool requires_position, char *failure_msg, uint8_t failure_msg_len) const +{ + if (!started) { + hal.util->snprintf(failure_msg, failure_msg_len, "EKF3 not started"); + return false; + } + return EKF3.pre_arm_check(requires_position, failure_msg, failure_msg_len); +} + +#endif // AP_AHRS_NAVEKF3_ENABLED diff --git a/libraries/AP_AHRS/AP_AHRS_NavEKF3.h b/libraries/AP_AHRS/AP_AHRS_NavEKF3.h new file mode 100644 index 00000000000..be268912bc7 --- /dev/null +++ b/libraries/AP_AHRS/AP_AHRS_NavEKF3.h @@ -0,0 +1,153 @@ +#pragma once + +/* + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/* + * shim AP_NavEKF3 into AP_AHRS_Backend + */ + +#include "AP_AHRS_config.h" + +#if AP_AHRS_NAVEKF3_ENABLED + +#include +#include "AP_AHRS_Backend.h" + +class AP_AHRS_NavEKF3 : public AP_AHRS_Backend { +public: + + /* Do not allow copies */ + CLASS_NO_COPY(AP_AHRS_NavEKF3); + AP_AHRS_NavEKF3() {} + + bool healthy(void) const override { + if (!started) { + return false; + } + if (!EKF3.healthy()) { + return false; + } + return true; + } + + void reset_gyro_drift() override { EKF3.resetGyroBias(); } + + void update() override { EKF3.UpdateFilter(); } + + void get_results(Estimates &results) override; + void reset() override { + if (!started) { + return; + } + started = EKF3.InitialiseFilter(); + } + + bool get_origin(Location &ret) const override { + return EKF3.getOriginLLH(ret); + } + bool set_origin(const Location &loc) override { + return EKF3.setOriginLLH(loc); + } + + // return a wind estimation vector, in m/s + bool wind_estimate(Vector3f &wind) const override { + return EKF3.getWind(wind); + } + + Vector2f groundspeed_vector(void) override { + Vector3f vec; + EKF3.getVelNED(vec); + return vec.xy(); + } + + bool use_compass() override { + return EKF3.use_compass(); + } + + // Set to true if the terrain underneath is stable enough to be used as a height reference + // this is not related to terrain following + void set_terrain_hgt_stable(bool stable) override { + EKF3.setTerrainHgtStable(stable); + } + + uint32_t getLastYawResetAngle(float &yawAng) override { + return EKF3.getLastYawResetAngle(yawAng); + }; + uint32_t getLastPosNorthEastReset(Vector2f &pos) override WARN_IF_UNUSED { + return EKF3.getLastPosNorthEastReset(pos); + }; + uint32_t getLastVelNorthEastReset(Vector2f &vel) const override WARN_IF_UNUSED { + return EKF3.getLastVelNorthEastReset(vel); + }; + uint32_t getLastPosDownReset(float &posDelta) override WARN_IF_UNUSED { + return EKF3.getLastPosDownReset(posDelta); + }; + void resetHeightDatum(void) override { + EKF3.resetHeightDatum(); + } + void request_yaw_reset() override { + EKF3.requestYawReset(); + } + // get latest altitude estimate above ground level in meters and validity flag + bool get_hagl(float &hagl) const override WARN_IF_UNUSED { + return EKF3.getHAGL(hagl); + } + + bool pre_arm_check(bool requires_position, char *failure_msg, uint8_t failure_msg_len) const override; + + void get_control_limits(float &ekfGndSpdLimit, float &controlScaleXY) const override { + return EKF3.getEkfControlLimits(ekfGndSpdLimit, controlScaleXY); + } + bool get_hgt_ctrl_limit(float &limit) const override WARN_IF_UNUSED { + return EKF3.getHeightControlLimit(limit); + } + + void send_ekf_status_report(class GCS_MAVLINK &link) const override { + EKF3.send_status_report(link); + } + + // get_filter_status - returns filter status as a series of flags + bool get_filter_status(nav_filter_status &status) const override { + EKF3.getFilterStatus(status); + return true; + } + + // return the innovations for the specified instance + // An out of range instance (eg -1) returns data for the primary instance + bool get_innovations(Vector3f &velInnov, Vector3f &posInnov, Vector3f &magInnov, float &tasInnov, float &yawInnov) const override { + return EKF3.getInnovations(velInnov, posInnov, magInnov, tasInnov, yawInnov); + } + + bool get_variances(float &velVar, float &posVar, float &hgtVar, Vector3f &magVar, float &tasVar) const override { + Vector2f offset; + return EKF3.getVariances(velVar, posVar, hgtVar, magVar, tasVar, offset); + } + + bool get_vel_innovations_and_variances_for_source(uint8_t source, Vector3f &innovations, Vector3f &variances) const override WARN_IF_UNUSED { + return EKF3.getVelInnovationsAndVariancesForSource((AP_NavEKF_Source::SourceXY)source, innovations, variances); + } + + void request_yaw_reset(void) override { + EKF3.requestYawReset(); + } + + // this is out here so parameters can be poked into it + NavEKF3 EKF3; + + bool started; +}; + +#endif // AP_AHRS_NAVEKF3_ENABLED diff --git a/libraries/AP_AHRS/AP_AHRS_config.h b/libraries/AP_AHRS/AP_AHRS_config.h index 91d82b14a12..8fef368d2e1 100644 --- a/libraries/AP_AHRS/AP_AHRS_config.h +++ b/libraries/AP_AHRS/AP_AHRS_config.h @@ -32,6 +32,11 @@ #ifndef HAL_NAVEKF3_AVAILABLE #define HAL_NAVEKF3_AVAILABLE AP_AHRS_BACKEND_DEFAULT_ENABLED && AP_INERTIALSENSOR_ENABLED #endif +#endif + +#ifndef AP_AHRS_NAVEKF3_ENABLED +#define AP_AHRS_NAVEKF3_ENABLED HAL_NAVEKF3_AVAILABLE +#endif #ifndef AP_AHRS_SIM_ENABLED #define AP_AHRS_SIM_ENABLED AP_AHRS_BACKEND_DEFAULT_ENABLED && AP_SIM_ENABLED && AP_INERTIALSENSOR_ENABLED