forked from Whiplash141/SpaceEngineersScripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPID.cs
More file actions
133 lines (110 loc) · 3.63 KB
/
Copy pathPID.cs
File metadata and controls
133 lines (110 loc) · 3.63 KB
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
#region PID Class
/// <summary>
/// Discrete time PID controller class.
/// Last edited: 2022/08/11 - Whiplash141
/// </summary>
public class PID
{
public double Kp { get; set; } = 0;
public double Ki { get; set; } = 0;
public double Kd { get; set; } = 0;
public double Value { get; private set; }
double _timeStep = 0;
double _inverseTimeStep = 0;
double _errorSum = 0;
double _lastError = 0;
bool _firstRun = true;
public PID(double kp, double ki, double kd, double timeStep)
{
Kp = kp;
Ki = ki;
Kd = kd;
_timeStep = timeStep;
_inverseTimeStep = 1 / _timeStep;
}
protected virtual double GetIntegral(double currentError, double errorSum, double timeStep)
{
return errorSum + currentError * timeStep;
}
public double Control(double error)
{
//Compute derivative term
double errorDerivative = (error - _lastError) * _inverseTimeStep;
if (_firstRun)
{
errorDerivative = 0;
_firstRun = false;
}
//Get error sum
_errorSum = GetIntegral(error, _errorSum, _timeStep);
//Store this error as last error
_lastError = error;
//Construct output
Value = Kp * error + Ki * _errorSum + Kd * errorDerivative;
return Value;
}
public double Control(double error, double timeStep)
{
if (timeStep != _timeStep)
{
_timeStep = timeStep;
_inverseTimeStep = 1 / _timeStep;
}
return Control(error);
}
public virtual void Reset()
{
_errorSum = 0;
_lastError = 0;
_firstRun = true;
}
}
public class DecayingIntegralPID : PID
{
public double IntegralDecayRatio { get; set; }
public DecayingIntegralPID(double kp, double ki, double kd, double timeStep, double decayRatio) : base(kp, ki, kd, timeStep)
{
IntegralDecayRatio = decayRatio;
}
protected override double GetIntegral(double currentError, double errorSum, double timeStep)
{
return errorSum * (1.0 - IntegralDecayRatio) + currentError * timeStep;
}
}
public class ClampedIntegralPID : PID
{
public double IntegralUpperBound { get; set; }
public double IntegralLowerBound { get; set; }
public ClampedIntegralPID(double kp, double ki, double kd, double timeStep, double lowerBound, double upperBound) : base(kp, ki, kd, timeStep)
{
IntegralUpperBound = upperBound;
IntegralLowerBound = lowerBound;
}
protected override double GetIntegral(double currentError, double errorSum, double timeStep)
{
errorSum = errorSum + currentError * timeStep;
return Math.Min(IntegralUpperBound, Math.Max(errorSum, IntegralLowerBound));
}
}
public class BufferedIntegralPID : PID
{
readonly Queue<double> _integralBuffer = new Queue<double>();
public int IntegralBufferSize { get; set; } = 0;
public BufferedIntegralPID(double kp, double ki, double kd, double timeStep, int bufferSize) : base(kp, ki, kd, timeStep)
{
IntegralBufferSize = bufferSize;
}
protected override double GetIntegral(double currentError, double errorSum, double timeStep)
{
if (_integralBuffer.Count == IntegralBufferSize)
_integralBuffer.Dequeue();
_integralBuffer.Enqueue(currentError * timeStep);
return _integralBuffer.Sum();
}
public override void Reset()
{
base.Reset();
_integralBuffer.Clear();
}
}
#endregion