Create algorithms.cpp
This commit is contained in:
252
cpp/algorithms.cpp
Normal file
252
cpp/algorithms.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
algorithms.cpp - C++ CoreSLAM algorithms
|
||||
|
||||
Copyright (C) 2013 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/>.
|
||||
*/
|
||||
|
||||
#include "coreslam.h"
|
||||
#include "random.h"
|
||||
|
||||
#include "Position.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "Laser.hpp"
|
||||
#include "Scan.hpp"
|
||||
#include "Velocities.hpp"
|
||||
#include "WheeledRobot.hpp"
|
||||
|
||||
#include "algorithms.hpp"
|
||||
|
||||
// Local helpers -------------------------------------------------------------------------------------------------------
|
||||
|
||||
static void Position2position_t(Position & cpp_pos, struct position_t * c_pos)
|
||||
{
|
||||
c_pos->x_mm = cpp_pos.x_mm;
|
||||
c_pos->y_mm = cpp_pos.y_mm;
|
||||
c_pos->theta_degrees = cpp_pos.theta_degrees;
|
||||
}
|
||||
|
||||
// CoreSLAM class -------------------------------------------------------------------------------------------------------
|
||||
|
||||
int CoreSLAM::distanceScanToMap(
|
||||
Scan & scan,
|
||||
Map & map,
|
||||
Position & position)
|
||||
{
|
||||
position_t pos_c;
|
||||
Position2position_t(position, &pos_c);
|
||||
|
||||
return distance_scan_to_map(map.map, scan.scan, pos_c);
|
||||
}
|
||||
|
||||
|
||||
CoreSLAM::CoreSLAM(
|
||||
Laser & laser,
|
||||
int map_size_pixels,
|
||||
double map_size_meters)
|
||||
{
|
||||
// Set default params
|
||||
this->map_quality = DEFAULT_MAP_QUALITY;
|
||||
this->hole_width_mm = DEFAULT_HOLE_WIDTH_MM;
|
||||
|
||||
// Store laser for later
|
||||
this->laser = new Laser(laser);
|
||||
|
||||
// Initialize velocities (dxyMillimeters, dthetaDegrees, dtSeconds) for odometry
|
||||
this->velocities = new Velocities();
|
||||
|
||||
// Initialize a scan for computing distance to map, and one for updating map
|
||||
this->scan_for_mapbuild = this->scan_create(3);
|
||||
this->scan_for_distance = this->scan_create(1);
|
||||
|
||||
// Initialize the map
|
||||
this->map = new Map(map_size_pixels, map_size_meters);
|
||||
}
|
||||
|
||||
CoreSLAM::~CoreSLAM(void)
|
||||
{
|
||||
delete this->map;
|
||||
delete this->scan_for_distance;
|
||||
delete this->scan_for_mapbuild;
|
||||
delete this->velocities;
|
||||
}
|
||||
|
||||
|
||||
void CoreSLAM::update(int * scan_mm, Velocities & velocities)
|
||||
{
|
||||
// Build a scan for computing distance to map, and one for updating map
|
||||
this->scan_update(this->scan_for_mapbuild, scan_mm);
|
||||
this->scan_update(this->scan_for_distance, scan_mm);
|
||||
|
||||
// Update velocities
|
||||
this->velocities->update(velocities.dxy_mm,
|
||||
velocities.dtheta_degrees,
|
||||
velocities.dt_seconds);
|
||||
|
||||
// Implementing class updates map and pointcloud
|
||||
this->updateMapAndPointcloud(velocities);
|
||||
}
|
||||
|
||||
|
||||
void CoreSLAM::getmap(unsigned char * mapbytes)
|
||||
{
|
||||
this->map->get((char *)mapbytes);
|
||||
}
|
||||
|
||||
Scan * CoreSLAM::scan_create(int span)
|
||||
{
|
||||
return new Scan(this->laser, span);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CoreSLAM::scan_update(Scan * scan, int * scan_mm)
|
||||
{
|
||||
scan->update(scan_mm, this->hole_width_mm, *this->velocities);
|
||||
}
|
||||
|
||||
SinglePositionSLAM::SinglePositionSLAM(Laser & laser, int map_size_pixels, double map_size_meters) :
|
||||
CoreSLAM(laser, map_size_pixels, map_size_meters)
|
||||
{
|
||||
this->position = Position(this->init_coord_mm(), this->init_coord_mm(), 0);
|
||||
}
|
||||
|
||||
|
||||
// SinglePositionSLAM class -------------------------------------------------------------------------------------------
|
||||
|
||||
void SinglePositionSLAM::updateMapAndPointcloud(Velocities & velocities)
|
||||
{
|
||||
// Start at current position
|
||||
Position start_pos = this->position;
|
||||
|
||||
// Add effect of velocities
|
||||
start_pos.x_mm += velocities.dxy_mm * this->costheta(),
|
||||
start_pos.y_mm += velocities.dxy_mm * this->sintheta(),
|
||||
start_pos.theta_degrees += velocities.dtheta_degrees;
|
||||
|
||||
// Add offset from laser
|
||||
start_pos.x_mm += this->laser->laser->offset_mm * this->costheta();
|
||||
start_pos.y_mm += this->laser->laser->offset_mm * this->sintheta();
|
||||
|
||||
// Get new position from implementing class
|
||||
Position new_position = this->getNewPosition(start_pos);
|
||||
|
||||
// Update the map with this new position
|
||||
this->map->update(*this->scan_for_mapbuild, new_position, this->map_quality, this->hole_width_mm);
|
||||
|
||||
// Update the current position with this new position, adjusted by laser offset
|
||||
this->position = Position(new_position);
|
||||
this->position.x_mm -= this->laser->laser->offset_mm * this->costheta();
|
||||
this->position.y_mm -= this->laser->laser->offset_mm * this->sintheta();
|
||||
}
|
||||
|
||||
Position & SinglePositionSLAM::getpos(void)
|
||||
{
|
||||
return this->position;
|
||||
}
|
||||
|
||||
double SinglePositionSLAM::init_coord_mm(void)
|
||||
{
|
||||
// Center of map
|
||||
return 500 * this->map->map->size_meters;
|
||||
}
|
||||
|
||||
|
||||
double SinglePositionSLAM::theta_radians(void)
|
||||
{
|
||||
return M_PI * this->position.theta_degrees / 180;
|
||||
}
|
||||
|
||||
double SinglePositionSLAM::costheta(void)
|
||||
{
|
||||
return cos(this->theta_radians());
|
||||
}
|
||||
|
||||
double SinglePositionSLAM::sintheta(void)
|
||||
{
|
||||
return sin(this->theta_radians());
|
||||
}
|
||||
|
||||
|
||||
// RMHC_SLAM class ------------------------------------------------------------------------------------------------------
|
||||
|
||||
RMHC_SLAM::RMHC_SLAM(Laser & laser, int map_size_pixels, double map_size_meters, unsigned random_seed) :
|
||||
SinglePositionSLAM(laser, map_size_pixels, map_size_meters)
|
||||
{
|
||||
this->sigma_xy_mm = DEFAULT_SIGMA_XY_MM;
|
||||
this->sigma_theta_degrees = DEFAULT_SIGMA_THETA_DEGREES;
|
||||
|
||||
this->max_search_iter = DEFAULT_MAX_SEARCH_ITER;
|
||||
|
||||
this->randomizer = random_init(random_seed);
|
||||
}
|
||||
|
||||
RMHC_SLAM::~RMHC_SLAM(void)
|
||||
{
|
||||
free(this->randomizer);
|
||||
}
|
||||
|
||||
void RMHC_SLAM::update(int * scan_mm)
|
||||
{
|
||||
Velocities zero_velocities;
|
||||
|
||||
CoreSLAM::update(scan_mm, zero_velocities);
|
||||
}
|
||||
|
||||
Position RMHC_SLAM::getNewPosition(Position & start_pos)
|
||||
{
|
||||
// Search for a new position if indicated
|
||||
Position likeliest_position = start_pos;
|
||||
if (this->randomizer)
|
||||
{
|
||||
// Use C to find likeliest position
|
||||
position_t start_pos_c;
|
||||
Position2position_t(start_pos, &start_pos_c);
|
||||
position_t c_likeliest_position =
|
||||
rmhc_position_search(
|
||||
start_pos_c,
|
||||
this->map->map,
|
||||
this->scan_for_distance->scan,
|
||||
*this->laser->laser,
|
||||
this->sigma_xy_mm,
|
||||
this->sigma_theta_degrees,
|
||||
this->max_search_iter,
|
||||
this->randomizer);
|
||||
|
||||
// Convert back to C++ object
|
||||
likeliest_position =
|
||||
Position(
|
||||
c_likeliest_position.x_mm,
|
||||
c_likeliest_position.y_mm,
|
||||
c_likeliest_position.theta_degrees);
|
||||
}
|
||||
|
||||
return likeliest_position;
|
||||
}
|
||||
|
||||
// DeterministicSLAM class ---------------------------------------------------------------------------------------------
|
||||
|
||||
Deterministic_SLAM::Deterministic_SLAM(Laser & laser, int map_size_pixels, double map_size_meters) :
|
||||
SinglePositionSLAM(laser, map_size_pixels, map_size_meters)
|
||||
{
|
||||
}
|
||||
|
||||
Position Deterministic_SLAM::getNewPosition(Position & start_pos)
|
||||
{
|
||||
return Position(start_pos.x_mm, start_pos.y_mm, start_pos.theta_degrees);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user