import numpy as np def get_delta_out_limits(aEgo, aMax, aMin, jMax, jMin): tDelta = 0. if aEgo > aMax: tDelta = (aMax - aEgo) / jMin elif aEgo < aMin: tDelta = (aMin - aEgo) / jMax return tDelta def speed_smoother(vEgo, aEgo, vT, aMax, aMin, jMax, jMin, ts): dV = vT - vEgo tDelta = get_delta_out_limits(aEgo, aMax, aMin, jMax, jMin) if (ts <= tDelta): if (aEgo < aMin): vEgo += ts * aEgo + 0.5 * ts**2 * jMax aEgo += ts * jMax return vEgo, aEgo elif (aEgo > aMax): vEgo += ts * aEgo + 0.5 * ts**2 * jMin aEgo += ts * jMin return vEgo, aEgo if aEgo > aMax: dV -= 0.5 * (aMax**2 - aEgo**2) / jMin vEgo += 0.5 * (aMax**2 - aEgo**2) / jMin aEgo += tDelta * jMin elif aEgo < aMin: dV -= 0.5 * (aMin**2 - aEgo**2) / jMax vEgo += 0.5 * (aMin**2 - aEgo**2) / jMax aEgo += tDelta * jMax ts -= tDelta jLim = jMin if aEgo >= 0 else jMax # if we reduce the accel to zero immediately, how much delta speed we generate? dv_min_shift = - 0.5 * aEgo**2 / jLim # flip signs so we can consider only one case flipped = False if dV < dv_min_shift: flipped = True dV *= -1 vEgo *= -1 aEgo *= -1 aMax = -aMin jMaxcopy = -jMin jMin = -jMax jMax = jMaxcopy # small addition needed to avoid numerical issues with sqrt of ~zero aPeak = np.sqrt((0.5 * aEgo**2 / jMax + dV + 1e-9) / (0.5 / jMax - 0.5 / jMin)) if aPeak > aMax: aPeak = aMax t1 = (aPeak - aEgo) / jMax vChange = dV - 0.5 * (aPeak**2 - aEgo**2) / jMax + 0.5 * aPeak**2 / jMin if vChange < aPeak * ts: t2 = t1 + vChange / aPeak else: t2 = t1 + ts else: t1 = (aPeak - aEgo) / jMax t2 = t1 t3 = t2 - aPeak / jMin dt1 = min(ts, t1) dt2 = max(min(ts, t2) - t1, 0.) dt3 = max(min(ts, t3) - t2, 0.) if ts > t3: vEgo += dV aEgo = 0. else: vEgo += aEgo * dt1 + 0.5 * dt1**2 * jMax + aPeak * dt2 + aPeak * dt3 + 0.5 * dt3**2 * jMin aEgo += jMax * dt1 + dt3 * jMin vEgo *= -1 if flipped else 1 aEgo *= -1 if flipped else 1 return float(vEgo), float(aEgo)