-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpid_control.py
99 lines (58 loc) · 2.15 KB
/
pid_control.py
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
import numpy as np
class BasePID:
def __init__(self, kp, ki, kd, ts, limit):
self.kp = kp
self.ki = ki
self.kd = kd
self.ts = ts
self.limit = limit
self.e_delay = 0.0
self.integrator = 0.0
def update(self, *args):
raise NotImplementedError('BasePID::update()')
def _saturate(self, u):
if u >= self.limit:
u_sat = self.limit
elif u <= -self.limit:
u_sat = -self.limit
else:
u_sat = u
return u_sat
class PIDControl(BasePID):
def __init__(self, kp=0.0, ki=0.0, kd=0.0, ts=0.01, sigma=0.05, limit=1.0):
super().__init__(kp=kp, ki=ki, kd=kd, ts=ts, limit=limit)
self.edot_delay = 0.0
self.a1 = (2.0 * sigma - ts) / (2.0 * sigma + ts)
self.a2 = 2.0 / (2.0 * sigma + ts)
def update(self, y_ref, y):
error = y_ref - y
self.integrator += (self.ts / 2) * (error + self.e_delay)
edot = self.a1 + self.edot_delay + self.a2 * (error - self.e_delay)
u = (self.kp * error
+ self.ki * self.integrator
+ self.kd * edot)
u_sat = self._saturate(u)
if np.abs(self.ki) > 0.0001:
self.integrator += (self.ts / self.ki) * (u_sat - u)
self.e_delay = error
return u_sat
class PIControl(BasePID):
def __init__(self, kp=0.0, ki=0.0, ts=0.01, limit=1.0):
super().__init__(kp=kp, ki=ki, kd=0, ts=ts, limit=limit)
def update(self, y_ref, y):
error = y_ref - y
self.integrator += (self.ts / 2) * (error + self.e_delay)
u = self.kp * error + self.ki * self.integrator
u_sat = self._saturate(u)
if np.abs(self.ki) > 0.0001:
self.integrator += (self.ts / self.ki) * (u_sat - u)
self.e_delay = error
return u_sat
class PDControlRate(BasePID):
def __init__(self, kp=0.0, kd=0.0, limit=1.0):
super().__init__(kp=kp, ki=0, kd=kd, ts=0, limit=limit)
def update(self, y_ref, y, ydot):
error = y_ref - y
u = self.kp * error - self.kd * ydot
u_sat = self._saturate(u)
return u_sat