Restored Matlab, Java
This commit is contained in:
363
examples/Log2PGM.java
Normal file
363
examples/Log2PGM.java
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
Log2PGM.java : BreezySLAM demo. Reads logfile with odometry and scan data from
|
||||
Paris Mines Tech and produces a .PGM image file showing robot path
|
||||
and final map.
|
||||
|
||||
For details see
|
||||
|
||||
@inproceedings{,
|
||||
author = {Bruno Steux and Oussama El Hamzaoui},
|
||||
title = {SinglePositionSLAM: a SLAM Algorithm in less than 200 lines of C code},
|
||||
booktitle = {11th International Conference on Control, Automation, Robotics and Vision, ICARCV 2010, Singapore, 7-10
|
||||
December 2010, Proceedings},
|
||||
pages = {1975-1979},
|
||||
publisher = {IEEE},
|
||||
year = {2010}
|
||||
}
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import edu.wlu.cs.levy.breezyslam.components.Map;
|
||||
import edu.wlu.cs.levy.breezyslam.components.Scan;
|
||||
import edu.wlu.cs.levy.breezyslam.components.Position;
|
||||
import edu.wlu.cs.levy.breezyslam.components.URG04LX;
|
||||
import edu.wlu.cs.levy.breezyslam.components.PoseChange;
|
||||
|
||||
import edu.wlu.cs.levy.breezyslam.robots.WheeledRobot;
|
||||
|
||||
import edu.wlu.cs.levy.breezyslam.algorithms.RMHCSLAM;
|
||||
import edu.wlu.cs.levy.breezyslam.algorithms.DeterministicSLAM;
|
||||
import edu.wlu.cs.levy.breezyslam.algorithms.SinglePositionSLAM;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Vector;
|
||||
|
||||
public class Log2PGM
|
||||
{
|
||||
private static int MAP_SIZE_PIXELS = 800;
|
||||
private static double MAP_SIZE_METERS = 32;
|
||||
private static int SCAN_SIZE = 682;
|
||||
|
||||
private SinglePositionSLAM slam;
|
||||
|
||||
private boolean use_odometry;
|
||||
private int random_seed;
|
||||
private Rover robot;
|
||||
|
||||
static int coords2index(double x, double y)
|
||||
{
|
||||
return (int)(y * MAP_SIZE_PIXELS + x);
|
||||
}
|
||||
|
||||
int mm2pix(double mm)
|
||||
{
|
||||
return (int)(mm / (MAP_SIZE_METERS * 1000. / MAP_SIZE_PIXELS));
|
||||
}
|
||||
|
||||
|
||||
// Class for Mines verison of URG-04LX Lidar -----------------------------------
|
||||
|
||||
private class MinesURG04LX extends URG04LX
|
||||
{
|
||||
public MinesURG04LX()
|
||||
{
|
||||
super( 70, // detectionMargin
|
||||
145); // offsetMillimeters
|
||||
}
|
||||
}
|
||||
|
||||
// Class for MinesRover custom robot -------------------------------------------
|
||||
|
||||
private class Rover extends WheeledRobot
|
||||
{
|
||||
public Rover()
|
||||
{
|
||||
super(77, // wheelRadiusMillimeters
|
||||
165); // halfAxleLengthMillimeters
|
||||
}
|
||||
|
||||
protected WheeledRobot.WheelOdometry extractOdometry(
|
||||
double timestamp,
|
||||
double leftWheelOdometry,
|
||||
double rightWheelOdometry)
|
||||
{
|
||||
// Convert microseconds to seconds, ticks to angles
|
||||
return new WheeledRobot.WheelOdometry(
|
||||
timestamp / 1e6,
|
||||
ticksToDegrees(leftWheelOdometry),
|
||||
ticksToDegrees(rightWheelOdometry));
|
||||
}
|
||||
|
||||
protected String descriptorString()
|
||||
{
|
||||
return String.format("ticks_per_cycle=%d", this.TICKS_PER_CYCLE);
|
||||
}
|
||||
|
||||
|
||||
private double ticksToDegrees(double ticks)
|
||||
{
|
||||
return ticks * (180. / this.TICKS_PER_CYCLE);
|
||||
}
|
||||
|
||||
private int TICKS_PER_CYCLE = 2000;
|
||||
}
|
||||
|
||||
// Progress-bar class ----------------------------------------------------------------
|
||||
// Adapted from http://code.activestate.com/recipes/168639-progress-bar-class/
|
||||
// Downloaded 12 January 2014
|
||||
|
||||
private class ProgressBar
|
||||
{
|
||||
public ProgressBar(int minValue, int maxValue, int totalWidth)
|
||||
{
|
||||
this.progBar = "[]";
|
||||
this.min = minValue;
|
||||
this.max = maxValue;
|
||||
this.span = maxValue - minValue;
|
||||
this.width = totalWidth;
|
||||
this.amount = 0; // When amount == max, we are 100% done
|
||||
this.updateAmount(0); // Build progress bar string
|
||||
}
|
||||
|
||||
void updateAmount(int newAmount)
|
||||
{
|
||||
if (newAmount < this.min)
|
||||
{
|
||||
newAmount = this.min;
|
||||
}
|
||||
if (newAmount > this.max)
|
||||
{
|
||||
newAmount = this.max;
|
||||
}
|
||||
|
||||
this.amount = newAmount;
|
||||
|
||||
// Figure out the new percent done, round to an integer
|
||||
float diffFromMin = (float)(this.amount - this.min);
|
||||
int percentDone = (int)java.lang.Math.round((diffFromMin / (float)this.span) * 100.0);
|
||||
|
||||
// Figure out how many hash bars the percentage should be
|
||||
int allFull = this.width - 2;
|
||||
int numHashes = (int)java.lang.Math.round((percentDone / 100.0) * allFull);
|
||||
|
||||
// Build a progress bar with hashes and spaces
|
||||
this.progBar = "[";
|
||||
this.addToProgBar("#", numHashes);
|
||||
this.addToProgBar(" ", allFull-numHashes);
|
||||
this.progBar += "]";
|
||||
|
||||
// Figure out where to put the percentage, roughly centered
|
||||
int percentPlace = (this.progBar.length() / 2) - ((int)(java.lang.Math.log10(percentDone+1)) + 1);
|
||||
String percentString = String.format("%d%%", percentDone);
|
||||
|
||||
// Put it there
|
||||
this.progBar = this.progBar.substring(0,percentPlace) + percentString + this.progBar.substring(percentPlace+percentString.length());
|
||||
}
|
||||
|
||||
String str()
|
||||
{
|
||||
return this.progBar;
|
||||
}
|
||||
|
||||
private String progBar;
|
||||
private int min;
|
||||
private int max;
|
||||
private int span;
|
||||
private int width;
|
||||
private int amount;
|
||||
|
||||
private void addToProgBar(String s, int n)
|
||||
{
|
||||
for (int k=0; k<n; ++k)
|
||||
{
|
||||
this.progBar += s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Log2PGM(boolean use_odometry, int random_seed)
|
||||
{
|
||||
MinesURG04LX laser = new MinesURG04LX();
|
||||
|
||||
this.robot = new Rover();
|
||||
|
||||
this.slam = random_seed > 0 ?
|
||||
new RMHCSLAM(laser, MAP_SIZE_PIXELS, MAP_SIZE_METERS, random_seed) :
|
||||
new DeterministicSLAM(laser, MAP_SIZE_PIXELS, MAP_SIZE_METERS);
|
||||
|
||||
this.use_odometry = use_odometry;
|
||||
this.random_seed = random_seed;
|
||||
}
|
||||
|
||||
public byte [] processData(Vector<int []> scans, Vector<long []> odometries)
|
||||
{
|
||||
// Report what we're doing
|
||||
int nscans = scans.size();
|
||||
ProgressBar progbar = new ProgressBar(0, nscans, 80);
|
||||
|
||||
System.out.printf("Processing %d scans with%s odometry / with%s particle filter...\n",
|
||||
nscans, this.use_odometry ? "" : "out", this.random_seed > 0 ? "" : "out");
|
||||
|
||||
Vector<double []> trajectory = new Vector<double []>();
|
||||
|
||||
for (int scanno=0; scanno<nscans; ++scanno)
|
||||
{
|
||||
int [] scan = scans.elementAt(scanno);
|
||||
|
||||
// Update with/out odometry
|
||||
if (this.use_odometry)
|
||||
{
|
||||
long [] odometry = odometries.elementAt(scanno);
|
||||
PoseChange poseChange = this.robot.computePoseChange(odometry[0], odometry[1], odometry[2]);
|
||||
slam.update(scan, poseChange);
|
||||
}
|
||||
else
|
||||
{
|
||||
slam.update(scan);
|
||||
}
|
||||
|
||||
Position position = slam.getpos();
|
||||
|
||||
// Add new coordinates to trajectory
|
||||
double [] v = new double[2];
|
||||
v[0] = position.x_mm;
|
||||
v[1] = position.y_mm;
|
||||
trajectory.add(v);
|
||||
|
||||
|
||||
progbar.updateAmount(scanno);
|
||||
System.out.printf("\r%s", progbar.str());
|
||||
}
|
||||
|
||||
// Get final map
|
||||
byte [] mapbytes = new byte [MAP_SIZE_PIXELS*MAP_SIZE_PIXELS];
|
||||
slam.getmap(mapbytes);
|
||||
|
||||
// Put trajectory into map as black pixels
|
||||
for (int k=0; k<trajectory.size(); ++k)
|
||||
{
|
||||
double [] v = trajectory.elementAt(k);
|
||||
|
||||
int x = mm2pix(v[0]);
|
||||
int y = mm2pix(v[1]);
|
||||
|
||||
mapbytes[coords2index(x, y)] = 0;
|
||||
}
|
||||
|
||||
return mapbytes;
|
||||
}
|
||||
|
||||
// main -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public static void main(String[] argv)
|
||||
{
|
||||
// Bozo filter for input args
|
||||
if (argv.length < 3)
|
||||
{
|
||||
System.err.println("Usage: java log2pgm <dataset> <use_odometry> <random_seed>");
|
||||
System.err.println("Example: java log2pgm exp2 1 9999");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Grab input args
|
||||
String dataset = argv[0];
|
||||
boolean use_odometry = Integer.parseInt(argv[1]) == 0 ? false : true;
|
||||
int random_seed = argv.length > 2 ? Integer.parseInt(argv[2]) : 0;
|
||||
|
||||
// Load the data from the file
|
||||
|
||||
Vector<int []> scans = new Vector<int []>();
|
||||
Vector<long []> odometries = new Vector<long []>();;
|
||||
|
||||
String filename = dataset + ".dat";
|
||||
System.out.printf("Loading data from %s ... \n", filename);
|
||||
|
||||
BufferedReader input = null;
|
||||
|
||||
try
|
||||
{
|
||||
FileReader fstream = new FileReader(filename);
|
||||
input = new BufferedReader(fstream);
|
||||
while (true)
|
||||
{
|
||||
String line = input.readLine();
|
||||
if (line == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
String [] toks = line.split(" +");
|
||||
|
||||
long [] odometry = new long [3];
|
||||
odometry[0] = Long.parseLong(toks[0]);
|
||||
odometry[1] = Long.parseLong(toks[2]);
|
||||
odometry[2] = Long.parseLong(toks[3]);
|
||||
odometries.add(odometry);
|
||||
|
||||
int [] scan = new int [SCAN_SIZE];
|
||||
for (int k=0; k<SCAN_SIZE; ++k)
|
||||
{
|
||||
scan[k] = Integer.parseInt(toks[k+24]);
|
||||
}
|
||||
scans.add(scan);
|
||||
}
|
||||
input.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Create a Log2PGM object to process the data
|
||||
Log2PGM log2pgm = new Log2PGM(use_odometry, random_seed);
|
||||
|
||||
// Process the scan and odometry data, returning a map
|
||||
byte [] mapbytes = log2pgm.processData(scans, odometries);
|
||||
|
||||
// Save map and trajectory as PGM file
|
||||
|
||||
filename = dataset + ".pgm";
|
||||
System.out.println("\nSaving map to file " + filename);
|
||||
|
||||
BufferedWriter output = null;
|
||||
|
||||
try
|
||||
{
|
||||
FileWriter fstream = new FileWriter(filename);
|
||||
output = new BufferedWriter(fstream);
|
||||
output.write(String.format("P2\n%d %d 255\n", MAP_SIZE_PIXELS, MAP_SIZE_PIXELS));
|
||||
for (int y=0; y<MAP_SIZE_PIXELS; y++)
|
||||
{
|
||||
for (int x=0; x<MAP_SIZE_PIXELS; x++)
|
||||
{
|
||||
// Output unsigned byte value
|
||||
output.write(String.format("%d ", (int)mapbytes[coords2index(x, y)] & 0xFF));
|
||||
}
|
||||
output.write("\n");
|
||||
}
|
||||
output.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
69
examples/MinesRover.m
Executable file
69
examples/MinesRover.m
Executable file
@@ -0,0 +1,69 @@
|
||||
classdef MinesRover < WheeledRobot
|
||||
%MinesRover Class for MinesRover custom robot
|
||||
%
|
||||
% 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 <http:#www.gnu.org/licenses/>.
|
||||
|
||||
properties (Access = 'private')
|
||||
TICKS_PER_CYCLE = 2000;
|
||||
end
|
||||
|
||||
methods (Access = 'private')
|
||||
|
||||
function degrees = ticks_to_degrees(obj, ticks)
|
||||
|
||||
degrees = ticks * (180. / obj.TICKS_PER_CYCLE);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
methods (Access = 'public')
|
||||
|
||||
function robot = MinesRover()
|
||||
|
||||
robot = robot@WheeledRobot(77, 165);
|
||||
|
||||
end
|
||||
|
||||
function disp(obj)
|
||||
% Displays information about this MinesRover
|
||||
|
||||
fprintf('<%s ticks_per_cycle=%d>\n', obj.str(), obj.TICKS_PER_CYCLE)
|
||||
|
||||
end
|
||||
|
||||
function [poseChange, obj] = computePoseChange(obj, odometry)
|
||||
|
||||
[poseChange, obj] = computePoseChange@WheeledRobot(obj, odometry(1), odometry(2), odometry(3));
|
||||
|
||||
end
|
||||
|
||||
function [timestampSeconds, leftWheelDegrees, rightWheelDegrees] = ...
|
||||
extractOdometry(obj, timestamp, leftWheel, rightWheel)
|
||||
|
||||
% Convert microseconds to seconds
|
||||
timestampSeconds = timestamp / 1e6;
|
||||
|
||||
% Convert ticks to angles
|
||||
leftWheelDegrees = obj.ticks_to_degrees(leftWheel);
|
||||
rightWheelDegrees = obj.ticks_to_degrees(rightWheel);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
175
examples/logdemo.m
Normal file
175
examples/logdemo.m
Normal file
@@ -0,0 +1,175 @@
|
||||
%
|
||||
% logdemo.m : BreezySLAM Matlab demo. Reads logfile with odometry and scan
|
||||
% data from Paris Mines Tech and displays the map and robot
|
||||
% position in real time.
|
||||
%
|
||||
% Usage:
|
||||
%
|
||||
% >> logdemo(dataset, [use_odometry], [random_seed])
|
||||
%
|
||||
% Examples:
|
||||
%
|
||||
% >> logdemo('exp2')
|
||||
%
|
||||
% For details see
|
||||
%
|
||||
% @inproceedings{coreslam-2010,
|
||||
% author = {Bruno Steux and Oussama El Hamzaoui},
|
||||
% title = {CoreSLAM: a SLAM Algorithm in less than 200 lines of C code},
|
||||
% booktitle = {11th International Conference on Control, Automation,
|
||||
% Robotics and Vision, ICARCV 2010, Singapore, 7-10
|
||||
% December 2010, Proceedings},
|
||||
% pages = {1975-1979},
|
||||
% publisher = {IEEE},
|
||||
% year = {2010}
|
||||
% }
|
||||
%
|
||||
% 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
function logdemo(dataset, use_odometry, seed)
|
||||
|
||||
% Params
|
||||
|
||||
MAP_SIZE_PIXELS = 800;
|
||||
MAP_SIZE_METERS = 32;
|
||||
ROBOT_SIZE_PIXELS = 10;
|
||||
|
||||
% Grab input args
|
||||
|
||||
if nargin < 2
|
||||
use_odometry = 0;
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
seed = 0;
|
||||
end
|
||||
|
||||
% Load data from file
|
||||
[times, scans, odometries] = load_data(dataset);
|
||||
|
||||
% Build a robot model if we want odometry
|
||||
robot = [];
|
||||
if use_odometry
|
||||
robot = MinesRover();
|
||||
end
|
||||
|
||||
% Create a CoreSLAM object with laser params and optional robot object
|
||||
if seed
|
||||
slam = RMHC_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS, seed);
|
||||
else
|
||||
slam = Deterministic_SLAM(MinesLaser(), MAP_SIZE_PIXELS, MAP_SIZE_METERS);
|
||||
end
|
||||
|
||||
% Initialize previous time for delay
|
||||
prevTime = 0;
|
||||
|
||||
% Loop over scans
|
||||
for scanno = 1:size(scans, 1)
|
||||
|
||||
if use_odometry
|
||||
|
||||
% Convert odometry to velocities
|
||||
[velocities,robot] = robot.computePoseChange(odometries(scanno, :));
|
||||
|
||||
% Update SLAM with lidar and velocities
|
||||
slam = slam.update(scans(scanno,:), velocities);
|
||||
|
||||
else
|
||||
|
||||
% Update SLAM with lidar alone
|
||||
slam = slam.update(scans(scanno,:));
|
||||
end
|
||||
|
||||
% Get new position
|
||||
[x_mm, y_mm, theta_degrees] = slam.getpos();
|
||||
|
||||
% Get current map
|
||||
map = slam.getmap();
|
||||
|
||||
% Display map
|
||||
hold off
|
||||
image(map/4) % Keep bytes in [0,64] for colormap
|
||||
axis('square')
|
||||
colormap('gray')
|
||||
hold on
|
||||
|
||||
% Generate a polyline to represent the robot
|
||||
[x_pix, y_pix] = robot_polyline(ROBOT_SIZE_PIXELS);
|
||||
|
||||
% Rotate the polyline based on the robot's angular rotation
|
||||
theta_radians = pi * theta_degrees / 180;
|
||||
x_pix_r = x_pix * cos(theta_radians) - y_pix * sin(theta_radians);
|
||||
y_pix_r = x_pix * sin(theta_radians) + y_pix * cos(theta_radians);
|
||||
|
||||
% Add the robot's position as offset to the polyline
|
||||
x_pix = x_pix_r + mm2pix(x_mm, MAP_SIZE_METERS, MAP_SIZE_PIXELS);
|
||||
y_pix = y_pix_r + mm2pix(y_mm, MAP_SIZE_METERS, MAP_SIZE_PIXELS);
|
||||
|
||||
% Add robot image to map
|
||||
fill(x_pix, y_pix, 'r')
|
||||
drawnow
|
||||
|
||||
% Delay based on current time in microseconds
|
||||
currTime = times(scanno);
|
||||
if scanno > 1
|
||||
pause((currTime-prevTime)/1e6)
|
||||
end
|
||||
prevTime = times(scanno);
|
||||
|
||||
|
||||
end
|
||||
|
||||
% Function to generate a x, y points for a polyline to display the robot
|
||||
% Currently we just generate a triangle.
|
||||
function [x_pix, y_pix] = robot_polyline(robot_size)
|
||||
HEIGHT_RATIO = 1.25;
|
||||
x_pix = [-robot_size, robot_size, -robot_size];
|
||||
y_pix = [-robot_size/HEIGHT_RATIO, 0 , robot_size/HEIGHT_RATIO];
|
||||
|
||||
% Function to convert millimeters to pixels -------------------------------
|
||||
|
||||
function pix = mm2pix(mm, MAP_SIZE_METERS, MAP_SIZE_PIXELS)
|
||||
pix = floor(mm / (MAP_SIZE_METERS * 1000. / MAP_SIZE_PIXELS));
|
||||
|
||||
|
||||
% Function to load all from file ------------------------------------------
|
||||
% Each line in the file has the format:
|
||||
%
|
||||
% TIMESTAMP ... Q1 Q1 ... Distances
|
||||
% (usec) (mm)
|
||||
% 0 ... 2 3 ... 24 ...
|
||||
%
|
||||
%where Q1, Q2 are odometry values
|
||||
|
||||
function [times, scans,odometries] = load_data(dataset)
|
||||
|
||||
data = load([dataset '.dat']);
|
||||
|
||||
times = data(:,1);
|
||||
scans = data(:,25:end-1); % avoid final ' '
|
||||
odometries = data(:,[1,3,4]);
|
||||
|
||||
% Function to build a Laser data structure for the Hokuyo URG04LX used for
|
||||
% collecting the logfile data.
|
||||
|
||||
function laser = MinesLaser()
|
||||
|
||||
laser.scan_size = 682;
|
||||
laser.scan_rate_hz = 10;
|
||||
laser.detection_angle_degrees = 240;
|
||||
laser.distance_no_detection_mm = 4000;
|
||||
laser.detection_margin = 70;
|
||||
laser.offset_mm = 145;
|
||||
@@ -30,6 +30,9 @@ from rplidar import RPLidar as Lidar
|
||||
|
||||
from pltslamshow import SlamShow
|
||||
|
||||
from scipy.interpolate import interp1d
|
||||
import numpy as np
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Connect to Lidar unit
|
||||
@@ -52,36 +55,33 @@ if __name__ == '__main__':
|
||||
|
||||
while True:
|
||||
|
||||
try:
|
||||
# Extrat (quality, angle, distance) triples from current scan
|
||||
items = [item for item in next(iterator)]
|
||||
|
||||
# Extrat (quality, angle, distance) triples from current scan
|
||||
items = [item for item in next(iterator)]
|
||||
# Extract distances and angles from triples
|
||||
distances = [item[2] for item in items]
|
||||
angles = [item[1] for item in items]
|
||||
|
||||
# Extract distances and angles from triples
|
||||
distances = [item[2] for item in items]
|
||||
angles = [item[1] for item in items]
|
||||
print(angles)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
# Interpolate to get 360 angles from 0 through 359, and corresponding distances
|
||||
f = interp1d(angles, distances, fill_value='extrapolate')
|
||||
distances = list(f(np.arange(360)))
|
||||
|
||||
# Update SLAM with current Lidar scan, using third element of (quality, angle, distance) triples
|
||||
#slam.update([item[2] for item in next(iterator)])
|
||||
slam.update(distances)
|
||||
|
||||
# Get current robot position
|
||||
#x, y, theta = slam.getpos()
|
||||
x, y, theta = slam.getpos()
|
||||
|
||||
# Get current map bytes as grayscale
|
||||
#slam.getmap(mapbytes)
|
||||
slam.getmap(mapbytes)
|
||||
|
||||
#display.displayMap(mapbytes)
|
||||
display.displayMap(mapbytes)
|
||||
|
||||
#display.setPose(x, y, theta)
|
||||
display.setPose(x, y, theta)
|
||||
|
||||
# Exit on ESCape
|
||||
#key = display.refresh()
|
||||
#if key != None and (key&0x1A):
|
||||
# exit(0)
|
||||
# Exit on window close
|
||||
if not display.refresh():
|
||||
exit(0)
|
||||
|
||||
lidar.stop()
|
||||
lidar.disconnect()
|
||||
|
||||
Reference in New Issue
Block a user