mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-03 14:38:30 -04:00
4f243aca02
when on landing approach we estimate time to flare based on two noisy numbers, the vertical speed and height above ground. With noisy rangefinders this can change rapidly, which resulted in the pitch limit changing rapidly, leading to a porpoising movement this limits the rate of change, and also prevents it coming down once it has nosed up due to pending flare on approach
378 lines
10 KiB
C++
378 lines
10 KiB
C++
/// @file AP_TECS.h
|
|
/// @brief Combined Total Energy Speed & Height Control. This is a instance of an
|
|
/// AP_SpdHgtControl class
|
|
|
|
/*
|
|
* Written by Paul Riseborough 2013 to provide:
|
|
* - Combined control of speed and height using throttle to control
|
|
* total energy and pitch angle to control exchange of energy between
|
|
* potential and kinetic.
|
|
* Selectable speed or height priority modes when calculating pitch angle
|
|
* - Fallback mode when no airspeed measurement is available that
|
|
* sets throttle based on height rate demand and switches pitch angle control to
|
|
* height priority
|
|
* - Underspeed protection that demands maximum throttle switches pitch angle control
|
|
* to speed priority mode
|
|
* - Relative ease of tuning through use of intuitive time constant, trim rate and damping parameters and the use
|
|
* of easy to measure aircraft performance data
|
|
*/
|
|
#pragma once
|
|
|
|
#include <AP_Math/AP_Math.h>
|
|
#include <AP_AHRS/AP_AHRS.h>
|
|
#include <AP_Param/AP_Param.h>
|
|
#include <AP_Vehicle/AP_Vehicle.h>
|
|
#include <AP_SpdHgtControl/AP_SpdHgtControl.h>
|
|
#include <AP_Landing/AP_Landing.h>
|
|
|
|
class AP_TECS : public AP_SpdHgtControl {
|
|
public:
|
|
AP_TECS(AP_AHRS &ahrs, const AP_Vehicle::FixedWing &parms, const AP_Landing &landing)
|
|
: _ahrs(ahrs)
|
|
, aparm(parms)
|
|
, _landing(landing)
|
|
{
|
|
AP_Param::setup_object_defaults(this, var_info);
|
|
}
|
|
|
|
/* Do not allow copies */
|
|
AP_TECS(const AP_TECS &other) = delete;
|
|
AP_TECS &operator=(const AP_TECS&) = delete;
|
|
|
|
// Update of the estimated height and height rate internal state
|
|
// Update of the inertial speed rate internal state
|
|
// Should be called at 50Hz or greater
|
|
void update_50hz(void) override;
|
|
|
|
// Update the control loop calculations
|
|
void update_pitch_throttle(int32_t hgt_dem_cm,
|
|
int32_t EAS_dem_cm,
|
|
enum AP_Vehicle::FixedWing::FlightStage flight_stage,
|
|
float distance_beyond_land_wp,
|
|
int32_t ptchMinCO_cd,
|
|
int16_t throttle_nudge,
|
|
float hgt_afe,
|
|
float load_factor,
|
|
bool soaring_active) override;
|
|
|
|
// demanded throttle in percentage
|
|
// should return -100 to 100, usually positive unless reverse thrust is enabled via _THRminf < 0
|
|
int32_t get_throttle_demand(void) override {
|
|
return int32_t(_throttle_dem * 100.0f);
|
|
}
|
|
|
|
// demanded pitch angle in centi-degrees
|
|
// should return between -9000 to +9000
|
|
int32_t get_pitch_demand(void) override {
|
|
return int32_t(_pitch_dem * 5729.5781f);
|
|
}
|
|
|
|
// Rate of change of velocity along X body axis in m/s^2
|
|
float get_VXdot(void) override {
|
|
return _vel_dot;
|
|
}
|
|
|
|
// return current target airspeed
|
|
float get_target_airspeed(void) const override {
|
|
return _TAS_dem / _ahrs.get_EAS2TAS();
|
|
}
|
|
|
|
// return maximum climb rate
|
|
float get_max_climbrate(void) const override {
|
|
return _maxClimbRate;
|
|
}
|
|
|
|
// added to let SoaringContoller reset pitch integrator to zero
|
|
void reset_pitch_I(void) override {
|
|
_integSEB_state = 0.0f;
|
|
}
|
|
|
|
// return landing sink rate
|
|
float get_land_sinkrate(void) const override {
|
|
return _land_sink;
|
|
}
|
|
|
|
// return landing airspeed
|
|
float get_land_airspeed(void) const override {
|
|
return _landAirspeed;
|
|
}
|
|
|
|
// return height rate demand, in m/s
|
|
float get_height_rate_demand(void) const {
|
|
return _hgt_rate_dem;
|
|
}
|
|
|
|
// set path_proportion
|
|
void set_path_proportion(float path_proportion) override {
|
|
_path_proportion = constrain_float(path_proportion, 0.0f, 1.0f);
|
|
}
|
|
|
|
// set pitch max limit in degrees
|
|
void set_pitch_max_limit(int8_t pitch_limit) {
|
|
_pitch_max_limit = pitch_limit;
|
|
}
|
|
|
|
// force use of synthetic airspeed for one loop
|
|
void use_synthetic_airspeed(void) {
|
|
_use_synthetic_airspeed_once = true;
|
|
}
|
|
|
|
// this supports the TECS_* user settable parameters
|
|
static const struct AP_Param::GroupInfo var_info[];
|
|
|
|
private:
|
|
// Last time update_50Hz was called
|
|
uint64_t _update_50hz_last_usec;
|
|
|
|
// Last time update_speed was called
|
|
uint64_t _update_speed_last_usec;
|
|
|
|
// Last time update_pitch_throttle was called
|
|
uint64_t _update_pitch_throttle_last_usec;
|
|
|
|
// reference to the AHRS object
|
|
AP_AHRS &_ahrs;
|
|
|
|
const AP_Vehicle::FixedWing &aparm;
|
|
|
|
// reference to const AP_Landing to access it's params
|
|
const AP_Landing &_landing;
|
|
|
|
// TECS tuning parameters
|
|
AP_Float _hgtCompFiltOmega;
|
|
AP_Float _spdCompFiltOmega;
|
|
AP_Float _maxClimbRate;
|
|
AP_Float _minSinkRate;
|
|
AP_Float _maxSinkRate;
|
|
AP_Float _timeConst;
|
|
AP_Float _landTimeConst;
|
|
AP_Float _ptchDamp;
|
|
AP_Float _land_pitch_damp;
|
|
AP_Float _landDamp;
|
|
AP_Float _thrDamp;
|
|
AP_Float _land_throttle_damp;
|
|
AP_Float _integGain;
|
|
AP_Float _integGain_takeoff;
|
|
AP_Float _integGain_land;
|
|
AP_Float _vertAccLim;
|
|
AP_Float _rollComp;
|
|
AP_Float _spdWeight;
|
|
AP_Float _spdWeightLand;
|
|
AP_Float _landThrottle;
|
|
AP_Float _landAirspeed;
|
|
AP_Float _land_sink;
|
|
AP_Float _land_sink_rate_change;
|
|
AP_Int8 _pitch_max;
|
|
AP_Int8 _pitch_min;
|
|
AP_Int8 _land_pitch_max;
|
|
AP_Float _maxSinkRate_approach;
|
|
AP_Int32 _options;
|
|
|
|
enum {
|
|
OPTION_GLIDER_ONLY=(1<<0),
|
|
};
|
|
|
|
// temporary _pitch_max_limit. Cleared on each loop. Clear when >= 90
|
|
int8_t _pitch_max_limit = 90;
|
|
|
|
// current height estimate (above field elevation)
|
|
float _height;
|
|
|
|
// throttle demand in the range from -1.0 to 1.0, usually positive unless reverse thrust is enabled via _THRminf < 0
|
|
float _throttle_dem;
|
|
|
|
// pitch angle demand in radians
|
|
float _pitch_dem;
|
|
|
|
// estimated climb rate (m/s)
|
|
float _climb_rate;
|
|
|
|
/*
|
|
a filter to estimate climb rate if we don't have it from the EKF
|
|
*/
|
|
struct {
|
|
// height filter second derivative
|
|
float dd_height;
|
|
|
|
// height integration
|
|
float height;
|
|
} _height_filter;
|
|
|
|
// Integrator state 4 - airspeed filter first derivative
|
|
float _integDTAS_state;
|
|
|
|
// Integrator state 5 - true airspeed
|
|
float _TAS_state;
|
|
|
|
// Integrator state 6 - throttle integrator
|
|
float _integTHR_state;
|
|
|
|
// Integrator state 6 - pitch integrator
|
|
float _integSEB_state;
|
|
|
|
// throttle demand rate limiter state
|
|
float _last_throttle_dem;
|
|
|
|
// pitch demand rate limiter state
|
|
float _last_pitch_dem;
|
|
|
|
// Rate of change of speed along X axis
|
|
float _vel_dot;
|
|
|
|
// Equivalent airspeed
|
|
float _EAS;
|
|
|
|
// True airspeed limits
|
|
float _TASmax;
|
|
float _TASmin;
|
|
|
|
// Current true airspeed demand
|
|
float _TAS_dem;
|
|
|
|
// Equivalent airspeed demand
|
|
float _EAS_dem;
|
|
|
|
// height demands
|
|
float _hgt_dem;
|
|
float _hgt_dem_in_old;
|
|
float _hgt_dem_adj;
|
|
float _hgt_dem_adj_last;
|
|
float _hgt_rate_dem;
|
|
float _hgt_dem_prev;
|
|
float _land_hgt_dem;
|
|
|
|
// Speed demand after application of rate limiting
|
|
// This is the demand tracked by the TECS control loops
|
|
float _TAS_dem_adj;
|
|
|
|
// Speed rate demand after application of rate limiting
|
|
// This is the demand tracked by the TECS control loops
|
|
float _TAS_rate_dem;
|
|
|
|
// Total energy rate filter state
|
|
float _STEdotErrLast;
|
|
|
|
struct flags {
|
|
// Underspeed condition
|
|
bool underspeed:1;
|
|
|
|
// Bad descent condition caused by unachievable airspeed demand
|
|
bool badDescent:1;
|
|
|
|
// true when plane is in auto mode and executing a land mission item
|
|
bool is_doing_auto_land:1;
|
|
|
|
// true when we have reached target speed in takeoff
|
|
bool reached_speed_takeoff:1;
|
|
};
|
|
union {
|
|
struct flags _flags;
|
|
uint8_t _flags_byte;
|
|
};
|
|
|
|
// time when underspeed started
|
|
uint32_t _underspeed_start_ms;
|
|
|
|
// auto mode flightstage
|
|
enum AP_Vehicle::FixedWing::FlightStage _flight_stage;
|
|
|
|
// pitch demand before limiting
|
|
float _pitch_dem_unc;
|
|
|
|
// Maximum and minimum specific total energy rate limits
|
|
float _STEdot_max;
|
|
float _STEdot_min;
|
|
|
|
// Maximum and minimum floating point throttle limits
|
|
float _THRmaxf;
|
|
float _THRminf;
|
|
|
|
// Maximum and minimum floating point pitch limits
|
|
float _PITCHmaxf;
|
|
float _PITCHminf;
|
|
|
|
// Specific energy quantities
|
|
float _SPE_dem;
|
|
float _SKE_dem;
|
|
float _SPEdot_dem;
|
|
float _SKEdot_dem;
|
|
float _SPE_est;
|
|
float _SKE_est;
|
|
float _SPEdot;
|
|
float _SKEdot;
|
|
|
|
// Specific energy error quantities
|
|
float _STE_error;
|
|
|
|
// Time since last update of main TECS loop (seconds)
|
|
float _DT;
|
|
|
|
// counter for demanded sink rate on land final
|
|
uint8_t _flare_counter;
|
|
|
|
// slew height demand lag filter value when transition to land
|
|
float hgt_dem_lag_filter_slew;
|
|
|
|
// percent traveled along the previous and next waypoints
|
|
float _path_proportion;
|
|
|
|
float _distance_beyond_land_wp;
|
|
|
|
float _land_pitch_min = -90;
|
|
|
|
// internal variables to be logged
|
|
struct {
|
|
float SKE_weighting;
|
|
float SPE_error;
|
|
float SKE_error;
|
|
float SEB_delta;
|
|
} logging;
|
|
|
|
AP_Int8 _use_synthetic_airspeed;
|
|
|
|
// use synthetic airspeed for next loop
|
|
bool _use_synthetic_airspeed_once;
|
|
|
|
// Update the airspeed internal state using a second order complementary filter
|
|
void _update_speed(float load_factor);
|
|
|
|
// Update the demanded airspeed
|
|
void _update_speed_demand(void);
|
|
|
|
// Update the demanded height
|
|
void _update_height_demand(void);
|
|
|
|
// Detect an underspeed condition
|
|
void _detect_underspeed(void);
|
|
|
|
// Update Specific Energy Quantities
|
|
void _update_energies(void);
|
|
|
|
// Update Demanded Throttle
|
|
void _update_throttle_with_airspeed(void);
|
|
|
|
// Update Demanded Throttle Non-Airspeed
|
|
void _update_throttle_without_airspeed(int16_t throttle_nudge);
|
|
|
|
// get integral gain which is flight_stage dependent
|
|
float _get_i_gain(void);
|
|
|
|
// Detect Bad Descent
|
|
void _detect_bad_descent(void);
|
|
|
|
// Update Demanded Pitch Angle
|
|
void _update_pitch(void);
|
|
|
|
// Initialise states and variables
|
|
void _initialise_states(int32_t ptchMinCO_cd, float hgt_afe);
|
|
|
|
// Calculate specific total energy rate limits
|
|
void _update_STE_rate_lim(void);
|
|
|
|
// declares a 5point average filter using floats
|
|
AverageFilterFloat_Size5 _vdot_filter;
|
|
|
|
// current time constant
|
|
float timeConstant(void) const;
|
|
};
|