MultiDimPIDController.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2017, 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 ArmarX
19  * @author Mirko Waechter( mirko.waechter at kit dot edu)
20  * @date 2018
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <mutex>
27 
28 #include <Eigen/Core>
29 
33 
35 
36 namespace armarx
37 {
38  template <int dimensions = Eigen::Dynamic>
40  {
41  public:
43 
45  float Ki,
46  float Kd,
49  bool threadSafe = true,
50  std::vector<bool> limitless = {}) :
51  Kp(Kp),
52  Ki(Ki),
53  Kd(Kd),
54  integral(0),
55  derivative(0),
56  previousError(0),
61  {
62  reset();
63  }
64 
65  void
66  preallocate(size_t size)
67  {
68  stackAllocations.zeroVec = PIDVectorX::Zero(size);
69  stackAllocations.errorVec = stackAllocations.zeroVec;
70  stackAllocations.direction = stackAllocations.zeroVec;
71  stackAllocations.oldControlValue = stackAllocations.zeroVec;
72  }
73 
75  {
76  }
77 
78  void
79  update(const double deltaSec,
80  const PIDVectorX& measuredValue,
81  const PIDVectorX& targetValue)
82  {
83  ScopedRecursiveLockPtr lock = getLock();
84  if (stackAllocations.zeroVec.rows() == 0)
85  {
86  preallocate(measuredValue.rows());
87  }
88  ARMARX_CHECK_EQUAL(measuredValue.rows(), targetValue.rows());
89  ARMARX_CHECK_EQUAL(measuredValue.rows(), stackAllocations.zeroVec.rows());
90  processValue = measuredValue;
91  target = targetValue;
92 
93  stackAllocations.errorVec = target - processValue;
94 
95  if (limitless.size() != 0)
96  {
97  ARMARX_CHECK_EQUAL(limitless.size(), (size_t)stackAllocations.errorVec.rows());
98  for (size_t i = 0; i < limitless.size(); i++)
99  {
100  if (limitless.at(i))
101  {
102  stackAllocations.errorVec(i) =
103  math::MathUtils::angleModPI(stackAllocations.errorVec(i));
104  }
105  }
106  }
107 
108 
109  double error = stackAllocations.errorVec.norm();
110 
111  //double dt = (now - lastUpdateTime).toSecondsDouble();
112  // ARMARX_INFO << deactivateSpam() << VAROUT(dt);
113  if (!firstRun)
114  {
115  integral += error * deltaSec;
117  if (deltaSec > 0.0)
118  {
119  derivative = (error - previousError) / deltaSec;
120  }
121  }
122 
123  firstRun = false;
124  stackAllocations.direction = targetValue; // copy size
125 
126  if (error > 0)
127  {
128  stackAllocations.direction = stackAllocations.errorVec.normalized();
129  }
130  else
131  {
132  stackAllocations.direction.setZero();
133  }
134 
135  if (controlValue.rows() > 0)
136  {
137  stackAllocations.oldControlValue = controlValue;
138  }
139  else
140  {
141  stackAllocations.oldControlValue = stackAllocations.zeroVec;
142  }
143  controlValue =
144  stackAllocations.direction * (Kp * error + Ki * integral + Kd * derivative);
145 
146  if (deltaSec > 0.0)
147  {
148  PIDVectorX accVec = (controlValue - stackAllocations.oldControlValue) / deltaSec;
149  float maxNewJointAcc = accVec.maxCoeff();
150  float minNewJointAcc = accVec.minCoeff();
151  maxNewJointAcc = std::max<float>(fabs(minNewJointAcc), fabs(maxNewJointAcc));
152  if (maxNewJointAcc > maxDerivation)
153  {
154  auto newValue = stackAllocations.oldControlValue +
155  accVec * maxDerivation / maxNewJointAcc * deltaSec;
157  << VAROUT(maxNewJointAcc) << VAROUT(controlValue)
158  << VAROUT(stackAllocations.oldControlValue) << VAROUT(newValue);
159  controlValue = newValue;
160  }
161  }
162 
163 
164  float max = controlValue.maxCoeff();
165  float min = controlValue.minCoeff();
166  max = std::max<float>(fabs(min), fabs(max));
167 
168 
169  if (max > maxControlValue)
170  {
171  auto newValue = controlValue * maxControlValue / max;
172  ARMARX_DEBUG << deactivateSpam(0.5) << " Control value to big: " << controlValue
173  << " max value: " << maxControlValue << " new value: " << newValue;
174  controlValue = newValue;
175  }
176  ARMARX_DEBUG << deactivateSpam(0.5) << " error: " << error << " cV: " << (controlValue)
177  << " i: " << (Ki * integral) << " d: " << (Kd * derivative)
178  << " dt: " << deltaSec;
179 
180  previousError = error;
181  lastUpdateTime += IceUtil::Time::seconds(deltaSec);
182  }
183 
184  void
185  update(const PIDVectorX& measuredValue, const PIDVectorX& targetValue)
186  {
187  ScopedRecursiveLockPtr lock = getLock();
189 
190  if (firstRun)
191  {
193  }
194 
195  double dt = (now - lastUpdateTime).toSecondsDouble();
196  update(dt, measuredValue, targetValue);
197  lastUpdateTime = now;
198  }
199 
200  const PIDVectorX&
202  {
203  return controlValue;
204  }
205 
206  void
208  {
209  ScopedRecursiveLockPtr lock = getLock();
211  }
212 
213  void
215  {
216  ScopedRecursiveLockPtr lock = getLock();
217  firstRun = true;
218  previousError = 0;
219  integral = 0;
221  //reset control
222  controlValue.setZero();
223  processValue.setZero();
224  target.setZero();
225  }
226 
227  // protected:
228  float Kp, Ki, Kd;
229  double integral;
231  double derivative;
239  bool firstRun;
240  mutable std::recursive_mutex mutex;
241  bool threadSafe = true;
242  std::vector<bool> limitless;
243 
244  private:
245  struct StackAllocationHelper
246  {
247  PIDVectorX errorVec;
248  PIDVectorX direction;
249  PIDVectorX oldControlValue;
250  PIDVectorX zeroVec;
251  } stackAllocations;
252 
253  using ScopedRecursiveLock = std::unique_lock<std::recursive_mutex>;
254  using ScopedRecursiveLockPtr = std::unique_ptr<ScopedRecursiveLock>;
255 
257  getLock() const
258  {
259  if (threadSafe)
260  {
262  }
263  else
264  {
265  return ScopedRecursiveLockPtr();
266  }
267  }
268  };
269 
271  using MultiDimPIDControllerPtr = std::shared_ptr<MultiDimPIDControllerTemplate<>>;
272 } // namespace armarx
armarx::MultiDimPIDControllerTemplate::processValue
PIDVectorX processValue
Definition: MultiDimPIDController.h:233
armarx::MultiDimPIDControllerTemplate::derivative
double derivative
Definition: MultiDimPIDController.h:231
MathUtils.h
armarx::MultiDimPIDControllerTemplate::~MultiDimPIDControllerTemplate
~MultiDimPIDControllerTemplate()
Definition: MultiDimPIDController.h:74
armarx::MultiDimPIDControllerTemplate::reset
void reset()
Definition: MultiDimPIDController.h:214
armarx::MultiDimPIDControllerTemplate::limitless
std::vector< bool > limitless
Definition: MultiDimPIDController.h:242
armarx::MultiDimPIDControllerTemplate::update
void update(const double deltaSec, const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:79
armarx::MultiDimPIDControllerTemplate::preallocate
void preallocate(size_t size)
Definition: MultiDimPIDController.h:66
armarx::MultiDimPIDControllerTemplate
Definition: MultiDimPIDController.h:39
armarx::max
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:297
armarx::MultiDimPIDControllerTemplate::threadSafe
bool threadSafe
Definition: MultiDimPIDController.h:241
armarx::MultiDimPIDControllerTemplate::Kp
float Kp
Definition: MultiDimPIDController.h:228
armarx::MultiDimPIDControllerTemplate::previousError
double previousError
Definition: MultiDimPIDController.h:232
armarx::MultiDimPIDControllerTemplate::integral
double integral
Definition: MultiDimPIDController.h:229
armarx::MultiDimPIDControllerTemplate::setMaxControlValue
void setMaxControlValue(double value)
Definition: MultiDimPIDController.h:207
armarx::MultiDimPIDControllerTemplate::maxDerivation
double maxDerivation
Definition: MultiDimPIDController.h:238
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::MultiDimPIDControllerPtr
std::shared_ptr< MultiDimPIDControllerTemplate<> > MultiDimPIDControllerPtr
Definition: MultiDimPIDController.h:271
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::ScopedRecursiveLock
RecursiveMutex::scoped_lock ScopedRecursiveLock
Definition: Synchronization.h:160
max
T max(T t1, T t2)
Definition: gdiam.h:51
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::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
ExpressionException.h
armarx::MultiDimPIDControllerTemplate::MultiDimPIDControllerTemplate
MultiDimPIDControllerTemplate(float Kp, float Ki, float Kd, double maxControlValue=std::numeric_limits< double >::max(), double maxDerivation=std::numeric_limits< double >::max(), bool threadSafe=true, std::vector< bool > limitless={})
Definition: MultiDimPIDController.h:44
armarx::MultiDimPIDControllerTemplate::target
PIDVectorX target
Definition: MultiDimPIDController.h:234
armarx::Logging
Base Class for all Logging classes.
Definition: Logging.h:239
TimeUtil.h
armarx::MultiDimPIDControllerTemplate::getControlValue
const PIDVectorX & getControlValue() const
Definition: MultiDimPIDController.h:201
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::min
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:327
armarx::MultiDimPIDControllerTemplate::firstRun
bool firstRun
Definition: MultiDimPIDController.h:239
armarx::MultiDimPIDControllerTemplate::controlValue
PIDVectorX controlValue
Definition: MultiDimPIDController.h:236
armarx::MultiDimPIDControllerTemplate::mutex
std::recursive_mutex mutex
Definition: MultiDimPIDController.h:240
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
Eigen::Matrix< float, dimensions, 1 >
armarx::MultiDimPIDControllerTemplate::maxControlValue
double maxControlValue
Definition: MultiDimPIDController.h:237
armarx::MultiDimPIDControllerTemplate::lastUpdateTime
IceUtil::Time lastUpdateTime
Definition: MultiDimPIDController.h:235
armarx::MultiDimPIDControllerTemplate::update
void update(const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:185
Logging.h
min
T min(T t1, T t2)
Definition: gdiam.h:44
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
armarx::ScopedRecursiveLockPtr
std::shared_ptr< ScopedRecursiveLock > ScopedRecursiveLockPtr
Definition: Synchronization.h:161
armarx::MultiDimPIDControllerTemplate::Kd
float Kd
Definition: MultiDimPIDController.h:228
armarx::MultiDimPIDControllerTemplate::PIDVectorX
Eigen::Matrix< float, dimensions, 1 > PIDVectorX
Definition: MultiDimPIDController.h:42
armarx::MultiDimPIDControllerTemplate::maxIntegral
double maxIntegral
Definition: MultiDimPIDController.h:230
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
dt
constexpr T dt
Definition: UnscentedKalmanFilterTest.cpp:45
armarx::MultiDimPIDControllerTemplate::Ki
float Ki
Definition: MultiDimPIDController.h:228