42 float directSetVLimit)
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);
56 const float curverror = targetV - currentV;
57 if (std::abs(curverror) < directSetVLimit)
63 const bool accelerate =
sign(targetV) ==
sign(currentV) &&
64 std::abs(targetV) > std::abs(currentV);
66 const float usedacc = accelerate ? acceleration : -deceleration;
67 const float maxDeltaV = std::abs(usedacc *
dt);
68 if (maxDeltaV >= std::abs(curverror))
75 const float deltaVel = std::clamp(
sign(currentV) * usedacc *
dt, -maxDeltaV, maxDeltaV);
76 const float nextV = currentV + deltaVel;
90 float directSetVLimit,
91 float currentPosition,
92 float positionLimitLoSoft,
93 float positionLimitHiSoft,
94 float positionLimitLoHard,
95 float positionLimitHiHard)
97 if (currentPosition <= positionLimitLoHard || currentPosition >= positionLimitHiHard)
99 return std::nanf(
"1");
102 float softLimitViolation = 0;
103 if (currentPosition <= positionLimitLoSoft)
105 softLimitViolation = -1;
107 if (currentPosition >= positionLimitHiSoft)
109 softLimitViolation = 1;
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);
123 const float vsquared = currentV * currentV;
124 const float brakingDist =
125 sign(currentV) * vsquared / 2.f /
126 std::abs(deceleration);
129 const float posIfBrakingNow = currentPosition + brakingDist;
130 if (posIfBrakingNow <= positionLimitLoSoft || posIfBrakingNow >= positionLimitHiSoft)
134 posIfBrakingNow <= positionLimitLoSoft ? positionLimitLoSoft : positionLimitHiSoft;
135 const float wayToGo = limit - currentPosition;
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);
152 dt, maxDt, currentV, targetV, maxV, acceleration, deceleration, directSetVLimit);
154 if (softLimitViolation ==
sign(nextv))
172 float currentPosition,
173 float targetPosition,
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);
189 const float positionError = targetPosition - currentPosition;
190 float newTargetVelPController = positionError * p;
194 signV * currentV * currentV / 2.f /
197 const float posErrorIfBrakingNow = targetPosition - posIfBrakingNow;
199 const bool decelerate =
200 std::abs(currentV) > maxV ||
202 sign(posErrorIfBrakingNow) != signV;
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);
207 float newTargetVel = std::clamp(currentV + deltaVel, -maxV, maxV);
208 bool usePID = std::abs(newTargetVelPController) < std::abs(newTargetVel);
213 return newTargetVelPController;
228 float currentPosition,
229 float targetPosition,
231 float positionLimitLo,
232 float positionLimitHi
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);
250 const float vsquared = currentV * currentV;
252 signV * vsquared / 2.f /
255 if (posIfBrakingNow <= positionLimitLo || posIfBrakingNow >= positionLimitHi)
258 const auto limit =
brakingDistance > 0 ? positionLimitHi : positionLimitLo;
259 const float wayToGo = std::abs(limit - currentPosition);
261 const float dec = std::abs(vsquared / 2.f / wayToGo);
262 const float vel = currentV - signV * dec *
dt;
275 std::clamp(targetPosition, positionLimitLo, positionLimitHi),
291 float currentPosition,
292 float targetPosition,
293 float pControlPosErrorLimit,
296 float positionPeriodLo,
297 float positionPeriodHi)
299 currentPosition =
periodicClamp(currentPosition, positionPeriodLo, positionPeriodHi);
300 targetPosition =
periodicClamp(targetPosition, positionPeriodLo, positionPeriodHi);
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)
323 const float positionPeriodLength = std::abs(positionPeriodHi - positionPeriodLo);
327 periodicClamp(currentPosition - targetPosition, 0.f, positionPeriodLength);
329 const float overshoot = std::trunc((currentPosition + brakingDist) / positionPeriodLength);
331 if (
true || direction == 0)
334 direction = (
periodicClamp(currentPosition + brakingDist, 0.f, positionPeriodLength) >=
335 positionPeriodLength / 2)
340 targetPosition = (overshoot - std::min(0.f, -direction)) *
341 positionPeriodLength;
365 const float useddt = std::min(std::abs(
dt), std::abs(
maxDt));
383 const float maxDeltaV = std::abs(usedacc * useddt);
384 if (maxDeltaV >= std::abs(curverror))
391 const float deltaVel = std::clamp(
sign(
currentV) * usedacc * useddt, -maxDeltaV, maxDeltaV);
392 const float nextV =
currentV + deltaVel;
405 const double useddt = std::min(std::abs(
dt), std::abs(
maxDt));
413 const double curverror = clampedTargetV -
currentV;
418 Output result{clampedTargetV, 0, 0};
428 bool increaseAcc =
true;
441 const double adjustedJerk =
443 double usedJerk = increaseAcc
445 : -goalDir * ((std::abs(
currentV) > 0.01 && !std::isnan(adjustedJerk))
455 if (maxDeltaV >= std::abs(curverror))
459 double nextAcc = (clampedTargetV -
currentV) / useddt;
460 double nextJerk = (nextAcc -
currentAcc) / useddt;
462 Output result{clampedTargetV, nextAcc, nextJerk};
469 Output result{nextV, nextAcc, usedJerk};
502 float softLimitViolation = 0;
505 softLimitViolation = -1;
509 softLimitViolation = 1;
512 const float upperDt = std::max(std::abs(
dt), std::abs(
maxDt));
522 const float brakingDist =
538 const float dec = std::abs(vsquared / 2.f / wayToGo);
540 nextv = std::clamp(vel, -
maxV,
maxV);
554 if (softLimitViolation ==
sign(nextv) && nextv != 0)
570 buffer = boost::circular_buffer<HelpStruct>(20);
573 pid->threadSafe =
false;
599 const float useddt = std::min(std::abs(
dt), std::abs(
maxDt));
611 float newTargetVelPController =
pid->getControlValue();
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
626 const bool decelerate =
629 sign(posErrorIfBrakingNow) != signV;
631 const float usedacc = decelerate ? -usedDeceleration :
acceleration;
632 const float deltaVel = signV * usedacc * useddt;
641 this->currentlyPIDActive = PIDActive;
642 float finalTargetVel =
643 (currentlyPIDActive) ? newTargetVelPController : newTargetVelRampCtrl;
644 if (std::abs(positionError) <
accuracy)
659 newTargetVelPController,
660 newTargetVelRampCtrl,
663 IceUtil::Time::now().toMicroSeconds()});
666 if (buffer.size() > 0 &&
667 sign(positionError) *
sign(buffer[buffer.size() - 2].currentError) < 0 &&
668 eventHappeningCounter < 0)
670 eventHappeningCounter = 10;
673 if (eventHappeningCounter == 0)
676 for (
auto& elem : buffer)
679 <<
VAROUT(elem.targetVelocityRAMP) <<
VAROUT(elem.currentV)
685 if (eventHappeningCounter >= 0)
687 eventHappeningCounter--;
694 PIDModeActive = usePID;
697 return finalTargetVel;
711 const float posErrorIfBrakingNow =
targetPosition - posIfBrakingNow;
720 if (
sign(posError) !=
sign(posErrorIfBrakingNow))
724 curPos = posIfBrakingNow;
745 return t + tr.at(0).dt + tr.at(1).dt + tr.at(2).dt;
760 const float useddt = std::min(std::abs(
dt), std::abs(
maxDt));
772 signV * vsquared / 2.f /
784 const float dec = std::abs(vsquared / 2.f / wayToGo);
785 const float vel =
currentV - signV * dec * useddt;
794 std::array<deltas, 3>
795 trapeze(
float v0,
float acc,
float vMax,
float dec,
float vt,
float dx)
798 vMax = std::abs(vMax);
800 auto calc = [&](
float vmax)
804 const float dxMax = dacc.
dx + ddec.
dx;
807 if (std::abs(dxMax) <= dx)
812 mid.
dt = std::abs(mid.
dx / mid.
dv);
813 return std::make_pair(
true, std::array<deltas, 3>{dacc, mid, ddec});
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;
834 (v0 * v0 / 2.f * (1.f / a0 - 1.f) + vt * vt / 2.f * (1.f / at - 1.f) - dx) /
836 const auto vxs =
pq(p,
q);
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)
843 return std::make_pair(
false, std::array<deltas, 3>());
846 float vx = vx1Valid ? vxs.first : vxs.second;
853 return std::make_pair(
true, std::array<deltas, 3>{daccvx, mid, ddecvx});
864 if (daccvx1.
dt + ddecvx1.
dt < daccvx2.
dt + ddecvx2.
dt)
867 return std::make_pair(
true,
868 std::array<deltas, 3>{daccvx1, mid, ddecvx1});
871 return std::make_pair(
true, std::array<deltas, 3>{daccvx2, mid, ddecvx2});
874 throw std::logic_error{
"unreachable code (bool + bool neither 0,1,2)"};
877 return std::make_pair(
false, std::array<deltas, 3>());
880 const auto plusVMax = calc(vMax);
881 const auto negVMax = calc(-vMax);
882 switch (plusVMax.first + negVMax.first)
885 throw std::invalid_argument(
"could not find a trapez to reach the goal");
887 return plusVMax.first ? plusVMax.second : negVMax.second;
891 plusVMax.second.at(0).dt + plusVMax.second.at(1).dt + plusVMax.second.at(2).dt;
893 negVMax.second.at(0).dt + negVMax.second.at(1).dt + negVMax.second.at(2).dt;
894 return dt1 < dt2 ? plusVMax.second : negVMax.second;
897 throw std::logic_error{
"unreachable code (bool + bool neither 0,1,2)"};
930 -positionPeriodLength * 0.5f,
931 positionPeriodLength * 0.5f);
933 const float overshoot = std::trunc((
currentPosition + brakingDist) / positionPeriodLength);
941 -positionPeriodLength * 0.5f,
942 positionPeriodLength * 0.5f) <= 0)
948 (overshoot * -direction) * positionPeriodLength;
963 return currentlyPIDActive;
994 const double useddt = std::min(std::abs(
dt), std::abs(
maxDt));
1005 double newTargetVelPController = (positionError *
p) * 0.5 +
currentV * 0.5;
1018 std::tie(newState, output) =
calcState();
1019 usedAbsJerk = output.
jerk;
1030 const double posErrorIfBrakingNow =
targetPosition - posIfBrakingNow;
1031 const bool hardBrakingNeeded = std::abs(
brakingDistance) > std::abs(positionError);
1034 const double jerkDir =
1036 const double usedJerk = goalDir * jerkDir * usedAbsJerk;
1037 const double deltaAcc = usedJerk * useddt;
1038 const double newAcceleration =
1043 result.
jerk = usedJerk;
1045 const double usedDeceleration =
1049 (void)usedDeceleration;
1051 const bool decelerate =
1053 hardBrakingNeeded ||
1054 sign(posErrorIfBrakingNow) != signV;
1057 const double deltaVel =
1058 ctrlutil::v(useddt, 0, newAcceleration, usedJerk);
1061 double newTargetVelRampCtrl =
1066 newTargetVelRampCtrl = std::clamp(newTargetVelRampCtrl, -
maxV,
maxV);
1067 bool usePID = std::abs(newTargetVelPController) < std::abs(newTargetVelRampCtrl);
1076 double finalTargetVel = usePID ? newTargetVelPController : newTargetVelRampCtrl;
1080 if (std::abs(positionError) <
accuracy)
1086#ifdef DEBUG_POS_CTRL
1088 newTargetVelPController,
1089 newTargetVelRampCtrl,
1092 IceUtil::Time::now().toMicroSeconds()});
1095 if (buffer.size() > 0 &&
1096 sign(positionError) *
sign(buffer[buffer.size() - 2].currentError) < 0 &&
1097 eventHappeningCounter < 0)
1099 eventHappeningCounter = 10;
1102 if (eventHappeningCounter == 0)
1105 for (
auto& elem : buffer)
1108 <<
VAROUT(elem.targetVelocityRAMP) <<
VAROUT(elem.currentV)
1109 <<
VAROUT(elem.currentError) <<
VAROUT(elem.timestamp);
1114 if (eventHappeningCounter >= 0)
1116 eventHappeningCounter--;
1123 PIDModeActive = usePID;
1132 throw LocalException(
"NYI");
1163 const auto straightBrakingDistance =
1165 const double brakingDistance = brData.dt2 < 0 ? straightBrakingDistance : brData.s_total;
1167 const double t_to_stop =
1169 const auto calculatedJerk =
1171 double tmp_t, tmp_acc, tmp_jerk;
1173 std::tie(tmp_t, tmp_acc, tmp_jerk) =
1175 const double posWhenBrakingWithCustomJerk =
1178 const double posWhenBrakingWithFixedJerk =
ctrlutil::s(
1180 (void)calculatedJerk, (
void)posWhenBrakingWithCustomJerk, (void)posWhenBrakingWithFixedJerk;
1202 || curVDir != goalDir))
1208 return std::make_pair(newState, result);
1217 return std::make_pair(newState, result);
1222 return std::make_pair(newState, result);
1232 const double posWhenBrakingNow =
1234 const double simpleBrakingDistance =
1236 (void)tmpV, (
void)vAfterBraking, (void)accAfterBraking, (
void)posWhenBrakingNow,
1237 (void)simpleBrakingDistance;
1240 std::tie(t, a0, newJerk) =
1245 (void)at, (
void)vt, (void)st;
1250 return std::make_pair(newState, result);
1255 result.
jerk = newJerk;
1258 return std::make_pair(newState, result);
1262 return std::make_pair(newState, result);
1265 throw LocalException();
1434 const double useddt = std::min(std::abs(
dt), std::abs(
maxDt));
1443 double softLimitViolation = 0;
1446 softLimitViolation = -1;
1450 softLimitViolation = 1;
1453 const double upperDt = std::max(std::abs(
dt), std::abs(
maxDt));
1463 const double brakingDist =
1479 const double dec = std::abs(vsquared / 2.0 / wayToGo);
1481 nextv = std::clamp<double>(vel, -
maxV,
maxV);
1495 if (softLimitViolation ==
sign(nextv) && nextv != 0)
1505 return Output{nextv, 0, 0};
1515 double rawFinishTime = 0.0;
1525 rawFinishTime = decelerationTime;
1530 double accelerationTime = std::abs(
1533 rawFinishTime = std::max(decelerationTime + accelerationTime,
1538 double minTime = 0.8;
1539 if (!std::isnan(estimatedTime))
1541 finishTime = std::max(estimatedTime, minTime);
1545 finishTime = std::max(rawFinishTime, minTime);
1555 auto min_jerk_calc_jerk =
1556 [&](
double tf,
double s0,
double v0,
double a0,
double xf = 0,
double t0 = 0.0)
1559 return 60.0 / (D * D * D) * (xf - s0) - 36.0 / (D * D) * v0 - 9.0 / D * a0;
1563 auto min_jerk = [&](
double t,
1574 double tau = (t - t0) / D;
1577 double b2 = D2 * a0 / 2;
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);
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 +
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};
1596 if (remainingTime <= 0.0)
1606 if (signedDistance == 0.0f)
1625 Output result{newPos, newVel, newAcc, newJerk};
1658 double newAcc = (newVelocity -
currentV) /
dt;
1667 Output result{newPos, newVelocity, newAcc, newJerk};
1672 double jerk = min_jerk_calc_jerk(
1682 std::vector<State> states;
1683 std::vector<State> states2;
1692 double jerk = min_jerk_calc_jerk(t, simS, simV, simAcc,
targetPosition);
1693 simAcc = simAcc + jerk *
dt;
1697 states.push_back(
State{t, simS, simV, simAcc, jerk});
1707 double jerk = min_jerk_calc_jerk(t, simS, simV, simAcc,
targetPosition);
1710 simAcc = simAcc + jerk *
dt;
1712 states2.push_back(
State{t, simS, simV, simAcc, jerk});
1721 Output result{newPos, newVelocity, newAcc, jerk};
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
double desiredDeceleration
double getTargetPosition() const
void setTargetPosition(double value)
std::unique_ptr< FixedMinJerkState > fixedMinJerkState
double phase2SwitchDistance
double phase2SwitchMaxRemainingTime
static int Sign(double value)
static double LimitTo(double value, double absThreshold)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
WedgeBrakingData braking_distance_with_wedge(double v0, double a0, double j)
double t_to_v_with_wedge_acc(double v, double a0, double j)
double s(double t, double s0, double v0, double a0, double j)
double a(double t, double a0, double j)
std::tuple< double, double, double > calcAccAndJerk(double s0, double v0)
double t_to_v(double v, double a, double j)
double brakingDistance(double v0, double a0, double j)
double jerk(double t, double s0, double v0, double a0)
double v(double t, double v0, double a0, double j)
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)
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::pair< T, T > pq(T p, T q)
T periodicClamp(T value, T periodLo, T periodHi)
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 positionThroughVelocityControlWithAccelerationBounds(float dt, float maxDt, float currentV, float maxV, float acceleration, float deceleration, float currentPosition, float targetPosition, float p)
bool isfinite(const std::vector< T, Ts... > &v)
Point sub(const Point &x, const Point &y)
double distance(const Point &a, const Point &b)
bool validParameters() const
float estimateTime() const
float pControlPosErrorLimit
bool validParameters() const
bool getCurrentlyPIDActive() const
std::shared_ptr< PIDController > pid
float calculateProportionalGain() const
PositionThroughVelocityControllerWithAccelerationBounds()
double pControlPosErrorLimit
PositionThroughVelocityControllerWithAccelerationRamps()
double estimateTime() const
std::pair< State, Output > calcState() const
double getTargetPosition() const
void setTargetPosition(double value)
bool validParameters() const
double calculateProportionalGain() const
float positionLimitHiSoft
bool validParameters() const
float positionLimitLoSoft
float estimateTime() const
bool validParameters() const
double positionLimitLoSoft
bool validParameters() const
double positionLimitHiSoft
bool validParameters() const