CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AC_PID/AC_P_1D.cpp
Views: 1798
1
/// @file AC_P_1D.cpp
2
/// @brief Generic P algorithm
3
4
#include <AP_Math/AP_Math.h>
5
#include "AC_P_1D.h"
6
7
const AP_Param::GroupInfo AC_P_1D::var_info[] = {
8
// @Param: P
9
// @DisplayName: P Proportional Gain
10
// @Description: P Gain which produces an output value that is proportional to the current error value
11
AP_GROUPINFO_FLAGS_DEFAULT_POINTER("P", 0, AC_P_1D, _kp, default_kp),
12
AP_GROUPEND
13
};
14
15
// Constructor
16
AC_P_1D::AC_P_1D(float initial_p) :
17
default_kp(initial_p)
18
{
19
// load parameter values from eeprom
20
AP_Param::setup_object_defaults(this, var_info);
21
}
22
23
// update_all - set target and measured inputs to P controller and calculate outputs
24
// target and measurement are filtered
25
float AC_P_1D::update_all(float &target, float measurement)
26
{
27
// calculate distance _error
28
_error = target - measurement;
29
30
if (is_negative(_error_min) && (_error < _error_min)) {
31
_error = _error_min;
32
target = measurement + _error;
33
} else if (is_positive(_error_max) && (_error > _error_max)) {
34
_error = _error_max;
35
target = measurement + _error;
36
}
37
38
// MIN(_Dxy_max, _D2xy_max / _kxy_P) limits the max accel to the point where max jerk is exceeded
39
return sqrt_controller(_error, _kp, _D1_max, 0.0);
40
}
41
42
// set_limits - sets the maximum error to limit output and first and second derivative of output
43
// when using for a position controller, lim_err will be position error, lim_out will be correction velocity, lim_D will be acceleration, lim_D2 will be jerk
44
void AC_P_1D::set_limits(float output_min, float output_max, float D_Out_max, float D2_Out_max)
45
{
46
_D1_max = 0.0f;
47
_error_min = 0.0f;
48
_error_max = 0.0f;
49
50
if (is_positive(D_Out_max)) {
51
_D1_max = D_Out_max;
52
}
53
54
if (is_positive(D2_Out_max) && is_positive(_kp)) {
55
// limit the first derivative so as not to exceed the second derivative
56
_D1_max = MIN(_D1_max, D2_Out_max / _kp);
57
}
58
59
if (is_negative(output_min) && is_positive(_kp)) {
60
_error_min = inv_sqrt_controller(output_min, _kp, _D1_max);
61
}
62
63
if (is_positive(output_max) && is_positive(_kp)) {
64
_error_max = inv_sqrt_controller(output_max, _kp, _D1_max);
65
}
66
}
67
68
// set_error_limits - reduce maximum error to error_max
69
// to be called after setting limits
70
void AC_P_1D::set_error_limits(float error_min, float error_max)
71
{
72
if (is_negative(error_min)) {
73
if (!is_zero(_error_min)) {
74
_error_min = MAX(_error_min, error_min);
75
} else {
76
_error_min = error_min;
77
}
78
}
79
80
if (is_positive(error_max)) {
81
if (!is_zero(_error_max)) {
82
_error_max = MIN(_error_max, error_max);
83
} else {
84
_error_max = error_max;
85
}
86
}
87
}
88
89