Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AC_PID/AC_PI_2D.cpp
Views: 1798
/// @file AC_PI_2D.cpp1/// @brief 2-axis PI controller23#include <AP_Math/AP_Math.h>4#include "AC_PI_2D.h"56const AP_Param::GroupInfo AC_PI_2D::var_info[] = {7// @Param: P8// @DisplayName: PI Proportional Gain9// @Description: P Gain which produces an output value that is proportional to the current error value10AP_GROUPINFO_FLAGS_DEFAULT_POINTER("P", 0, AC_PI_2D, _kp, default_kp),1112// @Param: I13// @DisplayName: PI Integral Gain14// @Description: I Gain which produces an output that is proportional to both the magnitude and the duration of the error15AP_GROUPINFO_FLAGS_DEFAULT_POINTER("I", 1, AC_PI_2D, _ki, default_ki),1617// @Param: IMAX18// @DisplayName: PI Integral Maximum19// @Description: The maximum/minimum value that the I term can output20AP_GROUPINFO_FLAGS_DEFAULT_POINTER("IMAX", 2, AC_PI_2D, _imax, default_imax),2122// @Param: FILT_HZ23// @DisplayName: PI Input filter frequency in Hz24// @Description: Input filter frequency in Hz25// @Units: Hz26AP_GROUPINFO_FLAGS_DEFAULT_POINTER("FILT_HZ", 3, AC_PI_2D, _filt_hz, default_filt_hz),2728AP_GROUPEND29};3031// Constructor32AC_PI_2D::AC_PI_2D(float initial_p, float initial_i, float initial_imax, float initial_filt_hz, float dt) :33_dt(dt),34default_kp(initial_p),35default_ki(initial_i),36default_imax(initial_imax),37default_filt_hz(initial_filt_hz)38{39// load parameter values from eeprom40AP_Param::setup_object_defaults(this, var_info);4142filt_hz(initial_filt_hz);4344// reset input filter to first value received45_flags._reset_filter = true;46}4748// set_dt - set time step in seconds49void AC_PI_2D::set_dt(float dt)50{51// set dt and calculate the input filter alpha52_dt = dt;53calc_filt_alpha();54}5556// filt_hz - set input filter hz57void AC_PI_2D::filt_hz(float hz)58{59_filt_hz.set(fabsf(hz));6061// sanity check _filt_hz62_filt_hz.set(MAX(_filt_hz, AC_PI_2D_FILT_HZ_MIN));6364// calculate the input filter alpha65calc_filt_alpha();66}6768// set_input - set input to PID controller69// input is filtered before the PID controllers are run70// this should be called before any other calls to get_p, get_i or get_d71void AC_PI_2D::set_input(const Vector2f &input)72{73// don't process inf or NaN74if (!isfinite(input.x) || !isfinite(input.y)) {75return;76}7778// reset input filter to value received79if (_flags._reset_filter) {80_flags._reset_filter = false;81_input = input;82}8384// update filter and calculate derivative85Vector2f input_filt_change = (input - _input) * _filt_alpha;86_input = _input + input_filt_change;87}8889Vector2f AC_PI_2D::get_p() const90{91return (_input * _kp);92}9394Vector2f AC_PI_2D::get_i()95{96if (!is_zero(_ki) && !is_zero(_dt)) {97_integrator += (_input * _ki) * _dt;98const float integrator_length = _integrator.length();99if ((integrator_length > _imax) && (is_positive(integrator_length))) {100_integrator *= (_imax / integrator_length);101}102return _integrator;103}104return Vector2f{};105}106107// get_i_shrink - get_i but do not allow integrator to grow in length (it may shrink)108Vector2f AC_PI_2D::get_i_shrink()109{110if (!is_zero(_ki) && !is_zero(_dt)) {111const float integrator_length_orig = MIN(_integrator.length(),_imax);112_integrator += (_input * _ki) * _dt;113const float integrator_length_new = _integrator.length();114if ((integrator_length_new > integrator_length_orig) && is_positive(integrator_length_new)) {115_integrator *= (integrator_length_orig / integrator_length_new);116}117return _integrator;118}119return Vector2f{};120}121122Vector2f AC_PI_2D::get_pi()123{124return get_p() + get_i();125}126127void AC_PI_2D::reset_I()128{129_integrator.zero();130}131132void AC_PI_2D::load_gains()133{134_kp.load();135_ki.load();136_imax.load();137_imax.set(fabsf(_imax));138_filt_hz.load();139140// calculate the input filter alpha141calc_filt_alpha();142}143144// save_gains - save gains to eeprom145void AC_PI_2D::save_gains()146{147_kp.save();148_ki.save();149_imax.save();150_filt_hz.save();151}152153// calc_filt_alpha - recalculate the input filter alpha154void AC_PI_2D::calc_filt_alpha()155{156if (is_zero(_filt_hz)) {157_filt_alpha = 1.0f;158return;159}160161// calculate alpha162const float rc = 1/(M_2PI*_filt_hz);163_filt_alpha = _dt / (_dt + rc);164}165166167