tomlankhorst/control
pid.h
1 /*
2  * Classic P/PI/PID control
3  */
4 
5 #pragma once
6 
7 #include <limits>
8 #include <algorithm>
9 
10 #include "control/filter/biquad.h"
11 #include "control/system/type.h"
12 
13 namespace control::classic {
14 
20 template<typename T>
21 constexpr T max() {
22  return std::numeric_limits<T>::has_infinity
23  ? std::numeric_limits<T>::infinity() : std::numeric_limits<T>::max();
24 }
25 
30 template<typename T>
31 class AbstractController : public system::SISO<T> {
32  static_assert(std::numeric_limits<T>::is_signed, "Signed type required");
33  public:
38  explicit AbstractController(T Limit_ = max<T>()) : Limit(Limit_) {};
39 
40  virtual ~AbstractController() = default;
41 
42  // Limit
43  T Limit;
44 
45  // Clipping status
46  bool clipping = false;
47 
54  T step(T e) final {
55  T u;
56 
57  // Get the control effort
58  u = control(e);
59 
60  // Clip the output
61  u = clip(u);
62 
63  // Return the output
64  return u;
65  };
66 
72  void setLimit(T limit) {
73  Limit = limit;
74  }
75 
79  virtual void reset() {};
80 
81  protected:
82 
89  T clip(T u) {
90  if (Limit == std::numeric_limits<T>::infinity()) {
91  return u;
92  }
93 
94  // Determine if the signal is in range
95  if (!clipping && (u > Limit || u < -Limit)) {
96  clipping = true;
97  } else if (clipping && (u >= -Limit && u <= Limit)) {
98  clipping = false;
99  }
100 
101  // If limiting, then clip to min / max
102  if (clipping) {
103  u = std::max(-Limit, std::min(Limit, u));
104  }
105 
106  return u;
107  }
108 
115  virtual T control(T e) = 0;
116 
117 };
118 
122 template<typename T>
123 class P : public AbstractController<T> {
124  public:
125 
132  explicit P(T Kp_ = 1.0, T Limit_ = max<T>()) : AbstractController<T>(Limit_), Kp(Kp_) {};
133 
134  ~P() = default;;
135 
136  // Proportional gain
137  const T Kp;
138 
139  protected:
143  T control(T e) {
144  // The output of the controller
145  T u;
146 
147  // Proportional gain
148  u = Kp * e;
149 
150  return u;
151  };
152 };
153 
157 template<typename T>
158 class PID : public AbstractController<T> {
159  public:
160 
170  explicit PID(T Ts = 1.0, T Kp = 1.0, T Ti = max<T>(), T Td = 0.0, T N = max<T>(), T Limit = max<T>())
171  : AbstractController<T>(Limit), B(
172  (Kp * (4 * Td / N + 2 * Td * Ts / Ti / N + Ts * Ts / Ti + 4 * Td + 2 * Ts)) / (4 * Td / N + 2 * Ts),
173  -(Kp * (-Ts * Ts / Ti + 4 * Td / N + 4 * Td)) / (2 * Td / N + Ts),
174  (Kp * (4 * Td / N - 2 * Td * Ts / Ti / N + Ts * Ts / Ti + 4 * Td - 2 * Ts)) / (4 * Td / N + 2 * Ts),
175  -(4 * Td / N) / (2 * Td / N + Ts),
176  (2 * Td / N - Ts) / (2 * Td / N + Ts)
177  ) {};
178 
184  filter::TCS<T> poles() {
185  return B.poles();
186  }
187 
191  void reset() {
192  B.reset();
193  }
194 
195  protected:
196 
201 
205  T control(T e) {
206  return B.step(e);
207  }
208 
209 };
210 
214 template<typename T>
215 class PI : public PID<T> {
216  public:
217 
225  explicit PI(T Ts_ = 1, T Kp_ = 1, T Ti_ = max<T>(), T Limit_ = max<T>()) : PID<T>(Ts_, Kp_, Ti_, 0, max<T>(),
226  Limit_) {};
227 };
228 
232 template<typename T>
233 class PD : public PID<T> {
234  public:
235 
244  explicit PD(T Ts_ = 1, T Kp_ = 1, T Td_ = 0, T N_ = max<T>(), T Limit_ = max<T>()) : PID<T>(Ts_, Kp_, max<T>(), Td_,
245  N_, Limit_) {};
246 };
247 
248 }
249 
Definition: pid.h:13
Definition: pid.h:233
filter::Biquad< T > B
Definition: pid.h:200
P(T Kp_=1.0, T Limit_=max< T >())
Definition: pid.h:132
AbstractController(T Limit_=max< T >())
Definition: pid.h:38
PID(T Ts=1.0, T Kp=1.0, T Ti=max< T >(), T Td=0.0, T N=max< T >(), T Limit=max< T >())
Definition: pid.h:170
T control(T e)
Definition: pid.h:205
Definition: type.h:16
Definition: pid.h:158
filter::TCS< T > poles()
Definition: pid.h:184
Definition: pid.h:215
void setLimit(T limit)
Definition: pid.h:72
virtual void reset()
Definition: pid.h:79
T step(T e) final
Definition: pid.h:54
void reset()
Definition: pid.h:191
T control(T e)
Definition: pid.h:143
Definition: pid.h:123
PI(T Ts_=1, T Kp_=1, T Ti_=max< T >(), T Limit_=max< T >())
Definition: pid.h:225
T clip(T u)
Definition: pid.h:89
PD(T Ts_=1, T Kp_=1, T Td_=0, T N_=max< T >(), T Limit_=max< T >())
Definition: pid.h:244
T step(T x)
Definition: biquad.h:81