88import matplotlib .pyplot as plt
99import math
1010import numpy as np
11- import sys
1211
1312from scipy import interpolate
1413from scipy import optimize
2423show_animation = True
2524
2625class State :
27- def __init__ (self , x = 0.0 , y = 0.0 , yaw = 0.0 , v = 0.0 ):
26+ def __init__ (self , x = 0.0 , y = 0.0 , yaw = 0.0 , v = 0.0 , direction = 1 ):
2827 self .x = x
2928 self .y = y
3029 self .yaw = yaw
3130 self .v = v
31+ self .direction = direction
3232
3333 def update (self , a , delta , dt ):
3434 self .x = self .x + self .v * math .cos (self .yaw ) * dt
@@ -52,36 +52,36 @@ def __init__(self, x, y):
5252
5353 self .length = s [- 1 ]
5454
55- def yaw (self , s ):
55+ def calc_yaw (self , s ):
5656 dx , dy = self .dX (s ), self .dY (s )
5757 return np .arctan2 (dy , dx )
5858
59- def curvature (self , s ):
59+ def calc_curvature (self , s ):
6060 dx , dy = self .dX (s ), self .dY (s )
6161 ddx , ddy = self .ddX (s ), self .ddY (s )
6262 return (ddy * dx - ddx * dy ) / ((dx ** 2 + dy ** 2 )** (3 / 2 ))
6363
64- def __findClosestPoint (self , s0 , x , y ):
65- def f (_s , * args ):
64+ def __find_nearest_point (self , s0 , x , y ):
65+ def calc_distance (_s , * args ):
6666 _x , _y = self .X (_s ), self .Y (_s )
6767 return (_x - args [0 ])** 2 + (_y - args [1 ])** 2
6868
69- def jac (_s , * args ):
69+ def calc_distance_jacobian (_s , * args ):
7070 _x , _y = self .X (_s ), self .Y (_s )
7171 _dx , _dy = self .dX (_s ), self .dY (_s )
7272 return 2 * _dx * (_x - args [0 ])+ 2 * _dy * (_y - args [1 ])
7373
74- minimum = optimize .fmin_cg (f , s0 , jac , args = (x , y ), full_output = True , disp = False )
74+ minimum = optimize .fmin_cg (calc_distance , s0 , calc_distance_jacobian , args = (x , y ), full_output = True , disp = False )
7575 return minimum
7676
77- def TrackError (self , x , y , s0 ):
78- ret = self .__findClosestPoint (s0 , x , y )
77+ def calc_track_error (self , x , y , s0 ):
78+ ret = self .__find_nearest_point (s0 , x , y )
7979
8080 s = ret [0 ][0 ]
8181 e = ret [1 ]
8282
83- k = self .curvature (s )
84- yaw = self .yaw (s )
83+ k = self .calc_curvature (s )
84+ yaw = self .calc_yaw (s )
8585
8686 dxl = self .X (s ) - x
8787 dyl = self .Y (s ) - y
@@ -91,7 +91,7 @@ def TrackError(self, x, y, s0):
9191
9292 return e , k , yaw , s
9393
94- def PIDControl (target , current ):
94+ def pid_control (target , current ):
9595 a = Kp * (target - current )
9696 return a
9797
@@ -119,10 +119,9 @@ def rear_wheel_feedback_control(state, e, k, yaw_r):
119119 return delta
120120
121121
122- def closed_loop_prediction (track , speed_profile , goal ):
122+ def simulate (track , goal ):
123123 T = 500.0 # max simulation time
124124 goal_dis = 0.3
125- stop_speed = 0.05
126125
127126 state = State (x = - 0.0 , y = - 0.0 , yaw = 0.0 , v = 0.0 )
128127
@@ -135,13 +134,14 @@ def closed_loop_prediction(track, speed_profile, goal):
135134 goal_flag = False
136135
137136 s = np .arange (0 , track .length , 0.1 )
138- e , k , yaw_r , s0 = track .TrackError (state .x , state .y , 0.0 )
137+ e , k , yaw_r , s0 = track .calc_track_error (state .x , state .y , 0.0 )
139138
140139 while T >= time :
141- e , k , yaw_r , s0 = track .TrackError (state .x , state .y , s0 )
140+ e , k , yaw_r , s0 = track .calc_track_error (state .x , state .y , s0 )
142141 di = rear_wheel_feedback_control (state , e , k , yaw_r )
143- #ai = PIDControl(speed_profile[target_ind], state.v)
144- ai = PIDControl (speed_profile , state .v )
142+
143+ speed_r = calc_target_speed (state , yaw_r )
144+ ai = pid_control (speed_r , state .v )
145145 state .update (ai , di , dt )
146146
147147 time = time + dt
@@ -175,29 +175,20 @@ def closed_loop_prediction(track, speed_profile, goal):
175175
176176 return t , x , y , yaw , v , goal_flag
177177
178- def calc_speed_profile (track , target_speed , s ):
179- speed_profile = [target_speed ] * len (cx )
180- direction = 1.0
181-
182- # Set stop point
183- for i in range (len (cx ) - 1 ):
184- dyaw = cyaw [i + 1 ] - cyaw [i ]
185- switch = math .pi / 4.0 <= dyaw < math .pi / 2.0
186-
187- if switch :
188- direction *= - 1
189-
190- if direction != 1.0 :
191- speed_profile [i ] = - target_speed
192- else :
193- speed_profile [i ] = target_speed
194-
195- if switch :
196- speed_profile [i ] = 0.0
178+ def calc_target_speed (state , yaw_r ):
179+ target_speed = 10.0 / 3.6
197180
198- speed_profile [- 1 ] = 0.0
181+ dyaw = yaw_r - state .yaw
182+ switch = math .pi / 4.0 <= dyaw < math .pi / 2.0
199183
200- return speed_profile
184+ if switch :
185+ state .direction *= - 1
186+ return 0.0
187+
188+ if state .direction != 1 :
189+ return - target_speed
190+ else :
191+ return target_speed
201192
202193def main ():
203194 print ("rear wheel feedback tracking start!!" )
@@ -208,13 +199,7 @@ def main():
208199 track = TrackSpline (ax , ay )
209200 s = np .arange (0 , track .length , 0.1 )
210201
211- target_speed = 10.0 / 3.6
212-
213- # Note: disable backward direction temporary
214- #sp = calc_speed_profile(track, target_speed, s)
215- sp = target_speed
216-
217- t , x , y , yaw , v , goal_flag = closed_loop_prediction (track , sp , goal )
202+ t , x , y , yaw , v , goal_flag = simulate (track , goal )
218203
219204 # Test
220205 assert goal_flag , "Cannot goal"
@@ -232,14 +217,14 @@ def main():
232217 plt .legend ()
233218
234219 plt .subplots (1 )
235- plt .plot (s , np .rad2deg (track .yaw (s )), "-r" , label = "yaw" )
220+ plt .plot (s , np .rad2deg (track .calc_yaw (s )), "-r" , label = "yaw" )
236221 plt .grid (True )
237222 plt .legend ()
238223 plt .xlabel ("line length[m]" )
239224 plt .ylabel ("yaw angle[deg]" )
240225
241226 plt .subplots (1 )
242- plt .plot (s , track .curvature (s ), "-r" , label = "curvature" )
227+ plt .plot (s , track .calc_curvature (s ), "-r" , label = "curvature" )
243228 plt .grid (True )
244229 plt .legend ()
245230 plt .xlabel ("line length[m]" )
0 commit comments