tarask
6 days ago 532005c6573d95199ce0ffbc33df4c7a0a4c3ef9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "AC_PID_Basic.h"
 
 
 
// Constructor
AC_PID_Basic::AC_PID_Basic(float initial_p, float initial_i, float initial_d, float initial_ff, float initial_imax, float initial_filt_E_hz, float initial_filt_D_hz)
{
    // load parameter values from eeprom
 
 
    _kp=(initial_p);
    _ki=(initial_i);
    _kd=(initial_d);
    _kff=(initial_ff);
    _kimax=(initial_imax);
    _filt_E_hz=(initial_filt_E_hz);
    _filt_D_hz=(initial_filt_D_hz);
 
    // reset input filter to first value received
    _reset_filter = true;
    _error=0;
}
 
float AC_PID_Basic::update_all(float target, float measurement, float dt, bool limit)
{
    return update_all(target, measurement, dt, (limit && is_negative(_integrator)), (limit && is_positive(_integrator)));
}
 
//  update_all - set target and measured inputs to PID controller and calculate outputs
//  target and error are filtered
//  the derivative is then calculated and filtered
//  the integral is then updated based on the setting of the limit flag
float AC_PID_Basic::update_all(float target, float measurement, float dt, bool limit_neg, bool limit_pos)
{
    // don't process inf or NaN
    /*if (!isfinite(target) || isnan(target) ||
        !isfinite(measurement) || isnan(measurement)) {
        INTERNAL_ERROR(AP_InternalError::error_t::invalid_arg_or_result);
        return 0.0f;
    }*/
 
    
    if(target<0)
        target+=2*M_PI;
    if(measurement<0)
        measurement+=2*M_PI;    
    _error=target-measurement;
    _target = target;
    float error_last = _error;
    if(_error>(M_PI+2.0*M_PI/180.0))
        _error=-2*M_PI+_error;
    if(_error<(-M_PI-2.0*M_PI/180.0))
            _error=2*M_PI+_error;
   _error*=180.0/M_PI;
    // reset input filter to value received
    if (_reset_filter) {
        _reset_filter = false;
        error_last=_error;
        //_error = _target - measurement;
        _derivative = 0.0f;
    } else {
        
        _error += get_filt_E_alpha(dt) * (_error - error_last);
 
        // calculate and filter derivative
        if (is_positive(dt)) {
            float derivative = (_error - error_last) / dt;
            _derivative += get_filt_D_alpha(dt) * (derivative - _derivative);
        }
    }
 
    // update I term
    update_i(dt, limit_neg, limit_pos);
 
    const float P_out = _error * _kp;
    const float D_out = _derivative * _kd;
 
    float out=P_out + _integrator + D_out + _target * _kff;
    if(out>45.0f)
        out=45.0f;
    if(out<-45.0f)
        out=-45.0f;    
    return out;
}
 
//  update_i - update the integral
//  if limit_neg is true, the integral can only increase
//  if limit_pos is true, the integral can only decrease
void AC_PID_Basic::update_i(float dt, bool limit_neg, bool limit_pos)
{
    if (!is_zero(_ki)) {
        // Ensure that integrator can only be reduced if the output is saturated
        if (!((limit_neg && is_negative(_error)) || (limit_pos && is_positive(_error)))) {
            _integrator += ((float)_error * _ki) * dt;
            _integrator = constrain_float(_integrator, -_kimax, _kimax);
        }
    } else {
        _integrator = 0.0f;
    }
}
 
void AC_PID_Basic::reset_I()
{
    _integrator = 0.0; 
 
}
 
 
// get_filt_T_alpha - get the target filter alpha
float AC_PID_Basic::get_filt_E_alpha(float dt)
{
    return calc_lowpass_alpha_dt(dt, _filt_E_hz);
}
 
// get_filt_D_alpha - get the derivative filter alpha
float AC_PID_Basic::get_filt_D_alpha(float dt)
{
    return calc_lowpass_alpha_dt(dt, _filt_D_hz);
}
 
void AC_PID_Basic::set_integrator(float target, float measurement, float i)
{
    set_integrator(target - measurement, i);
}
 
void AC_PID_Basic::set_integrator(float error, float i)
{
    set_integrator(i - error * _kp);
}
 
void AC_PID_Basic::set_integrator(float i)
{
    _integrator = constrain_float(i, -_kimax, _kimax);
 
}
 
float AC_PID_Basic::calc_lowpass_alpha_dt(float dt, float cutoff_freq)
{
    if (is_negative(dt) || is_negative(cutoff_freq)) {
 
        return 1.0;
    }
    if (is_zero(cutoff_freq)) {
        return 0.0;
    }
    if (is_zero(dt)) {
        return 0.0;
    }
    float rc = 1.0f / (M_2PI * cutoff_freq);
    return dt / (dt + rc);
}