77import math
88import os
99import sys
10+ from enum import IntEnum
1011
1112import matplotlib .pyplot as plt
1213import numpy as np
2122
2223
2324class SweepSearcher :
25+ class SweepDirection (IntEnum ):
26+ UP = 1
27+ DOWN = - 1
2428
25- def __init__ (self , mdirection , sdirection , xinds_miny , miny ):
26- self .moving_direction = mdirection # +1 or -1
27- self .sweep_direction = sdirection # +1 or -1
29+ class MovingDirection (IntEnum ):
30+ RIGHT = 1
31+ LEFT = - 1
32+
33+ def __init__ (self , mdirection , sdirection , xinds_goaly , goaly ):
34+ self .moving_direction = mdirection
35+ self .sweep_direction = sdirection
2836 self .turing_window = []
2937 self .update_turning_window ()
30- self .xinds_miny = xinds_miny
31- self .miny = miny
38+ self .xinds_goaly = xinds_goaly
39+ self .goaly = goaly
3240
3341 def move_target_grid (self , cxind , cyind , gmap ):
3442
@@ -48,6 +56,7 @@ def move_target_grid(self, cxind, cyind, gmap):
4856 # moved backward, but the grid is occupied by obstacle
4957 return None , None
5058 else :
59+ # keep moving until end
5160 while not gmap .check_occupied_from_xy_index (ncxind + self .moving_direction , ncyind , occupied_val = 0.5 ):
5261 ncxind += self .moving_direction
5362 self .swap_moving_direction ()
@@ -67,8 +76,8 @@ def find_safe_turning_grid(self, cxind, cyind, gmap):
6776 return None , None
6877
6978 def is_search_done (self , gmap ):
70- for ix in self .xinds_miny :
71- if not gmap .check_occupied_from_xy_index (ix , self .miny , occupied_val = 0.5 ):
79+ for ix in self .xinds_goaly :
80+ if not gmap .check_occupied_from_xy_index (ix , self .goaly , occupied_val = 0.5 ):
7281 return False
7382
7483 # all lower grid is occupied
@@ -86,19 +95,33 @@ def swap_moving_direction(self):
8695 self .moving_direction *= - 1
8796 self .update_turning_window ()
8897
98+ def search_start_grid (self , grid_map ):
99+ xinds = [], y_ind = 0
100+ if self .sweep_direction == self .SweepDirection .DOWN :
101+ xinds , y_ind = search_free_grid_index_at_edge_y (grid_map , from_upper = True )
102+ elif self .sweep_direction == self .SweepDirection .UP :
103+ xinds , y_ind = search_free_grid_index_at_edge_y (grid_map , from_upper = False )
104+
105+ if self .moving_direction == self .MovingDirection .RIGHT :
106+ return min (xinds ), y_ind
107+ elif self .moving_direction == self .MovingDirection .LEFT :
108+ return max (xinds ), y_ind
109+
110+ raise ValueError ("self.moving direction is invalid " )
111+
89112
90113def find_sweep_direction_and_start_posi (ox , oy ):
91114 # find sweep_direction
92- maxd = 0.0
115+ max_dist = 0.0
93116 vec = [0.0 , 0.0 ]
94117 sweep_start_pos = [0.0 , 0.0 ]
95118 for i in range (len (ox ) - 1 ):
96119 dx = ox [i + 1 ] - ox [i ]
97120 dy = oy [i + 1 ] - oy [i ]
98121 d = np .sqrt (dx ** 2 + dy ** 2 )
99122
100- if d > maxd :
101- maxd = d
123+ if d > max_dist :
124+ max_dist = d
102125 vec = [dx , dy ]
103126 sweep_start_pos = [ox [i ], oy [i ]]
104127
@@ -156,9 +179,7 @@ def search_free_grid_index_at_edge_y(grid_map, from_upper=False):
156179 return xinds , yind
157180
158181
159- def setup_grid_map (ox , oy , reso ):
160- offset_grid = 10
161-
182+ def setup_grid_map (ox , oy , reso , sweep_direction , offset_grid = 10 ):
162183 width = math .ceil ((max (ox ) - min (ox )) / reso ) + offset_grid
163184 height = math .ceil ((max (oy ) - min (oy )) / reso ) + offset_grid
164185 center_x = np .mean (ox )
@@ -170,27 +191,28 @@ def setup_grid_map(ox, oy, reso):
170191
171192 grid_map .expand_grid ()
172193
173- xinds , miny = search_free_grid_index_at_edge_y (grid_map )
174-
175- return grid_map , xinds , miny
176-
177-
178- def search_start_grid (grid_map ):
179- xinds , y_ind = search_free_grid_index_at_edge_y (grid_map , from_upper = True )
180-
181- return min (xinds ), y_ind
194+ xinds_goaly = [], goaly = 0
195+ if sweep_direction == SweepSearcher .SweepDirection .UP :
196+ xinds_goaly , goaly = search_free_grid_index_at_edge_y (grid_map , from_upper = True )
197+ elif sweep_direction == SweepSearcher .SweepDirection .DOWN :
198+ xinds_goaly , goaly = search_free_grid_index_at_edge_y (grid_map , from_upper = False )
182199
200+ return grid_map , xinds_goaly , goaly
183201
184- def sweep_path_search (sweep_searcher , gmap ):
185- px , py = [], []
186202
203+ def sweep_path_search (sweep_searcher , gmap , grid_search_animation = False ):
187204 # search start grid
188- cxind , cyind = search_start_grid (gmap )
205+ cxind , cyind = sweep_searcher . search_start_grid (gmap )
189206 if not gmap .set_value_from_xy_index (cxind , cyind , 0.5 ):
190207 print ("Cannot find start grid" )
191- return px , py
208+ return [], []
209+
210+ x , y = gmap .calc_grid_central_xy_position_from_xy_index (cxind , cyind )
211+ px , py = [x ], [y ]
212+
213+ if grid_search_animation :
214+ fig , ax = plt .subplots ()
192215
193- # fig, ax = plt.subplots()
194216 while True :
195217 cxind , cyind = sweep_searcher .move_target_grid (cxind , cyind , gmap )
196218
@@ -206,44 +228,39 @@ def sweep_path_search(sweep_searcher, gmap):
206228
207229 gmap .set_value_from_xy_index (cxind , cyind , 0.5 )
208230
209- # gmap.plot_grid_map(ax=ax)
210- # plt.pause(1.0)
231+ if grid_search_animation :
232+ gmap .plot_grid_map (ax = ax )
233+ plt .pause (1.0 )
211234
212235 gmap .plot_grid_map ()
213236
214237 return px , py
215238
216239
217- def planning (ox , oy , reso ):
240+ def planning (ox , oy , reso ,
241+ moving_direction = SweepSearcher .MovingDirection .RIGHT ,
242+ sweeping_direction = SweepSearcher .SweepDirection .UP ,
243+ ):
218244 sweep_vec , sweep_start_posi = find_sweep_direction_and_start_posi (ox , oy )
219245
220246 rox , roy = convert_grid_coordinate (ox , oy , sweep_vec , sweep_start_posi )
221247
222- moving_direction = 1
223- sweeping_direction = - 1
248+ gmap , xinds_goaly , goaly = setup_grid_map (rox , roy , reso , sweeping_direction )
224249
225- gmap , xinds_miny , miny = setup_grid_map (rox , roy , reso )
226-
227- sweep_searcher = SweepSearcher (moving_direction , sweeping_direction , xinds_miny , miny )
250+ sweep_searcher = SweepSearcher (moving_direction , sweeping_direction , xinds_goaly , goaly )
228251
229252 px , py = sweep_path_search (sweep_searcher , gmap )
230253
231254 rx , ry = convert_global_coordinate (px , py , sweep_vec , sweep_start_posi )
232255
233- return rx , ry
256+ print ( "Path length:" , len ( rx ))
234257
258+ return rx , ry
235259
236- def main ():
237- print ("start!!" )
238-
239- ox = [0.0 , 20.0 , 50.0 , 100.0 , 130.0 , 40.0 , 0.0 ]
240- oy = [0.0 , - 20.0 , 0.0 , 30.0 , 60.0 , 80.0 , 0.0 ]
241- reso = 5.0
242260
261+ def planning_animation (ox , oy , reso ):
243262 px , py = planning (ox , oy , reso )
244263
245- plt .subplots ()
246-
247264 # animation
248265 if do_animation :
249266 for ipx , ipy in zip (px , py ):
@@ -260,6 +277,27 @@ def main():
260277 plt .plot (px , py , "-r" )
261278 plt .axis ("equal" )
262279 plt .grid (True )
280+ plt .pause (0.1 )
281+
282+
283+ def main ():
284+ print ("start!!" )
285+
286+ ox = [0.0 , 20.0 , 50.0 , 100.0 , 130.0 , 40.0 , 0.0 ]
287+ oy = [0.0 , - 20.0 , 0.0 , 30.0 , 60.0 , 80.0 , 0.0 ]
288+ reso = 5.0
289+ planning_animation (ox , oy , reso )
290+
291+ ox = [0.0 , 50.0 , 50.0 , 0.0 , 0.0 ]
292+ oy = [0.0 , 0.0 , 30.0 , 30.0 , 0.0 ]
293+ reso = 1.3
294+ planning_animation (ox , oy , reso )
295+
296+ ox = [0.0 , 20.0 , 50.0 , 200.0 , 130.0 , 40.0 , 0.0 ]
297+ oy = [0.0 , - 80.0 , 0.0 , 30.0 , 60.0 , 80.0 , 0.0 ]
298+ reso = 5.0
299+ planning_animation (ox , oy , reso )
300+
263301 plt .show ()
264302
265303 print ("done!!" )
0 commit comments