MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
PIDController.cpp
Go to the documentation of this file.
1 // PIDController.cpp ---
2 //
3 // Filename: PIDController.cpp
4 // Description:
5 // Author: subhasis ray
6 // Maintainer:
7 // Created: Tue Dec 30 23:36:01 2008 (+0530)
8 // Version:
9 // Last-Updated: Tue Jun 11 17:00:51 2013 (+0530)
10 // By: subha
11 // Update #: 338
12 // URL:
13 // Keywords:
14 // Compatibility:
15 //
16 //
17 
18 // Commentary:
19 //
20 //
21 //
22 //
23 
24 // Change log:
25 //
26 //
27 //
28 //
29 /**********************************************************************
30  ** This program is part of 'MOOSE', the
31  ** Messaging Object Oriented Simulation Environment,
32  ** also known as GENESIS 3 base code.
33  ** copyright (C) 2003-2013 Upinder S. Bhalla. and NCBS
34  ** It is made available under the terms of the
35  ** GNU Lesser General Public License version 2.1
36  ** See the file COPYING.LIB for the full notice.
37  **********************************************************************/
38 
39 // Code:
40 
41 #include <cfloat>
42 #include "PIDController.h"
43 
44 
46 {
47  static SrcFinfo1 <double> outputOut("output",
48  "Sends the output of the PIDController. This is known as manipulated"
49  " variable (MV) in control theory. This should be fed into the process"
50  " which we are trying to control.");
51  return &outputOut;
52 }
53 
55 {
56  static DestFinfo process( "process",
57  "Handle process calls.",
59  static DestFinfo reinit( "reinit",
60  "Reinitialize the object.",
62  static Finfo* processShared[] = {
63  &process, &reinit
64  };
65 
66  static ValueFinfo<PIDController, double> gain( "gain",
67  "This is the proportional gain (Kp). This tuning parameter scales the"
68  " proportional term. Larger gain usually results in faster response, but"
69  " too much will lead to instability and oscillation.",
72  static ValueFinfo<PIDController, double> saturation("saturation",
73  "Bound on the permissible range of output. Defaults to maximum double"
74  " value.",
77  static ValueFinfo<PIDController, double> command("command",
78  "The command (desired) value of the sensed parameter. In control theory"
79  " this is commonly known as setpoint(SP).",
82  static ReadOnlyValueFinfo<PIDController, double> sensed( "sensed",
83  "Sensed (measured) value. This is commonly known as process variable"
84  "(PV) in control theory.",
86  static ValueFinfo<PIDController, double> tauI( "tauI",
87  "The integration time constant, typically = dt. This is actually"
88  " proportional gain divided by integral gain (Kp/Ki)). Larger Ki"
89  " (smaller tauI) usually leads to fast elimination of steady state"
90  " errors at the cost of larger overshoot.",
93  static ValueFinfo<PIDController, double> tauD( "tauD",
94  "The differentiation time constant, typically = dt / 4. This is"
95  " derivative gain (Kd) times proportional gain (Kp). Larger Kd (tauD)"
96  " decreases overshoot at the cost of slowing down transient response"
97  " and may lead to instability.",
100  static ReadOnlyValueFinfo<PIDController, double> outputValue( "outputValue",
101  "Output of the PIDController. This is given by:"
102  " gain * ( error + INTEGRAL[ error dt ] / tau_i + tau_d * d(error)/dt )\n"
103  "Where gain = proportional gain (Kp), tau_i = integral gain (Kp/Ki) and"
104  " tau_d = derivative gain (Kd/Kp). In control theory this is also known"
105  " as the manipulated variable (MV)",
108  "The error term, which is the difference between command and sensed"
109  " value.",
111  static ReadOnlyValueFinfo<PIDController, double> integral( "integral",
112  "The integral term. It is calculated as INTEGRAL(error dt) ="
113  " previous_integral + dt * (error + e_previous)/2.",
115  static ReadOnlyValueFinfo<PIDController, double> derivative( "derivative",
116  "The derivative term. This is (error - e_previous)/dt.",
118  static ReadOnlyValueFinfo<PIDController, double> e_previous( "e_previous",
119  "The error term for previous step.",
121  static DestFinfo commandIn( "commandIn",
122  "Command (desired value) input. This is known as setpoint (SP) in"
123  " control theory." ,
125  static DestFinfo sensedIn( "sensedIn",
126  "Sensed parameter - this is the one to be tuned. This is known as"
127  " process variable (PV) in control theory. This comes from the process"
128  " we are trying to control.",
130  static DestFinfo gainDest( "gainDest",
131  "Destination message to control the PIDController gain dynamically.",
133  static SharedFinfo proc( "proc",
134  "This is a shared message to receive Process messages "
135  "from the scheduler objects."
136  "The first entry in the shared msg is a MsgDest "
137  "for the Process operation. It has a single argument, "
138  "ProcInfo, which holds lots of information about current "
139  "time, thread, dt and so on. The second entry is a MsgDest "
140  "for the Reinit operation. It also uses ProcInfo. ",
141  processShared, sizeof( processShared ) / sizeof( Finfo* )
142  );
143 
144 
145  static Finfo* pidFinfos[] = {
146  &gain,
147  &saturation,
148  &command,
149  &sensed,
150  &tauI,
151  &tauD,
152  &outputValue,
153  &error,
154  &integral,
155  &derivative,
156  &e_previous,
157  outputOut(),
158  &commandIn,
159  &sensedIn,
160  &gainDest,
161  &proc
162  };
163  static string doc[] = {
164  "Name", "PIDController",
165  "Author", "Subhasis Ray",
166  "Description", "PID feedback controller."
167  "PID stands for Proportional-Integral-Derivative. It is used to"
168  " feedback control dynamical systems. It tries to create a feedback"
169  " output such that the sensed (measured) parameter is held at command"
170  " value. Refer to wikipedia (http://wikipedia.org) for details on PID"
171  " Controller." };
172  static Dinfo<PIDController> dinfo;
173  static Cinfo pidCinfo(
174  "PIDController",
176  pidFinfos,
177  sizeof( pidFinfos ) / sizeof( Finfo* ),
178  &dinfo,
179  doc,
180  sizeof(doc)/sizeof(string));
181  return &pidCinfo;
182 }
183 
185 
187  command_(0),
188  saturation_(DBL_MAX),
189  gain_(1),
190  tau_i_(0),
191  tau_d_(0),
192  sensed_(0),
193  output_(0),
194  error_(0),
195  e_integral_(0),
196  e_derivative_(0),
197  e_previous_(0)
198 {
199  ; // do nothing else
200 }
201 
202 void PIDController::setCommand( double command)
203 {
204  command_ = command;
205 }
206 
208 {
209  return command_;
210 }
211 
212 void PIDController::setSensed( double sensed )
213 {
214  sensed_ = sensed;
215 }
216 
218 {
219  return sensed_;
220 }
221 
223 {
224  return output_;
225 }
226 
227 void PIDController::setGain( double gain )
228 {
229  gain_ = gain;
230 }
231 
232 double PIDController::getGain( ) const
233 {
234  return gain_;
235 }
236 
237 void PIDController::setTauI( double tau_i )
238 {
239  tau_i_ = tau_i;
240 }
241 
242 double PIDController::getTauI( ) const
243 {
244  return tau_i_;
245 }
246 
247 void PIDController::setTauD( double tau_d )
248 {
249  tau_d_ = tau_d;
250 }
251 
252 double PIDController::getTauD( ) const
253 {
254  return tau_d_;
255 }
256 
257 void PIDController::setSaturation( double saturation )
258 {
259  if (saturation <= 0) {
260  cout << "Error: PIDController::setSaturation - saturation must be positive." << endl;
261  } else {
262  saturation_ = saturation;
263  }
264 }
265 
267 {
268  return saturation_;
269 }
270 
271 double PIDController::getError( ) const
272 {
273  return error_;
274 }
275 
277 {
278  return e_integral_;
279 }
280 
282 {
283  return e_derivative_;
284 }
285 
287 {
288  return e_previous_;
289 }
290 
291 void PIDController::process(const Eref& e, ProcPtr proc )
292 {
293  double dt = proc->dt;
295  error_ = command_ - sensed_;
296  e_integral_ += 0.5 * (error_ + e_previous_) * dt;
297  e_derivative_ = (error_ - e_previous_) / dt;
299  if (output_ > saturation_){
301  e_integral_ -= 0.5 * (error_ + e_previous_) * dt;
302  } else if (output_ < -saturation_){
303  output_ = -saturation_;
304  e_integral_ -= 0.5 * (error_ + e_previous_) * dt;
305  }
306  outputOut()->send(e, output_);
307 }
308 
309 
310 void PIDController::reinit(const Eref& e, ProcPtr proc )
311 {
312  if ( tau_i_ <= 0.0 ){
313  tau_i_ = proc->dt;
314  }
315  if ( tau_d_ < 0.0 ){
316  tau_d_ = proc->dt / 4;
317  }
318  sensed_ = 0.0;
319  output_ = 0;
320  error_ = 0;
322  e_integral_ = 0;
323  e_derivative_ = 0;
324  outputOut()->send(e, output_);
325 }
326 
327 
328 
329 //
330 // PIDController.cpp ends here
void reinit(const Eref &e, ProcPtr process)
double getTauD() const
double getEDerivative() const
double e_previous_
Definition: PIDController.h:80
double getGain() const
double getCommand() const
Definition: Dinfo.h:60
double getTauI() const
double getEPrevious() const
void setSensed(double sensed)
double getEIntegral() const
void setGain(double gain)
void process(const Eref &e, ProcPtr process)
double e_integral_
Definition: PIDController.h:78
double getSaturation() const
double e_derivative_
Definition: PIDController.h:79
void setTauD(double tau_d)
double dt
Definition: ProcInfo.h:18
double saturation_
Definition: PIDController.h:71
Definition: OpFunc.h:27
Definition: Eref.h:26
static const Cinfo * initCinfo()
void setCommand(double command)
double getOutput() const
double getSensed() const
static const Cinfo * pidCinfo
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
static SrcFinfo1< double > * outputOut()
Definition: Cinfo.h:18
void setSaturation(double saturation)
double getError() const
void setTauI(double tau_i)
Definition: Finfo.h:12