@@ -41,12 +41,13 @@ class DistanceTransformPlanner(PlannerBase):
41
41
Also known as wavefront, grassfire or brushfire planning algorithm.
42
42
43
43
Creates a planner that finds the path between two points in the
44
- plane using forward motion. The path comprises a set of points in
44
+ plane using forward motion. The path comprises a set of points in
45
45
adjacent cells.
46
46
47
47
:author: Peter Corke_
48
48
:seealso: :class:`Planner`
49
49
"""
50
+
50
51
def __init__ (self , occgrid = None , metric = "euclidean" , ** kwargs ):
51
52
52
53
super ().__init__ (occgrid = occgrid , ndims = 2 , ** kwargs )
@@ -85,29 +86,36 @@ def plan(self, goal=None, animate=False, verbose=False):
85
86
self .goal = goal
86
87
87
88
if self ._goal is None :
88
- raise ValueError (' No goal specified here or in constructor' )
89
+ raise ValueError (" No goal specified here or in constructor" )
89
90
90
- self ._distancemap = distancexform (self .occgrid .grid ,
91
- goal = self ._goal , metric = self ._metric , animate = animate ,
92
- verbose = verbose )
91
+ self ._distancemap = distancexform (
92
+ self .occgrid .grid ,
93
+ goal = self ._goal ,
94
+ metric = self ._metric ,
95
+ animate = animate ,
96
+ verbose = verbose ,
97
+ )
93
98
94
99
# Use plot from parent class
95
100
96
101
def next (self , position ):
97
102
if self .distancemap is None :
98
103
Error ("No distance map computed, you need to plan." )
99
104
100
- directions = np .array ([
101
- # dy dx
102
- [- 1 , - 1 ],
103
- [ 0 , - 1 ],
104
- [ 1 , - 1 ],
105
- [- 1 , 0 ],
106
- [ 0 , 0 ],
107
- [ 1 , 0 ],
108
- [ 0 , 1 ],
109
- [ 1 , 1 ],
110
- ], dtype = int )
105
+ directions = np .array (
106
+ [
107
+ # dy dx
108
+ [- 1 , - 1 ],
109
+ [0 , - 1 ],
110
+ [1 , - 1 ],
111
+ [- 1 , 0 ],
112
+ [0 , 0 ],
113
+ [1 , 0 ],
114
+ [0 , 1 ],
115
+ [1 , 1 ],
116
+ ],
117
+ dtype = int ,
118
+ )
111
119
112
120
x = int (position [0 ])
113
121
y = int (position [1 ])
@@ -137,28 +145,30 @@ def next(self, position):
137
145
138
146
def plot_3d (self , p = None , ls = None ):
139
147
fig = plt .figure ()
140
- ax = fig .gca (projection = '3d' )
148
+ ax = fig .gca (projection = "3d" )
141
149
142
150
distance = self ._distancemap
143
151
X , Y = np .meshgrid (np .arange (distance .shape [1 ]), np .arange (distance .shape [0 ]))
144
- surf = ax .plot_surface (X , Y , distance , #cmap='gray',
145
- linewidth = 1 , antialiased = False )
152
+ surf = ax .plot_surface (
153
+ X , Y , distance , linewidth = 1 , antialiased = False # cmap='gray',
154
+ )
146
155
147
156
if p is not None :
148
157
# k = sub2ind(np.shape(self._distancemap), p[:, 1], p[:, 0])
149
- height = distance [p [:,1 ], p [:,0 ]]
158
+ height = distance [p [:, 1 ], p [:, 0 ]]
150
159
ax .plot (p [:, 0 ], p [:, 1 ], height )
151
160
152
- plt .xlabel ('x' )
153
- plt .ylabel ('y' )
154
- ax .set_zlabel ('z' )
161
+ plt .xlabel ("x" )
162
+ plt .ylabel ("y" )
163
+ ax .set_zlabel ("z" )
155
164
plt .show ()
156
165
return ax
157
166
158
167
159
168
import numpy as np
160
169
161
- def distancexform (occgrid , goal , metric = 'cityblock' , animate = False , verbose = False ):
170
+
171
+ def distancexform (occgrid , goal , metric = "cityblock" , animate = False , verbose = False ):
162
172
"""
163
173
Distance transform for path planning
164
174
@@ -180,7 +190,7 @@ def distancexform(occgrid, goal, metric='cityblock', animate=False, verbose=Fals
180
190
``metric``. In addition:
181
191
182
192
- Obstacle cells will be set to ``nan``
183
- - Unreachable cells, ie. free cells _inside obstacles_ will be set
193
+ - Unreachable cells, ie. free cells _inside obstacles_ will be set
184
194
to ``inf``
185
195
186
196
The cells of the passed occupancy grid are:
@@ -197,19 +207,19 @@ def distancexform(occgrid, goal, metric='cityblock', animate=False, verbose=Fals
197
207
198
208
distance = occgrid .astype (np .float32 )
199
209
distance [occgrid > 0 ] = np .nan # assign nan to obstacle cells
200
- distance [occgrid == 0 ] = np .inf # assign inf to other cells
210
+ distance [occgrid == 0 ] = np .inf # assign inf to other cells
201
211
distance [goal [1 ], goal [0 ]] = 0 # assign zero to goal
202
-
212
+
203
213
# create the appropriate distance matrix D
204
- if metric .lower () in (' manhattan' , ' cityblock' ):
214
+ if metric .lower () in (" manhattan" , " cityblock" ):
205
215
# fmt: off
206
216
D = np .array ([
207
217
[ np .inf , 1 , np .inf ],
208
218
[ 1 , 0 , 1 ],
209
219
[ np .inf , 1 , np .inf ]
210
220
])
211
221
# fmt: on
212
- elif metric .lower () == ' euclidean' :
222
+ elif metric .lower () == " euclidean" :
213
223
r2 = np .sqrt (2 )
214
224
# fmt: off
215
225
D = np.array ([
@@ -236,15 +246,15 @@ def distancexform(occgrid, goal, metric='cityblock', animate=False, verbose=Fals
236
246
display [np .isinf (display )] = 0
237
247
if h is None :
238
248
plt .figure ()
239
- plt .xlabel ('x' )
240
- plt .ylabel ('y' )
249
+ plt .xlabel ("x" )
250
+ plt .ylabel ("y" )
241
251
ax = plt .gca ()
242
252
plt .pause (0.001 )
243
- cmap = cm .get_cmap (' gray' )
244
- cmap .set_bad (' red' )
245
- cmap .set_over (' white' )
253
+ cmap = cm .get_cmap (" gray" )
254
+ cmap .set_bad (" red" )
255
+ cmap .set_over (" white" )
246
256
h = plt .imshow (display , cmap = cmap )
247
- plt .colorbar (label = ' distance' )
257
+ plt .colorbar (label = " distance" )
248
258
else :
249
259
h .remove ()
250
260
h = plt .imshow (display , cmap = cmap )
@@ -262,12 +272,13 @@ def distancexform(occgrid, goal, metric='cityblock', animate=False, verbose=Fals
262
272
print (f"{ count :d} iterations, { ninf :d} unreachable cells" )
263
273
return distance
264
274
275
+
265
276
def grassfire_step (G , D ):
266
277
267
278
# pad with inf
268
- H = np .pad (G , max (D .shape ) // 2 , ' constant' , constant_values = np .inf )
279
+ H = np .pad (G , max (D .shape ) // 2 , " constant" , constant_values = np .inf )
269
280
rows , columns = G .shape
270
-
281
+
271
282
# inspired by https://landscapearchaeology.org/2018/numpy-loops/
272
283
minimum = np .full (G .shape , np .inf )
273
284
for y in range (3 ):
@@ -280,7 +291,7 @@ def grassfire_step(G, D):
280
291
281
292
282
293
if __name__ == "__main__" :
283
-
294
+ pass
284
295
285
296
# # make a simple map, as per the MOOCs
286
297
# occgrid = np.zeros((10,10))
@@ -296,16 +307,15 @@ def grassfire_step(G, D):
296
307
# dx = distancexform(occgrid, goal, metric='Euclidean')
297
308
# print(dx)
298
309
310
+ # from roboticstoolbox import DistanceTransformPlanner, rtb_loadmat
299
311
300
- from roboticstoolbox import DistanceTransformPlanner , rtb_loadmat
312
+ # house = rtb_loadmat('data/house.mat')
313
+ # floorplan = house['floorplan']
314
+ # places = house['places']
301
315
302
- house = rtb_loadmat ('data/house.mat' )
303
- floorplan = house ['floorplan' ]
304
- places = house ['places' ]
305
-
306
- dx = DistanceTransformPlanner (floorplan )
307
- print (dx )
308
- dx .goal = [1 ,2 ]
309
- dx .plan (places .kitchen )
310
- path = dx .query (places .br3 )
311
- dx .plot (path , block = True )
316
+ # dx = DistanceTransformPlanner(floorplan)
317
+ # print(dx)
318
+ # dx.goal = [1,2]
319
+ # dx.plan(places.kitchen)
320
+ # path = dx.query(places.br3)
321
+ # dx.plot(path, block=True)
0 commit comments