26
26
logger.setLevel(logging.INFO)
27
27
USE_BACKTRACING = True
29
30
_map_resolution_levels = 4 # number of different levels of resolution
31
32
def loadmap(fname):
32
33
return pickle.load(open(fname))
34
class MapBuilder(object):
35
def __init__(self, resolution,
37
levels=_map_resolution_levels,
40
self.vmap = VoxelMap(resolution, levels=levels,
42
self.odometry_map = odometry_map
44
self.bestpose = poseutil.Pose3D()
49
def add_pointcloud(self, pc):
50
if self.scancount == 0:
52
self.vmap.add_scan(pc, pc.pose)
53
pc.pose = (poseutil.Pose3D() if pc.pose is None else pc.pose)
54
return self.vmap.get_voxels(level=-1), pc.pose
56
# reduce number of scan points to one per voxel
57
# sample = pc.volumetricsample(self.vmap.resolution)
59
logger.info('--------- Scan %d ---------' % self.scancount)
63
guessPose = self.bestpose
68
if not self.odometry_map:
69
self.bestpose, maxcost = self.vmap.align_points(pc, guessPose)
71
alignment_time = time.time() - start
74
if self.odometry_map: # create map without aligning
75
self.vmap.add_scan(pc, guessPose)
77
self.vmap.add_scan(pc, self.bestpose)
79
mapupdate_time = time.time() - start
80
logger.info('Map voxel count:{0}'.format( len(self.vmap)))
82
logger.info('Aligned pose:{0}'.format(self.bestpose))
83
logger.info('Cost value: {0}'.format(maxcost))
85
logger.info('Alignment time(s): %.2f' % alignment_time)
86
logger.info('Map update time(s): %.2f' % mapupdate_time)
87
return self.vmap.get_voxels(level=-1), self.bestpose
89
35
def buildmap(pointclouds, resolution, visualise=True, odometry_map=False,
91
37
bestpose_queue=None,
97
43
optionally communicate back the bestpose got so far. This might be used to
98
44
optimize the pc.pose i.e. the initial guesspose
100
47
vmap = VoxelMap(resolution, levels=_map_resolution_levels, rotate=rotate)
101
48
pc = pointclouds.next()
102
49
vmap.add_scan(pc, pc.pose)
133
80
if not odometry_map:
134
81
bestpose, maxcost = vmap.align_points(sample, guessPose)
135
82
if bestpose_queue:
136
logger.info("Best pose {0}".format(bestpose))
137
83
bestpose_queue.put_force(bestpose)
139
85
alignment_time = time.time() - start
263
209
def display(self,npts=1e6,changes=False):
264
210
'''Shows a representation of the map in a gui'''
265
from visualiser.robotvisualiser import Visualiser
211
from visualiser.rviz import Visualiser
266
212
if self._rv is None:
267
213
self._rv_changes = changes
268
214
self._rv = Visualiser(npts=npts, Rotate=self._rotate)
280
def add_scan(self, pc, pose, timestamp=None):
226
def add_scan(self, xyzs, pose, timestamp=None, userdata=None):
281
227
'''Adds a new scan to the existing map.
283
229
Adds the occupied voxels and removes the freespace.
285
userdata = pc.userdata
287
231
if USE_BACKTRACING:
288
232
self.clear_freespace(xyzs, pose)
289
233
self.add_points(xyzs, pose, timestamp, userdata)
295
239
xyzs: The occupied PointCloud, with the sensor as origin.
296
240
pose: The pose of `xyzs` PointCloud with respect to global map.
298
243
xyzs, return_pose = poseutil.transformPoints(xyzs, pose)
299
244
sensor_loc = poseutil.transformPoints(np.array([[0, 0, 0]]), pose)
300
245
self.mrol.clear_freespace(xyzs, sensor_loc[0])
303
248
'''Adds the pointcloud xyzs to the map, transforming them by the given
304
249
pose if required. Returns the overlap of the new points against the
306
if isinstance(xyzs, pointcloud.PointCloud):
308
assert xyzs.shape[1] == 3, '3 dimensional points'
252
if xyzs.shape[1] > 3: # handling for additional information that is part of the pointcloud object (e.g. colour)
254
userdata = xyzs[:,3:]
256
userdata = np.hstack([xyzs[:,3:],userdata])
309
258
xyzs, return_pose = poseutil.transformPoints(xyzs, pose)
310
259
self.trajectory.append(return_pose)
311
260
if self._rv is not None: # visualisation
316
265
#ol.add_points(xyzs)
317
266
#ol = ol - finest
318
vox = ol.getvoxeldata()
319
self._rv.addmappts(vox)
267
self._rv.addmappts(ol.getpoints())
320
268
#self._rv.setminmax(np.min(self.get_points().points[:,2]),np.max(self.get_points().points[:,2]))
321
269
self._rv.setrobotpose(return_pose.getMatrix())
322
270
self._rv.addtrajectorypoint(return_pose.getTuple()[0:3])