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 
27 
31 
32 #include <Eigen/Core>
33 
34 #include <mutex>
35 
36 namespace armarx
37 {
38  template <int dimensions = Eigen::Dynamic>
40  public Logging
41  {
42  public:
44 
46  float Ki,
47  float Kd,
50  bool threadSafe = true,
51  std::vector<bool> limitless = {}) :
52  Kp(Kp),
53  Ki(Ki),
54  Kd(Kd),
55  integral(0),
56  derivative(0),
57  previousError(0),
62  {
63  reset();
64  }
65 
66  void 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  void update(const double deltaSec, const PIDVectorX& measuredValue, const PIDVectorX& targetValue)
76  {
77  ScopedRecursiveLockPtr lock = getLock();
78  if (stackAllocations.zeroVec.rows() == 0)
79  {
80  preallocate(measuredValue.rows());
81  }
82  ARMARX_CHECK_EQUAL(measuredValue.rows(), targetValue.rows());
83  ARMARX_CHECK_EQUAL(measuredValue.rows(), stackAllocations.zeroVec.rows());
84  processValue = measuredValue;
85  target = targetValue;
86 
87  stackAllocations.errorVec = target - processValue;
88 
89  if (limitless.size() != 0)
90  {
91  ARMARX_CHECK_EQUAL(limitless.size(), (size_t)stackAllocations.errorVec.rows());
92  for (size_t i = 0; i < limitless.size(); i++)
93  {
94  if (limitless.at(i))
95  {
96  stackAllocations.errorVec(i) = math::MathUtils::angleModPI(stackAllocations.errorVec(i));
97  }
98  }
99  }
100 
101 
102  double error = stackAllocations.errorVec.norm();
103 
104  //double dt = (now - lastUpdateTime).toSecondsDouble();
105  // ARMARX_INFO << deactivateSpam() << VAROUT(dt);
106  if (!firstRun)
107  {
108  integral += error * deltaSec;
110  if (deltaSec > 0.0)
111  {
112  derivative = (error - previousError) / deltaSec;
113  }
114  }
115 
116  firstRun = false;
117  stackAllocations.direction = targetValue; // copy size
118 
119  if (error > 0)
120  {
121  stackAllocations.direction = stackAllocations.errorVec.normalized();
122  }
123  else
124  {
125  stackAllocations.direction.setZero();
126  }
127 
128  if (controlValue.rows() > 0)
129  {
130  stackAllocations.oldControlValue = controlValue;
131  }
132  else
133  {
134  stackAllocations.oldControlValue = stackAllocations.zeroVec;
135  }
136  controlValue = stackAllocations.direction * (Kp * error + Ki * integral + Kd * derivative);
137 
138  if (deltaSec > 0.0)
139  {
140  PIDVectorX accVec = (controlValue - stackAllocations.oldControlValue) / deltaSec;
141  float maxNewJointAcc = accVec.maxCoeff();
142  float minNewJointAcc = accVec.minCoeff();
143  maxNewJointAcc = std::max<float>(fabs(minNewJointAcc), fabs(maxNewJointAcc));
144  if (maxNewJointAcc > maxDerivation)
145  {
146  auto newValue = stackAllocations.oldControlValue + accVec * maxDerivation / maxNewJointAcc * deltaSec;
147  ARMARX_DEBUG << deactivateSpam(0.5) << VAROUT(maxDerivation) << VAROUT(maxNewJointAcc) << VAROUT(controlValue) << VAROUT(stackAllocations.oldControlValue) << VAROUT(newValue);
148  controlValue = newValue;
149  }
150  }
151 
152 
153  float max = controlValue.maxCoeff();
154  float min = controlValue.minCoeff();
155  max = std::max<float>(fabs(min), fabs(max));
156 
157 
158 
159  if (max > maxControlValue)
160  {
161  auto newValue = controlValue * maxControlValue / max;
162  ARMARX_DEBUG << deactivateSpam(0.5) << " Control value to big: " << controlValue << " max value: " << maxControlValue << " new value: " << newValue;
163  controlValue = newValue;
164  }
165  ARMARX_DEBUG << deactivateSpam(0.5) << " error: " << error << " cV: " << (controlValue) << " i: " << (Ki * integral) << " d: " << (Kd * derivative) << " dt: " << deltaSec;
166 
167  previousError = error;
168  lastUpdateTime += IceUtil::Time::seconds(deltaSec);
169 
170  }
171  void update(const PIDVectorX& measuredValue, const PIDVectorX& targetValue)
172  {
173  ScopedRecursiveLockPtr lock = getLock();
175 
176  if (firstRun)
177  {
179  }
180 
181  double dt = (now - lastUpdateTime).toSecondsDouble();
182  update(dt, measuredValue, targetValue);
183  lastUpdateTime = now;
184  }
185  const PIDVectorX&
187  {
188  return controlValue;
189  }
191  {
192  ScopedRecursiveLockPtr lock = getLock();
194  }
195 
196  void reset()
197  {
198  ScopedRecursiveLockPtr lock = getLock();
199  firstRun = true;
200  previousError = 0;
201  integral = 0;
203  //reset control
204  controlValue.setZero();
205  processValue.setZero();
206  target.setZero();
207 
208 
209  }
210  // protected:
211  float Kp, Ki, Kd;
212  double integral;
214  double derivative;
222  bool firstRun;
223  mutable std::recursive_mutex mutex;
224  bool threadSafe = true;
225  std::vector<bool> limitless;
226  private:
227 
228  struct StackAllocationHelper
229  {
230  PIDVectorX errorVec;
231  PIDVectorX direction;
232  PIDVectorX oldControlValue;
233  PIDVectorX zeroVec;
234  } stackAllocations;
235 
236  using ScopedRecursiveLock = std::unique_lock<std::recursive_mutex>;
237  using ScopedRecursiveLockPtr = std::unique_ptr<ScopedRecursiveLock>;
238  ScopedRecursiveLockPtr getLock() const
239  {
240  if (threadSafe)
241  {
243  }
244  else
245  {
246  return ScopedRecursiveLockPtr();
247  }
248  }
249  };
251  using MultiDimPIDControllerPtr = std::shared_ptr<MultiDimPIDControllerTemplate<>>;
252 }
armarx::MultiDimPIDControllerTemplate::processValue
PIDVectorX processValue
Definition: MultiDimPIDController.h:216
armarx::MultiDimPIDControllerTemplate::derivative
double derivative
Definition: MultiDimPIDController.h:214
MathUtils.h
armarx::MultiDimPIDControllerTemplate::~MultiDimPIDControllerTemplate
~MultiDimPIDControllerTemplate()
Definition: MultiDimPIDController.h:74
armarx::MultiDimPIDControllerTemplate::reset
void reset()
Definition: MultiDimPIDController.h:196
armarx::MultiDimPIDControllerTemplate::limitless
std::vector< bool > limitless
Definition: MultiDimPIDController.h:225
armarx::MultiDimPIDControllerTemplate::update
void update(const double deltaSec, const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:75
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:267
armarx::MultiDimPIDControllerTemplate::threadSafe
bool threadSafe
Definition: MultiDimPIDController.h:224
armarx::MultiDimPIDControllerTemplate::Kp
float Kp
Definition: MultiDimPIDController.h:211
armarx::MultiDimPIDControllerTemplate::previousError
double previousError
Definition: MultiDimPIDController.h:215
armarx::MultiDimPIDControllerTemplate::integral
double integral
Definition: MultiDimPIDController.h:212
armarx::MultiDimPIDControllerTemplate::setMaxControlValue
void setMaxControlValue(double value)
Definition: MultiDimPIDController.h:190
armarx::MultiDimPIDControllerTemplate::maxDerivation
double maxDerivation
Definition: MultiDimPIDController.h:221
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::MultiDimPIDControllerPtr
std::shared_ptr< MultiDimPIDControllerTemplate<> > MultiDimPIDControllerPtr
Definition: MultiDimPIDController.h:251
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::ScopedRecursiveLock
RecursiveMutex::scoped_lock ScopedRecursiveLock
Definition: Synchronization.h:142
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::math::MathUtils::angleModPI
static float angleModPI(float value)
Definition: MathUtils.h:140
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:45
armarx::MultiDimPIDControllerTemplate::target
PIDVectorX target
Definition: MultiDimPIDController.h:217
armarx::Logging
Base Class for all Logging classes.
Definition: Logging.h:232
TimeUtil.h
armarx::MultiDimPIDControllerTemplate::getControlValue
const PIDVectorX & getControlValue() const
Definition: MultiDimPIDController.h:186
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::min
std::vector< T > min(const std::vector< T > &v1, const std::vector< T > &v2)
Definition: VectorHelpers.h:294
armarx::MultiDimPIDControllerTemplate::firstRun
bool firstRun
Definition: MultiDimPIDController.h:222
armarx::MultiDimPIDControllerTemplate::controlValue
PIDVectorX controlValue
Definition: MultiDimPIDController.h:219
armarx::MultiDimPIDControllerTemplate::mutex
std::recursive_mutex mutex
Definition: MultiDimPIDController.h:223
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:92
Eigen::Matrix< float, dimensions, 1 >
armarx::MultiDimPIDControllerTemplate::maxControlValue
double maxControlValue
Definition: MultiDimPIDController.h:220
armarx::MultiDimPIDControllerTemplate::lastUpdateTime
IceUtil::Time lastUpdateTime
Definition: MultiDimPIDController.h:218
armarx::MultiDimPIDControllerTemplate::update
void update(const PIDVectorX &measuredValue, const PIDVectorX &targetValue)
Definition: MultiDimPIDController.h:171
Logging.h
min
T min(T t1, T t2)
Definition: gdiam.h:42
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:143
armarx::MultiDimPIDControllerTemplate::Kd
float Kd
Definition: MultiDimPIDController.h:211
armarx::MultiDimPIDControllerTemplate::PIDVectorX
Eigen::Matrix< float, dimensions, 1 > PIDVectorX
Definition: MultiDimPIDController.h:43
armarx::MultiDimPIDControllerTemplate::maxIntegral
double maxIntegral
Definition: MultiDimPIDController.h:213
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
dt
constexpr T dt
Definition: UnscentedKalmanFilterTest.cpp:42
armarx::MultiDimPIDControllerTemplate::Ki
float Ki
Definition: MultiDimPIDController.h:211