From 3ff0ab8bc4b4a8bff2929081c9247af3ba725b52 Mon Sep 17 00:00:00 2001 From: simondlevy Date: Sun, 12 Nov 2017 16:49:23 -0500 Subject: [PATCH] Added script for pickling a map --- .gitignore | 1 + examples/log2pkl.py | 125 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100755 examples/log2pkl.py diff --git a/.gitignore b/.gitignore index 4b15c41..ae43b70 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ examples/__pycache__ examples/*.pyc examples/*.pgm examples/*.png +examples/*.map python/breezyslam/*.pyc python/breezyslam/__pycache__ python/build diff --git a/examples/log2pkl.py b/examples/log2pkl.py new file mode 100755 index 0000000..e2d6200 --- /dev/null +++ b/examples/log2pkl.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python + +''' +log2pkl.py : BreezySLAM Python demo. Reads logfile with odometry and scan data + from Paris Mines Tech and pickles the map file for loading by another + program + +Copyright (C) 2014 Simon D. Levy + +This code is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this code. If not, see . +''' + +# Map size, scale +MAP_SIZE_PIXELS = 800 +MAP_SIZE_METERS = 32 + +from breezyslam.algorithms import Deterministic_SLAM, RMHC_SLAM + +from mines import MinesLaser, Rover, load_data +from progressbar import ProgressBar + +from sys import argv, exit, stdout +from time import time +import pickle + +def main(): + + # Bozo filter for input args + if len(argv) < 3: + print('Usage: %s ' % argv[0]) + print('Example: %s exp2 1 9999' % argv[0]) + exit(1) + + # Grab input args + dataset = argv[1] + use_odometry = True if int(argv[2]) else False + seed = int(argv[3]) if len(argv) > 3 else 0 + + # Load the data from the file, ignoring timestamps + _, lidars, odometries = load_data('.', dataset) + + # Build a robot model if we want odometry + robot = Rover() if use_odometry else None + + # Create a CoreSLAM object with laser params and optional robot object + slam = RMHC_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed=seed) \ + if seed \ + else Deterministic_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS) + + # Report what we're doing + nscans = len(lidars) + print('Processing %d scans with%s odometry / with%s particle filter...' % \ + (nscans, \ + '' if use_odometry else 'out', '' if seed else 'out')) + progbar = ProgressBar(0, nscans, 80) + + # Start with an empty trajectory of positions + trajectory = [] + + # Start timing + start_sec = time() + + # Loop over scans + for scanno in range(nscans): + + if use_odometry: + + # Convert odometry to velocities + velocities = robot.computeVelocities(odometries[scanno]) + + # Update SLAM with lidar and velocities + slam.update(lidars[scanno], velocities) + + else: + + # Update SLAM with lidar alone + slam.update(lidars[scanno]) + + # Get new position + x_mm, y_mm, theta_degrees = slam.getpos() + + # Add new position to trajectory + trajectory.append((x_mm, y_mm)) + + # Tame impatience + progbar.updateAmount(scanno) + stdout.write('\r%s' % str(progbar)) + stdout.flush() + + # Report elapsed time + elapsed_sec = time() - start_sec + print('\n%d scans in %f sec = %f scans / sec' % (nscans, elapsed_sec, nscans/elapsed_sec)) + + + # Create a byte array to receive the computed maps + mapbytes = bytearray(MAP_SIZE_PIXELS * MAP_SIZE_PIXELS) + + # Get final map + slam.getmap(mapbytes) + + # Pickle the map to a file + pklname = dataset + '.map' + print('Writing map to file ' + pklname) + pickle.dump(mapbytes, open(pklname, 'wb')) + + +# Helpers --------------------------------------------------------- + +def mm2pix(mm): + + return int(mm / (MAP_SIZE_METERS * 1000. / MAP_SIZE_PIXELS)) + + +main()