11"""
22@file: grid.py
3- @breif: Grid Map for Path Planning
43@author: Wu Maojia
5- @update: 2025.9.5
4+ @update: 2025.10.3
65"""
76from itertools import product
87from typing import Iterable , Union , Tuple , Callable , List , Dict
1110import numpy as np
1211from scipy import ndimage
1312
14- from .base_map import BaseMap
13+ from python_motion_planning . common . env . map .base_map import BaseMap
1514from python_motion_planning .common .env import Node , TYPES
1615from python_motion_planning .common .utils .geometry import Geometry
1716
@@ -109,18 +108,17 @@ class Grid(BaseMap):
109108 resolution: resolution of the grid map
110109 type_map: initial type map of the grid map (its shape must be the same as the converted grid map shape, and its dtype must be int)
111110 dtype: data type of coordinates (must be int)
111+ inflation_radius: radius of the inflation
112112
113113 Examples:
114- >>> bounds = [[0, 30], [0, 40]]
115- >>> type_map = np.zeros((61, 81), dtype=np.int8)
116- >>> grid_map = Grid(bounds=bounds, resolution=0.5, type_map=type_map)
114+ >>> grid_map = Grid(bounds=[[0, 51], [0, 31]], resolution=0.5)
117115 >>> grid_map
118- Grid(bounds=[[ 0. 30 .]
119- [ 0. 40 .]], resolution=0.5)
116+ Grid(bounds=[[ 0. 51 .]
117+ [ 0. 31 .]], resolution=0.5)
120118
121119 >>> grid_map.bounds # bounds of the base world
122- array([[ 0., 30 .],
123- [ 0., 40 .]])
120+ array([[ 0., 51 .],
121+ [ 0., 31 .]])
124122
125123 >>> grid_map.dim
126124 2
@@ -129,7 +127,7 @@ class Grid(BaseMap):
129127 0.5
130128
131129 >>> grid_map.shape # shape of the grid map
132- (61, 81 )
130+ (102, 62 )
133131
134132 >>> grid_map.dtype
135133 <class 'numpy.int32'>
@@ -143,13 +141,13 @@ class Grid(BaseMap):
143141 [0 0 0 ... 0 0 0]
144142 [0 0 0 ... 0 0 0]
145143 [0 0 0 ... 0 0 0]]
146- ), shape=(61, 81 ), dtype=int8)
144+ ), shape=(102, 62 ), dtype=int8)
147145
148146 >>> grid_map.map_to_world((1, 2))
149- (0.5 , 1.0 )
147+ (0.75 , 1.25 )
150148
151149 >>> grid_map.world_to_map((0.5, 1.0))
152- (1 , 2)
150+ (0 , 2)
153151
154152 >>> grid_map.get_neighbors(Node((1, 2)))
155153 [Node((0, 1), (1, 2), 0, 0), Node((0, 2), (1, 2), 0, 0), Node((0, 3), (1, 2), 0, 0), Node((1, 1), (1, 2), 0, 0), Node((1, 3), (1, 2), 0, 0), Node((2, 1), (1, 2), 0, 0), Node((2, 2), (1, 2), 0, 0), Node((2, 3), (1, 2), 0, 0)]
@@ -159,10 +157,10 @@ class Grid(BaseMap):
159157
160158 >>> grid_map.type_map[1, 0] = TYPES.OBSTACLE # place an obstacle
161159 >>> grid_map.get_neighbors(Node((0, 0))) # limited within the bounds
162- [Node((0, 1), (0, 0), 0, 0), Node((1, 1), (0, 0), 0, 0)]
160+ [Node((0, 1), (0, 0), 0, 0), Node((1, 0), (0, 0), 0, 0), Node((1, 1), (0, 0), 0, 0)]
163161
164162 >>> grid_map.get_neighbors(Node((grid_map.shape[0] - 1, grid_map.shape[1] - 1)), diagonal=False) # limited within the boundss
165- [Node((59, 80 ), (60, 80 ), 0, 0), Node((60, 79 ), (60, 80 ), 0, 0)]
163+ [Node((100, 61 ), (101, 61 ), 0, 0), Node((101, 60 ), (101, 61 ), 0, 0)]
166164
167165 >>> grid_map.line_of_sight((1, 2), (3, 6))
168166 [(1, 2), (1, 3), (2, 4), (2, 5), (3, 6)]
@@ -174,6 +172,7 @@ class Grid(BaseMap):
174172 False
175173
176174 >>> grid_map.type_map[1, 3] = TYPES.OBSTACLE
175+ >>> grid_map.update_esdf()
177176 >>> grid_map.in_collision((1, 2), (3, 6))
178177 True
179178 """
@@ -364,7 +363,7 @@ def get_neighbors(self,
364363
365364 return filtered_neighbors
366365
367- def line_of_sight (self , p1 : Tuple [int , ...], p2 : Tuple [int , ...]) -> list :
366+ def line_of_sight (self , p1 : Tuple [int , ...], p2 : Tuple [int , ...]) -> List [ Tuple [ int , ...]] :
368367 """
369368 N-dimensional line of sight (Bresenham's line algorithm)
370369
@@ -396,7 +395,7 @@ def line_of_sight(self, p1: Tuple[int, ...], p2: Tuple[int, ...]) -> list:
396395
397396 # Allocate the result array
398397 result = []
399- result .append (tuple (current ))
398+ result .append (tuple (int ( x ) for x in current ))
400399
401400 for i in range (1 , steps + 1 ):
402401 current [primary_axis ] += primary_step
@@ -411,7 +410,7 @@ def line_of_sight(self, p1: Tuple[int, ...], p2: Tuple[int, ...]) -> list:
411410 current [d ] += 1 if delta [d ] > 0 else - 1
412411 error [d ] -= delta2 [primary_axis ]
413412
414- result .append (tuple (current ))
413+ result .append (tuple (int ( x ) for x in current ))
415414
416415 return result
417416
@@ -452,10 +451,6 @@ def in_collision(self, p1: Tuple[int, ...], p2: Tuple[int, ...]) -> bool:
452451 steps = abs_delta [primary_axis ]
453452 current = p1
454453
455- # # Check the start point
456- # if not self.is_expandable(tuple(current)):
457- # return True
458-
459454 for _ in range (steps ):
460455 last_point = current .copy ()
461456 current [primary_axis ] += primary_step
@@ -469,7 +464,7 @@ def in_collision(self, p1: Tuple[int, ...], p2: Tuple[int, ...]) -> bool:
469464 if error [d ] > abs_delta [primary_axis ]:
470465 current [d ] += 1 if delta [d ] > 0 else - 1
471466 error [d ] -= delta2 [primary_axis ]
472-
467+
473468 # Check the current point
474469 if not self .is_expandable (tuple (current ), tuple (last_point )):
475470 return True
0 commit comments