plot_solve_clothoid.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import clothoid
  2. from math import *
  3. print '%!PS-Adobe'
  4. def integ_spiro(k0, k1, k2, k3, n = 4):
  5. th1 = k0
  6. th2 = .5 * k1
  7. th3 = (1./6) * k2
  8. th4 = (1./24) * k3
  9. ds = 1. / n
  10. ds2 = ds * ds
  11. ds3 = ds2 * ds
  12. s = .5 * ds - .5
  13. k0 *= ds
  14. k1 *= ds
  15. k2 *= ds
  16. k3 *= ds
  17. x = 0
  18. y = 0
  19. for i in range(n):
  20. if n == 1:
  21. km0 = k0
  22. km1 = k1 * ds
  23. km2 = k2 * ds2
  24. else:
  25. km0 = (((1./6) * k3 * s + .5 * k2) * s + k1) * s + k0
  26. km1 = ((.5 * k3 * s + k2) * s + k1) * ds
  27. km2 = (k3 * s + k2) * ds2
  28. km3 = k3 * ds3
  29. t1_1 = km0
  30. t1_2 = .5 * km1
  31. t1_3 = (1./6) * km2
  32. t1_4 = (1./24) * km3
  33. t2_2 = t1_1 * t1_1
  34. t2_3 = 2 * (t1_1 * t1_2)
  35. t2_4 = 2 * (t1_1 * t1_3) + t1_2 * t1_2
  36. t2_5 = 2 * (t1_1 * t1_4 + t1_2 * t1_3)
  37. t2_6 = 2 * (t1_2 * t1_4) + t1_3 * t1_3
  38. t2_7 = 2 * (t1_3 * t1_4)
  39. t2_8 = t1_4 * t1_4
  40. t3_4 = t2_2 * t1_2 + t2_3 * t1_1
  41. t3_6 = t2_2 * t1_4 + t2_3 * t1_3 + t2_4 * t1_2 + t2_5 * t1_1
  42. t3_8 = t2_4 * t1_4 + t2_5 * t1_3 + t2_6 * t1_2 + t2_7 * t1_1
  43. t3_10 = t2_6 * t1_4 + t2_7 * t1_3 + t2_8 * t1_2
  44. t4_4 = t2_2 * t2_2
  45. t4_5 = 2 * (t2_2 * t2_3)
  46. t4_6 = 2 * (t2_2 * t2_4) + t2_3 * t2_3
  47. t4_7 = 2 * (t2_2 * t2_5 + t2_3 * t2_4)
  48. t4_8 = 2 * (t2_2 * t2_6 + t2_3 * t2_5) + t2_4 * t2_4
  49. t4_9 = 2 * (t2_2 * t2_7 + t2_3 * t2_6 + t2_4 * t2_5)
  50. t4_10 = 2 * (t2_2 * t2_8 + t2_3 * t2_7 + t2_4 * t2_6) + t2_5 * t2_5
  51. t5_6 = t4_4 * t1_2 + t4_5 * t1_1
  52. t5_8 = t4_4 * t1_4 + t4_5 * t1_3 + t4_6 * t1_2 + t4_7 * t1_1
  53. t5_10 = t4_6 * t1_4 + t4_7 * t1_3 + t4_8 * t1_2 + t4_9 * t1_1
  54. t6_6 = t4_4 * t2_2
  55. t6_7 = t4_4 * t2_3 + t4_5 * t2_2
  56. t6_8 = t4_4 * t2_4 + t4_5 * t2_3 + t4_6 * t2_2
  57. t6_9 = t4_4 * t2_5 + t4_5 * t2_4 + t4_6 * t2_3 + t4_7 * t2_2
  58. t6_10 = t4_4 * t2_6 + t4_5 * t2_5 + t4_6 * t2_4 + t4_7 * t2_3 + t4_8 * t2_2
  59. t7_8 = t6_6 * t1_2 + t6_7 * t1_1
  60. t7_10 = t6_6 * t1_4 + t6_7 * t1_3 + t6_8 * t1_2 + t6_9 * t1_1
  61. t8_8 = t6_6 * t2_2
  62. t8_9 = t6_6 * t2_3 + t6_7 * t2_2
  63. t8_10 = t6_6 * t2_4 + t6_7 * t2_3 + t6_8 * t2_2
  64. t9_10 = t8_8 * t1_2 + t8_9 * t1_1
  65. t10_10 = t8_8 * t2_2
  66. u = 1
  67. u -= (1./24) * t2_2 + (1./160) * t2_4 + (1./896) * t2_6 + (1./4608) * t2_8
  68. u += (1./1920) * t4_4 + (1./10752) * t4_6 + (1./55296) * t4_8 + (1./270336) * t4_10
  69. u -= (1./322560) * t6_6 + (1./1658880) * t6_8 + (1./8110080) * t6_10
  70. u += (1./92897280) * t8_8 + (1./454164480) * t8_10
  71. u -= 2.4464949595157930e-11 * t10_10
  72. v = (1./12) * t1_2 + (1./80) * t1_4
  73. v -= (1./480) * t3_4 + (1./2688) * t3_6 + (1./13824) * t3_8 + (1./67584) * t3_10
  74. v += (1./53760) * t5_6 + (1./276480) * t5_8 + (1./1351680) * t5_10
  75. v -= (1./11612160) * t7_8 + (1./56770560) * t7_10
  76. v += 2.4464949595157932e-10 * t9_10
  77. if n == 1:
  78. x = u
  79. y = v
  80. else:
  81. th = (((th4 * s + th3) * s + th2) * s + th1) * s
  82. cth = cos(th)
  83. sth = sin(th)
  84. x += cth * u - sth * v
  85. y += cth * v + sth * u
  86. s += ds
  87. return [x * ds, y * ds]
  88. count_iter = 0
  89. # Given th0 and th1 at endpoints (measured from chord), return k0
  90. # and k1 such that the clothoid k(s) = k0 + k1 s, evaluated from
  91. # s = -.5 to .5, has the tangents given
  92. def solve_clothoid(th0, th1, verbose = False):
  93. global count_iter
  94. k1_old = 0
  95. e_old = th1 - th0
  96. k0 = th0 + th1
  97. k1 = 6 * (1 - ((.5 / pi) * k0) ** 3) * e_old
  98. # secant method
  99. for i in range(10):
  100. x, y = integ_spiro(k0, k1, 0, 0)
  101. e = (th1 - th0) + 2 * atan2(y, x) - .25 * k1
  102. count_iter += 1
  103. if verbose:
  104. print k0, k1, e
  105. if abs(e) < 1e-9: break
  106. k1_old, e_old, k1 = k1, e, k1 + (k1_old - k1) * e / (e - e_old)
  107. return k0, k1
  108. def plot_by_thp():
  109. count = 0
  110. for i in range(11):
  111. thp = i * .1
  112. print .5 + .05 * i, .5, .5, 'setrgbcolor'
  113. print '.75 setlinewidth'
  114. cmd = 'moveto'
  115. for j in range(-40, 41):
  116. thm = j * .02
  117. k0, k1 = solve_clothoid(thp - thm, thp + thm, True)
  118. count += 1
  119. k1 = min(40, max(-40, k1))
  120. print 306 + 75 * thm, 396 - 10 * k1, cmd
  121. cmd = 'lineto'
  122. print 'stroke'
  123. print '% count_iter = ', count_iter, 'for', count
  124. def plot_by_thm():
  125. print '.75 setlinewidth'
  126. print 36, 396 - 350, 'moveto'
  127. print 0, 700, 'rlineto stroke'
  128. for i in range(-10, 10):
  129. if i == 0: wid = 636
  130. else: wid = 5
  131. print 36, 396 - 10 * i, 'moveto', wid, '0 rlineto stroke'
  132. cmd = 'moveto'
  133. thm = -.1
  134. for i in range(41):
  135. thp = i * .1
  136. k0, k1 = solve_clothoid(thp - thm, thp + thm)
  137. print 36 + 150 * thp, 396 - 100 * k1, cmd
  138. cmd = 'lineto'
  139. print 'stroke'
  140. print '0 0 1 setrgbcolor'
  141. cmd = 'moveto'
  142. for i in range(41):
  143. thp = i * .1
  144. k1 = 12 * thm * cos(.5 * thp)
  145. k1 = 12 * thm * (1 - (thp / pi) ** 3)
  146. print 36 + 150 * thp, 396 - 100 * k1, cmd
  147. cmd = 'lineto'
  148. print 'stroke'
  149. plot_by_thp()