BasicControllers.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI
17 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
18 * @date 2017
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <cmath>
26#include <type_traits>
27
29
32// #define DEBUG_POS_CTRL
33#ifdef DEBUG_POS_CTRL
34#include <boost/circular_buffer.hpp>
35#endif
36
37
38namespace armarx
39{
40 template <class T, class = typename std::enable_if<std::is_floating_point<T>::value>::type>
41 T
42 periodicClamp(T value, T periodLo, T periodHi)
43 {
44 float dist = periodHi - periodLo;
45 return std::fmod(value - periodLo + dist, dist) + periodLo;
46 }
47
48 template <class T, class = typename std::enable_if<std::is_floating_point<T>::value>::type>
49 std::pair<T, T>
50 pq(T p, T q)
51 {
52 T a = -p / 2;
53 T b = std::sqrt(std::pow(p / 2, 2) - q);
54 return {a + b, a - b};
55 }
56
57 struct deltas
58 {
59 float dv;
60 float dx;
61 float dt;
62 };
63
64 inline deltas
65 accelerateToVelocity(float v0, float acc, float vt)
66 {
67 acc = std::abs(acc);
68 deltas d;
69 d.dv = vt - v0;
70 d.dt = std::abs(d.dv / acc);
71 d.dx = sign(d.dv) * d.dv * d.dv / 2.f / acc + v0 * d.dt;
72 return d;
73 }
74
75 std::array<deltas, 3> trapeze(float v0, float acc, float vMax, float dec, float vt, float dx);
76
77 inline float
78 trapezeArea(float v0, float vmax, float dt1, float dt2, float dt3)
79 {
80 return (v0 + vmax) / 2 * dt1 + dt2 * vmax + dt3 * vmax * 0.5;
81 }
82
83 inline void
85 float v0,
86 float vmax,
87 float dec,
88 std::array<deltas, 3> trapeze,
89 float newDt,
90 float& newV,
91 float& newAcc,
92 float& newDec)
93 {
94
95
96 float oldDt = trapeze.at(0).dt + trapeze.at(1).dt + trapeze.at(2).dt;
97 float dt0 = trapeze.at(0).dt;
98 float dt1 = trapeze.at(1).dt;
99 float dt2 = trapeze.at(2).dt;
100 float area = trapezeArea(v0, vmax, dt0, dt1, dt2);
101 dt1 += newDt - oldDt;
102 newV = (-dt0 * v0 + 2 * area) / (dt0 + 2 * dt1 + dt2);
103 newAcc = (newV - v0) / dt0;
104 newDec = newV / dt2;
105
106 if (newV < std::abs(v0))
107 {
108 dt0 = v0 / dec;
109 dt1 = newDt - dt0;
110 deltas d = accelerateToVelocity(v0, dec, 0);
111 newV = (distance - d.dx) / dt1;
112 newAcc = dec;
113 newDec = dec;
114
115 // // float oldDt = trapeze.at(0).dt + trapeze.at(1).dt + trapeze.at(2).dt;
116 // // dt0 = trapeze.at(0).dt;
117 // // dt1 = trapeze.at(1).dt;
118 // // dt2 = trapeze.at(2).dt;
119 // // area = trapezeArea(v0, newV, dt0, dt1, dt2);
120 // // auto v_pair = pq(dt1*dec, -(area*dec+v0*v0*0.5f));
121 // auto v_pair = pq(-newDt * dec - v0, area * dec - v0 * v0 * 0.5f);
122 // if (std::isfinite(v_pair.first) && std::isfinite(v_pair.second))
123 // {
124 // newV = std::abs(v_pair.first) < std::abs(v_pair.second) ? v_pair.first : v_pair.second;
125 // }
126 // else if (std::isfinite(v_pair.first))
127 // {
128 // newV = v_pair.first;
129 // }
130 // else if (std::isfinite(v_pair.second))
131 // {
132 // newV = v_pair.second;
133 // }
134 // // float f = (v0+newV)/2*((newV-v0)/dec) + dt1*newV + (newV/dec)*newV*0.5;
135 // dt0 = std::abs(newV - v0) / dec;
136 // dt1 = (newDt - std::abs(newV - v0) / dec - (newV / dec));
137 // dt2 = (newV / dec);
138
139 // float f = (v0 + newV) / 2 * (std::abs(newV - v0) / dec);
140 // f += (newDt - std::abs(newV - v0) / dec - (newV / dec)) * newV;
141 // f += (newV / dec) * newV * 0.5;
142
143 // newAcc = dec;
144 // newDec = dec;
145 }
146 }
147
148 std::array<deltas, 3>
149 trapezeWithDt(float v0, float acc, float vMax, float dec, float vt, float dx, float dt);
150
151 /**
152 * @param v0 The initial velocity.
153 * @param deceleration The deceleration.
154 * @return The braking distance given the parameters.
155 */
156 inline float
157 brakingDistance(float v0, float deceleration)
158 {
159 return accelerateToVelocity(std::abs(v0), std::abs(deceleration), 0).dx;
160 }
161
162 inline float
163 angleDistance(float angle1, float angle2)
164 {
165 return M_PI - std::fabs(std::fmod(std::fabs(angle1 - angle2), M_PI * 2) - M_PI);
166 }
167
169 {
170 float dt;
171 float maxDt;
172 float currentV;
173 float targetV;
174 float maxV;
178
179 bool validParameters() const;
180 float run() const;
181 float estimateTime() const;
182 };
183
185 {
186
187 struct Output
188 {
189 double velocity;
191 double jerk;
192 };
193
194 // config
195 float maxDt;
196 float maxV;
197 float jerk;
199
200 // state
201 float dt;
202 float currentV;
204 float targetV;
205
206
207 bool validParameters() const;
208 Output run() const;
209 };
210
211 typedef std::shared_ptr<class RampedAccelerationVelocityControllerConfiguration>
213 typedef std::shared_ptr<const RampedAccelerationVelocityControllerConfiguration>
215
227
230 {
231
235 // double positionLimitLoHard;
236 // double positionLimitHiHard;
238 bool validParameters() const;
239 Output run() const;
240 };
241
243 float maxDt,
244 const float currentV,
245 float targetV,
246 float maxV,
247 float acceleration,
248 float deceleration,
249 float directSetVLimit);
250
251 /**
252 * @brief Performs velocity control while staying in positional bounds, obeying acceleration / deceleration and staying below a velocity bound.
253 *
254 * we can have 4 cases:
255 * 1. we need to decelerate now or we will violate the position limits (maybe we still will violate them. e.f. if we already violate them or the robot can't brake fast enough)
256 * 2. we directly set v and ignore acc/dec (if |currentV - targetV| <= directSetVLimit)
257 * 3. we need to accelerate (if currentV and targetV have same sign and |currentV| < |currentV|)
258 * 4. we need to decelerate (other cases)
259 * @param dt The time in seconds until the next call is made. (use the time since the last call as an approximate)
260 * @param maxDt Limits dt in case the given approximation has a sudden high value.
261 * @param currentV
262 * @param targetV
263 * @param maxV
264 * @param acceleration
265 * @param deceleration
266 * @param directSetVLimit In case |currentV - targetV| <= directSetVLimit this function will return targetV (if the position bounds are not violated)
267 * @param currentPosition
268 * @param positionLimitLo
269 * @param positionLimitHi
270 * @return The next velocity.
271 */
274 {
275
279 // float positionLimitLoHard;
280 // float positionLimitHiHard;
281
282 bool validParameters() const;
283 float run() const;
284 };
285
287 float maxDt,
288 float currentV,
289 float targetV,
290 float maxV,
291 float acceleration,
292 float deceleration,
293 float directSetVLimit,
294 float currentPosition,
295 float positionLimitLoSoft,
296 float positionLimitHiSoft,
297 float positionLimitLoHard,
298 float positionLimitHiHard);
299
301 {
302 float dt;
303 float maxDt;
304 float currentV;
305 float maxV;
312 0.002; // if target is below this threshold, PID controller will be used
313 float accuracy = 0.001;
314 std::shared_ptr<PIDController> pid;
315 // float p;
317 float calculateProportionalGain() const;
318 bool validParameters() const;
319 float run() const;
320 float estimateTime() const;
321#ifdef DEBUG_POS_CTRL
322 mutable bool PIDModeActive = false;
323
324 struct HelpStruct
325 {
326 float currentPosition;
327 float targetVelocityPID;
328 float targetVelocityRAMP;
329 float currentV;
330 float currentError;
331 long timestamp;
332 };
333
334 mutable boost::circular_buffer<HelpStruct> buffer;
335 mutable int eventHappeningCounter = -1;
336#endif
337
338 public:
339 bool getCurrentlyPIDActive() const;
340
341 private:
342 mutable bool currentlyPIDActive = false;
343 };
344
346 {
357
358 struct Output
359 {
360 double velocity;
362 double jerk;
363 };
364
365 double dt;
366 double maxDt;
367 double currentV;
369 double maxV;
372 double jerk;
374
375 protected:
377
378 public:
379 double getTargetPosition() const;
380 void setTargetPosition(double value);
381
384 0.002; // if target is below this threshold, PID controller will be used
385 double accuracy = 0.001;
386 double p;
387 bool usePIDAtEnd = true;
390 bool validParameters() const;
391 Output run();
392 double estimateTime() const;
393 double calculateProportionalGain() const;
394
395
396 std::pair<State, Output> calcState() const;
397#ifdef DEBUG_POS_CTRL
398 mutable bool PIDModeActive = false;
399
400 struct HelpStruct
401 {
402 double currentPosition;
403 double targetVelocityPID;
404 double targetVelocityRAMP;
405 double currentV;
406 double currentError;
407 long timestamp;
408 };
409
410 mutable boost::circular_buffer<HelpStruct> buffer;
411 mutable int eventHappeningCounter = -1;
412#endif
413 };
414
416 float maxDt,
417 float currentV,
418 float maxV,
419 float acceleration,
420 float deceleration,
421 float currentPosition,
422 float targetPosition,
423 float p);
424
434
436 float maxDt,
437 float currentV,
438 float maxV,
439 float acceleration,
440 float deceleration,
441 float currentPosition,
442 float targetPosition,
443 float p,
444 float positionLimitLo,
445 float positionLimitHi);
446
455
457 float dt,
458 float maxDt,
459 float currentV,
460 float maxV,
461 float acceleration,
462 float deceleration,
463 float currentPosition,
464 float targetPosition,
465 float pControlPosErrorLimit,
466 float p,
467 float& direction,
468 float positionPeriodLo,
469 float positionPeriodHi);
470
472 {
473 public:
474 struct State
475 {
476 double t, s, v, a;
477 };
478
480 {
481 double t0, s0, v0, a0;
482 };
483
484 struct Output
485 {
486 double position;
487 double velocity;
489 double jerk;
490 };
491
492 double dt;
493 double maxDt;
495 double currentV;
497 double maxV;
500 double p = 1.0;
502 double phase2SwitchMaxRemainingTime = 0.2; // seconds
503 double p_adjust_ratio = 0.8;
504 // PIDControllerPtr pid;
505 protected:
506 double currentP_Phase3 = -1;
507 double currentP_Phase2 = -1;
509 double finishTime = 0;
510 double currentTime = 0;
511 std::unique_ptr<FixedMinJerkState> fixedMinJerkState;
512
513 public:
514 void reset();
515 double getTargetPosition() const;
516 void setTargetPosition(double value);
517
518 Output run();
519 };
520} // namespace armarx
std::string timestamp()
#define M_PI
Definition MathTools.h:17
constexpr T dt
std::unique_ptr< FixedMinJerkState > fixedMinJerkState
#define q
This file offers overloads of toIce() and fromIce() functions for STL container types.
float positionThroughVelocityControlWithAccelerationAndPositionBounds(float dt, float maxDt, float currentV, float maxV, float acceleration, float deceleration, float currentPosition, float targetPosition, float p, float positionLimitLo, float positionLimitHi)
float velocityControlWithAccelerationBounds(float dt, float maxDt, const float currentV, float targetV, float maxV, float acceleration, float deceleration, float directSetVLimit)
std::array< deltas, 3 > trapeze(float v0, float acc, float vMax, float dec, float vt, float dx)
std::array< deltas, 3 > trapezeWithDt(float v0, float acc, float vMax, float dec, float vt, float dx, float dt)
std::shared_ptr< const RampedAccelerationVelocityControllerConfiguration > RampedAccelerationVelocityControllerConfigurationCPtr
deltas accelerateToVelocity(float v0, float acc, float vt)
float positionThroughVelocityControlWithAccelerationBoundsAndPeriodicPosition(float dt, float maxDt, float currentV, float maxV, float acceleration, float deceleration, float currentPosition, float targetPosition, float pControlPosErrorLimit, float p, float &direction, float positionPeriodLo, float positionPeriodHi)
std::shared_ptr< class RampedAccelerationVelocityControllerConfiguration > RampedAccelerationVelocityControllerConfigurationPtr
std::pair< T, T > pq(T p, T q)
float trapezeArea(float v0, float vmax, float dt1, float dt2, float dt3)
T periodicClamp(T value, T periodLo, T periodHi)
T sign(T t)
Definition algorithm.h:214
float brakingDistance(float v0, float deceleration)
float velocityControlWithAccelerationAndPositionBounds(float dt, float maxDt, float currentV, float targetV, float maxV, float acceleration, float deceleration, float directSetVLimit, float currentPosition, float positionLimitLoSoft, float positionLimitHiSoft, float positionLimitLoHard, float positionLimitHiHard)
float angleDistance(float angle1, float angle2)
void findVelocityAndAccelerationForTimeAndDistance(float distance, float v0, float vmax, float dec, std::array< deltas, 3 > trapeze, float newDt, float &newV, float &newAcc, float &newDec)
float positionThroughVelocityControlWithAccelerationBounds(float dt, float maxDt, float currentV, float maxV, float acceleration, float deceleration, float currentPosition, float targetPosition, float p)
double distance(const Point &a, const Point &b)
Definition point.hpp:95
Performs velocity control while staying in positional bounds, obeying acceleration / deceleration and...