Path: blob/master/libraries/APM_Control/AP_RollController.cpp
9325 views
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/1415// Code by Jon Challinger16// Modified by Paul Riseborough17//1819#include <AP_HAL/AP_HAL.h>20#include "AP_RollController.h"21#include <AP_AHRS/AP_AHRS.h>22#include <AP_Scheduler/AP_Scheduler.h>2324extern const AP_HAL::HAL& hal;2526const AP_Param::GroupInfo AP_RollController::var_info[] = {27// @Param: 2SRV_TCONST28// @DisplayName: Roll Time Constant29// @Description: Time constant in seconds from demanded to achieved roll angle. Most models respond well to 0.5. May be reduced for faster responses, but setting lower than a model can achieve will not help.30// @Range: 0.4 1.031// @Units: s32// @Increment: 0.133// @User: Advanced34AP_GROUPINFO("2SRV_TCONST", 0, AP_RollController, gains.tau, 0.5f),3536// index 1 to 3 reserved for old PID values3738// @Param: 2SRV_RMAX39// @DisplayName: Maximum Roll Rate40// @Description: This sets the maximum roll rate that the attitude controller will demand (degrees/sec) in angle stabilized modes. Setting it to zero disables this limit.41// @Range: 0 18042// @Units: deg/s43// @Increment: 144// @User: Advanced45AP_GROUPINFO("2SRV_RMAX", 4, AP_RollController, gains.rmax_pos, 0),4647// index 5, 6 reserved for old IMAX, FF4849// @Param: _RATE_P50// @DisplayName: Roll axis rate controller P gain51// @Description: Roll axis rate controller P gain. Corrects in proportion to the difference between the desired roll rate vs actual roll rate52// @Range: 0.08 0.3553// @Increment: 0.00554// @User: Standard5556// @Param: _RATE_I57// @DisplayName: Roll axis rate controller I gain58// @Description: Roll axis rate controller I gain. Corrects long-term difference in desired roll rate vs actual roll rate59// @Range: 0.01 0.660// @Increment: 0.0161// @User: Standard6263// @Param: _RATE_IMAX64// @DisplayName: Roll axis rate controller I gain maximum65// @Description: Roll axis rate controller I gain maximum. Constrains the maximum that the I term will output66// @Range: 0 167// @Increment: 0.0168// @User: Standard6970// @Param: _RATE_D71// @DisplayName: Roll axis rate controller D gain72// @Description: Roll axis rate controller D gain. Compensates for short-term change in desired roll rate vs actual roll rate73// @Range: 0.001 0.0374// @Increment: 0.00175// @User: Standard7677// @Param: _RATE_FF78// @DisplayName: Roll axis rate controller feed forward79// @Description: Roll axis rate controller feed forward80// @Range: 0 3.081// @Increment: 0.00182// @User: Standard8384// @Param: _RATE_FLTT85// @DisplayName: Roll axis rate controller target frequency in Hz86// @Description: Roll axis rate controller target frequency in Hz87// @Range: 2 5088// @Increment: 189// @Units: Hz90// @User: Standard9192// @Param: _RATE_FLTE93// @DisplayName: Roll axis rate controller error frequency in Hz94// @Description: Roll axis rate controller error frequency in Hz95// @Range: 2 5096// @Increment: 197// @Units: Hz98// @User: Standard99100// @Param: _RATE_FLTD101// @DisplayName: Roll axis rate controller derivative frequency in Hz102// @Description: Roll axis rate controller derivative frequency in Hz103// @Range: 0 50104// @Increment: 1105// @Units: Hz106// @User: Standard107108// @Param: _RATE_SMAX109// @DisplayName: Roll slew rate limit110// @Description: Sets an upper limit on the slew rate produced by the combined P and D gains. If the amplitude of the control action produced by the rate feedback exceeds this value, then the D+P gain is reduced to respect the limit. This limits the amplitude of high frequency oscillations caused by an excessive gain. The limit should be set to no more than 25% of the actuators maximum slew rate to allow for load effects. Note: The gain will not be reduced to less than 10% of the nominal value. A value of zero will disable this feature.111// @Range: 0 200112// @Increment: 0.5113// @User: Advanced114115// @Param: _RATE_PDMX116// @DisplayName: Roll axis rate controller PD sum maximum117// @Description: Roll axis rate controller PD sum maximum. The maximum/minimum value that the sum of the P and D term can output118// @Range: 0 1119// @Increment: 0.01120121// @Param: _RATE_D_FF122// @DisplayName: Roll Derivative FeedForward Gain123// @Description: FF D Gain which produces an output that is proportional to the rate of change of the target124// @Range: 0 0.03125// @Increment: 0.001126// @User: Advanced127128// @Param: _RATE_NTF129// @DisplayName: Roll Target notch filter index130// @Description: Roll Target notch filter index131// @Range: 1 8132// @User: Advanced133134// @Param: _RATE_NEF135// @DisplayName: Roll Error notch filter index136// @Description: Roll Error notch filter index137// @Range: 1 8138// @User: Advanced139140AP_SUBGROUPINFO(rate_pid, "_RATE_", 9, AP_RollController, AC_PID),141142AP_GROUPEND143};144145// constructor146AP_RollController::AP_RollController(const AP_FixedWing &parms)147: AP_FW_Controller(parms,148AC_PID::Defaults{149.p = 0.08,150.i = 0.15,151.d = 0.0,152.ff = 0.345,153.imax = 0.666,154.filt_T_hz = 3.0,155.filt_E_hz = 0.0,156.filt_D_hz = 12.0,157.srmax = 150.0,158.srtau = 1.0159},160AP_AutoTune::ATType::AUTOTUNE_ROLL)161{162AP_Param::setup_object_defaults(this, var_info);163}164165float AP_RollController::get_measured_rate() const166{167return AP::ahrs().get_gyro().x;168}169170float AP_RollController::get_airspeed() const171{172float aspeed;173if (!AP::ahrs().airspeed_EAS(aspeed)) {174// If no airspeed available use 0175aspeed = 0.0;176}177return aspeed;178}179180bool AP_RollController::is_underspeed(const float aspeed) const181{182return aspeed <= float(aparm.airspeed_min);183}184185/*186Function returns an equivalent aileron deflection in centi-degrees in the range from -4500 to 4500187A positive demand is up188Inputs are:1891) demanded bank angle in centi-degrees1902) control gain scaler = scaling_speed / aspeed1913) boolean which is true when stabilise mode is active1924) minimum FBW airspeed (metres/sec)193*/194float AP_RollController::get_servo_out(int32_t angle_err, float scaler, bool disable_integrator, bool ground_mode)195{196if (gains.tau < 0.05f) {197gains.tau.set(0.05f);198}199200// Calculate the desired roll rate (deg/sec) from the angle error201angle_err_deg = angle_err * 0.01;202float desired_rate = angle_err_deg/ gains.tau;203204/*205prevent indecision in the roll controller when target roll is206close to 180 degrees from the current roll207*/208const float indecision_threshold_deg = 160;209const float last_desired_rate = _pid_info.target;210const float abs_angle_err_deg = fabsf(angle_err_deg);211if (abs_angle_err_deg > indecision_threshold_deg &&212angle_err_deg <= 180) {213if (desired_rate * last_desired_rate < 0) {214desired_rate = -desired_rate;215// increase the desired rate in proportion to the extra216// angle we are requesting217const float new_angle_err_deg = abs_angle_err_deg + (180 - abs_angle_err_deg)*2;218desired_rate *= new_angle_err_deg / abs_angle_err_deg;219}220}221222if (!in_recovery) {223// Limit the demanded roll rate. When we are in a VTOL224// recovery we don't apply the limit225if (gains.rmax_pos && desired_rate < -gains.rmax_pos) {226desired_rate = - gains.rmax_pos;227} else if (gains.rmax_pos && desired_rate > gains.rmax_pos) {228desired_rate = gains.rmax_pos;229}230}231232// the in_recovery flag is single loop only233in_recovery = false;234235return _get_rate_out(desired_rate, scaler, disable_integrator, get_airspeed(), ground_mode);236}237238/*239convert from old to new PIDs240this is a temporary conversion function during development241*/242void AP_RollController::convert_pid()243{244AP_Float &ff = rate_pid.ff();245if (ff.configured()) {246return;247}248float old_ff=0, old_p=1.0, old_i=0.3, old_d=0.08;249int16_t old_imax=3000;250bool have_old = AP_Param::get_param_by_index(this, 1, AP_PARAM_FLOAT, &old_p);251have_old |= AP_Param::get_param_by_index(this, 3, AP_PARAM_FLOAT, &old_i);252have_old |= AP_Param::get_param_by_index(this, 2, AP_PARAM_FLOAT, &old_d);253have_old |= AP_Param::get_param_by_index(this, 6, AP_PARAM_FLOAT, &old_ff);254have_old |= AP_Param::get_param_by_index(this, 5, AP_PARAM_INT16, &old_imax);255if (!have_old) {256// none of the old gains were set257return;258}259260const float kp_ff = MAX((old_p - old_i * gains.tau) * gains.tau - old_d, 0);261rate_pid.ff().set_and_save(old_ff + kp_ff);262rate_pid.kI().set_and_save_ifchanged(old_i * gains.tau);263rate_pid.kP().set_and_save_ifchanged(old_d);264rate_pid.kD().set_and_save_ifchanged(0);265rate_pid.kIMAX().set_and_save_ifchanged(old_imax/4500.0);266}267268269