Overte C++ Documentation
PIDController.h
1 //
2 // PIDController.h
3 // libraries/shared/src
4 //
5 // Given a measure of system performance (such as frame rate, where bigger denotes more system work),
6 // compute a value that the system can take as input to control the amount of work done (such as an 1/LOD-distance,
7 // where bigger tends to give a higher measured system performance value). The controller's job is to compute a
8 // controlled value such that the measured value stays near the specified setpoint, even as system load changes.
9 // See http://www.wetmachine.com/inventing-the-future/mostly-reliable-performance-of-software-processes-by-dynamic-control-of-quality-parameters/
10 //
11 // Created by Howard Stearns 11/13/15.
12 // Copyright 2015 High Fidelity, Inc.
13 //
14 // Distributed under the Apache License, Version 2.0.
15 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
16 //
17 
18 #ifndef hifi_PIDController_h
19 #define hifi_PIDController_h
20 
21 #include <limits>
22 #include <QVector>
23 
24 // Although our coding standard shuns abbreviations, the control systems literature uniformly uses p, i, d, and dt rather than
25 // proportionalTerm, integralTerm, derivativeTerm, and deltaTime. Here we will be consistent with the literature.
26 class PIDController {
27 
28 public:
29  // These are the main interfaces:
30  void setMeasuredValueSetpoint(float newValue) { _measuredValueSetpoint = newValue; }
31  float update(float measuredValue, float dt, bool resetAccumulator = false); // returns the new computedValue
32  void setHistorySize(QString label = QString(""), int size = 0) { _history.reserve(size); _history.resize(0); _label = label; } // non-empty does logging
33 
34  bool getIsLogging() { return !_label.isEmpty(); }
35  float getMeasuredValueSetpoint() const { return _measuredValueSetpoint; }
36  // In normal operation (where we can easily reach setpoint), controlledValue is typcially pinned at max.
37  // Defaults to [0, max float], but for 1/LODdistance, it might be, say, [0, 0.2 or 0.1]
38  float getControlledValueLowLimit() const { return _controlledValueLowLimit; }
39  float getControlledValueHighLimit() const { return _controlledValueHighLimit; }
40  float getAntiWindupFactor() const { return _antiWindupFactor; } // default 10
41  float getKP() const { return _kp; } // proportional to error. See comment above class.
42  float getKI() const { return _ki; } // to time integral of error
43  float getKD() const { return _kd; } // to time derivative of error
44  float getAccumulatedValueHighLimit() const { return getAntiWindupFactor() * getMeasuredValueSetpoint(); }
45  float getAccumulatedValueLowLimit() const { return -getAntiWindupFactor() * getMeasuredValueSetpoint(); }
46 
47  // There are several values that rarely change and might be thought of as "constants", but which do change during tuning, debugging, or other
48  // special-but-expected circumstances. Thus the instance vars are not const.
49  void setControlledValueLowLimit(float newValue) { _controlledValueLowLimit = newValue; }
50  void setControlledValueHighLimit(float newValue) { _controlledValueHighLimit = newValue; }
51  void setAntiWindupFactor(float newValue) { _antiWindupFactor = newValue; }
52  void setKP(float newValue) { _kp = newValue; }
53  void setKI(float newValue) { _ki = newValue; }
54  void setKD(float newValue) { _kd = newValue; }
55 
56  class Row { // one row of accumulated history, used only for logging (if at all)
57  public:
58  float measured;
59  float dt;
60  float error;
61  float accumulated;
62  float changed;
63  float p;
64  float i;
65  float d;
66  float computed;
67  };
68 protected:
69  void reportHistory();
70  void updateHistory(float measured, float dt, float error, float accumulatedError, float changeInErro, float p, float i, float d, float computedValue);
71  float _measuredValueSetpoint { 0.0f };
72  float _controlledValueLowLimit { 0.0f };
73  float _controlledValueHighLimit { std::numeric_limits<float>::max() };
74  float _antiWindupFactor { 10.0f };
75  float _kp { 0.0f };
76  float _ki { 0.0f };
77  float _kd { 0.0f };
78 
79  // Controller operating state
80  float _lastError{ 0.0f };
81  float _lastAccumulation{ 0.0f };
82 
83  // reporting
84  QVector<Row> _history{};
85  QString _label{ "" };
86 
87 };
88 
89 #endif // hifi_PIDController_h