PIDController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package RobotAPI::core::PIDController
19  * @author Mirko Waechter ( mirko dot waechter at kit dot edu )
20  * @date 2014
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 #include "PIDController.h"
26 
27 #include <memory>
28 
33 
35 
36 namespace armarx
37 {
39  Kp(o.Kp),
40  Ki(o.Ki),
41  Kd(o.Kd),
42  integral(o.integral),
43  maxIntegral(o.maxIntegral),
44  conditionalIntegralErrorTreshold(o.conditionalIntegralErrorTreshold),
45  derivative(o.derivative),
46  previousError(o.previousError),
47  processValue(o.processValue),
48  target(o.target),
49  lastUpdateTime(o.lastUpdateTime),
50  controlValue(o.controlValue),
51  controlValueDerivation(o.controlValueDerivation),
52  maxControlValue(o.maxControlValue),
53  maxDerivation(o.maxDerivation),
54  firstRun(o.firstRun),
55  limitless(o.limitless),
56  threadSafe(o.threadSafe),
57  differentialFilter(std::move(o.differentialFilter)),
58  pdOutputFilter(std::move(o.pdOutputFilter))
59  {
60  }
61 
63  Kp(o.Kp),
64  Ki(o.Ki),
65  Kd(o.Kd),
66  integral(o.integral),
67  maxIntegral(o.maxIntegral),
68  conditionalIntegralErrorTreshold(o.conditionalIntegralErrorTreshold),
69  derivative(o.derivative),
70  previousError(o.previousError),
71  processValue(o.processValue),
72  target(o.target),
73  lastUpdateTime(o.lastUpdateTime),
74  controlValue(o.controlValue),
75  controlValueDerivation(o.controlValueDerivation),
76  maxControlValue(o.maxControlValue),
77  maxDerivation(o.maxDerivation),
78  firstRun(o.firstRun),
79  limitless(o.limitless),
80  threadSafe(o.threadSafe),
81  differentialFilter(o.differentialFilter->clone()),
82  pdOutputFilter(o.pdOutputFilter->clone())
83  {
84  }
85 
88  {
89  Kp = o.Kp;
90  Ki = o.Ki;
91  Kd = o.Kd;
92  integral = o.integral;
93  maxIntegral = o.maxIntegral;
94  conditionalIntegralErrorTreshold = o.conditionalIntegralErrorTreshold;
95  derivative = o.derivative;
96  previousError = o.previousError;
97  processValue = o.processValue;
98  target = o.target;
99  lastUpdateTime = o.lastUpdateTime;
100  controlValue = o.controlValue;
101  controlValueDerivation = o.controlValueDerivation;
102  maxControlValue = o.maxControlValue;
103  maxDerivation = o.maxDerivation;
104  firstRun = o.firstRun;
105  limitless = o.limitless;
106  threadSafe = o.threadSafe;
107  differentialFilter = std::move(o.differentialFilter);
108  pdOutputFilter = std::move(o.pdOutputFilter);
109  return *this;
110  }
111 
114  {
115  Kp = o.Kp;
116  Ki = o.Ki;
117  Kd = o.Kd;
118  integral = o.integral;
124  target = o.target;
130  firstRun = o.firstRun;
131  limitless = o.limitless;
134  pdOutputFilter = o.pdOutputFilter->clone();
135  return *this;
136  }
137 
139  float Ki,
140  float Kd,
141  double maxControlValue,
142  double maxDerivation,
143  bool limitless,
144  bool threadSafe) :
145  Kp(Kp),
146  Ki(Ki),
147  Kd(Kd),
148  integral(0),
149  derivative(0),
150  previousError(0),
151  processValue(0),
152  target(0),
153  controlValue(0),
154  controlValueDerivation(0),
155  maxControlValue(maxControlValue),
156  maxDerivation(maxDerivation),
157  limitless(limitless),
158  threadSafe(threadSafe)
159  {
160  reset();
161  }
162 
163  void
165  {
166  ScopedRecursiveLockPtr lock = getLock();
167  firstRun = true;
168  previousError = 0;
169  integral = 0;
171  if (pdOutputFilter)
172  {
173  pdOutputFilter->reset();
174  }
175  if (differentialFilter)
176  {
177  differentialFilter->reset();
178  }
179  }
180 
181  auto
182  PIDController::getLock() const -> ScopedRecursiveLockPtr
183  {
184  if (threadSafe)
185  {
186  return std::make_unique<ScopedRecursiveLock>(mutex);
187  }
188  else
189  {
190  return ScopedRecursiveLockPtr();
191  }
192  }
193 
194  void
195  PIDController::update(double measuredValue, double targetValue)
196  {
197  ScopedRecursiveLockPtr lock = getLock();
199 
200  if (firstRun)
201  {
203  }
204 
205  double dt = (now - lastUpdateTime).toSecondsDouble();
206  update(dt, measuredValue, targetValue);
207  lastUpdateTime = now;
208  }
209 
210  void
211  PIDController::update(double measuredValue)
212  {
213  ScopedRecursiveLockPtr lock = getLock();
214  update(measuredValue, target);
215  }
216 
217  void
218  PIDController::setTarget(double newTarget)
219  {
220  ScopedRecursiveLockPtr lock = getLock();
221  target = newTarget;
222  }
223 
224  void
226  {
227  ScopedRecursiveLockPtr lock = getLock();
228  maxControlValue = newMax;
229  }
230 
231  void
232  PIDController::update(double deltaSec, double measuredValue, double targetValue)
233  {
234  ScopedRecursiveLockPtr lock = getLock();
235  processValue = measuredValue;
236  target = targetValue;
237 
238 
239  double error = target - processValue;
240  //ARMARX_INFO << VAROUT(target) << ", " << VAROUT(processValue) << ", " << VAROUT(error);
241  if (limitless)
242  {
243  //ARMARX_INFO << VAROUT(error);
244  error = math::MathUtils::angleModPI(error);
245  //ARMARX_INFO << VAROUT(error);
246  //error = math::MathUtils::fmod(error, limitlessLimitHi - 2 * M_PI, limitlessLimitHi);
247  //ARMARX_INFO << "Limitless after mod:" << VAROUT(error);
248  }
249 
250  //double dt = (now - lastUpdateTime).toSecondsDouble();
251  // ARMARX_INFO << deactivateSpam() << VAROUT(dt);
252  if (!firstRun)
253  {
255  {
256  integral += error * deltaSec;
258  }
259  if (deltaSec > 0.0)
260  {
261  derivative = (error - previousError) / deltaSec;
262  if (differentialFilter)
263  {
264  derivative = differentialFilter->update(deltaSec, derivative);
265  }
266  }
267  }
268 
269  firstRun = false;
270  double oldControlValue = controlValue;
271  double pdControlValue = Kp * error + Kd * derivative;
272  if (pdOutputFilter)
273  {
274  pdControlValue = pdOutputFilter->update(deltaSec, pdControlValue);
275  }
276  controlValue = pdControlValue + Ki * integral;
277  if (deltaSec > 0.0)
278  {
279  double deriv = (controlValue - oldControlValue) / deltaSec;
280  if (fabs(deriv) > maxDerivation)
281  {
283  controlValue = oldControlValue + controlValueDerivation;
284  }
285  }
286 
287  double const controlValueClamped =
289 
290  ARMARX_DEBUG << deactivateSpam(0.5) << " error: " << error << ", kp*error: " << (Kp * error)
291  << ", cV: " << (controlValue) << ", max cV: " << (maxControlValue)
292  << ", cV clamped: " << controlValueClamped << ", i: " << (Ki * integral)
293  << ", d: " << (Kd * derivative) << ", dt: " << deltaSec;
294 
295  controlValue = controlValueClamped;
296 
297  previousError = error;
298  lastUpdateTime += IceUtil::Time::secondsDouble(deltaSec);
299  }
300 
301  double
303  {
304  ScopedRecursiveLockPtr lock = getLock();
305  return controlValue;
306  }
307 } // namespace armarx
armarx::PIDController::maxControlValue
double maxControlValue
Definition: PIDController.h:79
armarx::PIDController::processValue
double processValue
Definition: PIDController.h:74
armarx::PIDController::conditionalIntegralErrorTreshold
double conditionalIntegralErrorTreshold
Definition: PIDController.h:71
MathUtils.h
armarx::PIDController::Kp
float Kp
Definition: PIDController.h:68
armarx::PIDController::operator=
PIDController & operator=(PIDController &&o)
Definition: PIDController.cpp:87
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
armarx::PIDController::Ki
float Ki
Definition: PIDController.h:68
armarx::PIDController::Kd
float Kd
Definition: PIDController.h:68
armarx::PIDController::getControlValue
double getControlValue() const
Definition: PIDController.cpp:302
armarx::PIDController::setTarget
void setTarget(double newTarget)
Definition: PIDController.cpp:218
armarx::PIDController::update
void update(double deltaSec, double measuredValue, double targetValue)
Definition: PIDController.cpp:232
armarx::PIDController::reset
void reset()
Definition: PIDController.cpp:164
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:281
armarx::PIDController::PIDController
PIDController()=default
ButterworthFilter.h
armarx::PIDController
Definition: PIDController.h:43
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::PIDController::limitless
bool limitless
Definition: PIDController.h:82
armarx::PIDController::previousError
double previousError
Definition: PIDController.h:73
armarx::math::MathUtils::angleModPI
static float angleModPI(float value)
Definition: MathUtils.h:173
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::PIDController::controlValueDerivation
double controlValueDerivation
Definition: PIDController.h:78
armarx::PIDController::threadSafe
bool threadSafe
Definition: PIDController.h:83
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
armarx::PIDController::integral
double integral
Definition: PIDController.h:69
ExpressionException.h
PIDController.h
armarx::PIDController::controlValue
double controlValue
Definition: PIDController.h:77
armarx::math::MathUtils::LimitTo
static double LimitTo(double value, double absThreshold)
Definition: MathUtils.h:71
armarx::PIDController::maxIntegral
double maxIntegral
Definition: PIDController.h:70
TimeUtil.h
std
Definition: Application.h:66
armarx::math::MathUtils::Sign
static int Sign(double value)
Definition: MathUtils.h:37
RTFilterBase.h
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:99
armarx::PIDController::target
double target
Definition: PIDController.h:75
armarx::PIDController::derivative
double derivative
Definition: PIDController.h:72
min
T min(T t1, T t2)
Definition: gdiam.h:44
armarx::PIDController::lastUpdateTime
IceUtil::Time lastUpdateTime
Definition: PIDController.h:76
armarx::ScopedRecursiveLockPtr
std::shared_ptr< ScopedRecursiveLock > ScopedRecursiveLockPtr
Definition: Synchronization.h:161
armarx::PIDController::maxDerivation
double maxDerivation
Definition: PIDController.h:80
armarx::PIDController::pdOutputFilter
std::shared_ptr< rtfilters::RTFilterBase > pdOutputFilter
Definition: PIDController.h:85
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::PIDController::firstRun
bool firstRun
Definition: PIDController.h:81
dt
constexpr T dt
Definition: UnscentedKalmanFilterTest.cpp:45
armarx::PIDController::differentialFilter
std::shared_ptr< rtfilters::RTFilterBase > differentialFilter
Definition: PIDController.h:84
armarx::PIDController::setMaxControlValue
void setMaxControlValue(double newMax)
Definition: PIDController.cpp:225