00001 #ifndef __TINY_WORLD_H
00002 #define __TINY_WORLD_H
00003
00004 #include <iostream>
00005 #include <cmath>
00006 #include <memory>
00007
00008 #include "../core/state_data.h"
00009 #include "../core/sensor_data.h"
00010 #include "../core/laser_scan_grid_world.h"
00011 #include "../core/maps/grid_cell_strategy.h"
00012
00013 #include "tiny_grid_cells.h"
00014 #include "tiny_scan_matcher.h"
00015
00020 struct TinyWorldParams {
00021 double localized_scan_quality, raw_scan_quality;
00022 const double SIG_XY;
00023 const double SIG_TH;
00024 const unsigned BAD_LMT;
00025 const unsigned TOT_LMT;
00026 const double HOLE_WIDTH;
00027
00028 TinyWorldParams(double sig_XY, double sig_T, unsigned lim_bad,
00029 unsigned lim_totl, double hole_width) :
00030 SIG_XY(sig_XY), SIG_TH(sig_T), BAD_LMT(lim_bad), TOT_LMT(lim_totl),
00031 HOLE_WIDTH(hole_width) {}
00032 };
00033
00040 class TinyWorld : public LaserScanGridWorld {
00041 public:
00042 using Point = DiscretePoint2D;
00043 public:
00044
00050 TinyWorld(std::shared_ptr<GridCellStrategy> gcs,
00051 const TinyWorldParams ¶ms,
00052 const GridMapParams &init_map_params) :
00053 LaserScanGridWorld(gcs, init_map_params), _gcs(gcs), _params(params),
00054 _scan_matcher(new TinyScanMatcher(_gcs->cost_est(),
00055 params.BAD_LMT, params.TOT_LMT,
00056 params.SIG_XY, params.SIG_TH)) {}
00057
00064 virtual void handle_observation(TransformedLaserScan &scan) override {
00065 RobotState pose_delta;
00066 _scan_matcher->reset_state();
00067 _scan_matcher->process_scan(pose(), scan, map(), pose_delta);
00068 update_robot_pose(pose_delta.x, pose_delta.y, pose_delta.theta);
00069
00070 bool pose_was_fixed = pose_delta.x || pose_delta.y || pose_delta.theta;
00071 auto factory = _gcs->cell_factory();
00072 scan.quality = pose_was_fixed ? _params.localized_scan_quality :
00073 _params.raw_scan_quality;
00074 LaserScanGridWorld::handle_observation(scan);
00075 }
00076
00088 virtual void handle_scan_point(GridMap &map,
00089 double laser_x, double laser_y,
00090 double beam_end_x, double beam_end_y,
00091 bool is_occ, double quality) override {
00092 Beam beam{laser_x, laser_y, beam_end_x, beam_end_y};
00093 Point robot_pt = map.world_to_cell(laser_x, laser_y);
00094 Point obst_pt = map.world_to_cell(beam_end_x, beam_end_y);
00095
00096 double obst_dist_sq = robot_pt.dist_sq(obst_pt);
00097 std::vector<Point> pts = DiscreteLine2D(robot_pt, obst_pt).points();
00098 double hole_dist_sq = std::pow(_params.HOLE_WIDTH / map.cell_scale(), 2);
00099
00100 auto occ_est = _gcs->occupancy_est();
00101 Occupancy beam_end_occ = occ_est->estimate_occupancy(beam,
00102 map.world_cell_bounds(pts.back()), is_occ);
00103 map.update_cell(pts.back(), beam_end_occ, quality);
00104 pts.pop_back();
00105
00106 for (const auto &pt : pts) {
00107 Occupancy empty_cell_value = occ_est->estimate_occupancy(beam,
00108 map.world_cell_bounds(pts.back()), false);
00109
00110 double dist_sq = pt.dist_sq(obst_pt);
00111 if (dist_sq < hole_dist_sq && hole_dist_sq < obst_dist_sq && is_occ) {
00112 empty_cell_value.prob_occ +=
00113 (1.0 - dist_sq / hole_dist_sq) * beam_end_occ.prob_occ;
00114 }
00115
00116 map.update_cell(pt, empty_cell_value, quality);
00117 }
00118 }
00119
00123 std::shared_ptr<GridScanMatcher> scan_matcher() {
00124 return _scan_matcher;
00125 }
00126 private:
00127 std::shared_ptr<GridCellStrategy> _gcs;
00128 const TinyWorldParams _params;
00129 std::shared_ptr<TinyScanMatcher> _scan_matcher;
00130 };
00131
00132 #endif