Path: blob/master/libraries/APM_Control/AR_AttitudeControl.cpp
9374 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#include <AP_AHRS/AP_AHRS.h>16#include <AP_Math/AP_Math.h>17#include <AP_HAL/AP_HAL.h>18#include "AR_AttitudeControl.h"19#include <AP_GPS/AP_GPS.h>2021// attitude control default definition22#define AR_ATTCONTROL_STEER_ANG_P 2.00f23#define AR_ATTCONTROL_STEER_RATE_FF 0.20f24#define AR_ATTCONTROL_STEER_RATE_P 0.20f25#define AR_ATTCONTROL_STEER_RATE_I 0.20f26#define AR_ATTCONTROL_STEER_RATE_IMAX 1.00f27#define AR_ATTCONTROL_STEER_RATE_D 0.00f28#define AR_ATTCONTROL_STEER_RATE_FILT 10.00f29#define AR_ATTCONTROL_STEER_RATE_MAX 120.0f30#define AR_ATTCONTROL_STEER_ACCEL_MAX 120.0f31#define AR_ATTCONTROL_STEER_DECEL_MAX 0.0f32#define AR_ATTCONTROL_THR_SPEED_P 0.20f33#define AR_ATTCONTROL_THR_SPEED_I 0.20f34#define AR_ATTCONTROL_THR_SPEED_IMAX 1.00f35#define AR_ATTCONTROL_THR_SPEED_D 0.00f36#define AR_ATTCONTROL_THR_SPEED_FILT 10.00f37#define AR_ATTCONTROL_PITCH_THR_P 1.80f38#define AR_ATTCONTROL_PITCH_THR_I 1.50f39#define AR_ATTCONTROL_PITCH_THR_D 0.03f40#define AR_ATTCONTROL_PITCH_THR_IMAX 1.0f41#define AR_ATTCONTROL_PITCH_THR_FILT 10.0f42#define AR_ATTCONTROL_BAL_PITCH_FF 0.4f43#define AR_ATTCONTROL_PITCH_LIM_TC 0.5f // pitch limit default time constant44#define AR_ATTCONTROL_PITCH_RELAX_RATIO 0.5f // pitch limit relaxed 2x slower than it is limited45#define AR_ATTCONTROL_PITCH_LIM_THR_THRESH 0.60 // pitch limiting starts if throttle exceeds 60%46#define AR_ATTCONTROL_DT 0.02f47#define AR_ATTCONTROL_TIMEOUT_MS 20048#define AR_ATTCONTROL_HEEL_SAIL_P 1.0f49#define AR_ATTCONTROL_HEEL_SAIL_I 0.1f50#define AR_ATTCONTROL_HEEL_SAIL_D 0.0f51#define AR_ATTCONTROL_HEEL_SAIL_IMAX 1.0f52#define AR_ATTCONTROL_HEEL_SAIL_FILT 10.0f53#define AR_ATTCONTROL_DT 0.02f5455// throttle/speed control maximum acceleration/deceleration (in m/s) (_ACCEL_MAX parameter default)56#define AR_ATTCONTROL_THR_ACCEL_MAX 1.00f5758// minimum speed in m/s59#define AR_ATTCONTROL_STEER_SPEED_MIN 1.0f6061// speed (in m/s) at or below which vehicle is considered stopped (_STOP_SPEED parameter default)62#define AR_ATTCONTROL_STOP_SPEED_DEFAULT 0.1f6364extern const AP_HAL::HAL& hal;6566AR_AttitudeControl *AR_AttitudeControl::_singleton;6768const AP_Param::GroupInfo AR_AttitudeControl::var_info[] = {6970// @Param: _STR_RAT_P71// @DisplayName: Steering control rate P gain72// @Description: Steering control rate P gain. Converts the turn rate error (in radians/sec) to a steering control output (in the range -1 to +1)73// @Range: 0.000 2.00074// @Increment: 0.00175// @User: Standard7677// @Param: _STR_RAT_I78// @DisplayName: Steering control I gain79// @Description: Steering control I gain. Corrects long term error between the desired turn rate (in rad/s) and actual80// @Range: 0.000 2.00081// @Increment: 0.00182// @User: Standard8384// @Param: _STR_RAT_IMAX85// @DisplayName: Steering control I gain maximum86// @Description: Steering control I gain maximum. Constrains the steering output (range -1 to +1) that the I term will generate87// @Range: 0.000 1.00088// @Increment: 0.0189// @User: Standard9091// @Param: _STR_RAT_D92// @DisplayName: Steering control D gain93// @Description: Steering control D gain. Compensates for short-term change in desired turn rate vs actual94// @Range: 0.000 0.40095// @Increment: 0.00196// @User: Standard9798// @Param: _STR_RAT_FF99// @DisplayName: Steering control feed forward100// @Description: Steering control feed forward101// @Range: 0.000 3.000102// @Increment: 0.001103// @User: Standard104105// @Param: _STR_RAT_FILT106// @DisplayName: Steering control filter frequency107// @Description: Steering control input filter. Lower values reduce noise but add delay.108// @Range: 0.000 100.000109// @Increment: 0.1110// @Units: Hz111// @User: Standard112113// @Param: _STR_RAT_FLTT114// @DisplayName: Steering control Target filter frequency in Hz115// @Description: Target filter frequency in Hz116// @Range: 0.000 100.000117// @Increment: 0.1118// @Units: Hz119// @User: Standard120121// @Param: _STR_RAT_FLTE122// @DisplayName: Steering control Error filter frequency in Hz123// @Description: Error filter frequency in Hz124// @Range: 0.000 100.000125// @Increment: 0.1126// @Units: Hz127// @User: Standard128129// @Param: _STR_RAT_FLTD130// @DisplayName: Steering control Derivative term filter frequency in Hz131// @Description: Derivative filter frequency in Hz132// @Range: 0.000 100.000133// @Increment: 0.1134// @Units: Hz135// @User: Standard136137// @Param: _STR_RAT_SMAX138// @DisplayName: Steering slew rate limit139// @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.140// @Range: 0 200141// @Increment: 0.5142// @User: Advanced143144// @Param: _STR_RAT_PDMX145// @DisplayName: Steering control PD sum maximum146// @Description: Steering control PD sum maximum. The maximum/minimum value that the sum of the P and D term can output147// @Range: 0.000 1.000148// @Increment: 0.01149150// @Param: _STR_RAT_D_FF151// @DisplayName: Steering control Derivative FeedForward Gain152// @Description: FF D Gain which produces an output that is proportional to the rate of change of the target153// @Range: 0 0.03154// @Increment: 0.001155// @User: Advanced156157// @Param: _STR_RAT_NTF158// @DisplayName: Steering control Target notch filter index159// @Description: Steering control Target notch filter index160// @Range: 1 8161// @User: Advanced162163// @Param: _STR_RAT_NEF164// @DisplayName: Steering control Error notch filter index165// @Description: Steering control Error notch filter index166// @Range: 1 8167// @User: Advanced168169AP_SUBGROUPINFO(_steer_rate_pid, "_STR_RAT_", 1, AR_AttitudeControl, AC_PID),170171// @Param: _SPEED_P172// @DisplayName: Speed control P gain173// @Description: Speed control P gain. Converts the error between the desired speed (in m/s) and actual speed to a motor output (in the range -1 to +1)174// @Range: 0.010 2.000175// @Increment: 0.01176// @User: Standard177178// @Param: _SPEED_I179// @DisplayName: Speed control I gain180// @Description: Speed control I gain. Corrects long term error between the desired speed (in m/s) and actual speed181// @Range: 0.000 2.000182// @Increment: 0.01183// @User: Standard184185// @Param: _SPEED_IMAX186// @DisplayName: Speed control I gain maximum187// @Description: Speed control I gain maximum. Constrains the maximum motor output (range -1 to +1) that the I term will generate188// @Range: 0.000 1.000189// @Increment: 0.01190// @User: Standard191192// @Param: _SPEED_D193// @DisplayName: Speed control D gain194// @Description: Speed control D gain. Compensates for short-term change in desired speed vs actual195// @Range: 0.000 0.400196// @Increment: 0.001197// @User: Standard198199// @Param: _SPEED_FF200// @DisplayName: Speed control feed forward201// @Description: Speed control feed forward202// @Range: 0.000 0.500203// @Increment: 0.001204// @User: Standard205206// @Param: _SPEED_FILT207// @DisplayName: Speed control filter frequency208// @Description: Speed control input filter. Lower values reduce noise but add delay.209// @Range: 0.000 100.000210// @Increment: 0.1211// @Units: Hz212// @User: Standard213214// @Param: _SPEED_FLTT215// @DisplayName: Speed control Target filter frequency in Hz216// @Description: Target filter frequency in Hz217// @Range: 0.000 100.000218// @Increment: 0.1219// @Units: Hz220// @User: Standard221222// @Param: _SPEED_FLTE223// @DisplayName: Speed control Error filter frequency in Hz224// @Description: Error filter frequency in Hz225// @Range: 0.000 100.000226// @Increment: 0.1227// @Units: Hz228// @User: Standard229230// @Param: _SPEED_FLTD231// @DisplayName: Speed control Derivative term filter frequency in Hz232// @Description: Derivative filter frequency in Hz233// @Range: 0.000 100.000234// @Increment: 0.1235// @Units: Hz236// @User: Standard237238// @Param: _SPEED_SMAX239// @DisplayName: Speed control slew rate limit240// @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.241// @Range: 0 200242// @Increment: 0.5243// @User: Advanced244245// @Param: _SPEED_PDMX246// @DisplayName: Speed control PD sum maximum247// @Description: Speed control PD sum maximum. The maximum/minimum value that the sum of the P and D term can output248// @Range: 0.000 1.000249// @Increment: 0.01250251// @Param: _SPEED_D_FF252// @DisplayName: Speed control Derivative FeedForward Gain253// @Description: FF D Gain which produces an output that is proportional to the rate of change of the target254// @Range: 0 0.03255// @Increment: 0.001256// @User: Advanced257258// @Param: _SPEED_NTF259// @DisplayName: Speed control Target notch filter index260// @Description: Speed control Target notch filter index261// @Range: 1 8262// @User: Advanced263264// @Param: _SPEED_NEF265// @DisplayName: Speed control Error notch filter index266// @Description: Speed control Error notch filter index267// @Range: 1 8268// @User: Advanced269270AP_SUBGROUPINFO(_throttle_speed_pid, "_SPEED_", 2, AR_AttitudeControl, AC_PID),271272// @Param: _ACCEL_MAX273// @DisplayName: Speed control acceleration (and deceleration) maximum in m/s/s274// @Description: Speed control acceleration (and deceleration) maximum in m/s/s. 0 to disable acceleration limiting275// @Range: 0.0 10.0276// @Increment: 0.1277// @Units: m/s/s278// @User: Standard279AP_GROUPINFO("_ACCEL_MAX", 3, AR_AttitudeControl, _throttle_accel_max, AR_ATTCONTROL_THR_ACCEL_MAX),280281// @Param: _BRAKE282// @DisplayName: Speed control brake enable/disable283// @Description: Speed control brake enable/disable. Allows sending a reversed output to the motors to slow the vehicle.284// @Values: 0:Disable,1:Enable285// @User: Standard286AP_GROUPINFO("_BRAKE", 4, AR_AttitudeControl, _brake_enable, 1),287288// @Param: _STOP_SPEED289// @DisplayName: Speed control stop speed290// @Description: Speed control stop speed. Motor outputs to zero once vehicle speed falls below this value291// @Range: 0.00 0.50292// @Increment: 0.01293// @Units: m/s294// @User: Standard295AP_GROUPINFO("_STOP_SPEED", 5, AR_AttitudeControl, _stop_speed, AR_ATTCONTROL_STOP_SPEED_DEFAULT),296297// @Param: _STR_ANG_P298// @DisplayName: Steering control angle P gain299// @Description: Steering control angle P gain. Converts the error between the desired heading/yaw (in radians) and actual heading/yaw to a desired turn rate (in rad/sec)300// @Range: 1.000 10.000301// @Increment: 0.1302// @User: Standard303AP_SUBGROUPINFO(_steer_angle_p, "_STR_ANG_", 6, AR_AttitudeControl, AC_P),304305// @Param: _STR_ACC_MAX306// @DisplayName: Steering control angular acceleration maximum307// @Description: Steering control angular acceleration maximum (in deg/s/s). 0 to disable acceleration limiting308// @Range: 0 1000309// @Increment: 0.1310// @Units: deg/s/s311// @User: Standard312AP_GROUPINFO("_STR_ACC_MAX", 7, AR_AttitudeControl, _steer_accel_max, AR_ATTCONTROL_STEER_ACCEL_MAX),313314// @Param: _STR_RAT_MAX315// @DisplayName: Steering control rotation rate maximum316// @Description: Steering control rotation rate maximum in deg/s. 0 to remove rate limiting317// @Range: 0 1000318// @Increment: 0.1319// @Units: deg/s320// @User: Standard321AP_GROUPINFO("_STR_RAT_MAX", 8, AR_AttitudeControl, _steer_rate_max, AR_ATTCONTROL_STEER_RATE_MAX),322323// @Param: _DECEL_MAX324// @DisplayName: Speed control deceleration maximum in m/s/s325// @Description: Speed control and deceleration maximum in m/s/s. 0 to use ATC_ACCEL_MAX for deceleration326// @Range: 0.0 10.0327// @Increment: 0.1328// @Units: m/s/s329// @User: Standard330AP_GROUPINFO("_DECEL_MAX", 9, AR_AttitudeControl, _throttle_decel_max, 0.00f),331332// @Param: _BAL_P333// @DisplayName: Pitch control P gain334// @Description: Pitch control P gain for BalanceBots. Converts the error between the desired pitch (in radians) and actual pitch to a motor output (in the range -1 to +1)335// @Range: 0.000 2.000336// @Increment: 0.01337// @User: Standard338339// @Param: _BAL_I340// @DisplayName: Pitch control I gain341// @Description: Pitch control I gain for BalanceBots. Corrects long term error between the desired pitch (in radians) and actual pitch342// @Range: 0.000 2.000343// @Increment: 0.01344// @User: Standard345346// @Param: _BAL_IMAX347// @DisplayName: Pitch control I gain maximum348// @Description: Pitch control I gain maximum. Constrains the maximum motor output (range -1 to +1) that the I term will generate349// @Range: 0.000 1.000350// @Increment: 0.01351// @User: Standard352353// @Param: _BAL_D354// @DisplayName: Pitch control D gain355// @Description: Pitch control D gain. Compensates for short-term change in desired pitch vs actual356// @Range: 0.000 0.100357// @Increment: 0.001358// @User: Standard359360// @Param: _BAL_FF361// @DisplayName: Pitch control feed forward362// @Description: Pitch control feed forward363// @Range: 0.000 0.500364// @Increment: 0.001365// @User: Standard366367// @Param: _BAL_FILT368// @DisplayName: Pitch control filter frequency369// @Description: Pitch control input filter. Lower values reduce noise but add delay.370// @Range: 0.000 100.000371// @Increment: 0.1372// @Units: Hz373// @User: Standard374375// @Param: _BAL_FLTT376// @DisplayName: Pitch control Target filter frequency in Hz377// @Description: Pitch control Target filter frequency in Hz378// @Range: 0.000 100.000379// @Increment: 0.1380// @Units: Hz381// @User: Standard382383// @Param: _BAL_FLTE384// @DisplayName: Pitch control Error filter frequency in Hz385// @Description: Pitch control Error filter frequency in Hz386// @Range: 0.000 100.000387// @Increment: 0.1388// @Units: Hz389// @User: Standard390391// @Param: _BAL_FLTD392// @DisplayName: Pitch control Derivative term filter frequency in Hz393// @Description: Pitch control Derivative filter frequency in Hz394// @Range: 0.000 100.000395// @Increment: 0.1396// @Units: Hz397// @User: Standard398399// @Param: _BAL_SMAX400// @DisplayName: Pitch control slew rate limit401// @Description: Pitch control 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.402// @Range: 0 200403// @Increment: 0.5404// @User: Advanced405406// @Param: _BAL_PDMX407// @DisplayName: Pitch control PD sum maximum408// @Description: Pitch control PD sum maximum. The maximum/minimum value that the sum of the P and D term can output409// @Range: 0.000 1.000410// @Increment: 0.01411412// @Param: _BAL_D_FF413// @DisplayName: Pitch control Derivative FeedForward Gain414// @Description: FF D Gain which produces an output that is proportional to the rate of change of the target415// @Range: 0 0.03416// @Increment: 0.001417// @User: Advanced418419// @Param: _BAL_NTF420// @DisplayName: Pitch control Target notch filter index421// @Description: Pitch control Target notch filter index422// @Range: 1 8423// @User: Advanced424425// @Param: _BAL_NEF426// @DisplayName: Pitch control Error notch filter index427// @Description: Pitch control Error notch filter index428// @Range: 1 8429// @User: Advanced430431AP_SUBGROUPINFO(_pitch_to_throttle_pid, "_BAL_", 10, AR_AttitudeControl, AC_PID),432433// @Param: _BAL_PIT_FF434// @DisplayName: Pitch control feed forward from current pitch angle435// @Description: Pitch control feed forward from current pitch angle436// @Range: 0.0 1.0437// @Increment: 0.01438// @User: Standard439AP_GROUPINFO("_BAL_PIT_FF", 11, AR_AttitudeControl, _pitch_to_throttle_ff, AR_ATTCONTROL_BAL_PITCH_FF),440441// @Param: _SAIL_P442// @DisplayName: Sail Heel control P gain443// @Description: Sail Heel control P gain for sailboats. Converts the error between the desired heel angle (in radians) and actual heel to a main sail output (in the range -1 to +1)444// @Range: 0.000 2.000445// @Increment: 0.01446// @User: Standard447448// @Param: _SAIL_I449// @DisplayName: Sail Heel control I gain450// @Description: Sail Heel control I gain for sailboats. Corrects long term error between the desired heel angle (in radians) and actual451// @Range: 0.000 2.000452// @Increment: 0.01453// @User: Standard454455// @Param: _SAIL_IMAX456// @DisplayName: Sail Heel control I gain maximum457// @Description: Sail Heel control I gain maximum. Constrains the maximum I term contribution to the main sail output (range -1 to +1)458// @Range: 0.000 1.000459// @Increment: 0.01460// @User: Standard461462// @Param: _SAIL_D463// @DisplayName: Sail Heel control D gain464// @Description: Sail Heel control D gain. Compensates for short-term change in desired heel angle vs actual465// @Range: 0.000 0.100466// @Increment: 0.001467// @User: Standard468469// @Param: _SAIL_FF470// @DisplayName: Sail Heel control feed forward471// @Description: Sail Heel control feed forward472// @Range: 0.000 0.500473// @Increment: 0.001474// @User: Standard475476// @Param: _SAIL_FILT477// @DisplayName: Sail Heel control filter frequency478// @Description: Sail Heel control input filter. Lower values reduce noise but add delay.479// @Range: 0.000 100.000480// @Increment: 0.1481// @Units: Hz482// @User: Standard483484// @Param: _SAIL_FLTT485// @DisplayName: Sail Heel Target filter frequency in Hz486// @Description: Target filter frequency in Hz487// @Range: 0.000 100.000488// @Increment: 0.1489// @Units: Hz490// @User: Standard491492// @Param: _SAIL_FLTE493// @DisplayName: Sail Heel Error filter frequency in Hz494// @Description: Error filter frequency in Hz495// @Range: 0.000 100.000496// @Increment: 0.1497// @Units: Hz498// @User: Standard499500// @Param: _SAIL_FLTD501// @DisplayName: Sail Heel Derivative term filter frequency in Hz502// @Description: Derivative filter frequency in Hz503// @Range: 0.000 100.000504// @Increment: 0.1505// @Units: Hz506// @User: Standard507508// @Param: _SAIL_SMAX509// @DisplayName: Sail heel slew rate limit510// @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.511// @Range: 0 200512// @Increment: 0.5513// @User: Advanced514515// @Param: _SAIL_PDMX516// @DisplayName: Sail Heel control PD sum maximum517// @Description: Sail Heel control PD sum maximum. The maximum/minimum value that the sum of the P and D term can output518// @Range: 0.000 1.000519// @Increment: 0.01520521// @Param: _SAIL_D_FF522// @DisplayName: Sail Heel Derivative FeedForward Gain523// @Description: FF D Gain which produces an output that is proportional to the rate of change of the target524// @Range: 0 0.03525// @Increment: 0.001526// @User: Advanced527528// @Param: _SAIL_NTF529// @DisplayName: Sail Heel Target notch filter index530// @Description: Sail Heel Target notch filter index531// @Range: 1 8532// @User: Advanced533534// @Param: _SAIL_NEF535// @DisplayName: Sail Heel Error notch filter index536// @Description: Sail Heel Error notch filter index537// @Range: 1 8538// @User: Advanced539540AP_SUBGROUPINFO(_sailboat_heel_pid, "_SAIL_", 12, AR_AttitudeControl, AC_PID),541542// @Param: _TURN_MAX_G543// @DisplayName: Turning maximum G force544// @Description: The maximum turning acceleration (in units of gravities) that the rover can handle while remaining stable. The navigation code will keep the lateral acceleration below this level to avoid rolling over or slipping the wheels in turns545// @Units: gravities546// @Range: 0.1 10547// @Increment: 0.01548// @User: Standard549AP_GROUPINFO("_TURN_MAX_G", 13, AR_AttitudeControl, _turn_lateral_G_max, 0.6f),550551// @Param: _BAL_LIM_TC552// @DisplayName: Pitch control limit time constant553// @Description: Pitch control limit time constant to protect against falling. Lower values limit pitch more quickly, higher values limit more slowly. Set to 0 to disable554// @Range: 0.0 5.0555// @Increment: 0.01556// @User: Standard557AP_GROUPINFO("_BAL_LIM_TC", 14, AR_AttitudeControl, _pitch_limit_tc, AR_ATTCONTROL_PITCH_LIM_TC),558559// @Param: _BAL_LIM_THR560// @DisplayName: Pitch control limit throttle threshold561// @Description: Pitch control limit throttle threshold. Pitch angle will be limited if throttle crosses this threshold (from 0 to 1)562// @Range: 0.0 1.0563// @Increment: 0.01564// @User: Standard565AP_GROUPINFO("_BAL_LIM_THR", 15, AR_AttitudeControl, _pitch_limit_throttle_thresh, AR_ATTCONTROL_PITCH_LIM_THR_THRESH),566567// @Param: _STR_DEC_MAX568// @DisplayName: Steering control angular deceleration maximum569// @Description: Steering control angular deceleration maximum (in deg/s/s). 0 to disable deceleration limiting570// @Range: 0 1000571// @Increment: 0.1572// @Units: deg/s/s573// @User: Standard574AP_GROUPINFO("_STR_DEC_MAX", 16, AR_AttitudeControl, _steer_decel_max, AR_ATTCONTROL_STEER_DECEL_MAX),575576AP_GROUPEND577};578579AR_AttitudeControl::AR_AttitudeControl() :580_steer_angle_p(AR_ATTCONTROL_STEER_ANG_P),581_steer_rate_pid(AR_ATTCONTROL_STEER_RATE_P, AR_ATTCONTROL_STEER_RATE_I, AR_ATTCONTROL_STEER_RATE_D, AR_ATTCONTROL_STEER_RATE_FF, AR_ATTCONTROL_STEER_RATE_IMAX, 0.0f, AR_ATTCONTROL_STEER_RATE_FILT, 0.0f),582_throttle_speed_pid(AR_ATTCONTROL_THR_SPEED_P, AR_ATTCONTROL_THR_SPEED_I, AR_ATTCONTROL_THR_SPEED_D, 0.0f, AR_ATTCONTROL_THR_SPEED_IMAX, 0.0f, AR_ATTCONTROL_THR_SPEED_FILT, 0.0f),583_pitch_to_throttle_pid(AR_ATTCONTROL_PITCH_THR_P, AR_ATTCONTROL_PITCH_THR_I, AR_ATTCONTROL_PITCH_THR_D, 0.0f, AR_ATTCONTROL_PITCH_THR_IMAX, 0.0f, AR_ATTCONTROL_PITCH_THR_FILT, 0.0f),584_sailboat_heel_pid(AR_ATTCONTROL_HEEL_SAIL_P, AR_ATTCONTROL_HEEL_SAIL_I, AR_ATTCONTROL_HEEL_SAIL_D, 0.0f, AR_ATTCONTROL_HEEL_SAIL_IMAX, 0.0f, AR_ATTCONTROL_HEEL_SAIL_FILT, 0.0f)585{586_singleton = this;587AP_Param::setup_object_defaults(this, var_info);588}589590// return a steering servo output from -1.0 to +1.0 given a desired lateral acceleration rate in m/s/s.591// positive lateral acceleration is to the right.592float AR_AttitudeControl::get_steering_out_lat_accel(float desired_accel, bool motor_limit_left, bool motor_limit_right, float dt)593{594// record desired accel for reporting purposes595_steer_lat_accel_last_ms = AP_HAL::millis();596_desired_lat_accel = desired_accel;597598// get speed forward599float speed;600if (!get_forward_speed(speed)) {601// we expect caller will not try to control heading using rate control without a valid speed estimate602// on failure to get speed we do not attempt to steer603return 0.0f;604}605606const float desired_rate = get_turn_rate_from_lat_accel(desired_accel, speed);607608return get_steering_out_rate(desired_rate, motor_limit_left, motor_limit_right, dt);609}610611// return a steering servo output from -1 to +1 given a heading in radians612// set rate_max_rads to a non-zero number to apply a limit on the desired turn rate613// return value is normally in range -1.0 to +1.0 but can be higher or lower614float AR_AttitudeControl::get_steering_out_heading(float heading_rad, float rate_max_rads, bool motor_limit_left, bool motor_limit_right, float dt)615{616// calculate the desired turn rate (in radians) from the angle error (also in radians)617float desired_rate = get_turn_rate_from_heading(heading_rad, rate_max_rads);618619return get_steering_out_rate(desired_rate, motor_limit_left, motor_limit_right, dt);620}621622// return a desired turn-rate given a desired heading in radians623float AR_AttitudeControl::get_turn_rate_from_heading(float heading_rad, float rate_max_rads) const624{625const float yaw_error = wrap_PI(heading_rad - AP::ahrs().get_yaw_rad());626627// Calculate the desired turn rate (in radians) from the angle error (also in radians)628float desired_rate = _steer_angle_p.get_p(yaw_error);629630// limit desired_rate if a custom pivot turn rate is selected, otherwise use ATC_STR_RAT_MAX631if (is_positive(rate_max_rads)) {632desired_rate = constrain_float(desired_rate, -rate_max_rads, rate_max_rads);633}634635// if deceleration limit is provided, ensure rate can be slowed to zero in time to stop at heading_rad (i.e. avoid overshoot)636if (is_positive(_steer_decel_max)) {637const float steer_decel_rate_max_rads = safe_sqrt(2.0 * fabsf(yaw_error) * radians(_steer_decel_max));638desired_rate = constrain_float(desired_rate, -steer_decel_rate_max_rads, steer_decel_rate_max_rads);639} else if (is_positive(_steer_accel_max)) {640// if no deceleration limit, use acceleration limit641const float steer_accel_rate_max_rads = safe_sqrt(2.0 * fabsf(yaw_error) * radians(_steer_accel_max));642desired_rate = constrain_float(desired_rate, -steer_accel_rate_max_rads, steer_accel_rate_max_rads);643}644645return desired_rate;646}647648// return a steering servo output given a desired yaw rate in radians/sec.649// positive yaw is to the right650// return value is normally in range -1.0 to +1.0 but can be higher or lower651// also sets steering_limit_left and steering_limit_right flags652float AR_AttitudeControl::get_steering_out_rate(float desired_rate, bool motor_limit_left, bool motor_limit_right, float dt)653{654// sanity check dt655dt = constrain_float(dt, 0.0f, 1.0f);656657// update steering limit flags used by higher level controllers (e.g. position controller)658_steering_limit_left = motor_limit_left;659_steering_limit_right = motor_limit_right;660661// if not called recently, reset input filter and desired turn rate to actual turn rate (used for accel limiting)662const uint32_t now = AP_HAL::millis();663if ((_steer_turn_last_ms == 0) || ((now - _steer_turn_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {664_steer_rate_pid.reset_filter();665_steer_rate_pid.reset_I();666_desired_turn_rate = AP::ahrs().get_yaw_rate_earth();667}668_steer_turn_last_ms = now;669670// acceleration limit desired turn rate671if (is_positive(_steer_accel_max)) {672const float change_max = radians(_steer_accel_max) * dt;673if (desired_rate <= _desired_turn_rate - change_max) {674_steering_limit_left = true;675}676if (desired_rate >= _desired_turn_rate + change_max) {677_steering_limit_right = true;678}679desired_rate = constrain_float(desired_rate, _desired_turn_rate - change_max, _desired_turn_rate + change_max);680}681_desired_turn_rate = desired_rate;682683// rate limit desired turn rate684if (is_positive(_steer_rate_max)) {685const float steer_rate_max_rad = radians(_steer_rate_max);686if (_desired_turn_rate <= -steer_rate_max_rad) {687_steering_limit_left = true;688}689if (_desired_turn_rate >= steer_rate_max_rad) {690_steering_limit_right = true;691}692_desired_turn_rate = constrain_float(_desired_turn_rate, -steer_rate_max_rad, steer_rate_max_rad);693}694695// G limit based on speed696float speed;697if (get_forward_speed(speed)) {698// do not limit to less than 1 deg/s699const float turn_rate_max = MAX(get_turn_rate_from_lat_accel(get_turn_lat_accel_max(), fabsf(speed)), radians(1.0f));700if (_desired_turn_rate <= -turn_rate_max) {701_steering_limit_left = true;702}703if (_desired_turn_rate >= turn_rate_max) {704_steering_limit_right = true;705}706_desired_turn_rate = constrain_float(_desired_turn_rate, -turn_rate_max, turn_rate_max);707}708709// update pid to calculate output to motors710float output = _steer_rate_pid.update_all(_desired_turn_rate, AP::ahrs().get_yaw_rate_earth(), dt, (motor_limit_left || motor_limit_right));711output += _steer_rate_pid.get_ff();712// constrain and return final output713return output;714}715716// get latest desired turn rate in rad/sec (recorded during calls to get_steering_out_rate)717float AR_AttitudeControl::get_desired_turn_rate() const718{719// return zero if no recent calls to turn rate controller720if ((_steer_turn_last_ms == 0) || ((AP_HAL::millis() - _steer_turn_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {721return 0.0f;722}723return _desired_turn_rate;724}725726// get latest desired lateral acceleration in m/s/s (recorded during calls to get_steering_out_lat_accel)727float AR_AttitudeControl::get_desired_lat_accel() const728{729// return zero if no recent calls to lateral acceleration controller730if ((_steer_lat_accel_last_ms == 0) || ((AP_HAL::millis() - _steer_lat_accel_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {731return 0.0f;732}733return _desired_lat_accel;734}735736// get actual lateral acceleration in m/s/s. returns true on success737bool AR_AttitudeControl::get_lat_accel(float &lat_accel) const738{739float speed;740if (!get_forward_speed(speed)) {741return false;742}743lat_accel = speed * AP::ahrs().get_yaw_rate_earth();744return true;745}746747// calculate the turn rate in rad/sec given a lateral acceleration (in m/s/s) and speed (in m/s)748float AR_AttitudeControl::get_turn_rate_from_lat_accel(float lat_accel, float speed) const749{750// enforce minimum speed to stop oscillations when first starting to move751if (fabsf(speed) < AR_ATTCONTROL_STEER_SPEED_MIN) {752if (is_negative(speed)) {753speed = -AR_ATTCONTROL_STEER_SPEED_MIN;754} else {755speed = AR_ATTCONTROL_STEER_SPEED_MIN;756}757}758759return lat_accel / speed;760}761762// return a throttle output from -1 to +1 given a desired speed in m/s (use negative speeds to travel backwards)763// motor_limit should be true if motors have hit their upper or lower limits764// cruise speed should be in m/s, cruise throttle should be a number from -1 to +1765float AR_AttitudeControl::get_throttle_out_speed(float desired_speed, bool motor_limit_low, bool motor_limit_high, float cruise_speed, float cruise_throttle, float dt)766{767// sanity check dt768dt = constrain_float(dt, 0.0f, 1.0f);769770// get speed forward771float speed;772if (!get_forward_speed(speed)) {773// we expect caller will not try to control heading using rate control without a valid speed estimate774// on failure to get speed we do not attempt to steer775return 0.0f;776}777778// if not called recently, reset input filter and desired speed to actual speed (used for accel limiting)779if (!speed_control_active()) {780_throttle_speed_pid.reset_filter();781_throttle_speed_pid.reset_I();782_desired_speed = speed;783}784_speed_last_ms = AP_HAL::millis();785786// acceleration limit desired speed787_desired_speed = get_desired_speed_accel_limited(desired_speed, dt);788789// calculate base throttle (protect against divide by zero)790float throttle_base = 0.0f;791if (is_positive(cruise_speed) && is_positive(cruise_throttle)) {792throttle_base = _desired_speed * (cruise_throttle / cruise_speed);793}794795// calculate final output796float throttle_out = _throttle_speed_pid.update_all(_desired_speed, speed, dt, (motor_limit_low || motor_limit_high || _throttle_limit_low || _throttle_limit_high));797throttle_out += _throttle_speed_pid.get_ff();798throttle_out += throttle_base;799800// update PID info for reporting purposes801_throttle_speed_pid_info = _throttle_speed_pid.get_pid_info();802_throttle_speed_pid_info.FF += throttle_base;803804// clear local limit flags used to stop i-term build-up as we stop reversed outputs going to motors805_throttle_limit_low = false;806_throttle_limit_high = false;807808// protect against reverse output being sent to the motors unless braking has been enabled809if (!_brake_enable) {810// if both desired speed and actual speed are positive, do not allow negative values811if ((_desired_speed >= 0.0f) && (throttle_out <= 0.0f)) {812throttle_out = 0.0f;813_throttle_limit_low = true;814} else if ((_desired_speed <= 0.0f) && (throttle_out >= 0.0f)) {815throttle_out = 0.0f;816_throttle_limit_high = true;817}818}819820// final output throttle in range -1 to 1821return throttle_out;822}823824// return a throttle output from -1 to +1 to perform a controlled stop. returns true once the vehicle has stopped825float AR_AttitudeControl::get_throttle_out_stop(bool motor_limit_low, bool motor_limit_high, float cruise_speed, float cruise_throttle, float dt, bool &stopped)826{827// get current system time828const uint32_t now = AP_HAL::millis();829830// if we were stopped in the last 300ms, assume we are still stopped831bool _stopped = (_stop_last_ms != 0) && (now - _stop_last_ms) < 300;832833// get deceleration limited speed834float desired_speed_limited = get_desired_speed_accel_limited(0.0f, dt);835836// get speed forward837float speed;838if (!get_forward_speed(speed)) {839// could not get speed so assume stopped840_stopped = true;841} else {842// if desired speed is zero and vehicle drops below _stop_speed consider it stopped843if (is_zero(desired_speed_limited) && fabsf(speed) <= fabsf(_stop_speed)) {844_stopped = true;845}846}847848// set stopped status for caller849stopped = _stopped;850851// if stopped return zero852if (stopped) {853// update last time we thought we were stopped854_stop_last_ms = now;855// set last time speed controller was run so accelerations are limited856_speed_last_ms = now;857// reset filters and I-term858_throttle_speed_pid.reset_filter();859_throttle_speed_pid.reset_I();860// ensure desired speed is zero861_desired_speed = 0.0f;862return 0.0f;863}864865// clear stopped system time866_stop_last_ms = 0;867// run speed controller to bring vehicle to stop868return get_throttle_out_speed(desired_speed_limited, motor_limit_low, motor_limit_high, cruise_speed, cruise_throttle, dt);869}870871// balancebot pitch to throttle controller872// returns a throttle output from -1 to +1 given a desired pitch angle (in radians)873// pitch_max should be the user defined max pitch angle (in radians)874// motor_limit should be true if the motors have hit their upper or lower limit875float AR_AttitudeControl::get_throttle_out_from_pitch(float desired_pitch, float pitch_max, bool motor_limit, float dt)876{877// sanity check dt878dt = constrain_float(dt, 0.0f, 1.0f);879880// if not called recently, reset input filter881const uint32_t now = AP_HAL::millis();882if ((_balance_last_ms == 0) || ((now - _balance_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {883_pitch_to_throttle_pid.reset_filter();884_pitch_to_throttle_pid.reset_I();885_pitch_limit_low = -pitch_max;886_pitch_limit_high = pitch_max;887}888_balance_last_ms = now;889890// limit desired pitch to protect against falling891const bool pitch_limit_active = (_pitch_limit_tc >= 0.01) && (_pitch_limit_throttle_thresh > 0);892if (pitch_limit_active) {893desired_pitch = constrain_float(desired_pitch, _pitch_limit_low, _pitch_limit_high);894_pitch_limited = (desired_pitch <= _pitch_limit_low || desired_pitch >= _pitch_limit_high);895} else {896_pitch_limited = false;897}898899// initialise output to feed forward from current pitch angle900const float pitch_rad = AP::ahrs().get_pitch_rad();901float output = sinf(pitch_rad) * _pitch_to_throttle_ff;902903// add regular PID control904output += _pitch_to_throttle_pid.update_all(desired_pitch, pitch_rad, dt, motor_limit);905output += _pitch_to_throttle_pid.get_ff();906907// update pitch limits for next iteration908// note: pitch is positive when leaning backwards, negative when leaning forward909if (pitch_limit_active) {910const float pitch_limit_incr = 1.0/_pitch_limit_tc * dt * pitch_max;911const float pitch_relax_incr = pitch_limit_incr * AR_ATTCONTROL_PITCH_RELAX_RATIO;912if (output <= -_pitch_limit_throttle_thresh) {913// very low negative throttle output means we must lower pitch_high (e.g. reduce leaning backwards)914_pitch_limit_high = MAX(_pitch_limit_high - pitch_limit_incr, 0);915} else {916_pitch_limit_high = MIN(_pitch_limit_high + pitch_relax_incr, pitch_max);917}918if (output >= _pitch_limit_throttle_thresh) {919// very high positive throttle output means we must raise pitch_low (reduce leaning forwards)920_pitch_limit_low = MIN(_pitch_limit_low + pitch_limit_incr, 0);921} else {922_pitch_limit_low = MAX(_pitch_limit_low - pitch_relax_incr, -pitch_max);923}924}925926// constrain and return final output927return output;928}929930// get latest desired pitch in radians for reporting purposes931float AR_AttitudeControl::get_desired_pitch() const932{933// if not called recently, return 0934if ((_balance_last_ms == 0) || ((AP_HAL::millis() - _balance_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {935return 0.0f;936}937938return _pitch_to_throttle_pid.get_pid_info().target;939}940941// Sailboat heel(roll) angle controller releases sail to keep at maximum heel angle942// but does not attempt to reach maximum heel angle, ie only lets sails out, does not pull them in943float AR_AttitudeControl::get_sail_out_from_heel(float desired_heel, float dt)944{945// sanity check dt946dt = constrain_float(dt, 0.0f, 1.0f);947948// if not called recently, reset input filter949const uint32_t now = AP_HAL::millis();950if ((_heel_controller_last_ms == 0) || ((now - _heel_controller_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {951_sailboat_heel_pid.reset_filter();952_sailboat_heel_pid.reset_I();953}954_heel_controller_last_ms = now;955956_sailboat_heel_pid.update_all(desired_heel, fabsf(AP::ahrs().get_roll_rad()), dt);957958// get feed-forward959const float ff = _sailboat_heel_pid.get_ff();960961// get p, constrain to be zero or negative962float p = _sailboat_heel_pid.get_p();963if (is_positive(p)) {964p = 0.0f;965}966967// get i, constrain to be zero or negative968float i = _sailboat_heel_pid.get_i();969if (is_positive(i)) {970i = 0.0f;971_sailboat_heel_pid.reset_I();972}973974// get d975const float d = _sailboat_heel_pid.get_d();976977// constrain and return final output978return (ff + p + i + d) * -1.0f;979}980981// get the slew rate value for speed and steering for oscillation detection in lua scripts982void AR_AttitudeControl::get_srate(float &steering_srate, float &speed_srate)983{984steering_srate = get_steering_rate_pid().get_pid_info().slew_rate;985speed_srate = _throttle_speed_pid_info.slew_rate;986}987988// get forward speed in m/s (earth-frame horizontal velocity but only along vehicle x-axis). returns true on success989bool AR_AttitudeControl::get_forward_speed(float &speed) const990{991Vector3f velocity;992const AP_AHRS &_ahrs = AP::ahrs();993if (!_ahrs.get_velocity_NED(velocity)) {994// use less accurate GPS, assuming entire length is along forward/back axis of vehicle995if (AP::gps().status() >= AP_GPS::GPS_OK_FIX_3D) {996if (abs(wrap_180_cd(_ahrs.yaw_sensor - AP::gps().ground_course_cd())) <= 9000) {997speed = AP::gps().ground_speed();998} else {999speed = -AP::gps().ground_speed();1000}1001return true;1002} else {1003return false;1004}1005}1006// calculate forward speed velocity into body frame1007speed = velocity.x*_ahrs.cos_yaw() + velocity.y*_ahrs.sin_yaw();1008return true;1009}10101011float AR_AttitudeControl::get_decel_max() const1012{1013if (is_positive(_throttle_decel_max)) {1014return _throttle_decel_max;1015} else {1016return _throttle_accel_max;1017}1018}10191020// check if speed controller active1021bool AR_AttitudeControl::speed_control_active() const1022{1023// active if there have been recent calls to speed controller1024if ((_speed_last_ms == 0) || ((AP_HAL::millis() - _speed_last_ms) > AR_ATTCONTROL_TIMEOUT_MS)) {1025return false;1026}1027return true;1028}10291030// get latest desired speed recorded during call to get_throttle_out_speed. For reporting purposes only1031float AR_AttitudeControl::get_desired_speed() const1032{1033// return zero if no recent calls to speed controller1034if (!speed_control_active()) {1035return 0.0f;1036}1037return _desired_speed;1038}10391040// get acceleration limited desired speed1041float AR_AttitudeControl::get_desired_speed_accel_limited(float desired_speed, float dt) const1042{1043// return input value if no recent calls to speed controller1044// apply no limiting when ATC_ACCEL_MAX is set to zero1045if (!speed_control_active() || !is_positive(_throttle_accel_max)) {1046return desired_speed;1047}10481049// sanity check dt1050dt = constrain_float(dt, 0.0f, 1.0f);10511052// use previous desired speed as basis for accel limiting1053float speed_prev = _desired_speed;10541055// if no recent calls to speed controller limit based on current speed1056if (!speed_control_active()) {1057get_forward_speed(speed_prev);1058}10591060// acceleration limit desired speed1061float speed_change_max;1062if (fabsf(desired_speed) < fabsf(_desired_speed) && is_positive(_throttle_decel_max)) {1063speed_change_max = _throttle_decel_max * dt;1064} else {1065speed_change_max = _throttle_accel_max * dt;1066}1067return constrain_float(desired_speed, speed_prev - speed_change_max, speed_prev + speed_change_max);1068}10691070// get minimum stopping distance (in meters) given a speed (in m/s)1071float AR_AttitudeControl::get_stopping_distance(float speed) const1072{1073// get maximum vehicle deceleration1074const float decel_max = get_decel_max();10751076if ((decel_max <= 0.0f) || is_zero(speed)) {1077return 0.0f;1078}10791080// assume linear deceleration1081return 0.5f * sq(speed) / decel_max;1082}10831084// relax I terms of throttle and steering controllers1085void AR_AttitudeControl::relax_I()1086{1087_steer_rate_pid.reset_I();1088_throttle_speed_pid.reset_I();1089_pitch_to_throttle_pid.reset_I();1090}10911092void AR_AttitudeControl::set_notch_sample_rate(float sample_rate)1093{1094#if AP_FILTER_ENABLED1095_steer_rate_pid.set_notch_sample_rate(sample_rate);1096_throttle_speed_pid.set_notch_sample_rate(sample_rate);1097_pitch_to_throttle_pid.set_notch_sample_rate(sample_rate);1098#endif1099}110011011102