8
8
import matplotlib .pyplot as plt
9
9
import math
10
10
import numpy as np
11
- import sys
12
11
13
12
from scipy import interpolate
14
13
from scipy import optimize
24
23
show_animation = True
25
24
26
25
class 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 ):
28
27
self .x = x
29
28
self .y = y
30
29
self .yaw = yaw
31
30
self .v = v
31
+ self .direction = direction
32
32
33
33
def update (self , a , delta , dt ):
34
34
self .x = self .x + self .v * math .cos (self .yaw ) * dt
@@ -52,36 +52,36 @@ def __init__(self, x, y):
52
52
53
53
self .length = s [- 1 ]
54
54
55
- def yaw (self , s ):
55
+ def calc_yaw (self , s ):
56
56
dx , dy = self .dX (s ), self .dY (s )
57
57
return np .arctan2 (dy , dx )
58
58
59
- def curvature (self , s ):
59
+ def calc_curvature (self , s ):
60
60
dx , dy = self .dX (s ), self .dY (s )
61
61
ddx , ddy = self .ddX (s ), self .ddY (s )
62
62
return (ddy * dx - ddx * dy ) / ((dx ** 2 + dy ** 2 )** (3 / 2 ))
63
63
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 ):
66
66
_x , _y = self .X (_s ), self .Y (_s )
67
67
return (_x - args [0 ])** 2 + (_y - args [1 ])** 2
68
68
69
- def jac (_s , * args ):
69
+ def calc_distance_jacobian (_s , * args ):
70
70
_x , _y = self .X (_s ), self .Y (_s )
71
71
_dx , _dy = self .dX (_s ), self .dY (_s )
72
72
return 2 * _dx * (_x - args [0 ])+ 2 * _dy * (_y - args [1 ])
73
73
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 )
75
75
return minimum
76
76
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 )
79
79
80
80
s = ret [0 ][0 ]
81
81
e = ret [1 ]
82
82
83
- k = self .curvature (s )
84
- yaw = self .yaw (s )
83
+ k = self .calc_curvature (s )
84
+ yaw = self .calc_yaw (s )
85
85
86
86
dxl = self .X (s ) - x
87
87
dyl = self .Y (s ) - y
@@ -91,7 +91,7 @@ def TrackError(self, x, y, s0):
91
91
92
92
return e , k , yaw , s
93
93
94
- def PIDControl (target , current ):
94
+ def pid_control (target , current ):
95
95
a = Kp * (target - current )
96
96
return a
97
97
@@ -119,10 +119,9 @@ def rear_wheel_feedback_control(state, e, k, yaw_r):
119
119
return delta
120
120
121
121
122
- def closed_loop_prediction (track , speed_profile , goal ):
122
+ def simulate (track , goal ):
123
123
T = 500.0 # max simulation time
124
124
goal_dis = 0.3
125
- stop_speed = 0.05
126
125
127
126
state = State (x = - 0.0 , y = - 0.0 , yaw = 0.0 , v = 0.0 )
128
127
@@ -135,13 +134,14 @@ def closed_loop_prediction(track, speed_profile, goal):
135
134
goal_flag = False
136
135
137
136
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 )
139
138
140
139
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 )
142
141
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 )
145
145
state .update (ai , di , dt )
146
146
147
147
time = time + dt
@@ -175,29 +175,20 @@ def closed_loop_prediction(track, speed_profile, goal):
175
175
176
176
return t , x , y , yaw , v , goal_flag
177
177
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
197
180
198
- speed_profile [- 1 ] = 0.0
181
+ dyaw = yaw_r - state .yaw
182
+ switch = math .pi / 4.0 <= dyaw < math .pi / 2.0
199
183
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
201
192
202
193
def main ():
203
194
print ("rear wheel feedback tracking start!!" )
@@ -208,13 +199,7 @@ def main():
208
199
track = TrackSpline (ax , ay )
209
200
s = np .arange (0 , track .length , 0.1 )
210
201
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 )
218
203
219
204
# Test
220
205
assert goal_flag , "Cannot goal"
@@ -232,14 +217,14 @@ def main():
232
217
plt .legend ()
233
218
234
219
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" )
236
221
plt .grid (True )
237
222
plt .legend ()
238
223
plt .xlabel ("line length[m]" )
239
224
plt .ylabel ("yaw angle[deg]" )
240
225
241
226
plt .subplots (1 )
242
- plt .plot (s , track .curvature (s ), "-r" , label = "curvature" )
227
+ plt .plot (s , track .calc_curvature (s ), "-r" , label = "curvature" )
243
228
plt .grid (True )
244
229
plt .legend ()
245
230
plt .xlabel ("line length[m]" )
0 commit comments