@ -2,6 +2,7 @@
@@ -2,6 +2,7 @@
# include "AP_TECS.h"
# include <AP_HAL.h>
# include <stdio.h>
extern const AP_HAL : : HAL & hal ;
@ -393,6 +394,7 @@ void AP_TECS::_update_height_demand(void)
@@ -393,6 +394,7 @@ void AP_TECS::_update_height_demand(void)
// configured sink rate and adjust the demanded height to
// be kinematically consistent with the height rate.
if ( _flight_stage = = FLIGHT_LAND_FINAL ) {
_integ7_state = 0 ;
if ( _flare_counter = = 0 ) {
_hgt_rate_dem = _climb_rate ;
_land_hgt_dem = _hgt_dem_adj ;
@ -462,12 +464,18 @@ void AP_TECS::_update_energies(void)
@@ -462,12 +464,18 @@ void AP_TECS::_update_energies(void)
/*
current time constant . It is lower in landing to try to give a precise approach
*/
float AP_TECS : : timeConstant ( void )
float AP_TECS : : timeConstant ( void ) const
{
if ( _flight_stage = = FLIGHT_LAND_FINAL | |
_flight_stage = = FLIGHT_LAND_APPROACH ) {
if ( _landTimeConst < 0.1f ) {
return 0.1f ;
}
return _landTimeConst ;
}
if ( _timeConst < 0.1f ) {
return 0.1f ;
}
return _timeConst ;
}
@ -650,16 +658,25 @@ void AP_TECS::_update_pitch(void)
@@ -650,16 +658,25 @@ void AP_TECS::_update_pitch(void)
// Calculate integrator state, constraining input if pitch limits are exceeded
float integ7_input = SEB_error * _integGain ;
if ( _pitch_dem_unc > _PITCHmaxf )
if ( _pitch_dem > _PITCHmaxf )
{
integ7_input = min ( integ7_input , _PITCHmaxf - _pitch_dem_unc ) ;
integ7_input = min ( integ7_input , _PITCHmaxf - _pitch_dem ) ;
}
else if ( _pitch_dem_unc < _PITCHminf )
else if ( _pitch_dem < _PITCHminf )
{
integ7_input = max ( integ7_input , _PITCHminf - _pitch_dem_unc ) ;
integ7_input = max ( integ7_input , _PITCHminf - _pitch_dem ) ;
}
_integ7_state = _integ7_state + integ7_input * _DT ;
#if 0
if ( _flight_stage = = FLIGHT_LAND_FINAL & & fabsf ( _climb_rate ) > 0.2f ) {
: : printf ( " _hgt_rate_dem=%.1f _hgt_dem_adj=%.1f climb=%.1f _flare_counter=%u _pitch_dem=%.1f SEB_dem=%.2f SEBdot_dem=%.2f SEB_error=%.2f SEBdot_error=%.2f \n " ,
_hgt_rate_dem , _hgt_dem_adj , _climb_rate , _flare_counter , degrees ( _pitch_dem ) ,
SEB_dem , SEBdot_dem , SEB_error , SEBdot_error ) ;
}
# endif
// Apply max and min values for integrator state that will allow for no more than
// 5deg of saturation. This allows for some pitch variation due to gusts before the
// integrator is clipped. Otherwise the effectiveness of the integrator will be reduced in turbulence
@ -697,6 +714,10 @@ void AP_TECS::_update_pitch(void)
@@ -697,6 +714,10 @@ void AP_TECS::_update_pitch(void)
{
_pitch_dem = _last_pitch_dem - ptchRateIncr ;
}
// re-constrain pitch demand
_pitch_dem = constrain_float ( _pitch_dem , _PITCHminf , _PITCHmaxf ) ;
_last_pitch_dem = _pitch_dem ;
}
@ -784,6 +805,25 @@ void AP_TECS::update_pitch_throttle(int32_t hgt_dem_cm,
@@ -784,6 +805,25 @@ void AP_TECS::update_pitch_throttle(int32_t hgt_dem_cm,
// and allow zero throttle
_THRminf = 0 ;
} else if ( flight_stage = = FLIGHT_LAND_APPROACH & & ( - _climb_rate ) > _land_sink ) {
// constrain the pitch in landing as we get close to the flare
// point. Use a simple linear limit from 15 meters after the
// landing point
float time_to_flare = ( - hgt_afe / _climb_rate ) - aparm . land_flare_sec ;
if ( time_to_flare < 0 ) {
// we should be flaring already
_PITCHminf = max ( _PITCHminf , aparm . land_pitch_cd * 0.01f ) ;
} else if ( time_to_flare < timeConstant ( ) * 2 ) {
// smoothly move the min pitch to the flare min pitch over
// twice the time constant
float p = time_to_flare / ( 2 * timeConstant ( ) ) ;
float pitch_limit_cd = p * aparm . pitch_limit_min_cd + ( 1 - p ) * aparm . land_pitch_cd ;
#if 0
: : printf ( " ttf=%.1f hgt_afe=%.1f _PITCHminf=%.1f pitch_limit=%.1f climb=%.1f \n " ,
time_to_flare , hgt_afe , _PITCHminf , pitch_limit_cd * 0.01f , _climb_rate ) ;
# endif
_PITCHminf = max ( _PITCHminf , pitch_limit_cd * 0.01f ) ;
}
}
// convert to radians
_PITCHmaxf = radians ( _PITCHmaxf ) ;