11
11
12
12
show_animation = True
13
13
14
+
14
15
class Dijkstra :
15
16
16
- def __init__ (self , ox , oy , reso , rr ):
17
+ def __init__ (self , ox , oy , resolution , robot_radius ):
17
18
"""
18
19
Initialize map for a star planning
19
20
20
21
ox: x position list of Obstacles [m]
21
22
oy: y position list of Obstacles [m]
22
- reso : grid resolution [m]
23
+ resolution : grid resolution [m]
23
24
rr: robot radius[m]
24
25
"""
25
26
26
- self .reso = reso
27
- self .rr = rr
27
+ self .min_x = None
28
+ self .min_y = None
29
+ self .max_x = None
30
+ self .max_y = None
31
+ self .x_width = None
32
+ self .y_width = None
33
+ self .obstacle_map = None
34
+
35
+ self .resolution = resolution
36
+ self .robot_radius = robot_radius
28
37
self .calc_obstacle_map (ox , oy )
29
38
self .motion = self .get_motion_model ()
30
39
31
40
class Node :
32
- def __init__ (self , x , y , cost , pind ):
41
+ def __init__ (self , x , y , cost , parent ):
33
42
self .x = x # index of grid
34
43
self .y = y # index of grid
35
44
self .cost = cost
36
- self .pind = pind # index of previous Node
45
+ self .parent = parent # index of previous Node
37
46
38
47
def __str__ (self ):
39
- return str (self .x ) + "," + str (self .y ) + "," + str (self .cost ) + "," + str (self .pind )
48
+ return str (self .x ) + "," + str (self .y ) + "," + str (
49
+ self .cost ) + "," + str (self .parent )
40
50
41
51
def planning (self , sx , sy , gx , gy ):
42
52
"""
@@ -53,39 +63,40 @@ def planning(self, sx, sy, gx, gy):
53
63
ry: y position list of the final path
54
64
"""
55
65
56
- nstart = self .Node (self .calc_xyindex (sx , self .minx ),
57
- self .calc_xyindex (sy , self .miny ), 0.0 , - 1 )
58
- ngoal = self .Node (self .calc_xyindex (gx , self .minx ),
59
- self .calc_xyindex (gy , self .miny ), 0.0 , - 1 )
66
+ start_node = self .Node (self .calc_xy_index (sx , self .min_x ),
67
+ self .calc_xy_index (sy , self .min_y ), 0.0 , - 1 )
68
+ goal_node = self .Node (self .calc_xy_index (gx , self .min_x ),
69
+ self .calc_xy_index (gy , self .min_y ), 0.0 , - 1 )
60
70
61
- openset , closedset = dict (), dict ()
62
- openset [self .calc_index (nstart )] = nstart
71
+ open_set , closed_set = dict (), dict ()
72
+ open_set [self .calc_index (start_node )] = start_node
63
73
64
74
while 1 :
65
- c_id = min (openset , key = lambda o : openset [o ].cost )
66
- current = openset [c_id ]
75
+ c_id = min (open_set , key = lambda o : open_set [o ].cost )
76
+ current = open_set [c_id ]
67
77
68
78
# show graph
69
79
if show_animation : # pragma: no cover
70
- plt .plot (self .calc_position (current .x , self .minx ),
71
- self .calc_position (current .y , self .miny ), "xc" )
80
+ plt .plot (self .calc_position (current .x , self .min_x ),
81
+ self .calc_position (current .y , self .min_y ), "xc" )
72
82
# for stopping simulation with the esc key.
73
- plt .gcf ().canvas .mpl_connect ('key_release_event' ,
74
- lambda event : [exit (0 ) if event .key == 'escape' else None ])
75
- if len (closedset .keys ()) % 10 == 0 :
83
+ plt .gcf ().canvas .mpl_connect (
84
+ 'key_release_event' ,
85
+ lambda event : [exit (0 ) if event .key == 'escape' else None ])
86
+ if len (closed_set .keys ()) % 10 == 0 :
76
87
plt .pause (0.001 )
77
88
78
- if current .x == ngoal .x and current .y == ngoal .y :
89
+ if current .x == goal_node .x and current .y == goal_node .y :
79
90
print ("Find goal" )
80
- ngoal . pind = current .pind
81
- ngoal .cost = current .cost
91
+ goal_node . parent = current .parent
92
+ goal_node .cost = current .cost
82
93
break
83
94
84
95
# Remove the item from the open set
85
- del openset [c_id ]
96
+ del open_set [c_id ]
86
97
87
98
# Add it to the closed set
88
- closedset [c_id ] = current
99
+ closed_set [c_id ] = current
89
100
90
101
# expand search grid based on motion model
91
102
for move_x , move_y , move_cost in self .motion :
@@ -94,94 +105,95 @@ def planning(self, sx, sy, gx, gy):
94
105
current .cost + move_cost , c_id )
95
106
n_id = self .calc_index (node )
96
107
97
- if n_id in closedset :
108
+ if n_id in closed_set :
98
109
continue
99
110
100
111
if not self .verify_node (node ):
101
112
continue
102
113
103
- if n_id not in openset :
104
- openset [n_id ] = node # Discover a new node
114
+ if n_id not in open_set :
115
+ open_set [n_id ] = node # Discover a new node
105
116
else :
106
- if openset [n_id ].cost >= node .cost :
117
+ if open_set [n_id ].cost >= node .cost :
107
118
# This path is the best until now. record it!
108
- openset [n_id ] = node
119
+ open_set [n_id ] = node
109
120
110
- rx , ry = self .calc_final_path (ngoal , closedset )
121
+ rx , ry = self .calc_final_path (goal_node , closed_set )
111
122
112
123
return rx , ry
113
124
114
- def calc_final_path (self , ngoal , closedset ):
125
+ def calc_final_path (self , goal_node , closed_set ):
115
126
# generate final course
116
- rx , ry = [self .calc_position (ngoal .x , self .minx )], [
117
- self .calc_position (ngoal .y , self .miny )]
118
- pind = ngoal . pind
119
- while pind != - 1 :
120
- n = closedset [ pind ]
121
- rx .append (self .calc_position (n .x , self .minx ))
122
- ry .append (self .calc_position (n .y , self .miny ))
123
- pind = n .pind
127
+ rx , ry = [self .calc_position (goal_node .x , self .min_x )], [
128
+ self .calc_position (goal_node .y , self .min_y )]
129
+ parent = goal_node . parent
130
+ while parent != - 1 :
131
+ n = closed_set [ parent ]
132
+ rx .append (self .calc_position (n .x , self .min_x ))
133
+ ry .append (self .calc_position (n .y , self .min_y ))
134
+ parent = n .parent
124
135
125
136
return rx , ry
126
137
127
138
def calc_position (self , index , minp ):
128
- pos = index * self .reso + minp
139
+ pos = index * self .resolution + minp
129
140
return pos
130
141
131
- def calc_xyindex (self , position , minp ):
132
- return round ((position - minp )/ self .reso )
142
+ def calc_xy_index (self , position , minp ):
143
+ return round ((position - minp ) / self .resolution )
133
144
134
145
def calc_index (self , node ):
135
- return (node .y - self .miny ) * self .xwidth + (node .x - self .minx )
146
+ return (node .y - self .min_y ) * self .x_width + (node .x - self .min_x )
136
147
137
148
def verify_node (self , node ):
138
- px = self .calc_position (node .x , self .minx )
139
- py = self .calc_position (node .y , self .miny )
149
+ px = self .calc_position (node .x , self .min_x )
150
+ py = self .calc_position (node .y , self .min_y )
140
151
141
- if px < self .minx :
152
+ if px < self .min_x :
142
153
return False
143
- elif py < self .miny :
154
+ if py < self .min_y :
144
155
return False
145
- elif px >= self .maxx :
156
+ if px >= self .max_x :
146
157
return False
147
- elif py >= self .maxy :
158
+ if py >= self .max_y :
148
159
return False
149
160
150
- if self .obmap [node .x ][node .y ]:
161
+ if self .obstacle_map [node .x ][node .y ]:
151
162
return False
152
163
153
164
return True
154
165
155
166
def calc_obstacle_map (self , ox , oy ):
156
167
157
- self .minx = round (min (ox ))
158
- self .miny = round (min (oy ))
159
- self .maxx = round (max (ox ))
160
- self .maxy = round (max (oy ))
161
- print ("minx :" , self .minx )
162
- print ("miny :" , self .miny )
163
- print ("maxx :" , self .maxx )
164
- print ("maxy :" , self .maxy )
168
+ self .min_x = round (min (ox ))
169
+ self .min_y = round (min (oy ))
170
+ self .max_x = round (max (ox ))
171
+ self .max_y = round (max (oy ))
172
+ print ("min_x :" , self .min_x )
173
+ print ("min_y :" , self .min_y )
174
+ print ("max_x :" , self .max_x )
175
+ print ("max_y :" , self .max_y )
165
176
166
- self .xwidth = round ((self .maxx - self .minx ) / self .reso )
167
- self .ywidth = round ((self .maxy - self .miny ) / self .reso )
168
- print ("xwidth :" , self .xwidth )
169
- print ("ywidth :" , self .ywidth )
177
+ self .x_width = round ((self .max_x - self .min_x ) / self .resolution )
178
+ self .y_width = round ((self .max_y - self .min_y ) / self .resolution )
179
+ print ("x_width :" , self .x_width )
180
+ print ("y_width :" , self .y_width )
170
181
171
182
# obstacle map generation
172
- self .obmap = [[False for i in range (self .ywidth )]
173
- for i in range (self .xwidth )]
174
- for ix in range (self .xwidth ):
175
- x = self .calc_position (ix , self .minx )
176
- for iy in range (self .ywidth ):
177
- y = self .calc_position (iy , self .miny )
183
+ self .obstacle_map = [[False for _ in range (self .y_width )]
184
+ for _ in range (self .x_width )]
185
+ for ix in range (self .x_width ):
186
+ x = self .calc_position (ix , self .min_x )
187
+ for iy in range (self .y_width ):
188
+ y = self .calc_position (iy , self .min_y )
178
189
for iox , ioy in zip (ox , oy ):
179
190
d = math .hypot (iox - x , ioy - y )
180
- if d <= self .rr :
181
- self .obmap [ix ][iy ] = True
191
+ if d <= self .robot_radius :
192
+ self .obstacle_map [ix ][iy ] = True
182
193
break
183
194
184
- def get_motion_model (self ):
195
+ @staticmethod
196
+ def get_motion_model ():
185
197
# dx, dy, cost
186
198
motion = [[1 , 0 , 1 ],
187
199
[0 , 1 , 1 ],
@@ -239,6 +251,7 @@ def main():
239
251
240
252
if show_animation : # pragma: no cover
241
253
plt .plot (rx , ry , "-r" )
254
+ plt .pause (0.01 )
242
255
plt .show ()
243
256
244
257
0 commit comments