42 float directSetVLimit)
46 acceleration =
std::abs(acceleration);
47 deceleration =
std::abs(deceleration);
56 const float curverror = targetV - currentV;
57 if (
std::abs(curverror) < directSetVLimit)
63 const bool accelerate =
sign(targetV) ==
sign(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;
123 const float vsquared = currentV * currentV;
124 const float brakingDist =
125 sign(currentV) * vsquared / 2.f /
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;
152 dt, maxDt, currentV, targetV, maxV, acceleration, deceleration, directSetVLimit);
154 if (softLimitViolation ==
sign(nextv))
172 float currentPosition,
173 float targetPosition,
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 =
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);
213 return newTargetVelPController;
228 float currentPosition,
229 float targetPosition,
231 float positionLimitLo,
232 float positionLimitHi
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;
383 const float maxDeltaV =
std::abs(usedacc * useddt);
384 if (maxDeltaV >=
std::abs(curverror))
392 const float nextV =
currentV + deltaVel;
399 return maxV > 0 &&
jerk > 0 && targetV <= maxV && targetV >= -
maxV;
413 const double curverror = clampedTargetV -
currentV;
418 Output result{clampedTargetV, 0, 0};
428 bool increaseAcc =
true;
441 const double adjustedJerk =
443 double usedJerk = increaseAcc
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;
522 const float brakingDist =
538 const float dec =
std::abs(vsquared / 2.f / wayToGo);
554 if (softLimitViolation ==
sign(nextv) && nextv != 0)
569 #ifdef DEBUG_POS_CTRL
570 buffer = boost::circular_buffer<HelpStruct>(20);
573 pid->threadSafe =
false;
611 float newTargetVelPController =
pid->getControlValue();
618 const float posErrorIfBrakingNow =
targetPosition - posIfBrakingNow;
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;
657 #ifdef DEBUG_POS_CTRL
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;
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)
800 auto calc = [&](
float vmax)
804 const float dxMax = dacc.
dx + ddec.
dx;
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);
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;
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;
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 =
1067 bool usePID =
std::abs(newTargetVelPController) <
std::abs(newTargetVelRampCtrl);
1076 double finalTargetVel = usePID ? newTargetVelPController : newTargetVelRampCtrl;
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();
1443 double softLimitViolation = 0;
1446 softLimitViolation = -1;
1450 softLimitViolation = 1;
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))
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;
1693 simAcc = simAcc +
jerk *
dt;
1697 states.push_back(
State{t, simS, simV, simAcc,
jerk});
1710 simAcc = simAcc +
jerk *
dt;
1712 states2.push_back(
State{t, simS, simV, simAcc,
jerk});
1721 Output result{newPos, newVelocity, newAcc,
jerk};