diff --git a/src/modules/attitude_estimator_q/attitude_estimator_q_main.cpp b/src/modules/attitude_estimator_q/attitude_estimator_q_main.cpp index af2ad11dfe..c8232eee43 100644 --- a/src/modules/attitude_estimator_q/attitude_estimator_q_main.cpp +++ b/src/modules/attitude_estimator_q/attitude_estimator_q_main.cpp @@ -141,6 +141,7 @@ private: param_t bias_max; param_t vibe_thresh; param_t ext_hdg_mode; + param_t airspeed_mode; } _params_handles; /**< handles for interesting parameters */ float _w_accel = 0.0f; @@ -154,6 +155,7 @@ private: float _vibration_warning_threshold = 2.0f; hrt_abstime _vibration_warning_timestamp = 0; int _ext_hdg_mode = 0; + int _airspeed_mode = 0; Vector<3> _gyro; Vector<3> _accel; @@ -232,6 +234,7 @@ AttitudeEstimatorQ::AttitudeEstimatorQ() : _params_handles.bias_max = param_find("ATT_BIAS_MAX"); _params_handles.vibe_thresh = param_find("ATT_VIBE_THRESH"); _params_handles.ext_hdg_mode = param_find("ATT_EXT_HDG_M"); + _params_handles.airspeed_mode = param_find("FW_ARSP_MODE"); } /** @@ -626,14 +629,25 @@ void AttitudeEstimatorQ::task_main() ctrl_state.yaw_rate = _lp_yaw_rate.apply(_rates(2)); - /* Airspeed - take airspeed measurement directly here as no wind is estimated */ - if (PX4_ISFINITE(_airspeed.indicated_airspeed_m_s) && hrt_absolute_time() - _airspeed.timestamp < 1e6 - && _airspeed.timestamp > 0) { - ctrl_state.airspeed = _airspeed.indicated_airspeed_m_s; - ctrl_state.airspeed_valid = true; + ctrl_state.airspeed_valid = false; + // use estimated velocity for airspeed estimate + if (_airspeed_mode == 1) { + if (hrt_absolute_time() - _gpos.timestamp < 1e6) { + ctrl_state.airspeed = sqrtf(_gpos.vel_n * _gpos.vel_n + _gpos.vel_e * _gpos.vel_e +_gpos.vel_d * _gpos.vel_d); + } + // do nothing, airspeed has been declared as non-valid above, controllers will handle this assuming always trim airspeed + } else if (_airspeed_mode == 2) { + + // use the measured airspeed } else { - ctrl_state.airspeed_valid = false; + /* Airspeed - take airspeed measurement directly here as no wind is estimated */ + if (PX4_ISFINITE(_airspeed.indicated_airspeed_m_s) && hrt_absolute_time() - _airspeed.timestamp < 1e6 + && _airspeed.timestamp > 0) { + ctrl_state.airspeed = _airspeed.indicated_airspeed_m_s; + ctrl_state.airspeed_valid = true; + + } } /* the instance count is not used here */ @@ -688,6 +702,7 @@ void AttitudeEstimatorQ::update_parameters(bool force) param_get(_params_handles.bias_max, &_bias_max); param_get(_params_handles.vibe_thresh, &_vibration_warning_threshold); param_get(_params_handles.ext_hdg_mode, &_ext_hdg_mode); + param_get(_params_handles.airspeed_mode, &_airspeed_mode); } } diff --git a/src/modules/ekf2/ekf2_main.cpp b/src/modules/ekf2/ekf2_main.cpp index 864505c7fe..ca94eaa7ce 100644 --- a/src/modules/ekf2/ekf2_main.cpp +++ b/src/modules/ekf2/ekf2_main.cpp @@ -271,6 +271,9 @@ private: control::BlockParamFloat _acc_bias_init; // 1-sigma accelerometer bias uncertainty at switch-on (m/s**2) control::BlockParamFloat _ang_err_init; // 1-sigma uncertainty in tilt angle after gravity vector alignment (rad) + // airspeed mode parameter + control::BlockParamInt _airspeed_mode; + int update_subscriptions(); }; @@ -366,7 +369,8 @@ Ekf2::Ekf2(): _tau_pos(this, "EKF2_TAU_POS", false, &_params->pos_Tau), _gyr_bias_init(this, "EKF2_GBIAS_INIT", false, &_params->switch_on_gyro_bias), _acc_bias_init(this, "EKF2_ABIAS_INIT", false, &_params->switch_on_accel_bias), - _ang_err_init(this, "EKF2_ANGERR_INIT", false, &_params->initial_tilt_err) + _ang_err_init(this, "EKF2_ANGERR_INIT", false, &_params->initial_tilt_err), + _airspeed_mode(this, "FW_ARSP_MODE", false) { } @@ -655,14 +659,27 @@ void Ekf2::task_main() 1) * acceleration(1)); ctrl_state.horz_acc_mag = _acc_hor_filt; - // Airspeed - take airspeed measurement directly here as no wind is estimated - if (PX4_ISFINITE(airspeed.indicated_airspeed_m_s) && hrt_absolute_time() - airspeed.timestamp < 1e6 - && airspeed.timestamp > 0) { - ctrl_state.airspeed = airspeed.indicated_airspeed_m_s; - ctrl_state.airspeed_valid = true; + float vel[3] = {}; + _ekf.get_velocity(vel); + ctrl_state.airspeed_valid = false; + + // use estimated velocity for airspeed estimate + if (_airspeed_mode.get() == 1) { + if (_ekf.local_position_is_valid()) { + ctrl_state.airspeed = sqrtf(vel[0] * vel[0] + vel[1] * vel[1] +vel[2] * vel[2]); + } + // do nothing, airspeed has been declared as non-valid above, controllers will handle this assuming always trim airspeed + } else if (_airspeed_mode.get() == 2) { + + // use the measured airspeed } else { - ctrl_state.airspeed_valid = false; + /* Airspeed - take airspeed measurement directly here as no wind is estimated */ + if (PX4_ISFINITE(airspeed.indicated_airspeed_m_s) && hrt_absolute_time() - airspeed.timestamp < 1e6 + && airspeed.timestamp > 0) { + ctrl_state.airspeed = airspeed.indicated_airspeed_m_s; + ctrl_state.airspeed_valid = true; + } } // publish control state data @@ -702,7 +719,6 @@ void Ekf2::task_main() // generate vehicle local position data struct vehicle_local_position_s lpos = {}; float pos[3] = {}; - float vel[3] = {}; lpos.timestamp = hrt_absolute_time(); @@ -713,7 +729,6 @@ void Ekf2::task_main() lpos.z = pos[2]; // Velocity of body origin in local NED frame (m/s) - _ekf.get_velocity(vel); lpos.vx = vel[0]; lpos.vy = vel[1]; lpos.vz = vel[2];