-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathgridmap.py
206 lines (174 loc) · 7.29 KB
/
gridmap.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import numpy
import matplotlib.pyplot as plt
from utils import png_to_ogm
class OccupancyGridMap:
def __init__(self, data_array, cell_size, occupancy_threshold=0.8):
"""
Creates a grid map
:param data_array: a 2D array with a value of occupancy per cell (values from 0 - 1)
:param cell_size: cell size in meters
:param occupancy_threshold: A threshold to determine whether a cell is occupied or free.
A cell is considered occupied if its value >= occupancy_threshold, free otherwise.
"""
self.data = data_array
self.dim_cells = data_array.shape
self.dim_meters = (self.dim_cells[0] * cell_size, self.dim_cells[1] * cell_size)
self.cell_size = cell_size
self.occupancy_threshold = occupancy_threshold
# 2D array to mark visited nodes (in the beginning, no node has been visited)
self.visited = numpy.zeros(self.dim_cells, dtype=numpy.float32)
def mark_visited_idx(self, point_idx):
"""
Mark a point as visited.
:param point_idx: a point (x, y) in data array
"""
x_index, y_index = point_idx
if x_index < 0 or y_index < 0 or x_index >= self.dim_cells[0] or y_index >= self.dim_cells[1]:
raise Exception('Point is outside map boundary')
self.visited[y_index][x_index] = 1.0
def mark_visited(self, point):
"""
Mark a point as visited.
:param point: a 2D point (x, y) in meters
"""
x, y = point
x_index, y_index = self.get_index_from_coordinates(x, y)
return self.mark_visited_idx((x_index, y_index))
def is_visited_idx(self, point_idx):
"""
Check whether the given point is visited.
:param point_idx: a point (x, y) in data array
:return: True if the given point is visited, false otherwise
"""
x_index, y_index = point_idx
if x_index < 0 or y_index < 0 or x_index >= self.dim_cells[0] or y_index >= self.dim_cells[1]:
raise Exception('Point is outside map boundary')
if self.visited[y_index][x_index] == 1.0:
return True
else:
return False
def is_visited(self, point):
"""
Check whether the given point is visited.
:param point: a 2D point (x, y) in meters
:return: True if the given point is visited, false otherwise
"""
x, y = point
x_index, y_index = self.get_index_from_coordinates(x, y)
return self.is_visited_idx((x_index, y_index))
def get_data_idx(self, point_idx):
"""
Get the occupancy value of the given point.
:param point_idx: a point (x, y) in data array
:return: the occupancy value of the given point
"""
x_index, y_index = point_idx
if x_index < 0 or y_index < 0 or x_index >= self.dim_cells[0] or y_index >= self.dim_cells[1]:
raise Exception('Point is outside map boundary')
return self.data[y_index][x_index]
def get_data(self, point):
"""
Get the occupancy value of the given point.
:param point: a 2D point (x, y) in meters
:return: the occupancy value of the given point
"""
x, y = point
x_index, y_index = self.get_index_from_coordinates(x, y)
return self.get_data_idx((x_index, y_index))
def set_data_idx(self, point_idx, new_value):
"""
Set the occupancy value of the given point.
:param point_idx: a point (x, y) in data array
:param new_value: the new occupancy values
"""
x_index, y_index = point_idx
if x_index < 0 or y_index < 0 or x_index >= self.dim_cells[0] or y_index >= self.dim_cells[1]:
raise Exception('Point is outside map boundary')
self.data[y_index][x_index] = new_value
def set_data(self, point, new_value):
"""
Set the occupancy value of the given point.
:param point: a 2D point (x, y) in meters
:param new_value: the new occupancy value
"""
x, y = point
x_index, y_index = self.get_index_from_coordinates(x, y)
self.set_data_idx((x_index, y_index), new_value)
def is_inside_idx(self, point_idx):
"""
Check whether the given point is inside the map.
:param point_idx: a point (x, y) in data array
:return: True if the given point is inside the map, false otherwise
"""
x_index, y_index = point_idx
if x_index < 0 or y_index < 0 or x_index >= self.dim_cells[0] or y_index >= self.dim_cells[1]:
return False
else:
return True
def is_inside(self, point):
"""
Check whether the given point is inside the map.
:param point: a 2D point (x, y) in meters
:return: True if the given point is inside the map, false otherwise
"""
x, y = point
x_index, y_index = self.get_index_from_coordinates(x, y)
return self.is_inside_idx((x_index, y_index))
def is_occupied_idx(self, point_idx):
"""
Check whether the given point is occupied according the the occupancy threshold.
:param point_idx: a point (x, y) in data array
:return: True if the given point is occupied, false otherwise
"""
x_index, y_index = point_idx
if self.get_data_idx((x_index, y_index)) >= self.occupancy_threshold:
return True
else:
return False
def is_occupied(self, point):
"""
Check whether the given point is occupied according the the occupancy threshold.
:param point: a 2D point (x, y) in meters
:return: True if the given point is occupied, false otherwise
"""
x, y = point
x_index, y_index = self.get_index_from_coordinates(x, y)
return self.is_occupied_idx((x_index, y_index))
def get_index_from_coordinates(self, x, y):
"""
Get the array indices of the given point.
:param x: the point's x-coordinate in meters
:param y: the point's y-coordinate in meters
:return: the corresponding array indices as a (x, y) tuple
"""
x_index = int(round(x/self.cell_size))
y_index = int(round(y/self.cell_size))
return x_index, y_index
def get_coordinates_from_index(self, x_index, y_index):
"""
Get the coordinates of the given array point in meters.
:param x_index: the point's x index
:param y_index: the point's y index
:return: the corresponding point in meters as a (x, y) tuple
"""
x = x_index*self.cell_size
y = y_index*self.cell_size
return x, y
def plot(self, alpha=1, min_val=0, origin='lower'):
"""
plot the grid map
"""
plt.imshow(self.data, vmin=min_val, vmax=1, origin=origin, interpolation='none', alpha=alpha)
plt.draw()
@staticmethod
def from_png(filename, cell_size):
"""
Create an OccupancyGridMap from a png image
:param filename: the image filename
:param cell_size: the image pixel size in meters
:return: the created OccupancyGridMap
"""
ogm_data = png_to_ogm(filename, normalized=True)
ogm_data_arr = numpy.array(ogm_data)
ogm = OccupancyGridMap(ogm_data_arr, cell_size)
return ogm