quintic_polynomial.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. """
  2. Quintic Polynomial
  3. """
  4. import math
  5. import numpy as np
  6. import matplotlib.pyplot as plt
  7. import draw
  8. class QuinticPolynomial:
  9. def __init__(self, x0, v0, a0, x1, v1, a1, T):
  10. A = np.array([[T ** 3, T ** 4, T ** 5],
  11. [3 * T ** 2, 4 * T ** 3, 5 * T ** 4],
  12. [6 * T, 12 * T ** 2, 20 * T ** 3]])
  13. b = np.array([x1 - x0 - v0 * T - a0 * T ** 2 / 2,
  14. v1 - v0 - a0 * T,
  15. a1 - a0])
  16. X = np.linalg.solve(A, b)
  17. self.a0 = x0
  18. self.a1 = v0
  19. self.a2 = a0 / 2.0
  20. self.a3 = X[0]
  21. self.a4 = X[1]
  22. self.a5 = X[2]
  23. def calc_xt(self, t):
  24. xt = self.a0 + self.a1 * t + self.a2 * t ** 2 + \
  25. self.a3 * t ** 3 + self.a4 * t ** 4 + self.a5 * t ** 5
  26. return xt
  27. def calc_dxt(self, t):
  28. dxt = self.a1 + 2 * self.a2 * t + \
  29. 3 * self.a3 * t ** 2 + 4 * self.a4 * t ** 3 + 5 * self.a5 * t ** 4
  30. return dxt
  31. def calc_ddxt(self, t):
  32. ddxt = 2 * self.a2 + 6 * self.a3 * t + 12 * self.a4 * t ** 2 + 20 * self.a5 * t ** 3
  33. return ddxt
  34. def calc_dddxt(self, t):
  35. dddxt = 6 * self.a3 + 24 * self.a4 * t + 60 * self.a5 * t ** 2
  36. return dddxt
  37. class Trajectory:
  38. def __init__(self):
  39. self.t = []
  40. self.x = []
  41. self.y = []
  42. self.yaw = []
  43. self.v = []
  44. self.a = []
  45. self.jerk = []
  46. def simulation():
  47. sx, sy, syaw, sv, sa = 10.0, 10.0, np.deg2rad(10.0), 1.0, 0.1
  48. gx, gy, gyaw, gv, ga = 30.0, -10.0, np.deg2rad(180.0), 1.0, 0.1
  49. MAX_ACCEL = 1.0 # max accel [m/s2]
  50. MAX_JERK = 0.5 # max jerk [m/s3]
  51. dt = 0.1 # T tick [s]
  52. MIN_T = 5
  53. MAX_T = 100
  54. T_STEP = 5
  55. sv_x = sv * math.cos(syaw)
  56. sv_y = sv * math.sin(syaw)
  57. gv_x = gv * math.cos(gyaw)
  58. gv_y = gv * math.sin(gyaw)
  59. sa_x = sa * math.cos(syaw)
  60. sa_y = sa * math.sin(syaw)
  61. ga_x = ga * math.cos(gyaw)
  62. ga_y = ga * math.sin(gyaw)
  63. path = Trajectory()
  64. for T in np.arange(MIN_T, MAX_T, T_STEP):
  65. path = Trajectory()
  66. xqp = QuinticPolynomial(sx, sv_x, sa_x, gx, gv_x, ga_x, T)
  67. yqp = QuinticPolynomial(sy, sv_y, sa_y, gy, gv_y, ga_y, T)
  68. for t in np.arange(0.0, T + dt, dt):
  69. path.t.append(t)
  70. path.x.append(xqp.calc_xt(t))
  71. path.y.append(yqp.calc_xt(t))
  72. vx = xqp.calc_dxt(t)
  73. vy = yqp.calc_dxt(t)
  74. path.v.append(np.hypot(vx, vy))
  75. path.yaw.append(math.atan2(vy, vx))
  76. ax = xqp.calc_ddxt(t)
  77. ay = yqp.calc_ddxt(t)
  78. a = np.hypot(ax, ay)
  79. if len(path.v) >= 2 and path.v[-1] - path.v[-2] < 0.0:
  80. a *= -1
  81. path.a.append(a)
  82. jx = xqp.calc_dddxt(t)
  83. jy = yqp.calc_dddxt(t)
  84. j = np.hypot(jx, jy)
  85. if len(path.a) >= 2 and path.a[-1] - path.a[-2] < 0.0:
  86. j *= -1
  87. path.jerk.append(j)
  88. if max(np.abs(path.a)) <= MAX_ACCEL and max(np.abs(path.jerk)) <= MAX_JERK:
  89. break
  90. print("t_len: ", path.t, "s")
  91. print("max_v: ", max(path.v), "m/s")
  92. print("max_a: ", max(np.abs(path.a)), "m/s2")
  93. print("max_jerk: ", max(np.abs(path.jerk)), "m/s3")
  94. for i in range(len(path.t)):
  95. plt.cla()
  96. plt.gcf().canvas.mpl_connect('key_release_event',
  97. lambda event: [exit(0) if event.key == 'escape' else None])
  98. plt.axis("equal")
  99. plt.plot(path.x, path.y, linewidth=2, color='gray')
  100. draw.Car(sx, sy, syaw, 1.5, 3)
  101. draw.Car(gx, gy, gyaw, 1.5, 3)
  102. draw.Car(path.x[i], path.y[i], path.yaw[i], 1.5, 3)
  103. plt.title("Quintic Polynomial Curves")
  104. plt.grid(True)
  105. plt.pause(0.001)
  106. plt.show()
  107. if __name__ == '__main__':
  108. simulation()