2013-10-12 09:28:18 -03:00
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*-
/// @file AC_AttitudeControl.h
/// @brief ArduCopter attitude control library
# ifndef AC_AttitudeControl_H
# define AC_AttitudeControl_H
# include <AP_Common.h>
# include <AP_Param.h>
# include <AP_Math.h>
# include <AP_InertialSensor.h>
# include <AP_AHRS.h>
# include <AP_Motors.h>
# include <AC_PID.h>
2014-02-14 03:06:21 -04:00
# include <AC_P.h>
2013-10-12 09:28:18 -03:00
// To-Do: change the name or move to AP_Math?
2015-05-06 04:11:48 -03:00
# define AC_ATTITUDE_CONTROL_DEGX100 5729.57795f // constant to convert from radians to centi-degrees
# define AC_ATTITUDE_ACCEL_RP_CONTROLLER_MIN 36000.0f // minimum body-frame acceleration limit for the stability controller (for roll and pitch axis)
# define AC_ATTITUDE_ACCEL_RP_CONTROLLER_MAX 72000.0f // maximum body-frame acceleration limit for the stability controller (for roll and pitch axis)
# define AC_ATTITUDE_ACCEL_Y_CONTROLLER_MIN 9000.0f // minimum body-frame acceleration limit for the stability controller (for yaw axis)
# define AC_ATTITUDE_ACCEL_Y_CONTROLLER_MAX 36000.0f // maximum body-frame acceleration limit for the stability controller (for yaw axis)
# define AC_ATTITUDE_CONTROL_SLEW_YAW_DEFAULT 1000 // constraint on yaw angle error in degrees. This should lead to maximum turn rate of 10deg/sed * Stab Rate P so by default will be 45deg/sec.
# define AC_ATTITUDE_CONTROL_ACCEL_RP_MAX_DEFAULT 110000.0f // default maximum acceleration for roll/pitch axis in centi-degrees/sec/sec
# define AC_ATTITUDE_CONTROL_ACCEL_Y_MAX_DEFAULT 27000.0f // default maximum acceleration for yaw axis in centi-degrees/sec/sec
2014-02-14 21:07:49 -04:00
2014-02-03 00:29:17 -04:00
# define AC_ATTITUDE_RATE_CONTROLLER_TIMEOUT 1.0f // body-frame rate controller timeout in seconds
# define AC_ATTITUDE_RATE_RP_CONTROLLER_OUT_MAX 5000.0f // body-frame rate controller maximum output (for roll-pitch axis)
# define AC_ATTITUDE_RATE_YAW_CONTROLLER_OUT_MAX 4500.0f // body-frame rate controller maximum output (for yaw axis)
# define AC_ATTITUDE_ANGLE_YAW_CONTROLLER_OUT_MAX 4500.0f // earth-frame angle controller maximum output (for yaw axis)
# define AC_ATTITUDE_ANGLE_CONTROLLER_ANGLE_MAX 4500.0f // earth-frame angle controller maximum input angle (To-Do: replace with reference to aparm.angle_max)
2013-10-12 09:28:18 -03:00
2015-03-22 08:25:23 -03:00
# define AC_ATTITUDE_RATE_STAB_ROLL_OVERSHOOT_ANGLE_MAX 30000.0f // earth-frame rate stabilize controller's maximum overshoot angle (never limited)
# define AC_ATTITUDE_RATE_STAB_PITCH_OVERSHOOT_ANGLE_MAX 30000.0f // earth-frame rate stabilize controller's maximum overshoot angle (never limited)
2013-10-12 09:28:18 -03:00
# define AC_ATTITUDE_RATE_STAB_YAW_OVERSHOOT_ANGLE_MAX 1000.0f // earth-frame rate stabilize controller's maximum overshoot angle
2015-02-11 08:08:49 -04:00
# define AC_ATTITUDE_RATE_STAB_ACRO_OVERSHOOT_ANGLE_MAX 3000.0f // earth-frame rate stabilize controller's maximum overshoot angle
2013-10-12 09:28:18 -03:00
# define AC_ATTITUDE_100HZ_DT 0.0100f // delta time in seconds for 100hz update rate
# define AC_ATTITUDE_400HZ_DT 0.0025f // delta time in seconds for 400hz update rate
2015-05-03 19:05:15 -03:00
# define AC_ATTITUDE_CONTROL_RATE_BF_FF_DEFAULT 1 // body-frame rate feedforward enabled by default
2014-06-06 02:04:06 -03:00
2013-10-12 09:28:18 -03:00
class AC_AttitudeControl {
public :
AC_AttitudeControl ( AP_AHRS & ahrs ,
2014-01-17 22:54:23 -04:00
const AP_Vehicle : : MultiCopter & aparm ,
2013-10-12 09:28:18 -03:00
AP_Motors & motors ,
2014-02-14 03:06:21 -04:00
AC_P & pi_angle_roll , AC_P & pi_angle_pitch , AC_P & pi_angle_yaw ,
2014-02-10 00:23:52 -04:00
AC_PID & pid_rate_roll , AC_PID & pid_rate_pitch , AC_PID & pid_rate_yaw
2013-10-12 09:28:18 -03:00
) :
_ahrs ( ahrs ) ,
2014-01-17 22:54:23 -04:00
_aparm ( aparm ) ,
2013-10-12 09:28:18 -03:00
_motors ( motors ) ,
2014-02-14 03:06:21 -04:00
_p_angle_roll ( pi_angle_roll ) ,
_p_angle_pitch ( pi_angle_pitch ) ,
_p_angle_yaw ( pi_angle_yaw ) ,
2013-10-12 09:28:18 -03:00
_pid_rate_roll ( pid_rate_roll ) ,
_pid_rate_pitch ( pid_rate_pitch ) ,
_pid_rate_yaw ( pid_rate_yaw ) ,
2014-01-05 23:28:35 -04:00
_dt ( AC_ATTITUDE_100HZ_DT ) ,
2014-07-14 10:35:52 -03:00
_angle_boost ( 0 ) ,
_acro_angle_switch ( 0 )
2013-10-12 09:28:18 -03:00
{
AP_Param : : setup_object_defaults ( this , var_info ) ;
2014-02-01 02:27:58 -04:00
// initialise flags
_flags . limit_angle_to_rate_request = true ;
2013-10-12 09:28:18 -03:00
}
2014-07-14 10:37:31 -03:00
// empty destructor to suppress compiler warning
virtual ~ AC_AttitudeControl ( ) { }
2013-10-12 09:28:18 -03:00
//
// initialisation functions
//
// set_dt - sets time delta in seconds for all controllers (i.e. 100hz = 0.01, 400hz = 0.0025)
2014-05-27 10:44:29 -03:00
void set_dt ( float delta_sec ) ;
2013-10-12 09:28:18 -03:00
2015-05-06 04:11:48 -03:00
// get_accel_roll_max - gets the roll acceleration limit
float get_accel_roll_max ( ) { return _accel_roll_max ; }
2015-06-05 05:21:56 -03:00
// set_accel_roll_max - sets the roll acceleration limit
void set_accel_roll_max ( float accel_roll_max ) { _accel_roll_max = accel_roll_max ; }
2015-02-11 08:10:56 -04:00
// save_accel_roll_max - sets and saves the roll acceleration limit
void save_accel_roll_max ( float accel_roll_max ) { _accel_roll_max = accel_roll_max ; _accel_roll_max . save ( ) ; }
2015-05-06 04:11:48 -03:00
// get_accel_pitch_max - gets the pitch acceleration limit
float get_accel_pitch_max ( ) { return _accel_pitch_max ; }
2015-06-05 05:21:56 -03:00
// set_accel_pitch_max - sets the pitch acceleration limit
void set_accel_pitch_max ( float accel_pitch_max ) { _accel_pitch_max = accel_pitch_max ; }
2015-02-11 08:10:56 -04:00
// save_accel_pitch_max - sets and saves the pitch acceleration limit
void save_accel_pitch_max ( float accel_pitch_max ) { _accel_pitch_max = accel_pitch_max ; _accel_pitch_max . save ( ) ; }
2015-05-06 04:11:48 -03:00
// get_accel_yaw_max - gets the yaw acceleration limit
float get_accel_yaw_max ( ) { return _accel_yaw_max ; }
2015-06-05 05:21:56 -03:00
// set_accel_yaw_max - sets the yaw acceleration limit
void set_accel_yaw_max ( float accel_yaw_max ) { _accel_yaw_max = accel_yaw_max ; }
2015-02-11 08:10:56 -04:00
// save_accel_yaw_max - sets and saves the yaw acceleration limit
void save_accel_yaw_max ( float accel_yaw_max ) { _accel_yaw_max = accel_yaw_max ; _accel_yaw_max . save ( ) ; }
2014-06-06 00:03:06 -03:00
// relax_bf_rate_controller - ensure body-frame rate controller has zero errors to relax rate controller output
void relax_bf_rate_controller ( ) ;
2014-01-11 04:02:42 -04:00
2014-06-06 02:45:18 -03:00
// set_yaw_target_to_current_heading - sets yaw target to current heading
void set_yaw_target_to_current_heading ( ) { _angle_ef_target . z = _ahrs . yaw_sensor ; }
2015-06-23 04:49:12 -03:00
// shifts earth frame yaw target by yaw_shift_cd. yaw_shift_cd should be in centi-degreesa and is added to the current target heading
void shift_ef_yaw_target ( float yaw_shift_cd ) ;
2014-02-09 22:59:51 -04:00
//
// methods to be called by upper controllers to request and implement a desired attitude
//
2014-02-19 04:05:29 -04:00
// angle_ef_roll_pitch_rate_ef_yaw_smooth - attempts to maintain a roll and pitch angle and yaw rate (all earth frame) while smoothing the attitude based on the feel parameter
// smoothing_gain : a number from 1 to 50 with 1 being sluggish and 50 being very crisp
void angle_ef_roll_pitch_rate_ef_yaw_smooth ( float roll_angle_ef , float pitch_angle_ef , float yaw_rate_ef , float smoothing_gain ) ;
2014-02-19 02:55:45 -04:00
2014-02-13 22:52:58 -04:00
// angle_ef_roll_pitch_rate_ef_yaw - attempts to maintain a roll and pitch angle and yaw rate (all earth frame)
void angle_ef_roll_pitch_rate_ef_yaw ( float roll_angle_ef , float pitch_angle_ef , float yaw_rate_ef ) ;
2014-01-11 04:02:42 -04:00
2014-02-13 22:52:58 -04:00
// angle_ef_roll_pitch_yaw - attempts to maintain a roll, pitch and yaw angle (all earth frame)
2014-02-03 00:29:17 -04:00
// if yaw_slew is true then target yaw movement will be gradually moved to the new target based on the YAW_SLEW parameter
2014-02-13 22:52:58 -04:00
void angle_ef_roll_pitch_yaw ( float roll_angle_ef , float pitch_angle_ef , float yaw_angle_ef , bool slew_yaw ) ;
2014-01-11 04:02:42 -04:00
2014-02-13 22:52:58 -04:00
// rate_ef_roll_pitch_yaw - attempts to maintain a roll, pitch and yaw rate (all earth frame)
void rate_ef_roll_pitch_yaw ( float roll_rate_ef , float pitch_rate_ef , float yaw_rate_ef ) ;
2014-01-28 04:30:33 -04:00
2014-02-13 22:52:58 -04:00
// rate_bf_roll_pitch_yaw - attempts to maintain a roll, pitch and yaw rate (all body frame)
void rate_bf_roll_pitch_yaw ( float roll_rate_bf , float pitch_rate_bf , float yaw_rate_bf ) ;
2014-01-24 22:59:48 -04:00
2013-10-12 09:28:18 -03:00
//
2014-02-09 22:59:51 -04:00
// rate_controller_run - run lowest level body-frame rate controller and send outputs to the motors
// should be called at 100hz or more
2013-10-12 09:28:18 -03:00
//
2014-02-09 22:59:51 -04:00
virtual void rate_controller_run ( ) ;
2013-10-12 09:28:18 -03:00
//
2014-02-09 22:59:51 -04:00
// earth-frame <-> body-frame conversion functions
2013-10-12 09:28:18 -03:00
//
2014-08-22 10:50:10 -03:00
// frame_conversion_ef_to_bf - converts earth frame angles or rates to body frame
2014-02-13 22:52:58 -04:00
void frame_conversion_ef_to_bf ( const Vector3f & ef_vector , Vector3f & bf_vector ) ;
2013-10-12 09:28:18 -03:00
2014-08-22 10:50:10 -03:00
// frame_conversion_bf_to_ef - converts body frame angles or rates to earth frame
// returns false if conversion fails due to gimbal lock
bool frame_conversion_bf_to_ef ( const Vector3f & bf_vector , Vector3f & ef_vector ) ;
2013-10-12 09:28:18 -03:00
//
2014-02-09 22:59:51 -04:00
// public accessor functions
2013-10-12 09:28:18 -03:00
//
2014-02-09 22:59:51 -04:00
// limit_angle_to_rate_request
void limit_angle_to_rate_request ( bool limit_request ) { _flags . limit_angle_to_rate_request = limit_request ; }
2013-10-12 09:28:18 -03:00
2014-02-09 22:59:51 -04:00
// angle_ef_targets - returns angle controller earth-frame targets (for reporting)
2014-04-02 12:21:28 -03:00
const Vector3f & angle_ef_targets ( ) const { return _angle_ef_target ; }
2013-10-12 09:28:18 -03:00
2015-04-14 10:00:44 -03:00
// angle_bf_error - returns angle controller body-frame errors (for stability checking)
const Vector3f & angle_bf_error ( ) const { return _angle_bf_error ; }
2015-03-22 09:01:13 -03:00
// rate_bf_targets - sets rate controller body-frame targets
2014-02-01 02:27:58 -04:00
void rate_bf_roll_target ( float rate_cds ) { _rate_bf_target . x = rate_cds ; }
void rate_bf_pitch_target ( float rate_cds ) { _rate_bf_target . y = rate_cds ; }
void rate_bf_yaw_target ( float rate_cds ) { _rate_bf_target . z = rate_cds ; }
2013-10-12 09:28:18 -03:00
2015-02-11 09:03:36 -04:00
// Maximum roll rate step size that results in maximum output after 4 time steps
float max_rate_step_bf_roll ( ) ;
// Maximum pitch rate step size that results in maximum output after 4 time steps
float max_rate_step_bf_pitch ( ) ;
// Maximum yaw rate step size that results in maximum output after 4 time steps
float max_rate_step_bf_yaw ( ) ;
// Maximum roll step size that results in maximum output after 4 time steps
float max_angle_step_bf_roll ( ) { return max_rate_step_bf_roll ( ) / _p_angle_roll . kP ( ) ; }
// Maximum pitch step size that results in maximum output after 4 time steps
float max_angle_step_bf_pitch ( ) { return max_rate_step_bf_pitch ( ) / _p_angle_pitch . kP ( ) ; }
// Maximum yaw step size that results in maximum output after 4 time steps
float max_angle_step_bf_yaw ( ) { return max_rate_step_bf_yaw ( ) / _p_angle_yaw . kP ( ) ; }
2015-02-11 09:01:11 -04:00
// rate_ef_targets - returns rate controller body-frame targets (for reporting)
const Vector3f & rate_bf_targets ( ) const { return _rate_bf_target ; }
2015-02-11 07:07:29 -04:00
// bf_feedforward - enable or disable body-frame feed forward
2014-06-10 03:49:49 -03:00
void bf_feedforward ( bool enable_or_disable ) { _rate_bf_ff_enabled = enable_or_disable ; }
2015-05-06 04:11:48 -03:00
// bf_feedforward - enable or disable body-frame feed forward and save
2015-05-08 02:28:41 -03:00
void bf_feedforward_save ( bool enable_or_disable ) { _rate_bf_ff_enabled . set_and_save ( enable_or_disable ) ; }
2015-05-06 04:11:48 -03:00
2015-02-11 07:07:29 -04:00
// get_bf_feedforward - return body-frame feed forward setting
bool get_bf_feedforward ( ) { return _rate_bf_ff_enabled ; }
2014-06-10 03:49:49 -03:00
// enable_bf_feedforward - enable or disable body-frame feed forward
void accel_limiting ( bool enable_or_disable ) ;
2013-10-12 09:28:18 -03:00
//
// throttle functions
//
// set_throttle_out - to be called by upper throttle controllers when they wish to provide throttle output directly to motors
2015-04-16 01:55:59 -03:00
void set_throttle_out ( float throttle_pwm , bool apply_angle_boost , float filt_cutoff ) ;
2013-10-12 09:28:18 -03:00
2015-03-25 05:18:40 -03:00
// outputs a throttle to all motors evenly with no stabilization
2015-04-16 01:55:59 -03:00
void set_throttle_out_unstabilized ( float throttle_in , bool reset_attitude_control , float filt_cutoff ) ;
2015-03-25 05:18:40 -03:00
2014-01-05 23:28:35 -04:00
// angle_boost - accessor for angle boost so it can be logged
int16_t angle_boost ( ) const { return _angle_boost ; }
2013-10-12 09:28:18 -03:00
//
// helper functions
//
2014-01-17 22:54:23 -04:00
// lean_angle_max - maximum lean angle of the copter in centi-degrees
2014-05-06 04:35:19 -03:00
int16_t lean_angle_max ( ) const { return _aparm . angle_max ; }
2014-01-17 22:54:23 -04:00
2014-10-27 02:58:56 -03:00
// sqrt_controller - response based on the sqrt of the error instead of the more common linear response
static float sqrt_controller ( float error , float p , float second_ord_lim ) ;
2013-10-12 09:28:18 -03:00
// user settable parameters
static const struct AP_Param : : GroupInfo var_info [ ] ;
2014-01-29 09:50:32 -04:00
protected :
2013-10-12 09:28:18 -03:00
2014-02-01 02:27:58 -04:00
// attitude control flags
struct AttControlFlags {
uint8_t limit_angle_to_rate_request : 1 ; // 1 if the earth frame angle controller is limiting it's maximum rate request
} _flags ;
2014-02-13 08:34:27 -04:00
2014-02-13 22:52:58 -04:00
// update_ef_roll_angle_and_error - update _angle_ef_target.x using an earth frame roll rate request
2014-07-12 12:53:19 -03:00
void update_ef_roll_angle_and_error ( float roll_rate_ef , Vector3f & angle_ef_error , float overshoot_max ) ;
2014-02-13 08:34:27 -04:00
2014-02-13 22:52:58 -04:00
// update_ef_pitch_angle_and_error - update _angle_ef_target.y using an earth frame pitch rate request
2014-07-12 12:53:19 -03:00
void update_ef_pitch_angle_and_error ( float pitch_rate_ef , Vector3f & angle_ef_error , float overshoot_max ) ;
2014-02-13 08:34:27 -04:00
2014-02-13 22:52:58 -04:00
// update_ef_yaw_angle_and_error - update _angle_ef_target.z using an earth frame yaw rate request
2014-07-12 12:53:19 -03:00
void update_ef_yaw_angle_and_error ( float yaw_rate_ef , Vector3f & angle_ef_error , float overshoot_max ) ;
2014-02-01 02:27:58 -04:00
2014-02-13 22:52:58 -04:00
// integrate_bf_rate_error_to_angle_errors - calculates body frame angle errors
2014-02-09 22:59:51 -04:00
// body-frame feed forward rates (centi-degrees / second) taken from _angle_bf_error
// angle errors in centi-degrees placed in _angle_bf_error
2014-02-13 22:52:58 -04:00
void integrate_bf_rate_error_to_angle_errors ( ) ;
2014-02-09 22:59:51 -04:00
2014-02-13 22:52:58 -04:00
// update_rate_bf_targets - converts body-frame angle error to body-frame rate targets for roll, pitch and yaw axis
2014-02-09 22:59:51 -04:00
// targets rates in centi-degrees taken from _angle_bf_error
// results in centi-degrees/sec put into _rate_bf_target
2014-02-13 22:52:58 -04:00
void update_rate_bf_targets ( ) ;
2014-02-09 22:59:51 -04:00
2013-10-12 09:28:18 -03:00
//
// body-frame rate controller
//
// rate_bf_to_motor_roll - ask the rate controller to calculate the motor outputs to achieve the target body-frame rate (in centi-degrees/sec) for roll, pitch and yaw
float rate_bf_to_motor_roll ( float rate_target_cds ) ;
float rate_bf_to_motor_pitch ( float rate_target_cds ) ;
2014-01-29 09:50:32 -04:00
virtual float rate_bf_to_motor_yaw ( float rate_target_cds ) ;
2013-10-12 09:28:18 -03:00
//
// throttle methods
//
2015-04-03 15:52:20 -03:00
// calculate total body frame throttle required to produce the given earth frame throttle
2015-07-13 03:00:24 -03:00
virtual float get_boosted_throttle ( float throttle_in ) = 0 ;
2013-10-12 09:28:18 -03:00
// references to external libraries
2014-01-27 01:08:59 -04:00
const AP_AHRS & _ahrs ;
2014-01-17 22:54:23 -04:00
const AP_Vehicle : : MultiCopter & _aparm ;
2013-10-12 09:28:18 -03:00
AP_Motors & _motors ;
2014-02-14 03:06:21 -04:00
AC_P & _p_angle_roll ;
AC_P & _p_angle_pitch ;
AC_P & _p_angle_yaw ;
2013-10-12 09:28:18 -03:00
AC_PID & _pid_rate_roll ;
AC_PID & _pid_rate_pitch ;
AC_PID & _pid_rate_yaw ;
// parameters
2014-02-03 00:29:17 -04:00
AP_Float _slew_yaw ; // maximum rate the yaw target can be updated in Loiter, RTL, Auto flight modes
2015-02-11 08:10:56 -04:00
AP_Float _accel_roll_max ; // maximum rotation acceleration for earth-frame roll axis
AP_Float _accel_pitch_max ; // maximum rotation acceleration for earth-frame pitch axis
AP_Float _accel_yaw_max ; // maximum rotation acceleration for earth-frame yaw axis
2014-06-06 02:04:06 -03:00
AP_Int8 _rate_bf_ff_enabled ; // Enable/Disable body frame rate feed forward
2013-10-12 09:28:18 -03:00
// internal variables
// To-Do: make rate targets a typedef instead of Vector3f?
float _dt ; // time delta in seconds
2014-01-05 23:28:35 -04:00
Vector3f _angle_ef_target ; // angle controller earth-frame targets
2014-06-06 00:03:06 -03:00
Vector3f _angle_bf_error ; // angle controller body-frame error
2014-01-05 23:28:35 -04:00
Vector3f _rate_bf_target ; // rate controller body-frame targets
2014-02-14 21:07:49 -04:00
Vector3f _rate_ef_desired ; // earth-frame feed forward rates
Vector3f _rate_bf_desired ; // body-frame feed forward rates
2014-01-05 23:28:35 -04:00
int16_t _angle_boost ; // used only for logging
2014-02-13 08:34:27 -04:00
int16_t _acro_angle_switch ; // used only for logging
2013-10-12 09:28:18 -03:00
} ;
# define AC_ATTITUDE_CONTROL_LOG_FORMAT(msg) { msg, sizeof(AC_AttitudeControl::log_Attitude), \
" ATT " , " cccccCC " , " RollIn,Roll,PitchIn,Pitch,YawIn,Yaw,NavYaw " }
# endif //AC_AttitudeControl_H