/// @file AC_P_1D.cpp1/// @brief Position-based P controller with optional limits on output and its first derivative.23#include <AP_Math/AP_Math.h>4#include "AC_P_1D.h"56const AP_Param::GroupInfo AC_P_1D::var_info[] = {7// @Param: P8// @DisplayName: P 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_P_1D, _kp, default_kp),11AP_GROUPEND12};1314// Constructor15AC_P_1D::AC_P_1D(float initial_p) :16default_kp(initial_p)17{18// load parameter values from eeprom19AP_Param::setup_object_defaults(this, var_info);20}2122// Computes the P controller output given a target and measurement.23// Applies position error clamping based on configured limits.24// Optionally constrains output slope using the sqrt_controller.25float AC_P_1D::update_all(postype_t &target, postype_t measurement)26{27// Compute position error between target and measurement28_error = (float)(target - measurement);2930// Clamp error to configured min/max bounds31if (is_negative(_error_min) && (_error < _error_min)) {32_error = _error_min;33target = measurement + _error;34} else if (is_positive(_error_max) && (_error > _error_max)) {35_error = _error_max;36target = measurement + _error;37}3839// Use sqrt_controller to limit output and/or its derivative40return sqrt_controller(_error, _kp, _D1_max, 0.0);41}4243// Sets limits on output, output slope (D1), and output acceleration (D2).44// For position controllers: output = velocity, D1 = acceleration, D2 = jerk.45void AC_P_1D::set_limits(float output_min, float output_max, float D_Out_max, float D2_Out_max)46{47// Reset all limits to zero before applying new ones48_D1_max = 0.0f;49_error_min = 0.0f;50_error_max = 0.0f;5152// Set first derivative (acceleration) limit if specified53if (is_positive(D_Out_max)) {54_D1_max = D_Out_max;55}5657// If second derivative (jerk) limit is specified, constrain velocity limit accordingly58if (is_positive(D2_Out_max) && is_positive(_kp)) {59// limit the first derivative so as not to exceed the second derivative60_D1_max = MIN(_D1_max, D2_Out_max / _kp);61}6263// Compute min/max allowable error from output limits64if (is_negative(output_min) && is_positive(_kp)) {65_error_min = inv_sqrt_controller(output_min, _kp, _D1_max);66}67if (is_positive(output_max) && is_positive(_kp)) {68_error_max = inv_sqrt_controller(output_max, _kp, _D1_max);69}70}7172// Reduces error limits to user-specified bounds, respecting previously computed limits.73// Intended to be called after `set_limits()`.74void AC_P_1D::set_error_limits(float error_min, float error_max)75{76// Update _error_min if it's non-zero and the new value is more conservative77if (is_negative(error_min)) {78if (!is_zero(_error_min)) {79_error_min = MAX(_error_min, error_min);80} else {81_error_min = error_min;82}83}8485// Update _error_max if it's non-zero and the new value is more conservative86if (is_positive(error_max)) {87if (!is_zero(_error_max)) {88_error_max = MIN(_error_max, error_max);89} else {90_error_max = error_max;91}92}93}949596