Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AC_PID/AC_P_1D.cpp
9531 views
1
/// @file AC_P_1D.cpp
2
/// @brief Position-based P controller with optional limits on output and its first derivative.
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
// Computes the P controller output given a target and measurement.
24
// Applies position error clamping based on configured limits.
25
// Optionally constrains output slope using the sqrt_controller.
26
float AC_P_1D::update_all(postype_t &target, postype_t measurement)
27
{
28
// Compute position error between target and measurement
29
_error = (float)(target - measurement);
30
31
// Clamp error to configured min/max bounds
32
if (is_negative(_error_min) && (_error < _error_min)) {
33
_error = _error_min;
34
target = measurement + _error;
35
} else if (is_positive(_error_max) && (_error > _error_max)) {
36
_error = _error_max;
37
target = measurement + _error;
38
}
39
40
// Use sqrt_controller to limit output and/or its derivative
41
return sqrt_controller(_error, _kp, _D1_max, 0.0);
42
}
43
44
// Sets limits on output, output slope (D1), and output acceleration (D2).
45
// For position controllers: output = velocity, D1 = acceleration, D2 = jerk.
46
void AC_P_1D::set_limits(float output_min, float output_max, float D_Out_max, float D2_Out_max)
47
{
48
// Reset all limits to zero before applying new ones
49
_D1_max = 0.0f;
50
_error_min = 0.0f;
51
_error_max = 0.0f;
52
53
// Set first derivative (acceleration) limit if specified
54
if (is_positive(D_Out_max)) {
55
_D1_max = D_Out_max;
56
}
57
58
// If second derivative (jerk) limit is specified, constrain velocity limit accordingly
59
if (is_positive(D2_Out_max) && is_positive(_kp)) {
60
// limit the first derivative so as not to exceed the second derivative
61
_D1_max = MIN(_D1_max, D2_Out_max / _kp);
62
}
63
64
// Compute min/max allowable error from output limits
65
if (is_negative(output_min) && is_positive(_kp)) {
66
_error_min = inv_sqrt_controller(output_min, _kp, _D1_max);
67
}
68
if (is_positive(output_max) && is_positive(_kp)) {
69
_error_max = inv_sqrt_controller(output_max, _kp, _D1_max);
70
}
71
}
72
73
// Reduces error limits to user-specified bounds, respecting previously computed limits.
74
// Intended to be called after `set_limits()`.
75
void AC_P_1D::set_error_limits(float error_min, float error_max)
76
{
77
// Update _error_min if it's non-zero and the new value is more conservative
78
if (is_negative(error_min)) {
79
if (!is_zero(_error_min)) {
80
_error_min = MAX(_error_min, error_min);
81
} else {
82
_error_min = error_min;
83
}
84
}
85
86
// Update _error_max if it's non-zero and the new value is more conservative
87
if (is_positive(error_max)) {
88
if (!is_zero(_error_max)) {
89
_error_max = MIN(_error_max, error_max);
90
} else {
91
_error_max = error_max;
92
}
93
}
94
}
95
96