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
36namespace armarx
37{
61
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
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),
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 }
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();
198 IceUtil::Time now = TimeUtil::GetTime();
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 {
254 if (std::abs(error) < conditionalIntegralErrorTreshold)
255 {
256 integral += error * deltaSec;
258 }
259 if (deltaSec > 0.0)
260 {
261 derivative = (error - previousError) / deltaSec;
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
constexpr T dt
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
double getControlValue() const
void update(double deltaSec, double measuredValue, double targetValue)
std::shared_ptr< rtfilters::RTFilterBase > differentialFilter
double conditionalIntegralErrorTreshold
void setTarget(double newTarget)
void setMaxControlValue(double newMax)
PIDController & operator=(PIDController &&o)
IceUtil::Time lastUpdateTime
std::shared_ptr< rtfilters::RTFilterBase > pdOutputFilter
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition TimeUtil.cpp:42
static int Sign(double value)
Definition MathUtils.h:37
static float angleModPI(float value)
Definition MathUtils.h:173
static double LimitTo(double value, double absThreshold)
Definition MathUtils.h:71
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
std::shared_ptr< ScopedRecursiveLock > ScopedRecursiveLockPtr
This file offers overloads of toIce() and fromIce() functions for STL container types.