diff --git a/ArduPlane/Parameters.cpp b/ArduPlane/Parameters.cpp index f107918e55fc9..135c2977d3dec 100644 --- a/ArduPlane/Parameters.cpp +++ b/ArduPlane/Parameters.cpp @@ -323,7 +323,7 @@ const AP_Param::Info Plane::var_info[] = { // @Param: AIRSPEED_STALL // @DisplayName: Stall airspeed - // @Description: If stall prevention is enabled this speed is used to calculate the minimum airspeed while banking. If this is set to 0 then the stall speed is assumed to be the minimum airspeed speed. Typically set slightly higher then true stall speed. Value is as an indicated (calibrated/apparent) airspeed. + // @Description: If stall prevention is enabled this speed is used to calculate the minimum airspeed while banking. It is also used during landing final as the minimum airspeed that can be demanded by the TECS, which allows using TECS_LAND_ARSPD or LAND_PF_ARSPD to achieve landings slower than AIRSPEED_MIN. If this is set to 0 then the stall speed is assumed to be the minimum airspeed speed. Typically set slightly higher then true stall speed. // @Units: m/s // @Range: 5 75 // @User: Standard diff --git a/ArduPlane/navigation.cpp b/ArduPlane/navigation.cpp index b47160836aff8..3b439c31e7da0 100644 --- a/ArduPlane/navigation.cpp +++ b/ArduPlane/navigation.cpp @@ -267,8 +267,12 @@ void Plane::calc_airspeed_errors() target_airspeed_cm += airspeed_nudge_cm; } + int32_t airspeed_lower_bound = is_positive(aparm.airspeed_stall) + ? aparm.airspeed_stall + : aparm.airspeed_min; + // Apply airspeed limit - target_airspeed_cm = constrain_int32(target_airspeed_cm, aparm.airspeed_min*100, aparm.airspeed_max*100); + target_airspeed_cm = constrain_int32(target_airspeed_cm, airspeed_lower_bound*100, aparm.airspeed_max*100); // use the TECS view of the target airspeed for reporting, to take // account of the landing speed diff --git a/libraries/AP_Landing/AP_Landing.cpp b/libraries/AP_Landing/AP_Landing.cpp index ac080c52dbdfd..aaee758fbf6a2 100644 --- a/libraries/AP_Landing/AP_Landing.cpp +++ b/libraries/AP_Landing/AP_Landing.cpp @@ -347,6 +347,24 @@ bool AP_Landing::is_flaring(void) const } } +// return true if the landing is at the pre-flare stage or later +bool AP_Landing::is_on_final(void) const +{ + if (!flags.in_progress) { + return false; + } + + switch (type) { + case TYPE_STANDARD_GLIDE_SLOPE: + return type_slope_is_on_final(); +#if HAL_LANDING_DEEPSTALL_ENABLED + case TYPE_DEEPSTALL: +#endif + default: + return false; + } +} + // return true while the aircraft is performing a landing approach // when true the vehicle will: // - disable ground steering diff --git a/libraries/AP_Landing/AP_Landing.h b/libraries/AP_Landing/AP_Landing.h index e9bc8e37f7d86..4739905afc0a3 100644 --- a/libraries/AP_Landing/AP_Landing.h +++ b/libraries/AP_Landing/AP_Landing.h @@ -79,6 +79,7 @@ class AP_Landing { void check_if_need_to_abort(const AP_FixedWing::Rangefinder_State &rangefinder_state); bool request_go_around(void); bool is_flaring(void) const; + bool is_on_final(void) const; bool is_on_approach(void) const; bool is_ground_steering_allowed(void) const; bool is_throttle_suppressed(void) const; @@ -206,6 +207,7 @@ class AP_Landing { void type_slope_log(void) const; bool type_slope_is_complete(void) const; bool type_slope_is_flaring(void) const; + bool type_slope_is_on_final(void) const; bool type_slope_is_on_approach(void) const; bool type_slope_is_expecting_impact(void) const; bool type_slope_is_throttle_suppressed(void) const; diff --git a/libraries/AP_Landing/AP_Landing_Slope.cpp b/libraries/AP_Landing/AP_Landing_Slope.cpp index 4ebecb3b84e9e..9af76f7b63dcb 100644 --- a/libraries/AP_Landing/AP_Landing_Slope.cpp +++ b/libraries/AP_Landing/AP_Landing_Slope.cpp @@ -390,6 +390,12 @@ bool AP_Landing::type_slope_is_flaring(void) const return (type_slope_stage == SlopeStage::FINAL); } +bool AP_Landing::type_slope_is_on_final(void) const +{ + return (type_slope_stage == SlopeStage::PREFLARE || + type_slope_stage == SlopeStage::FINAL); +} + bool AP_Landing::type_slope_is_on_approach(void) const { return (type_slope_stage == SlopeStage::APPROACH || @@ -398,8 +404,7 @@ bool AP_Landing::type_slope_is_on_approach(void) const bool AP_Landing::type_slope_is_expecting_impact(void) const { - return (type_slope_stage == SlopeStage::PREFLARE || - type_slope_stage == SlopeStage::FINAL); + return type_slope_is_on_final(); } bool AP_Landing::type_slope_is_complete(void) const diff --git a/libraries/AP_TECS/AP_TECS.cpp b/libraries/AP_TECS/AP_TECS.cpp index b0cbe34087e29..2c4ce56e813c2 100644 --- a/libraries/AP_TECS/AP_TECS.cpp +++ b/libraries/AP_TECS/AP_TECS.cpp @@ -411,6 +411,12 @@ void AP_TECS::_update_speed(float DT) _TASmax = MIN(_TASmax, aparm.airspeed_max * EAS2TAS); _TASmin = aparm.airspeed_min * EAS2TAS; + if (_landing.is_on_final()) { + if (is_positive(aparm.airspeed_stall)) { + _TASmin = aparm.airspeed_stall * EAS2TAS; + } + } + if (aparm.stall_prevention) { // when stall prevention is active we raise the minimum // airspeed based on aerodynamic load factor