BasicControllers.cpp
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 #include "BasicControllers.h"
24 
25 #include <algorithm>
26 
29 
30 #include "util/CtrlUtil.h"
31 
32 namespace armarx
33 {
34  float
36  float maxDt,
37  const float currentV,
38  float targetV,
39  float maxV,
40  float acceleration,
41  float deceleration,
42  float directSetVLimit)
43  {
44  dt = std::min(std::abs(dt), std::abs(maxDt));
45  maxV = std::abs(maxV);
46  acceleration = std::abs(acceleration);
47  deceleration = std::abs(deceleration);
48  targetV = std::clamp(targetV, -maxV, maxV);
49 
50  //we can have 3 cases:
51  // 1. we directly set v and ignore acc/dec (if |curr - target| <= limit)
52  // 2. we need to accelerate (if curr and target v have same sign and |curr| < |target|)
53  // 3. we need to decelerate (other cases)
54 
55  //handle case 1
56  const float curverror = targetV - currentV;
57  if (std::abs(curverror) < directSetVLimit)
58  {
59  return targetV;
60  }
61 
62  //handle case 2 + 3
63  const bool accelerate = sign(targetV) == sign(currentV) && // v in same direction
64  std::abs(targetV) > std::abs(currentV); // currently to slow
65 
66  const float usedacc = accelerate ? acceleration : -deceleration;
67  const float maxDeltaV = std::abs(usedacc * dt);
68  if (maxDeltaV >= std::abs(curverror))
69  {
70  //we change our v too much with the used acceleration
71  //but we could reach our target with a lower acceleration ->set the target
72 
73  return targetV;
74  }
75  const float deltaVel = std::clamp(sign(currentV) * usedacc * dt, -maxDeltaV, maxDeltaV);
76  const float nextV = currentV + deltaVel;
77  return nextV;
78  }
79 
80  ////////////////////////////
81  //wip?
82  float
84  float maxDt,
85  float currentV,
86  float targetV,
87  float maxV,
88  float acceleration,
89  float deceleration,
90  float directSetVLimit,
91  float currentPosition,
92  float positionLimitLoSoft,
93  float positionLimitHiSoft,
94  float positionLimitLoHard,
95  float positionLimitHiHard)
96  {
97  if (currentPosition <= positionLimitLoHard || currentPosition >= positionLimitHiHard)
98  {
99  return std::nanf("1");
100  }
101 
102  float softLimitViolation = 0;
103  if (currentPosition <= positionLimitLoSoft)
104  {
105  softLimitViolation = -1;
106  }
107  if (currentPosition >= positionLimitHiSoft)
108  {
109  softLimitViolation = 1;
110  }
111 
112  const float upperDt = std::max(std::abs(dt), std::abs(maxDt));
113  dt = std::min(std::abs(dt), std::abs(maxDt));
114  maxV = std::abs(maxV);
115 
116  //we can have 4 cases:
117  // 1. we need to decelerate now or we will violate the position limits (maybe we still will violate them, e.g. if we violated them initially)
118  // 2. we directly set v and ignore acc/dec (if |curr - target| <= limit)
119  // 3. we need to accelerate (if curr and target v have same sign and |curr| < |target|)
120  // 4. we need to decelerate (other cases)
121  float nextv;
122  //handle case 1
123  const float vsquared = currentV * currentV;
124  const float brakingDist =
125  sign(currentV) * vsquared / 2.f /
126  std::abs(deceleration); //the braking distance points in the direction of the velocity
127 
128 
129  const float posIfBrakingNow = currentPosition + brakingDist;
130  if (posIfBrakingNow <= positionLimitLoSoft || posIfBrakingNow >= positionLimitHiSoft)
131  {
132  //case 1. -> brake now! (we try to have v=0 at the limit)
133  const auto limit =
134  posIfBrakingNow <= positionLimitLoSoft ? positionLimitLoSoft : positionLimitHiSoft;
135  const float wayToGo = limit - currentPosition;
136 
137  //decelerate!
138  // s = v²/(2a) <=> a = v²/(2s)
139  const float dec = std::abs(vsquared / 2.f / wayToGo);
140  const float vel = currentV - sign(currentV) * dec * upperDt;
141  nextv = std::clamp(vel, -maxV, maxV);
142  if (sign(currentV) != sign(nextv))
143  {
144  //stop now
145  nextv = 0;
146  }
147  }
148  else
149  {
150  //handle 2-3
152  dt, maxDt, currentV, targetV, maxV, acceleration, deceleration, directSetVLimit);
153  }
154  if (softLimitViolation == sign(nextv))
155  {
156  //the area between soft and hard limits is sticky
157  //the controller can only move out of it (not further in)
158  return 0;
159  }
160 
161  //the next velocity will not violate the pos bounds harder than they are already
162  return nextv;
163  }
164 
165  float
167  float maxDt,
168  float currentV,
169  float maxV,
170  float acceleration,
171  float deceleration,
172  float currentPosition,
173  float targetPosition,
174  float p)
175  {
176  dt = std::min(std::abs(dt), std::abs(maxDt));
177  maxV = std::abs(maxV);
178  acceleration = std::abs(acceleration);
179  deceleration = std::abs(deceleration);
180  const float signV = sign(currentV);
181  //we can have 3 cases:
182  // 1. we use a p controller and ignore acc/dec (if velocity target from p controller < velocity target from ramp controller)
183  // 2. we need to accelerate (or hold vel) (if e = (targetPosition - currentPosition)
184  // the brakingDistance have the same sign and brakingDistance < e
185  // and currentVel <= maxV)
186  // 3. we need to decelerate (other cases)
187 
188  //handle case 1
189  const float positionError = targetPosition - currentPosition;
190  float newTargetVelPController = positionError * p;
191 
192  //handle case 2-3
193  const float brakingDistance =
194  signV * currentV * currentV / 2.f /
195  deceleration; //the braking distance points in the direction of the velocity
196  const float posIfBrakingNow = currentPosition + brakingDistance;
197  const float posErrorIfBrakingNow = targetPosition - posIfBrakingNow;
198 
199  const bool decelerate =
200  std::abs(currentV) > maxV || // we need to slow down (to stay in [-maxV,maxV]
201  // std::abs(posIfBrakingNow - targetPosition) <= pControlPosErrorLimit || // we want to hit the target
202  sign(posErrorIfBrakingNow) != signV; // we are moving away from the target
203  const float usedacc = decelerate ? -deceleration : acceleration;
204  const float maxDeltaV = std::abs(usedacc * dt);
205  const float deltaVel = std::clamp(signV * usedacc * dt, -maxDeltaV, maxDeltaV);
206 
207  float newTargetVel = std::clamp(currentV + deltaVel, -maxV, maxV);
208  bool usePID = std::abs(newTargetVelPController) < std::abs(newTargetVel);
209  // ARMARX_INFO << deactivateSpam(0.01) << VAROUT(usePID) << VAROUT(dt) << VAROUT(decelerate) << VAROUT(usedacc) << VAROUT(maxDeltaV) << VAROUT(deltaVel) << VAROUT(newTargetVel) << VAROUT(newTargetVelPController)
210  // << VAROUT(currentPosition) << VAROUT(targetPosition);
211  if (usePID)
212  {
213  return newTargetVelPController;
214  }
215  else
216  {
217  return newTargetVel;
218  }
219  }
220 
221  float
223  float maxDt,
224  float currentV,
225  float maxV,
226  float acceleration,
227  float deceleration,
228  float currentPosition,
229  float targetPosition,
230  float p,
231  float positionLimitLo,
232  float positionLimitHi
233 
234  )
235  {
236  dt = std::min(std::abs(dt), std::abs(maxDt));
237  maxV = std::abs(maxV);
238  acceleration = std::abs(acceleration);
239  deceleration = std::abs(deceleration);
240  const float signV = sign(currentV);
241  //we can have 4 cases:
242  // 1. we need to decelerate now or we will violate the position limits (maybe we still will violate them)
243  // 2. we use a p controller and ignore acc/dec (if |currentPosition - targetPosition| <= pControlPosErrorLimit AND |currentPosition - targetPosition|*p < maxV)
244  // 4. we need to accelerate (or hold vel) (if e = (targetPosition - currentPosition)
245  // and the brakingDistance have the same sign and brakingDistance < e
246  // and currentVel <= maxV)
247  // 5. we need to decelerate (other cases)
248 
249  //handle case 1
250  const float vsquared = currentV * currentV;
251  const float brakingDistance =
252  signV * vsquared / 2.f /
253  deceleration; //the braking distance points in the direction of the velocity
254  const float posIfBrakingNow = currentPosition + brakingDistance;
255  if (posIfBrakingNow <= positionLimitLo || posIfBrakingNow >= positionLimitHi)
256  {
257  //case 1. -> brake now! (we try to have v=0 at the limit)
258  const auto limit = brakingDistance > 0 ? positionLimitHi : positionLimitLo;
259  const float wayToGo = std::abs(limit - currentPosition);
260  // s = v²/(2a) <=> a = v²/(2s)
261  const float dec = std::abs(vsquared / 2.f / wayToGo);
262  const float vel = currentV - signV * dec * dt;
263  return vel;
264  }
265 
266  //handle case 2-3
268  dt,
269  maxDt,
270  currentV,
271  maxV,
272  acceleration,
273  deceleration,
274  currentPosition,
275  std::clamp(targetPosition, positionLimitLo, positionLimitHi),
276  p);
277  }
278 
279  ////////////////////////////
280  //wip
281 
282 
283  float
285  float dt,
286  float maxDt,
287  float currentV,
288  float maxV,
289  float acceleration,
290  float deceleration,
291  float currentPosition,
292  float targetPosition,
293  float pControlPosErrorLimit,
294  float p,
295  float& direction,
296  float positionPeriodLo,
297  float positionPeriodHi)
298  {
299  currentPosition = periodicClamp(currentPosition, positionPeriodLo, positionPeriodHi);
300  targetPosition = periodicClamp(targetPosition, positionPeriodLo, positionPeriodHi);
301 
302  const float brakingDist = brakingDistance(currentV, deceleration);
303  const float posIfBrakingNow = currentPosition + brakingDist;
304  const float posIfBrakingNowError = targetPosition - posIfBrakingNow;
305  const float posError = targetPosition - currentPosition;
306  if (std::abs(posIfBrakingNowError) <= pControlPosErrorLimit ||
307  std::abs(posError) <= pControlPosErrorLimit)
308  {
309  //this allows slight overshooting (in the limits of the p controller)
311  maxDt,
312  currentV,
313  maxV,
314  acceleration,
315  deceleration,
316  currentPosition,
317  targetPosition,
318  p);
319  }
320 
321  //we transform the problem with periodic bounds into
322  //a problem with position bounds
323  const float positionPeriodLength = std::abs(positionPeriodHi - positionPeriodLo);
324 
325  //we shift the positions such that 0 == target
326  currentPosition =
327  periodicClamp(currentPosition - targetPosition, 0.f, positionPeriodLength);
328  //how many times will we go ovet the target if we simply bake now?
329  const float overshoot = std::trunc((currentPosition + brakingDist) / positionPeriodLength);
330 
331  if (true || direction == 0)
332  {
333  //determine the direction to go (1 == pos vel, -1 == neg vel)
334  direction = (periodicClamp(currentPosition + brakingDist, 0.f, positionPeriodLength) >=
335  positionPeriodLength / 2)
336  ? 1
337  : -1;
338  }
339  //shift the target away from 0
340  targetPosition = (overshoot - std::min(0.f, -direction)) *
341  positionPeriodLength; // - direction * pControlPosErrorLimit;
342 
343  //move
345  maxDt,
346  currentV,
347  maxV,
348  acceleration,
349  deceleration,
350  currentPosition,
351  targetPosition,
352  p);
353  }
354 
355  bool
357  {
358  return maxV > 0 && acceleration > 0 && deceleration > 0 && targetV <= maxV &&
359  targetV >= -maxV;
360  }
361 
362  float
364  {
365  const float useddt = std::min(std::abs(dt), std::abs(maxDt));
366 
367  //we can have 3 cases:
368  // 1. we directly set v and ignore acc/dec (if |curr - target| <= limit)
369  // 2. we need to accelerate (if curr and target v have same sign and |curr| < |target|)
370  // 3. we need to decelerate (other cases)
371  //handle case 1
372  const float curverror = targetV - currentV;
373  if (std::abs(curverror) < directSetVLimit)
374  {
375  return targetV;
376  }
377 
378  //handle case 2 + 3
379  const bool accelerate = sign(targetV) == sign(currentV) && // v in same direction
380  std::abs(targetV) > std::abs(currentV); // currently to slow
381 
382  const float usedacc = accelerate ? acceleration : -deceleration;
383  const float maxDeltaV = std::abs(usedacc * useddt);
384  if (maxDeltaV >= std::abs(curverror))
385  {
386  //we change our v too much with the used acceleration
387  //but we could reach our target with a lower acceleration ->set the target
388 
389  return targetV;
390  }
391  const float deltaVel = std::clamp(sign(currentV) * usedacc * useddt, -maxDeltaV, maxDeltaV);
392  const float nextV = currentV + deltaVel;
393  return nextV;
394  }
395 
396  bool
398  {
399  return maxV > 0 && jerk > 0 && targetV <= maxV && targetV >= -maxV;
400  }
401 
404  {
405  const double useddt = std::min(std::abs(dt), std::abs(maxDt));
406 
407  //we can have 3 cases:
408  // 1. we directly set v and ignore acc/dec (if |curr - target| <= limit)
409  // 2. we need to accelerate (if curr and target v have same sign and |curr| < |target|)
410  // 3. we need to decelerate (other cases)
411  //handle case 1
412  const double clampedTargetV = math::MathUtils::LimitTo(targetV, maxV);
413  const double curverror = clampedTargetV - currentV;
414  if (std::abs(curverror) < directSetVLimit)
415  {
416  // double nextAcc = (clampedTargetV - currentV) / useddt; // calculated acc is unstable!!!
417  // double nextJerk = (nextAcc - currentAcc) / useddt;
418  Output result{clampedTargetV, 0, 0};
419 
420  return result;
421  }
422 
423  //handle case 2 + 3
424  // const bool accelerate = sign(clampedTargetV) == sign(currentV) && // v in same direction
425  // std::abs(clampedTargetV) > std::abs(currentV); // currently to slow
426  const auto goalDir = math::MathUtils::Sign(clampedTargetV - currentV);
427  // calculate if we need to increase or decrease acc
428  bool increaseAcc = true;
429  if (goalDir == math::MathUtils::Sign(currentAcc))
430  {
431  // double t_to_v = ctrlutil::t_to_v(clampedTargetV - currentV, currentAcc, goalDir * jerk);
432  // double acc_at_t = ctrlutil::a(t_to_v, std::abs(currentAcc), -jerk);
433  // increaseJerk = acc_at_t < 0.0;
434 
435  double t_to_zero_acc = std::abs(currentAcc) / jerk;
436  double v_at_t = ctrlutil::v(t_to_zero_acc, currentV, currentAcc, -goalDir * jerk);
437  increaseAcc = math::MathUtils::Sign(v_at_t - clampedTargetV) != goalDir;
438  // ARMARX_INFO << VAROUT(t_to_zero_acc) << VAROUT(v_at_t) << VAROUT(increaseAcc);
439  }
440  // v = a*a/(2j)
441  const double adjustedJerk =
442  std::abs(currentAcc * currentAcc / (2 * (clampedTargetV - currentV)));
443  double usedJerk = increaseAcc
444  ? goalDir * jerk
445  : -goalDir * ((std::abs(currentV) > 0.01 && !std::isnan(adjustedJerk))
446  ? adjustedJerk
447  : jerk);
448  // double t_to_target_v = ctrlutil::t_to_v(clampedTargetV - currentV, currentAcc, usedJerk);
449  // double v_at_t2 = ctrlutil::v(t_to_target_v, currentV, currentAcc, usedJerk);
450  // ctrlutil::t_to_v(currentV, currentAcc, jerk);
451  // const double usedacc = currentAcc + useddt * usedJerk;
452  // const double maxDeltaVSimple = usedacc * useddt;
453 
454  const double maxDeltaV = std::abs(ctrlutil::v(useddt, 0, currentAcc, usedJerk));
455  if (maxDeltaV >= std::abs(curverror))
456  {
457  //we change our v too much with the used acceleration
458  //but we could reach our target with a lower acceleration ->set the target
459  double nextAcc = (clampedTargetV - currentV) / useddt;
460  double nextJerk = (nextAcc - currentAcc) / useddt;
461  // ARMARX_INFO << "overshooting! " << VAROUT(clampedTargetV) << VAROUT(nextAcc) << VAROUT(nextJerk);
462  Output result{clampedTargetV, nextAcc, nextJerk};
463  return result;
464  }
465  // const double deltaVel = boost::algorithm::clamp(sign(currentV) * usedacc * useddt, -maxDeltaV, maxDeltaV);
466  const double nextV = ctrlutil::v(useddt, currentV, currentAcc, usedJerk);
467  const double nextAcc = ctrlutil::a(useddt, currentAcc, usedJerk);
468  // ARMARX_INFO << VAROUT(clampedTargetV) << VAROUT(nextV) << VAROUT(nextAcc) << VAROUT(usedJerk);
469  Output result{nextV, nextAcc, usedJerk};
470  return result;
471  }
472 
473  float
475  {
476  const float curverror = std::abs(targetV - currentV);
477  if (curverror < directSetVLimit)
478  {
479  return maxDt;
480  }
481  return curverror / ((targetV > currentV) ? acceleration : deceleration);
482  }
483 
484  bool
486  {
488  // positionLimitLoHard < positionLimitLoSoft &&
490  // positionLimitHiSoft < positionLimitHiHard;
491  }
492 
493  float
495  {
496  // if (currentPosition <= positionLimitLoHard || currentPosition >= positionLimitHiHard)
497  // {
498  // ARMARX_INFO << deactivateSpam(1) << "Hard limit violation. " << VAROUT(currentPosition) << VAROUT(positionLimitLoHard) << VAROUT(positionLimitHiHard);
499  // return std::nanf("1");
500  // }
501 
502  float softLimitViolation = 0;
504  {
505  softLimitViolation = -1;
506  }
508  {
509  softLimitViolation = 1;
510  }
511 
512  const float upperDt = std::max(std::abs(dt), std::abs(maxDt));
513 
514  //we can have 4 cases:
515  // 1. we need to decelerate now or we will violate the position limits (maybe we still will violate them, e.g. if we violated them initially)
516  // 2. we directly set v and ignore acc/dec (if |curr - target| <= limit)
517  // 3. we need to accelerate (if curr and target v have same sign and |curr| < |target|)
518  // 4. we need to decelerate (other cases)
519  float nextv;
520  //handle case 1
521  const float vsquared = currentV * currentV;
522  const float brakingDist =
523  sign(currentV) * vsquared / 2.f /
524  std::abs(deceleration); //the braking distance points in the direction of the velocity
525 
526  const float posIfBrakingNow = currentPosition + brakingDist;
527  // ARMARX_INFO << deactivateSpam(1) << VAROUT(currentPosition) << VAROUT(positionLimitLoSoft) << VAROUT(positionLimitHiSoft) << VAROUT(posIfBrakingNow);
528  if ((posIfBrakingNow <= positionLimitLoSoft && currentV < 0) ||
529  (posIfBrakingNow >= positionLimitHiSoft && currentV > 0))
530  {
531  //case 1. -> brake now! (we try to have v=0 at the limit)
532  const auto limit =
534  const float wayToGo = limit - currentPosition;
535 
536  //decelerate!
537  // s = v²/(2a) <=> a = v²/(2s)
538  const float dec = std::abs(vsquared / 2.f / wayToGo);
539  const float vel = currentV - sign(currentV) * dec * upperDt;
540  nextv = std::clamp(vel, -maxV, maxV);
541  // ARMARX_INFO << deactivateSpam(1) << "clamped new Vel: " << VAROUT(nextv);
542  if (sign(currentV) != sign(nextv))
543  {
544  // ARMARX_INFO << deactivateSpam(1) << "wrong sign: stopping"; //stop now
545  nextv = 0;
546  }
547  }
548  else
549  {
550  //handle 2-3
552  // ARMARX_INFO << deactivateSpam(1) << "Desired target Vel: " << targetV << " " << VAROUT(nextv);
553  }
554  if (softLimitViolation == sign(nextv) && nextv != 0)
555  {
556  //the area between soft and hard limits is sticky
557  //the controller can only move out of it (not further in)
558  // ARMARX_DEBUG << deactivateSpam(1) << "Soft limit violation. " << softLimitViolation << VAROUT(nextv);
559  return 0;
560  }
561 
562  //the next velocity will not violate the pos bounds harder than they are already
563  return nextv;
564  }
565 
568  {
569 #ifdef DEBUG_POS_CTRL
570  buffer = boost::circular_buffer<HelpStruct>(20);
571 #endif
572  pid.reset(new PIDController(1, 0, 0));
573  pid->threadSafe = false;
574  }
575 
576  float
578  {
579  /* s = v_0*v_0/(2*a) -> sqrt(s*2*a) = v_0;
580 
581  K_p * error = v_0; -> v_0/error = K_p;
582  */
583  auto v_0 = std::sqrt(pControlPosErrorLimit * 2 * deceleration);
584  return v_0 / pControlPosErrorLimit;
585  }
586 
587  bool
589  {
590  return maxV > 0 && acceleration > 0 && deceleration > 0 &&
591  // pControlPosErrorLimit > 0 &&
592  // pControlVelLimit > 0 &&
593  pid->Kp > 0;
594  }
595 
596  float
598  {
599  const float useddt = std::min(std::abs(dt), std::abs(maxDt));
600  const float signV = sign(currentV);
601  //we can have 3 cases:
602  // 1. we use a p controller and ignore acc/dec (if |currentPosition - targetPosition| <= pControlPosErrorLimit AND |currentV| < pControlVelLimit)
603  // 2. we need to accelerate (or hold vel) (if e = (targetPosition - currentPosition)
604  // the brakingDistance have the same sign and brakingDistance < e
605  // and currentVel <= maxV)
606  // 3. we need to decelerate (other cases)
607 
608  //handle case 1
609  const float positionError = targetPosition - currentPosition;
610  pid->update((double)useddt, (double)currentPosition, (double)targetPosition);
611  float newTargetVelPController = pid->getControlValue();
612 
613  //handle case 2-3
614  const float brakingDistance =
615  signV * currentV * currentV / 2.f /
616  deceleration; //the braking distance points in the direction of the velocity
617  const float posIfBrakingNow = currentPosition + brakingDistance;
618  const float posErrorIfBrakingNow = targetPosition - posIfBrakingNow;
619  const bool hardBrakingNeeded = std::abs(brakingDistance) > std::abs(positionError);
620  const float safePositionError =
621  (std::abs(positionError) < 0.0001) ? (sign(positionError) * 0.0001) : positionError;
622  const float usedDeceleration = hardBrakingNeeded
623  ? std::abs(currentV * currentV / 2.f / safePositionError)
624  : deceleration;
625 
626  const bool decelerate =
627  std::abs(currentV) > maxV || // we need to slow down (to stay in [-maxV,maxV]
628  hardBrakingNeeded ||
629  sign(posErrorIfBrakingNow) != signV; // we are moving away from the target
630 
631  const float usedacc = decelerate ? -usedDeceleration : acceleration;
632  const float deltaVel = signV * usedacc * useddt;
633  float newTargetVelRampCtrl = std::clamp(currentV + deltaVel, -maxV, maxV);
634  bool PIDActive = /*std::abs(newTargetVelPController) < std::abs(newTargetVelRampCtrl)
635  || std::abs(newTargetVelPController) < pControlVelLimit ||*/
636  std::abs(positionError) < pControlPosErrorLimit;
637  // if (currentlyPIDActive != PIDActive && PIDActive)
638  // {
639  // ARMARX_INFO << "Switching to PID mode: " << VAROUT(positionError) << VAROUT(newTargetVelPController) << VAROUT(newTargetVelRampCtrl);
640  // }
641  this->currentlyPIDActive = PIDActive;
642  float finalTargetVel =
643  (currentlyPIDActive) ? newTargetVelPController : newTargetVelRampCtrl;
644  if (std::abs(positionError) < accuracy)
645  {
646  return 0.0; // if close to target set zero velocity to avoid oscillating around target
647  }
648  // if (hardBrakingNeeded)
649  // {
650  // ARMARX_INFO /*<< deactivateSpam(0.1)*/ << "Hard braking! " << VAROUT(positionError) << VAROUT(brakingDistance) << VAROUT(finalTargetVel) << VAROUT(currentV);
651  // }
652  // if (decelerate)
653  // {
654  // ARMARX_INFO /*<< deactivateSpam(0.1)*/ << "Decelerating! " << VAROUT(targetPosition) << VAROUT(currentPosition) << VAROUT(positionError) << VAROUT(brakingDistance) << VAROUT(finalTargetVel) << VAROUT(currentV) <<
655  // VAROUT(usedacc) << VAROUT(deltaVel) << VAROUT(useddt);
656  // }
657 #ifdef DEBUG_POS_CTRL
658  buffer.push_back({currentPosition,
659  newTargetVelPController,
660  newTargetVelRampCtrl,
661  currentV,
662  positionError,
663  IceUtil::Time::now().toMicroSeconds()});
664 
665  // if (PIDModeActive != usePID)
666  if (buffer.size() > 0 &&
667  sign(positionError) * sign(buffer[buffer.size() - 2].currentError) < 0 &&
668  eventHappeningCounter < 0)
669  {
670  eventHappeningCounter = 10;
671  ARMARX_IMPORTANT << "HIGH VELOCITY DETECTED";
672  }
673  if (eventHappeningCounter == 0)
674  {
675  ARMARX_IMPORTANT << "BUFFER CONTENT";
676  for (auto& elem : buffer)
677  {
678  ARMARX_INFO << VAROUT(elem.currentPosition) << VAROUT(elem.targetVelocityPID)
679  << VAROUT(elem.targetVelocityRAMP) << VAROUT(elem.currentV)
680  << VAROUT(elem.currentError) << VAROUT(elem.timestamp);
681  }
682  ARMARX_IMPORTANT << VAROUT(newTargetVelPController) << VAROUT(newTargetVelRampCtrl)
683  << VAROUT(currentPosition) << VAROUT(usePID) << VAROUT(positionError);
684  }
685  if (eventHappeningCounter >= 0)
686  {
687  eventHappeningCounter--;
688  }
689 
690  ARMARX_INFO << deactivateSpam(5) << VAROUT(newTargetVelPController)
691  << VAROUT(newTargetVelRampCtrl) << VAROUT(currentPosition) << VAROUT(usePID)
692  << VAROUT(positionError) << VAROUT(targetPosition) << VAROUT(currentV)
693  << VAROUT(deltaVel) << VAROUT(useddt) << VAROUT(usedacc);
694  PIDModeActive = usePID;
695 #endif
696 
697  return finalTargetVel;
698  }
699 
700  float
702  {
703  // const float brakingDistance = sign(currentV) * currentV * currentV / 2.f / deceleration;
704  const float posError = targetPosition - currentPosition;
705  const float posIfBrakingNow = currentPosition + brakingDistance(currentV, deceleration);
706  //we are near the goal if we break now
707  // if (std::abs(posIfBrakingNow - targetPosition) <= pControlPosErrorLimit && currentV <= pControlVelLimit)
708  // {
709  // return std::sqrt(2 * std::abs(brakingDistance(currentV, deceleration)) / deceleration);
710  // }
711  const float posErrorIfBrakingNow = targetPosition - posIfBrakingNow;
712 
713  float t = 0;
714  float curVel = currentV;
715  float curPos = currentPosition;
716  auto curPosEr = [&] { return targetPosition - curPos; };
717  // auto curBrake = [&] {return std::abs(brakingDistance(curVel, deceleration));};
718 
719  //check for overshooting of target
720  if (sign(posError) != sign(posErrorIfBrakingNow))
721  {
722  t = currentV / deceleration;
723  curVel = 0;
724  curPos = posIfBrakingNow;
725  }
726  // //check for to high v
727  // if (std::abs(curVel) > maxV)
728  // {
729  // const float dv = curVel - maxV;
730  // float dt = dv / deceleration;
731  // t += dt;
732  // // curPos += 0.5f / deceleration * dv * dv * sign(curVel);
733  // curPos += 0.5 * deceleration * dt * dt + curVel * dt * sign(curVel);
734  // curVel = maxV;
735  // }
736  //curBrake()<=curPosEr() && curVel <= maxV
737  // auto tr = trapeze(curVel, acceleration, maxV, deceleration, 0, curPosEr());
738  auto tr = trapeze(curVel,
739  std::abs(curVel) > maxV ? deceleration : acceleration,
740  maxV,
741  deceleration,
742  0,
743  curPosEr());
744 
745  return t + tr.at(0).dt + tr.at(1).dt + tr.at(2).dt;
746  }
747 
748  bool
750  {
752  !std::isnan(positionLimitLo) && !std::isnan(positionLimitHi) &&
755  }
756 
757  float
759  {
760  const float useddt = std::min(std::abs(dt), std::abs(maxDt));
761  const float signV = sign(currentV);
762  //we can have 4 cases:
763  // 1. we need to decelerate now or we will violate the position limits (maybe we still will violate them)
764  // 2. we use a p controller and ignore acc/dec (if |currentPosition - targetPosition| <= pControlPosErrorLimit AND |currentPosition - targetPosition|*p < maxV)
765  // 4. we need to accelerate (or hold vel) (if e = (targetPosition - currentPosition)
766  // and the brakingDistance have the same sign and brakingDistance < e
767  // and currentVel <= maxV)
768  // 5. we need to decelerate (other cases)
769  //handle case 1
770  const float vsquared = currentV * currentV;
771  const float brakingDistance =
772  signV * vsquared / 2.f /
773  deceleration; //the braking distance points in the direction of the velocity
774  const float posIfBrakingNow = currentPosition + brakingDistance;
775  float direction = targetPosition < currentPosition ? -1 : 1;
776  // ARMARX_INFO << deactivateSpam(0.5) << VAROUT(direction) << VAROUT(brakingDistance) << VAROUT(currentPosition) << VAROUT(targetPosition);
777  if ((posIfBrakingNow <= positionLimitLo && direction < 1) ||
778  (posIfBrakingNow >= positionLimitHi && direction > 1))
779  {
780  //case 1. -> brake now! (we try to have v=0 at the limit)
781  const auto limit = brakingDistance > 0 ? positionLimitHi : positionLimitLo;
782  const float wayToGo = std::abs(limit - currentPosition);
783  // s = v²/(2a) <=> a = v²/(2s)
784  const float dec = std::abs(vsquared / 2.f / wayToGo);
785  const float vel = currentV - signV * dec * useddt;
786  // ARMARX_INFO << /*deactivateSpam(0.1) <<*/ "Braking now! " << VAROUT(vel) << VAROUT(wayToGo) << VAROUT(limit);
787  return vel;
788  }
789 
790  //handle case 2-3
792  }
793 
794  std::array<deltas, 3>
795  trapeze(float v0, float acc, float vMax, float dec, float vt, float dx)
796  {
797  acc = std::abs(acc);
798  vMax = std::abs(vMax);
799  dec = std::abs(dec);
800  auto calc = [&](float vmax)
801  {
802  const deltas dacc = accelerateToVelocity(v0, acc, vmax);
803  const deltas ddec = accelerateToVelocity(vmax, dec, vt);
804  const float dxMax = dacc.dx + ddec.dx;
805  if (sign(dxMax) == sign(dx))
806  {
807  if (std::abs(dxMax) <= dx)
808  {
809  deltas mid;
810  mid.dx = dxMax - dx;
811  mid.dv = vMax;
812  mid.dt = std::abs(mid.dx / mid.dv);
813  return std::make_pair(true, std::array<deltas, 3>{dacc, mid, ddec});
814  }
815  //we need a lower vMax (vx)
816  //in all following formulas # elem {0,t}
817  //a0=acc , at = dec
818  //vx=v0+dv0 = vt + dvt -> dv# = vx-v#
819  //dx=dx0+dxt
820  //dx#=dv#^2/2/a#+dv#/a#*v#
821  //dx#=(vx-v#)^2/2/a#+(vx-v#)/a#*v#
822  //dx#=vx^2*(1/2/a#) + vx*(v#/2 - v#/a#) + (v#^2/2/a# - v#^2/2)
823  //dx=vx^2*(1/2/a0+1/2/at) + vx*(v0/2 - v0/a0 + vt/2 - vt/at) + (v0^2/2/a0 - v0^2/2 +vt^2/2/at - vt^2/2)
824  //0 =vx^2*(1/2/a0+1/2/at) + vx*(v0/2 - v0/a0 + vt/2 - vt/at) + (v0^2/2/a0 - v0^2/2 +vt^2/2/at - vt^2/2 -dx)
825  //div = (1/2/a0 + 1/2/at )
826  //p = (v0/2 - v0/a0 + vt/2 - vt/at )/div
827  //q = (v0^2/2/a0 - v0^2/2 + vt^2/2/at - vt^2/2 -dx)/div
828  // -> vx1/2 = pq(p,q)
829  const float a0 = acc;
830  const float at = dec;
831  const float div = (1.f / 2.f / a0 + 1.f / 2.f / at);
832  const float p = (v0 / 2.f - v0 / a0 + vt / 2.f - vt / at) / div;
833  const float q =
834  (v0 * v0 / 2.f * (1.f / a0 - 1.f) + vt * vt / 2.f * (1.f / at - 1.f) - dx) /
835  div;
836  const auto vxs = pq(p, q);
837  //one or both of the results may be invalid
838  bool vx1Valid = std::isfinite(vxs.first) && std::abs(vxs.first) <= std::abs(vmax);
839  bool vx2Valid = std::isfinite(vxs.second) && std::abs(vxs.second) <= std::abs(vmax);
840  switch (vx1Valid + vx2Valid)
841  {
842  case 0:
843  return std::make_pair(false, std::array<deltas, 3>());
844  case 1:
845  {
846  float vx = vx1Valid ? vxs.first : vxs.second;
847  const deltas daccvx = accelerateToVelocity(v0, acc, vx);
848  const deltas ddecvx = accelerateToVelocity(vx, dec, vt);
849  deltas mid;
850  mid.dx = 0;
851  mid.dv = vx;
852  mid.dt = 0;
853  return std::make_pair(true, std::array<deltas, 3>{daccvx, mid, ddecvx});
854  }
855  case 2:
856  {
857  const deltas daccvx1 = accelerateToVelocity(v0, acc, vxs.first);
858  const deltas ddecvx1 = accelerateToVelocity(vxs.first, dec, vt);
859  const deltas daccvx2 = accelerateToVelocity(v0, acc, vxs.second);
860  const deltas ddecvx2 = accelerateToVelocity(vxs.second, dec, vt);
861  deltas mid;
862  mid.dx = 0;
863  mid.dt = 0;
864  if (daccvx1.dt + ddecvx1.dt < daccvx2.dt + ddecvx2.dt)
865  {
866  mid.dv = vxs.first;
867  return std::make_pair(true,
868  std::array<deltas, 3>{daccvx1, mid, ddecvx1});
869  }
870  mid.dv = vxs.second;
871  return std::make_pair(true, std::array<deltas, 3>{daccvx2, mid, ddecvx2});
872  }
873  default:
874  throw std::logic_error{"unreachable code (bool + bool neither 0,1,2)"};
875  }
876  }
877  return std::make_pair(false, std::array<deltas, 3>());
878  };
879 
880  const auto plusVMax = calc(vMax);
881  const auto negVMax = calc(-vMax);
882  switch (plusVMax.first + negVMax.first)
883  {
884  case 0:
885  throw std::invalid_argument("could not find a trapez to reach the goal");
886  case 1:
887  return plusVMax.first ? plusVMax.second : negVMax.second;
888  case 2:
889  {
890  const float dt1 =
891  plusVMax.second.at(0).dt + plusVMax.second.at(1).dt + plusVMax.second.at(2).dt;
892  const float dt2 =
893  negVMax.second.at(0).dt + negVMax.second.at(1).dt + negVMax.second.at(2).dt;
894  return dt1 < dt2 ? plusVMax.second : negVMax.second;
895  }
896  default:
897  throw std::logic_error{"unreachable code (bool + bool neither 0,1,2)"};
898  }
899  }
900 
901  float
903  {
904  //run should be static, but we need to adapt the parabs for the subcontroler -> have the subcontroler as value;
906  *this; // slice parent class from this
908  // ARMARX_INFO << deactivateSpam(1) << VAROUT(currentPosition) << VAROUT(sub.currentPosition) << VAROUT(positionPeriodLo) << VAROUT(positionPeriodHi);
910 
911  const float brakingDist = brakingDistance(currentV, deceleration);
912  // const float posIfBrakingNow = currentPosition + brakingDist;
913  // const float posIfBrakingNowError = targetPosition - posIfBrakingNow;
914  // const float posError = targetPosition - currentPosition;
915  // if (
916  // std::abs(posIfBrakingNowError) <= pControlPosErrorLimit ||
917  // std::abs(posError) <= pControlPosErrorLimit
918  // )
919  // {
920  // //this allows slight overshooting (in the limits of the p controller)
921  // return PositionThroughVelocityControllerWithAccelerationBounds::run();
922  // }
923 
924  //we transform the problem with periodic bounds into
925  //a problem with position bounds
926  const float positionPeriodLength = std::abs(positionPeriodHi - positionPeriodLo);
927 
928  //we shift the positions such that 0 == target
929  sub.currentPosition = periodicClamp(currentPosition - targetPosition,
930  -positionPeriodLength * 0.5f,
931  positionPeriodLength * 0.5f);
932  //how many times will we go over the target if we simply brake now?
933  const float overshoot = std::trunc((currentPosition + brakingDist) / positionPeriodLength);
934 
935  ///TODO check if there may be a case requiring the direction
936  float direction = 0;
937  if (direction == 0)
938  {
939  //determine the direction to go (1 == pos vel, -1 == neg vel)
940  direction = (periodicClamp(currentPosition + brakingDist,
941  -positionPeriodLength * 0.5f,
942  positionPeriodLength * 0.5f) <= 0)
943  ? 1
944  : -1;
945  }
946  //shift the target away from 0
947  sub.targetPosition =
948  (overshoot * -direction) * positionPeriodLength; // - direction * pControlPosErrorLimit;
949 
950  //move
951  return sub.run();
952  }
953 
954  double
956  {
957  return targetPosition;
958  }
959 
960  bool
962  {
963  return currentlyPIDActive;
964  }
965 
966  void
968  {
969  if (std::abs(value - targetPosition) > 0.0001)
970  {
972  }
974  }
975 
978  {
979  }
980 
981  bool
983  {
984  return maxV > 0 && acceleration > 0 && deceleration > 0 && jerk > 0 &&
985  // pControlPosErrorLimit > 0 &&
986  // pControlVelLimit > 0 &&
987  p > 0;
988  }
989 
992  {
994  const double useddt = std::min(std::abs(dt), std::abs(maxDt));
995  const double signV = sign(currentV);
996  //we can have 3 cases:
997  // 1. we use a p controller and ignore acc/dec (if |currentPosition - targetPosition| <= pControlPosErrorLimit AND |currentV| < pControlVelLimit)
998  // 2. we need to accelerate (or hold vel) (if e = (targetPosition - currentPosition)
999  // the brakingDistance have the same sign and brakingDistance < e
1000  // and currentVel <= maxV)
1001  // 3. we need to decelerate (other cases)
1002 
1003  //handle case 1
1004  const double positionError = targetPosition - currentPosition;
1005  double newTargetVelPController = (positionError * p) * 0.5 + currentV * 0.5;
1006 
1007  //handle case 2-3
1009  if (brData.dt2 < 0)
1010  {
1012  }
1013  const auto goalDir = math::MathUtils::Sign(targetPosition - currentPosition);
1014  // State currentState;
1015  double usedAbsJerk;
1016  State newState;
1017  Output output;
1018  std::tie(newState, output) = calcState();
1019  usedAbsJerk = output.jerk;
1020  // double newJerk = output.jerk;
1021  // double newAcceleration = output.acceleration;
1022  // ARMARX_INFO << "state: " << (int)state << " new state: " << (int)newState;
1023  state = newState;
1024  const double brakingDistance =
1025  brData.dt2 >= 0
1026  ? brData.s_total
1027  : signV * currentV * currentV / 2.f /
1028  deceleration; //the braking distance points in the direction of the velocity
1029  const double posIfBrakingNow = currentPosition + brakingDistance;
1030  const double posErrorIfBrakingNow = targetPosition - posIfBrakingNow;
1031  const bool hardBrakingNeeded = std::abs(brakingDistance) > std::abs(positionError);
1032  // const double usedJerk = jerk;//currentState==State::DecAccDecJerk?std::abs(ctrlutil::jerk(ctrlutil::t_to_v(currentV, -signV*currentAcc, signV*jerk), positionError, currentV, currentAcc))
1033  // :jerk;
1034  const double jerkDir =
1035  (newState == State::DecAccIncJerk || newState == State::IncAccDecJerk) ? -1.0f : 1.0f;
1036  const double usedJerk = goalDir * jerkDir * usedAbsJerk;
1037  const double deltaAcc = usedJerk * useddt;
1038  const double newAcceleration =
1039  (newState == State::Keep)
1040  ? currentAcc
1041  : (newState == State::DecAccDecJerk ? output.acceleration : currentAcc + deltaAcc);
1042  result.acceleration = newAcceleration;
1043  result.jerk = usedJerk;
1044 
1045  const double usedDeceleration =
1046  hardBrakingNeeded ? -std::abs(currentV * currentV / 2.f /
1047  math::MathUtils::LimitTo(positionError, 0.0001))
1048  : newAcceleration;
1049  (void)usedDeceleration;
1050 
1051  const bool decelerate =
1052  std::abs(currentV) > maxV || // we need to slow down (to stay in [-maxV,maxV]
1053  hardBrakingNeeded ||
1054  sign(posErrorIfBrakingNow) != signV; // we are moving away from the target
1055  (void)decelerate;
1056 
1057  const double deltaVel =
1058  ctrlutil::v(useddt, 0, newAcceleration, usedJerk); //signV * newAcceleration * useddt;
1059  (void)deltaVel;
1060 
1061  double newTargetVelRampCtrl =
1062  ctrlutil::v(useddt,
1063  currentV,
1064  currentAcc,
1065  usedJerk); //boost::algorithm::clamp(currentV + deltaVel, -maxV, maxV);
1066  newTargetVelRampCtrl = std::clamp(newTargetVelRampCtrl, -maxV, maxV);
1067  bool usePID = std::abs(newTargetVelPController) < std::abs(newTargetVelRampCtrl); //||
1068  // std::abs(newTargetVelPController) < pControlVelLimit &&
1069  //std::abs(positionError) < pControlPosErrorLimit;
1070  usePID |= state == State::PCtrl;
1071  usePID &= usePIDAtEnd;
1072  if (usePID)
1073  {
1074  state = State::PCtrl;
1075  }
1076  double finalTargetVel = usePID ? newTargetVelPController : newTargetVelRampCtrl;
1077  ARMARX_INFO << VAROUT(usePID) << VAROUT(result.jerk) << VAROUT(newTargetVelPController)
1078  << VAROUT(currentV);
1079  // ARMARX_INFO << VAROUT(currentV) << VAROUT(currentAcc) << VAROUT(usedJerk) << VAROUT(newAcceleration) << VAROUT(deltaVel) << VAROUT(finalTargetVel) << " new distance: " << (targetPosition - ctrlutil::s(dt, currentPosition, currentV, currentAcc, usedJerk));
1080  if (std::abs(positionError) < accuracy)
1081  {
1082  finalTargetVel =
1083  0.0f; // if close to target set zero velocity to avoid oscillating around target
1084  }
1085 
1086 #ifdef DEBUG_POS_CTRL
1087  buffer.push_back({currentPosition,
1088  newTargetVelPController,
1089  newTargetVelRampCtrl,
1090  currentV,
1091  positionError,
1092  IceUtil::Time::now().toMicroSeconds()});
1093 
1094  // if (PIDModeActive != usePID)
1095  if (buffer.size() > 0 &&
1096  sign(positionError) * sign(buffer[buffer.size() - 2].currentError) < 0 &&
1097  eventHappeningCounter < 0)
1098  {
1099  eventHappeningCounter = 10;
1100  ARMARX_IMPORTANT << "HIGH VELOCITY DETECTED";
1101  }
1102  if (eventHappeningCounter == 0)
1103  {
1104  ARMARX_IMPORTANT << "BUFFER CONTENT";
1105  for (auto& elem : buffer)
1106  {
1107  ARMARX_INFO << VAROUT(elem.currentPosition) << VAROUT(elem.targetVelocityPID)
1108  << VAROUT(elem.targetVelocityRAMP) << VAROUT(elem.currentV)
1109  << VAROUT(elem.currentError) << VAROUT(elem.timestamp);
1110  }
1111  ARMARX_IMPORTANT << VAROUT(newTargetVelPController) << VAROUT(newTargetVelRampCtrl)
1112  << VAROUT(currentPosition) << VAROUT(usePID) << VAROUT(positionError);
1113  }
1114  if (eventHappeningCounter >= 0)
1115  {
1116  eventHappeningCounter--;
1117  }
1118 
1119  ARMARX_INFO << deactivateSpam(5) << VAROUT(newTargetVelPController)
1120  << VAROUT(newTargetVelRampCtrl) << VAROUT(currentPosition) << VAROUT(usePID)
1121  << VAROUT(positionError) << VAROUT(targetPosition) << VAROUT(currentV)
1122  << VAROUT(deltaVel) << VAROUT(useddt) << VAROUT(usedacc);
1123  PIDModeActive = usePID;
1124 #endif
1125  result.velocity = finalTargetVel;
1126  return result;
1127  }
1128 
1129  double
1131  {
1132  throw LocalException("NYI");
1133  return 0;
1134  }
1135 
1136  double
1138  {
1139  /* s = v_0*v_0/(2*a) -> sqrt(s*2*a) = v_0;
1140 
1141  K_p * error = v_0; -> v_0/error = K_p;
1142  */
1143  auto v_0 = std::sqrt(pControlPosErrorLimit * 2 * deceleration);
1144  return v_0 / pControlPosErrorLimit;
1145  }
1146 
1150  {
1151  // auto integratedChange = [](v0)
1152 
1153  // double newJerk = this->jerk;
1154  // double newAcc = currentAcc;
1155  // double newVel = currentV;
1156  State newState = state;
1157  double a0 = currentAcc, newJerk = jerk, t;
1158  Output result = {currentV, a0, newJerk};
1159 
1160  const auto brData = ctrlutil::braking_distance_with_wedge(currentV, currentAcc, newJerk);
1161  const auto goalDir = math::MathUtils::Sign(targetPosition - currentPosition);
1162  const auto curVDir = math::MathUtils::Sign(currentV);
1163  const auto straightBrakingDistance =
1165  const double brakingDistance = brData.dt2 < 0 ? straightBrakingDistance : brData.s_total;
1166  const double distance = std::abs(targetPosition - currentPosition);
1167  const double t_to_stop =
1168  ctrlutil::t_to_v(currentV, -curVDir * currentAcc, curVDir * newJerk);
1169  const auto calculatedJerk =
1171  double tmp_t, tmp_acc, tmp_jerk;
1172  // std::tie( tmp_t, tmp_acc, tmp_jerk) = ctrlutil::calcAccAndJerk(targetPosition-(currentPosition+brData.s1), brData.v1);
1173  std::tie(tmp_t, tmp_acc, tmp_jerk) =
1175  const double posWhenBrakingWithCustomJerk =
1176  ctrlutil::s(tmp_t, currentPosition + brData.s1, brData.v1, tmp_acc, curVDir * tmp_jerk);
1177  // const double brakingDistanceWithCustomJerk = ctrlutil::s(tmp_t, 0, currentV, tmp_acc, curVDir * tmp_jerk);
1178  const double posWhenBrakingWithFixedJerk = ctrlutil::s(
1179  brData.dt2, currentPosition + brData.s1, brData.v1, brData.a1, curVDir * jerk);
1180  (void)calculatedJerk, (void)posWhenBrakingWithCustomJerk, (void)posWhenBrakingWithFixedJerk;
1181 
1182  ARMARX_INFO
1183  << VAROUT((int)state) << VAROUT(distance)
1184  << VAROUT(
1185  brakingDistance); //VAROUT(straightBrakingDistance) << VAROUT(brData.dt1) << VAROUT(brData.dt2) << VAROUT(brData.s_total) << VAROUT(calculatedJerk);
1186 
1187  // if(brData.dt2 < 0)
1188  // {
1189  // ARMARX_INFO << "distance with fixed jerk: " << ctrlutil::brakingDistance(currentV, currentAcc, newJerk)
1190  // << " distance with custom jerk: " << ctrlutil::brakingDistance(currentV, currentAcc, calculatedJerk)
1191  // << " vel after: " << ctrlutil::v(t_to_stop, currentV, currentAcc, -curVDir * newJerk) << " vel after next step: " << ctrlutil::v(dt, currentV, currentAcc, -curVDir * newJerk);
1192  //// << " acc at stop: " << ctrlutil::a(t_to_stop, currentAcc, -curVDir *newJerk);
1193  // jerk = 0.95*calculatedJerk;
1194  // state = State::DecAccDecJerk;
1195  // return;
1196  // }
1197  if (state < State::DecAccIncJerk &&
1199  std::abs(currentAcc) < 0.1)) // we are accelerating
1200  || distance > brakingDistance *
1201  2 // we are decelerating -> dont switch to accelerating to easily
1202  || curVDir != goalDir)) // we are moving away from goal
1203  {
1204  if (std::abs(maxV - currentV) < 0.1 && std::abs(currentAcc) < 0.1)
1205  {
1206  newState = State::Keep;
1207  newJerk = 0;
1208  return std::make_pair(newState, result);
1209  }
1210  // calculate if we need to increase or decrease acc
1211  double t_to_max_v =
1212  ctrlutil::t_to_v(goalDir * maxV - currentV, currentAcc, goalDir * newJerk);
1213  double acc_at_t = ctrlutil::a(t_to_max_v, std::abs(currentAcc), -newJerk);
1214  if (acc_at_t < 0.1)
1215  {
1216  newState = State::IncAccIncJerk;
1217  return std::make_pair(newState, result);
1218  }
1219  else
1220  {
1221  newState = State::IncAccDecJerk;
1222  return std::make_pair(newState, result);
1223  }
1224  }
1225  else
1226  {
1227  // calculate if we need to increase or decrease acc
1228  double t_to_0 = ctrlutil::t_to_v(currentV, -curVDir * currentAcc, curVDir * newJerk);
1229  double tmpV = ctrlutil::v(t_to_0, 0, currentAcc, -curVDir * newJerk);
1230  double vAfterBraking = ctrlutil::v(t_to_0, currentV, currentAcc, -curVDir * newJerk);
1231  double accAfterBraking = ctrlutil::a(t_to_0, currentAcc, curVDir * newJerk);
1232  const double posWhenBrakingNow =
1233  ctrlutil::s(t_to_0, currentPosition, currentV, currentAcc, -curVDir * newJerk);
1234  const double simpleBrakingDistance =
1235  ctrlutil::s(t_to_0, 0, currentV, currentAcc, -curVDir * newJerk);
1236  (void)tmpV, (void)vAfterBraking, (void)accAfterBraking, (void)posWhenBrakingNow,
1237  (void)simpleBrakingDistance;
1238  double acc_at_t = ctrlutil::a(t_to_0, std::abs(currentAcc), -newJerk);
1239 
1240  std::tie(t, a0, newJerk) =
1242  double at = ctrlutil::a(t, a0, newJerk);
1243  double vt = ctrlutil::v(t, currentV, a0, newJerk);
1244  double st = ctrlutil::s(t, targetPosition - currentPosition, currentV, a0, newJerk);
1245  (void)at, (void)vt, (void)st;
1246 
1247  if (this->state <= State::Keep)
1248  {
1249  newState = State::DecAccIncJerk;
1250  return std::make_pair(newState, result);
1251  }
1252  else if ((state == State::DecAccIncJerk && acc_at_t > 1) ||
1254  {
1255  result.jerk = newJerk;
1256  result.acceleration = currentAcc + (a0 - currentAcc) * 0.5 + dt * newJerk;
1257  newState = State::DecAccDecJerk;
1258  return std::make_pair(newState, result);
1259  }
1260  else
1261  {
1262  return std::make_pair(newState, result);
1263  }
1264  }
1265  throw LocalException();
1266  }
1267 
1268  void
1270  {
1271  currentTime = 0;
1272 
1273  fixedMinJerkState.reset();
1274  // pid.reset();
1275  currentP_Phase2 = -1;
1276  currentP_Phase3 = -1;
1277  }
1278 
1279  double
1281  {
1282  return targetPosition;
1283  }
1284 
1285  // MinJerkPositionController::Output MinJerkPositionController::run()
1286  // {
1287  // auto min_jerk_calc_jerk = [&](double tf, double s0, double v0, double a0, double xf = 0, double t0 = 0.0)
1288  // {
1289  // double D = tf - t0;
1290  // return 60.0 / (D * D * D) * (xf - s0) - 36.0 / (D * D) * v0 - 9.0 / D * a0;
1291  // };
1292 
1293 
1294  // auto min_jerk = [&](double t, double tf, double s0, double v0, double a0, double xf = 0, double t0 = 0.0)
1295  // {
1296  // double D = tf - t0;
1297  // BOOST_ASSERT(D != 0.0);
1298  // double D2 = D * D;
1299  // double tau = (t - t0) / D;
1300  // double b0 = s0;
1301  // double b1 = D * v0;
1302  // double b2 = D2 * a0 / 2;
1303 
1304  // double b3 = (-3 * D2) / 2 * a0 - 6 * D * v0 + 10 * (xf - s0);
1305  // double b4 = (3 * D2) / 2 * a0 + 8 * D * v0 - 15 * (xf - s0);
1306  // double b5 = (-D2) / 2 * a0 - 3 * D * v0 + 6 * (xf - s0);
1307 
1308  // double tau2 = tau * tau;
1309  // double tau3 = tau2 * tau;
1310  // double tau4 = tau3 * tau;
1311  // double tau5 = tau4 * tau;
1312  // double st = b0 + b1 * tau + b2 * tau2 + b3 * tau3 + b4 * tau4 + b5 * tau5;
1313  // double vt = b1 / D + 2 * b2 / D * tau + 3 * b3 / D * tau2 + 4 * b4 / D * tau3 + 5 * b5 / D * tau4;
1314  // double at = 2 * b2 / D2 + 6 * b3 / D2 * tau + 12 * b4 / D2 * tau2 + 20 * b5 / D2 * tau3;
1315  // return State{t, st, vt, at};
1316  // };
1317 
1318  // double remainingTime = finishTime - currentTime;
1319  // double signedDistance = targetPosition - currentPosition;
1320  // if (remainingTime <= 0.0)
1321  // {
1322  // // if(!pid)
1323  // // {
1324  // // double Kd = (currentV - distance * p) /(-currentV);
1325  // // ARMARX_INFO << VAROUT(Kd);
1326  // // pid.reset(new PIDController(1, 0, Kd));
1327  // // }
1328  // if (currentP_Phase3 < 0)
1329  // {
1330  // currentP_Phase3 = std::abs(currentV / signedDistance);
1331  // ARMARX_DEBUG << "optimal P: " << currentP_Phase3;
1332  // }
1333 
1334 
1335  // currentP_Phase3 = currentP_Phase3 * p_adjust_ratio + p * (1.0 - p_adjust_ratio);
1336  // double newVel = signedDistance * currentP_Phase3;
1337  // double newAcc = (newVel - currentV) / dt;
1338  // double newJerk = (newAcc - currentAcc) / dt;
1339  // double newPos = currentPosition + newVel * dt;
1340  // Output result {newPos, newVel, newAcc, newJerk};
1341  // currentTime += dt;
1342  // // State s = min_jerk(currentTime, finishTime, fixedMinJerkState->s0, fixedMinJerkState->v0, fixedMinJerkState->a0, targetPosition, fixedMinJerkState->t0);
1343  // ARMARX_DEBUG << VAROUT(remainingTime) << VAROUT(signedDistance) << VAROUT(signedDistance * currentP_Phase3) << VAROUT(currentP_Phase3);// << VAROUT(s.s) << VAROUT(s.v) << VAROUT(s.a);
1344  // return result;
1345  // }
1346 
1347  // if (std::abs(signedDistance) < phase2SwitchDistance && remainingTime < phase2SwitchMaxRemainingTime)
1348  // {
1349  // if (!fixedMinJerkState)
1350  // {
1351  // fixedMinJerkState.reset(new FixedMinJerkState{currentTime, currentPosition, currentV, currentAcc});
1352  // currentP_Phase2 = 0;
1353  // }
1354  // // std::vector<State> states;
1355  // // double t = currentTime;
1356  // // while(t < finishTime)
1357  // // {
1358  // // State s = min_jerk(t, finishTime, fixedMinJerkState->s0, fixedMinJerkState->v0, fixedMinJerkState->a0, targetPosition, fixedMinJerkState->t0);
1359  // // t += dt;
1360  // // states.push_back(s);
1361  // // }
1362  // currentTime += dt;
1363  // State s = min_jerk(currentTime, finishTime, fixedMinJerkState->s0, fixedMinJerkState->v0, fixedMinJerkState->a0, targetPosition, fixedMinJerkState->t0);
1364  // currentP_Phase2 = currentP_Phase2 * p_adjust_ratio + p * (1.0 - p_adjust_ratio);
1365  // double newVel = (s.s - currentPosition) * currentP_Phase2 + s.v;
1366  // ARMARX_DEBUG << VAROUT(s.s) << VAROUT(s.v) << VAROUT(newVel);
1367  // double newAcc = (newVel - currentV) / dt;
1368  // double newJerk = (newAcc - currentAcc) / dt;
1369  // double newPos = currentPosition + newVel * dt;
1370  // Output result {newPos, newVel, newAcc, newJerk};
1371  // return result;
1372  // }
1373 
1374 
1375  // double jerk = min_jerk_calc_jerk(remainingTime, currentPosition, currentV, currentAcc, targetPosition);
1376  // double newAcc = currentAcc + jerk * dt;
1377  // double newVelocity = ctrlutil::v(dt, currentV, currentAcc, jerk);
1378  // double accAtEnd = ctrlutil::a(remainingTime, currentAcc, jerk);
1379 
1380  // std::vector<State> states;
1381  // std::vector<State> states2;
1382  // //#define debug
1383  //#ifdef debug
1384  // {
1385  // double dt = 0.001;
1386  // double t = 1;
1387  // double simS = currentPosition, simV = currentV, simAcc = currentAcc;
1388  // while (t > 0)
1389  // {
1390  // double jerk = min_jerk_calc_jerk(t, simS, simV, simAcc, targetPosition);
1391  // simAcc = simAcc + jerk * dt;
1392  // simV = ctrlutil::v(dt, simV, simAcc, 0);
1393  // simS += dt * simV;
1394  // t -= dt;
1395  // states.push_back(State{t, simS, simV, simAcc, jerk});
1396  // }
1397  // }
1398  // {
1399  // double dt = 0.001;
1400 
1401  // double t = 1;
1402  // double simS = currentPosition, simV = currentV, simAcc = currentAcc;
1403  // while (t > 0)
1404  // {
1405  // double jerk = min_jerk_calc_jerk(t, simS, simV, simAcc, targetPosition);
1406  // simS += ctrlutil::s(dt, 0, simV, simAcc, jerk);
1407  // simV = ctrlutil::v(dt, simV, simAcc, jerk);
1408  // simAcc = simAcc + jerk * dt;
1409  // t -= dt;
1410  // states2.push_back(State{t, simS, simV , simAcc, jerk});
1411  // }
1412  // }
1413  //#endif
1414  // ARMARX_DEBUG << VAROUT(currentTime) << VAROUT(remainingTime) << VAROUT(jerk) << VAROUT(accAtEnd) << VAROUT(signedDistance) << " delta acc: " << jerk* dt;
1415  // currentTime += dt;
1416 
1417 
1418  // double newPos = ctrlutil::s(dt, currentPosition, currentV, currentAcc, jerk);
1419  // Output result { newPos, newVelocity, newAcc, jerk};
1420  // return result;
1421 
1422  // }
1423 
1424  bool
1426  {
1429  }
1430 
1433  {
1434  const double useddt = std::min(std::abs(dt), std::abs(maxDt));
1435  (void)useddt;
1436 
1437  // if (currentPosition <= positionLimitLoHard || currentPosition >= positionLimitHiHard)
1438  // {
1439  // ARMARX_INFO << deactivateSpam(1) << "Hard limit violation. " << VAROUT(currentPosition) << VAROUT(positionLimitLoHard) << VAROUT(positionLimitHiHard);
1440  // return std::nanf("1");
1441  // }
1442 
1443  double softLimitViolation = 0;
1445  {
1446  softLimitViolation = -1;
1447  }
1449  {
1450  softLimitViolation = 1;
1451  }
1452 
1453  const double upperDt = std::max(std::abs(dt), std::abs(maxDt));
1454 
1455  //we can have 4 cases:
1456  // 1. we need to decelerate now or we will violate the position limits (maybe we still will violate them, e.g. if we violated them initially)
1457  // 2. we directly set v and ignore acc/dec (if |curr - target| <= limit)
1458  // 3. we need to accelerate (if curr and target v have same sign and |curr| < |target|)
1459  // 4. we need to decelerate (other cases)
1460  double nextv;
1461  //handle case 1
1462  const double vsquared = currentV * currentV;
1463  const double brakingDist =
1464  sign(currentV) * vsquared / 2.f /
1465  std::abs(deceleration); //the braking distance points in the direction of the velocity
1466 
1467  const double posIfBrakingNow = currentPosition + brakingDist;
1468  // ARMARX_INFO << deactivateSpam(0.1) << VAROUT(currentPosition) << VAROUT(positionLimitLoSoft) << VAROUT(positionLimitHiSoft) << VAROUT(posIfBrakingNow) << VAROUT(currentV);
1469  if ((posIfBrakingNow <= positionLimitLoSoft && currentV < 0) ||
1470  (posIfBrakingNow >= positionLimitHiSoft && currentV > 0))
1471  {
1472  //case 1. -> brake now! (we try to have v=0 at the limit)
1473  const auto limit =
1475  const double wayToGo = limit - currentPosition;
1476 
1477  //decelerate!
1478  // s = v²/(2a) <=> a = v²/(2s)
1479  const double dec = std::abs(vsquared / 2.0 / wayToGo);
1480  const double vel = currentV - sign(currentV) * dec * upperDt;
1481  nextv = std::clamp<double>(vel, -maxV, maxV);
1482  // ARMARX_INFO /*<< deactivateSpam(0.1)*/ << "clamped new Vel: " << VAROUT(nextv) << VAROUT(currentV);
1483  if (sign(currentV) != sign(nextv))
1484  {
1485  // ARMARX_INFO << deactivateSpam(1) << "wrong sign: stopping"; //stop now
1486  nextv = 0;
1487  }
1488  }
1489  else
1490  {
1491  //handle 2-3
1493  // ARMARX_INFO << deactivateSpam(1) << "Desired target Vel: " << targetV << " " << VAROUT(nextv);
1494  }
1495  if (softLimitViolation == sign(nextv) && nextv != 0)
1496  {
1497  //the area between soft and hard limits is sticky
1498  //the controller can only move out of it (not further in)
1499  // ARMARX_INFO << deactivateSpam(1) << "Soft limit violation. " << softLimitViolation << VAROUT(nextv);
1500  nextv = 0;
1501  }
1502  // double nextAcc = (nextv - currentV) / useddt; // doesnt work with calculated acc!!
1503  // double nextJerk = (nextAcc - currentAcc) / useddt;
1504  //the next velocity will not violate the pos bounds harder than they are already
1505  return Output{nextv, 0, 0};
1506  }
1507 
1508  void
1510  {
1511  if (std::abs(targetPosition - newTargetPosition) > 0.0001)
1512  {
1513  reset();
1514  double distance = newTargetPosition - currentPosition;
1515  double rawFinishTime = 0.0;
1516  double decelerationTime = std::abs(currentV / desiredDeceleration);
1517  // calculate the time it should take to reach the goal (ToDo: find exact time)
1519  std::abs(currentV) > 0.0 &&
1520  ctrlutil::s(decelerationTime, 0, std::abs(currentV), -desiredDeceleration, 0) >
1521  std::abs(distance))
1522  // && ctrlutil::brakingDistance(currentV, currentAcc, desiredJerk) < distance)
1523  {
1524  // ARMARX_INFO << "branch 1: " << VAROUT(currentV) << VAROUT(desiredDeceleration) << VAROUT(distance);
1525  rawFinishTime = decelerationTime;
1526  }
1527  else
1528  {
1529  // ARMARX_INFO << "branch 2: " << VAROUT(currentV) << VAROUT(desiredDeceleration) << VAROUT(distance);
1530  double accelerationTime = std::abs(
1532  double decelerationTime = std::abs(maxV / desiredDeceleration);
1533  rawFinishTime = std::max(decelerationTime + accelerationTime,
1534  std::abs(distance / (maxV * 0.75)));
1535  }
1536  double estimatedTime = ctrlutil::t_to_v_with_wedge_acc(
1538  double minTime = 0.8;
1539  if (!std::isnan(estimatedTime))
1540  {
1541  finishTime = std::max(estimatedTime, minTime);
1542  }
1543  else
1544  {
1545  finishTime = std::max(rawFinishTime, minTime);
1546  }
1547  targetPosition = newTargetPosition;
1548  // ARMARX_INFO << "New finish time: " << finishTime << " " << VAROUT(rawFinishTime) << VAROUT(estimatedTime);
1549  }
1550  }
1551 
1554  {
1555  auto min_jerk_calc_jerk =
1556  [&](double tf, double s0, double v0, double a0, double xf = 0, double t0 = 0.0)
1557  {
1558  double D = tf - t0;
1559  return 60.0 / (D * D * D) * (xf - s0) - 36.0 / (D * D) * v0 - 9.0 / D * a0;
1560  };
1561 
1562 
1563  auto min_jerk = [&](double t,
1564  double tf,
1565  double s0,
1566  double v0,
1567  double a0,
1568  double xf = 0,
1569  double t0 = 0.0)
1570  {
1571  double D = tf - t0;
1572  ARMARX_CHECK(D != 0.0);
1573  double D2 = D * D;
1574  double tau = (t - t0) / D;
1575  double b0 = s0;
1576  double b1 = D * v0;
1577  double b2 = D2 * a0 / 2;
1578 
1579  double b3 = (-3 * D2) / 2 * a0 - 6 * D * v0 + 10 * (xf - s0);
1580  double b4 = (3 * D2) / 2 * a0 + 8 * D * v0 - 15 * (xf - s0);
1581  double b5 = (-D2) / 2 * a0 - 3 * D * v0 + 6 * (xf - s0);
1582 
1583  double tau2 = tau * tau;
1584  double tau3 = tau2 * tau;
1585  double tau4 = tau3 * tau;
1586  double tau5 = tau4 * tau;
1587  double st = b0 + b1 * tau + b2 * tau2 + b3 * tau3 + b4 * tau4 + b5 * tau5;
1588  double vt = b1 / D + 2 * b2 / D * tau + 3 * b3 / D * tau2 + 4 * b4 / D * tau3 +
1589  5 * b5 / D * tau4;
1590  double at = 2 * b2 / D2 + 6 * b3 / D2 * tau + 12 * b4 / D2 * tau2 + 20 * b5 / D2 * tau3;
1591  return State{t, st, vt, at};
1592  };
1593 
1594  double remainingTime = finishTime - currentTime;
1595  double signedDistance = targetPosition - currentPosition;
1596  if (remainingTime <= 0.0)
1597  {
1598  // if(!pid)
1599  // {
1600  // double Kd = (currentV - distance * p) /(-currentV);
1601  // ARMARX_INFO << VAROUT(Kd);
1602  // pid.reset(new PIDController(1, 0, Kd));
1603  // }
1604  if (currentP_Phase3 < 0)
1605  {
1606  if (signedDistance == 0.0f)
1607  {
1608  currentP_Phase3 = p;
1609  }
1610  else
1611  {
1612  currentP_Phase3 = std::abs(currentV / signedDistance);
1614  }
1615  // ARMARX_INFO << deactivateSpam(0.1) << "optimal P: " << currentP_Phase3 << VAROUT(currentV) << VAROUT(signedDistance);
1616  }
1617 
1618 
1620  double newVel = signedDistance * currentP_Phase3;
1621  double newAcc = (newVel - currentV) / dt;
1622  double newJerk = (newAcc - currentAcc) / dt;
1623  double newPos = currentPosition + newVel * dt;
1624 
1625  Output result{newPos, newVel, newAcc, newJerk};
1626  currentTime += dt;
1627  // State s = min_jerk(currentTime, finishTime, fixedMinJerkState->s0, fixedMinJerkState->v0, fixedMinJerkState->a0, targetPosition, fixedMinJerkState->t0);
1628  // ARMARX_INFO << deactivateSpam(0.1) << VAROUT(remainingTime) << VAROUT(signedDistance) << VAROUT(signedDistance * currentP_Phase3) << VAROUT(currentP_Phase3);// << VAROUT(s.s) << VAROUT(s.v) << VAROUT(s.a);
1629  return result;
1630  }
1631 
1632  if (std::abs(signedDistance) < phase2SwitchDistance &&
1633  remainingTime < phase2SwitchMaxRemainingTime)
1634  {
1635  if (!fixedMinJerkState)
1636  {
1637  fixedMinJerkState.reset(
1639  currentP_Phase2 = 0;
1640  }
1641  // std::vector<State> states;
1642  // double t = currentTime;
1643  // while(t < finishTime)
1644  // {
1645  // State s = min_jerk(t, finishTime, fixedMinJerkState->s0, fixedMinJerkState->v0, fixedMinJerkState->a0, targetPosition, fixedMinJerkState->t0);
1646  // t += dt;
1647  // states.push_back(s);
1648  // }
1649  currentTime += dt;
1650  State s = min_jerk(currentTime,
1651  finishTime,
1652  fixedMinJerkState->s0,
1653  fixedMinJerkState->v0,
1654  fixedMinJerkState->a0,
1656  fixedMinJerkState->t0);
1657  double newVelocity = (s.s - (currentPosition + s.v * dt)) * currentP_Phase2 + s.v;
1658  double newAcc = (newVelocity - currentV) / dt;
1659  double newJerk = (newAcc - currentAcc) / dt;
1660  double newPos = ctrlutil::s(dt,
1662  currentV,
1663  currentAcc,
1664  newJerk); //currentPosition + newVelocity * dt;
1665  // ARMARX_INFO /*<< deactivateSpam(0.1) */ << VAROUT(currentP_Phase2) << VAROUT(currentPosition) << VAROUT(signedDistance) << VAROUT(s.s) << VAROUT(s.v) << VAROUT(newVelocity) << VAROUT(newAcc) << VAROUT(newJerk) << VAROUT(s.a);
1667  Output result{newPos, newVelocity, newAcc, newJerk};
1668  return result;
1669  }
1670 
1671 
1672  double jerk = min_jerk_calc_jerk(
1674  double newAcc = currentAcc + jerk * dt;
1675  double newVelocity = ctrlutil::v(dt, currentV, currentAcc, jerk);
1676  double accAtEnd =
1677  ctrlutil::a(remainingTime,
1678  currentAcc,
1679  jerk); // assumes that fixed jerk would be used, which is not the case here
1680  (void)accAtEnd;
1681 
1682  std::vector<State> states;
1683  std::vector<State> states2;
1684  //#define debug
1685 #ifdef debug
1686  {
1687  double dt = 0.001;
1688  double t = 1;
1689  double simS = currentPosition, simV = currentV, simAcc = currentAcc;
1690  while (t > 0)
1691  {
1692  double jerk = min_jerk_calc_jerk(t, simS, simV, simAcc, targetPosition);
1693  simAcc = simAcc + jerk * dt;
1694  simV = ctrlutil::v(dt, simV, simAcc, 0);
1695  simS += dt * simV;
1696  t -= dt;
1697  states.push_back(State{t, simS, simV, simAcc, jerk});
1698  }
1699  }
1700  {
1701  double dt = 0.001;
1702 
1703  double t = 1;
1704  double simS = currentPosition, simV = currentV, simAcc = currentAcc;
1705  while (t > 0)
1706  {
1707  double jerk = min_jerk_calc_jerk(t, simS, simV, simAcc, targetPosition);
1708  simS += ctrlutil::s(dt, 0, simV, simAcc, jerk);
1709  simV = ctrlutil::v(dt, simV, simAcc, jerk);
1710  simAcc = simAcc + jerk * dt;
1711  t -= dt;
1712  states2.push_back(State{t, simS, simV, simAcc, jerk});
1713  }
1714  }
1715 #endif
1716  // ARMARX_INFO << /*deactivateSpam(0.1) <<*/ VAROUT(currentTime) << VAROUT(remainingTime) << VAROUT(jerk) << VAROUT(accAtEnd) << VAROUT(signedDistance) << " new acc: " << newAcc << VAROUT(currentV);
1717  currentTime += dt;
1718 
1719 
1720  double newPos = ctrlutil::s(dt, currentPosition, currentV, currentAcc, jerk);
1721  Output result{newPos, newVelocity, newAcc, jerk};
1722  return result;
1723  }
1724 } // namespace armarx
armarx::PositionThroughVelocityControllerWithAccelerationBounds::acceleration
float acceleration
Definition: BasicControllers.h:306
armarx::PositionThroughVelocityControllerWithAccelerationRamps::estimateTime
double estimateTime() const
Definition: BasicControllers.cpp:1130
armarx::PositionThroughVelocityControllerWithAccelerationRamps::p
double p
Definition: BasicControllers.h:386
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:662
armarx::PositionThroughVelocityControllerWithAccelerationBounds::targetPosition
float targetPosition
Definition: BasicControllers.h:309
armarx::VelocityControllerWithRampedAcceleration::Output
Definition: BasicControllers.h:187
armarx::PositionThroughVelocityControllerWithAccelerationRamps::maxV
double maxV
Definition: BasicControllers.h:369
armarx::positionThroughVelocityControlWithAccelerationBoundsAndPeriodicPosition
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)
Definition: BasicControllers.cpp:284
armarx::brakingDistance
float brakingDistance(float v0, float deceleration)
Definition: BasicControllers.h:157
algorithm.h
armarx::deltas::dv
float dv
Definition: BasicControllers.h:59
armarx::deltas::dt
float dt
Definition: BasicControllers.h:61
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::PositionThroughVelocityControllerWithAccelerationRamps::calcState
std::pair< State, Output > calcState() const
Definition: BasicControllers.cpp:1149
armarx::MinJerkPositionController::currentTime
double currentTime
Definition: BasicControllers.h:510
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::PCtrl
@ PCtrl
armarx::positionThroughVelocityControlWithAccelerationAndPositionBounds
float positionThroughVelocityControlWithAccelerationAndPositionBounds(float dt, float maxDt, float currentV, float maxV, float acceleration, float deceleration, float currentPosition, float targetPosition, float p, float positionLimitLo, float positionLimitHi)
Definition: BasicControllers.cpp:222
armarx::ctrlutil::calcAccAndJerk
std::tuple< double, double, double > calcAccAndJerk(double s0, double v0)
Definition: CtrlUtil.h:147
armarx::VelocityControllerWithRampedAccelerationAndPositionBounds::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:1425
armarx::PositionThroughVelocityControllerWithAccelerationRamps::run
Output run()
Definition: BasicControllers.cpp:991
armarx::PositionThroughVelocityControllerWithAccelerationRamps::usePIDAtEnd
bool usePIDAtEnd
Definition: BasicControllers.h:387
armarx::MinJerkPositionController::currentP_Phase3
double currentP_Phase3
Definition: BasicControllers.h:506
armarx::PositionThroughVelocityControllerWithAccelerationRamps::currentAcc
double currentAcc
Definition: BasicControllers.h:368
armarx::MinJerkPositionController::fixedMinJerkState
std::unique_ptr< FixedMinJerkState > fixedMinJerkState
Definition: BasicControllers.h:511
armarx::VelocityControllerWithAccelerationAndPositionBounds::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:485
armarx::MinJerkPositionController::desiredDeceleration
double desiredDeceleration
Definition: BasicControllers.h:498
armarx::PositionThroughVelocityControllerWithAccelerationRamps::Output::acceleration
double acceleration
Definition: BasicControllers.h:361
armarx::MinJerkPositionController::p_adjust_ratio
double p_adjust_ratio
Definition: BasicControllers.h:503
armarx::ctrlutil::brakingDistance
double brakingDistance(double v0, double a0, double j)
Definition: CtrlUtil.h:76
armarx::PositionThroughVelocityControllerWithAccelerationRamps::pControlPosErrorLimit
double pControlPosErrorLimit
Definition: BasicControllers.h:382
armarx::VelocityControllerWithAccelerationAndPositionBounds::run
float run() const
Definition: BasicControllers.cpp:494
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::DecAccIncJerk
@ DecAccIncJerk
armarx::VelocityControllerWithAccelerationBounds::dt
float dt
Definition: BasicControllers.h:170
armarx::sign
T sign(T t)
Definition: algorithm.h:194
armarx::PositionThroughVelocityControllerWithAccelerationBounds::deceleration
float deceleration
Definition: BasicControllers.h:307
armarx::VelocityControllerWithRampedAcceleration::maxV
float maxV
Definition: BasicControllers.h:196
armarx::VelocityControllerWithAccelerationBounds::maxV
float maxV
Definition: BasicControllers.h:174
armarx::PositionThroughVelocityControllerWithAccelerationBounds::PositionThroughVelocityControllerWithAccelerationBounds
PositionThroughVelocityControllerWithAccelerationBounds()
Definition: BasicControllers.cpp:567
armarx::VelocityControllerWithRampedAccelerationAndPositionBounds::positionLimitLoSoft
double positionLimitLoSoft
Definition: BasicControllers.h:233
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::IncAccIncJerk
@ IncAccIncJerk
armarx::PositionThroughVelocityControllerWithAccelerationBounds
Definition: BasicControllers.h:300
armarx::VelocityControllerWithAccelerationBounds::estimateTime
float estimateTime() const
Definition: BasicControllers.cpp:474
armarx::velocityControlWithAccelerationAndPositionBounds
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)
Definition: BasicControllers.cpp:83
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::Keep
@ Keep
armarx::PositionThroughVelocityControllerWithAccelerationBounds::pControlPosErrorLimit
float pControlPosErrorLimit
Definition: BasicControllers.h:310
armarx::PositionThroughVelocityControllerWithAccelerationBounds::run
float run() const
Definition: BasicControllers.cpp:597
armarx::VelocityControllerWithAccelerationAndPositionBounds::positionLimitLoSoft
float positionLimitLoSoft
Definition: BasicControllers.h:277
armarx::deltas::dx
float dx
Definition: BasicControllers.h:60
armarx::PositionThroughVelocityControllerWithAccelerationBoundsAndPeriodicPosition::run
float run() const
Definition: BasicControllers.cpp:902
armarx::MinJerkPositionController::run
Output run()
Definition: BasicControllers.cpp:1553
armarx::MinJerkPositionController::FixedMinJerkState
Definition: BasicControllers.h:479
armarx::PositionThroughVelocityControllerWithAccelerationRamps::dt
double dt
Definition: BasicControllers.h:365
armarx::PositionThroughVelocityControllerWithAccelerationRamps::targetPosition
double targetPosition
Definition: BasicControllers.h:376
armarx::PositionThroughVelocityControllerWithAccelerationAndPositionBounds::positionLimitLo
float positionLimitLo
Definition: BasicControllers.h:428
armarx::velocityControlWithAccelerationBounds
float velocityControlWithAccelerationBounds(float dt, float maxDt, const float currentV, float targetV, float maxV, float acceleration, float deceleration, float directSetVLimit)
Definition: BasicControllers.cpp:35
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::MinJerkPositionController::phase2SwitchMaxRemainingTime
double phase2SwitchMaxRemainingTime
Definition: BasicControllers.h:502
clamp
double clamp(double x, double a, double b)
Definition: point.hpp:125
armarx::PositionThroughVelocityControllerWithAccelerationRamps::accuracy
double accuracy
Definition: BasicControllers.h:385
armarx::VelocityControllerWithRampedAcceleration::targetV
float targetV
Definition: BasicControllers.h:204
armarx::VelocityControllerWithAccelerationBounds::currentV
float currentV
Definition: BasicControllers.h:172
armarx::VelocityControllerWithRampedAcceleration::dt
float dt
Definition: BasicControllers.h:201
armarx::MinJerkPositionController::Output
Definition: BasicControllers.h:484
BasicControllers.h
armarx::PositionThroughVelocityControllerWithAccelerationRamps::acceleration
double acceleration
Definition: BasicControllers.h:370
armarx::PositionThroughVelocityControllerWithAccelerationRamps::Output::velocity
double velocity
Definition: BasicControllers.h:360
std::isfinite
bool isfinite(const std::vector< T, Ts... > &v)
Definition: algorithm.h:327
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State
State
Definition: BasicControllers.h:347
armarx::VelocityControllerWithAccelerationBounds::maxDt
float maxDt
Definition: BasicControllers.h:171
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
armarx::VelocityControllerWithRampedAcceleration::jerk
float jerk
Definition: BasicControllers.h:197
armarx::VelocityControllerWithAccelerationBounds::directSetVLimit
float directSetVLimit
Definition: BasicControllers.h:177
armarx::VelocityControllerWithRampedAcceleration::maxDt
float maxDt
Definition: BasicControllers.h:195
armarx::MinJerkPositionController::targetPosition
double targetPosition
Definition: BasicControllers.h:508
armarx::VelocityControllerWithAccelerationBounds::run
float run() const
Definition: BasicControllers.cpp:363
armarx::MinJerkPositionController::currentV
double currentV
Definition: BasicControllers.h:495
armarx::MinJerkPositionController::currentAcc
double currentAcc
Definition: BasicControllers.h:496
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::MinJerkPositionController::p
double p
Definition: BasicControllers.h:500
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::IncAccDecJerk
@ IncAccDecJerk
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:253
armarx::PositionThroughVelocityControllerWithAccelerationBounds::currentPosition
float currentPosition
Definition: BasicControllers.h:308
armarx::PositionThroughVelocityControllerWithAccelerationRamps::calculateProportionalGain
double calculateProportionalGain() const
Definition: BasicControllers.cpp:1137
armarx::PositionThroughVelocityControllerWithAccelerationBounds::maxV
float maxV
Definition: BasicControllers.h:305
armarx::PIDController
Definition: PIDController.h:43
armarx::PositionThroughVelocityControllerWithAccelerationBounds::currentV
float currentV
Definition: BasicControllers.h:304
armarx::PositionThroughVelocityControllerWithAccelerationBounds::getCurrentlyPIDActive
bool getCurrentlyPIDActive() const
Definition: BasicControllers.cpp:961
armarx::VelocityControllerWithRampedAccelerationAndPositionBounds::run
Output run() const
Definition: BasicControllers.cpp:1432
armarx::pq
std::pair< T, T > pq(T p, T q)
Definition: BasicControllers.h:50
armarx::periodicClamp
T periodicClamp(T value, T periodLo, T periodHi)
Definition: BasicControllers.h:42
armarx::VelocityControllerWithRampedAcceleration::run
Output run() const
Definition: BasicControllers.cpp:403
armarx::VelocityControllerWithRampedAccelerationAndPositionBounds::deceleration
double deceleration
Definition: BasicControllers.h:237
armarx::VelocityControllerWithAccelerationAndPositionBounds::positionLimitHiSoft
float positionLimitHiSoft
Definition: BasicControllers.h:278
armarx::ctrlutil::braking_distance_with_wedge
WedgeBrakingData braking_distance_with_wedge(double v0, double a0, double j)
Definition: CtrlUtil.h:157
armarx::VelocityControllerWithRampedAcceleration::currentV
float currentV
Definition: BasicControllers.h:202
armarx::MinJerkPositionController::finishTime
double finishTime
Definition: BasicControllers.h:509
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::VelocityControllerWithRampedAcceleration::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:397
armarx::MinJerkPositionController::phase2SwitchDistance
double phase2SwitchDistance
Definition: BasicControllers.h:501
q
#define q
armarx::PositionThroughVelocityControllerWithAccelerationBounds::pid
std::shared_ptr< PIDController > pid
Definition: BasicControllers.h:314
armarx::MinJerkPositionController::currentP_Phase2
double currentP_Phase2
Definition: BasicControllers.h:507
armarx::deltas
Definition: BasicControllers.h:57
armarx::VelocityControllerWithAccelerationBounds::acceleration
float acceleration
Definition: BasicControllers.h:175
armarx::PositionThroughVelocityControllerWithAccelerationBounds::maxDt
float maxDt
Definition: BasicControllers.h:303
armarx::PositionThroughVelocityControllerWithAccelerationRamps::PositionThroughVelocityControllerWithAccelerationRamps
PositionThroughVelocityControllerWithAccelerationRamps()
Definition: BasicControllers.cpp:977
armarx::MinJerkPositionController::getTargetPosition
double getTargetPosition() const
Definition: BasicControllers.cpp:1280
armarx::VelocityControllerWithRampedAcceleration::currentAcc
float currentAcc
Definition: BasicControllers.h:203
armarx::trapeze
std::array< deltas, 3 > trapeze(float v0, float acc, float vMax, float dec, float vt, float dx)
Definition: BasicControllers.cpp:795
armarx::PositionThroughVelocityControllerWithAccelerationRamps::maxDt
double maxDt
Definition: BasicControllers.h:366
armarx::VelocityControllerWithRampedAccelerationAndPositionBounds::positionLimitHiSoft
double positionLimitHiSoft
Definition: BasicControllers.h:234
armarx::PositionThroughVelocityControllerWithAccelerationBounds::estimateTime
float estimateTime() const
Definition: BasicControllers.cpp:701
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::math::MathUtils::LimitTo
static double LimitTo(double value, double absThreshold)
Definition: MathUtils.h:56
armarx::VelocityControllerWithAccelerationBounds::deceleration
float deceleration
Definition: BasicControllers.h:176
armarx::PositionThroughVelocityControllerWithAccelerationBounds::accuracy
float accuracy
Definition: BasicControllers.h:313
armarx::PositionThroughVelocityControllerWithAccelerationAndPositionBounds::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:749
armarx::PositionThroughVelocityControllerWithAccelerationAndPositionBounds::run
float run() const
Definition: BasicControllers.cpp:758
CtrlUtil.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::VelocityControllerWithAccelerationAndPositionBounds::currentPosition
float currentPosition
Definition: BasicControllers.h:276
armarx::MinJerkPositionController::maxV
double maxV
Definition: BasicControllers.h:497
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::PositionThroughVelocityControllerWithAccelerationBoundsAndPeriodicPosition::positionPeriodLo
float positionPeriodLo
Definition: BasicControllers.h:451
armarx::MinJerkPositionController::setTargetPosition
void setTargetPosition(double value)
Definition: BasicControllers.cpp:1509
armarx::math::MathUtils::Sign
static int Sign(double value)
Definition: MathUtils.h:34
sub
Point sub(const Point &x, const Point &y)
Definition: point.hpp:43
armarx::PositionThroughVelocityControllerWithAccelerationRamps::jerk
double jerk
Definition: BasicControllers.h:372
armarx::PositionThroughVelocityControllerWithAccelerationRamps::deceleration
double deceleration
Definition: BasicControllers.h:371
armarx::PositionThroughVelocityControllerWithAccelerationRamps::getTargetPosition
double getTargetPosition() const
Definition: BasicControllers.cpp:955
armarx::PositionThroughVelocityControllerWithAccelerationBounds::dt
float dt
Definition: BasicControllers.h:302
armarx::PositionThroughVelocityControllerWithAccelerationRamps::Output
Definition: BasicControllers.h:358
armarx::MinJerkPositionController::reset
void reset()
Definition: BasicControllers.cpp:1269
armarx::PositionThroughVelocityControllerWithAccelerationBounds::calculateProportionalGain
float calculateProportionalGain() const
Definition: BasicControllers.cpp:577
armarx::MinJerkPositionController::currentPosition
double currentPosition
Definition: BasicControllers.h:494
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::Unknown
@ Unknown
armarx::PositionThroughVelocityControllerWithAccelerationRamps::currentPosition
double currentPosition
Definition: BasicControllers.h:373
Logging.h
armarx::MinJerkPositionController::State
Definition: BasicControllers.h:474
armarx::PositionThroughVelocityControllerWithAccelerationRamps::Output::jerk
double jerk
Definition: BasicControllers.h:362
min
T min(T t1, T t2)
Definition: gdiam.h:42
armarx::positionThroughVelocityControlWithAccelerationBounds
float positionThroughVelocityControlWithAccelerationBounds(float dt, float maxDt, float currentV, float maxV, float acceleration, float deceleration, float currentPosition, float targetPosition, float p)
Definition: BasicControllers.cpp:166
armarx::MinJerkPositionController::dt
double dt
Definition: BasicControllers.h:492
armarx::PositionThroughVelocityControllerWithAccelerationRamps::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:982
armarx::PositionThroughVelocityControllerWithAccelerationBounds::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:588
armarx::ctrlutil::jerk
double jerk(double t, double s0, double v0, double a0)
Definition: CtrlUtil.h:141
armarx::ctrlutil::t_to_v_with_wedge_acc
double t_to_v_with_wedge_acc(double v, double a0, double j)
Definition: CtrlUtil.h:64
armarx::accelerateToVelocity
deltas accelerateToVelocity(float v0, float acc, float vt)
Definition: BasicControllers.h:65
armarx::VelocityControllerWithAccelerationBounds::targetV
float targetV
Definition: BasicControllers.h:173
armarx::PositionThroughVelocityControllerWithAccelerationAndPositionBounds::positionLimitHi
float positionLimitHi
Definition: BasicControllers.h:429
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::VelocityControllerWithRampedAcceleration::directSetVLimit
float directSetVLimit
Definition: BasicControllers.h:198
armarx::VelocityControllerWithRampedAccelerationAndPositionBounds::currentPosition
double currentPosition
Definition: BasicControllers.h:232
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::PositionThroughVelocityControllerWithAccelerationRamps::currentV
double currentV
Definition: BasicControllers.h:367
dt
constexpr T dt
Definition: UnscentedKalmanFilterTest.cpp:42
armarx::PositionThroughVelocityControllerWithAccelerationRamps::State::DecAccDecJerk
@ DecAccDecJerk
armarx::VelocityControllerWithAccelerationBounds::validParameters
bool validParameters() const
Definition: BasicControllers.cpp:356
armarx::PositionThroughVelocityControllerWithAccelerationRamps::state
State state
Definition: BasicControllers.h:388
armarx::PositionThroughVelocityControllerWithAccelerationRamps::setTargetPosition
void setTargetPosition(double value)
Definition: BasicControllers.cpp:967
armarx::PositionThroughVelocityControllerWithAccelerationBoundsAndPeriodicPosition::positionPeriodHi
float positionPeriodHi
Definition: BasicControllers.h:452
armarx::ctrlutil::t_to_v
double t_to_v(double v, double a, double j)
Definition: CtrlUtil.h:51