clothoid.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. from math import *
  2. import cornu
  3. def mod_2pi(th):
  4. u = th / (2 * pi)
  5. return 2 * pi * (u - floor(u + 0.5))
  6. # Given clothoid k(s) = k0 + k1 s, compute th1 - th0 of chord from s = -.5
  7. # to .5.
  8. def compute_dth(k0, k1):
  9. if k1 < 0:
  10. return -compute_dth(k0, -k1)
  11. elif k1 == 0:
  12. return 0
  13. sqrk1 = sqrt(2 * k1)
  14. t0 = (k0 - .5 * k1) / sqrk1
  15. t1 = (k0 + .5 * k1) / sqrk1
  16. (y0, x0) = cornu.eval_cornu(t0)
  17. (y1, x1) = cornu.eval_cornu(t1)
  18. chord_th = atan2(y1 - y0, x1 - x0)
  19. return mod_2pi(t1 * t1 - chord_th) - mod_2pi(chord_th - t0 * t0)
  20. def compute_chord(k0, k1):
  21. if k1 == 0:
  22. if k0 == 0:
  23. return 1
  24. else:
  25. return sin(k0 * .5) / (k0 * .5)
  26. sqrk1 = sqrt(2 * abs(k1))
  27. t0 = (k0 - .5 * k1) / sqrk1
  28. t1 = (k0 + .5 * k1) / sqrk1
  29. (y0, x0) = cornu.eval_cornu(t0)
  30. (y1, x1) = cornu.eval_cornu(t1)
  31. return hypot(y1 - y0, x1 - x0) / abs(t1 - t0)
  32. # Given th0 and th1 at endpoints (measured from chord), return k0
  33. # and k1 such that the clothoid k(s) = k0 + k1 s, evaluated from
  34. # s = -.5 to .5, has the tangents given
  35. def solve_clothoid(th0, th1, verbose = False):
  36. k0 = th0 + th1
  37. # initial guess
  38. k1 = 6 * (th1 - th0)
  39. error = (th1 - th0) - compute_dth(k0, k1)
  40. if verbose:
  41. print k0, k1, error
  42. k1_old, error_old = k1, error
  43. # second guess based on d(dth)/dk1 ~ 1/6
  44. k1 += 6 * error
  45. error = (th1 - th0) - compute_dth(k0, k1)
  46. if verbose:
  47. print k0, k1, error
  48. # secant method
  49. for i in range(10):
  50. if abs(error) < 1e-9: break
  51. k1_old, error_old, k1 = k1, error, k1 + (k1_old - k1) * error / (error - error_old)
  52. error = (th1 - th0) - compute_dth(k0, k1)
  53. if verbose:
  54. print k0, k1, error
  55. return k0, k1
  56. if __name__ == '__main__':
  57. print solve_clothoid(.06, .05, True)