|  |  |  | 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
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # recover quickly if dV is positive and aEgo is negative or viceversa
 | 
					
						
							|  |  |  |   if dV > 0. and aEgo < 0.:
 | 
					
						
							|  |  |  |     jMax *= 3.
 | 
					
						
							|  |  |  |   elif dV < 0. and aEgo > 0.:
 | 
					
						
							|  |  |  |     jMin *= 3.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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
 | 
					
						
							|  |  |  |     if aPeak <= 0:  # there is no solution, so stop after t1
 | 
					
						
							|  |  |  |       t2 = t1 + ts + 1e-9
 | 
					
						
							|  |  |  |       t3 = t2
 | 
					
						
							|  |  |  |     else:
 | 
					
						
							|  |  |  |       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
 | 
					
						
							|  |  |  |       t3 = t2 - aPeak / jMin
 | 
					
						
							|  |  |  |   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)
 |