weighted_mean_point_probability_spe.h
Go to the documentation of this file.
1 #ifndef SLAM_CTOR_CORE_WEIGHTED_MEAN_DISCREPANCY_SP_ESTIMATOR
2 #define SLAM_CTOR_CORE_WEIGHTED_MEAN_DISCREPANCY_SP_ESTIMATOR
3 
4 #include <cmath>
5 #include "grid_scan_matcher.h"
6 #include "../math_utils.h"
7 #include "../maps/grid_rasterization.h"
8 #include "../features/angle_histogram.h"
9 
10 //============================================================================//
11 // Scan Point Weighting //
12 
14 public:
15  using PointId = LaserScan2D::Points::size_type;
16  virtual void reset(const LaserScan2D &scan) {}
17  virtual double weight(const LaserScan2D::Points &, PointId) const = 0;
18  virtual ~ScanPointWeighting() {}
19 };
20 
21 class EvenSPW : public ScanPointWeighting {
22 public:
23  void reset(const LaserScan2D &scan) override {
24  _common_weight = 1.0 / scan.points().size();
25  }
26 
27  double weight(const LaserScan2D::Points &, PointId) const override {
28  return _common_weight;
29  }
30 private:
32 };
33 
35 public:
36  void reset(const LaserScan2D &scan) override { _hist.reset(scan); }
37 
38  double weight(const LaserScan2D::Points &pts, PointId id) const override {
39  auto v = _hist.value(pts, id);
40  assert(v && "[BUG] AHR-SPW. Unknown point.");
41  return 1.0 / v;
42  }
43 private:
45 };
46 
48 public:
49  double weight(const LaserScan2D::Points &pts, PointId id) const override {
50  const auto &sp = pts[id];
51  auto angle = sp.angle();
52  auto weight = std::abs(std::sin(angle)) + std::abs(std::cos(angle));
53  if (0.9 < std::abs(std::cos(angle))) {
54  weight = 3;
55  } else if (0.8 < std::abs(std::cos(angle))) {
56  weight = 2;
57  }
58  return weight * std::sqrt(sp.range());
59  }
60 };
61 
62 //============================================================================//
63 // Weighted Mean Discrepancy SPE //
64 
66 protected:
67  using SPW = std::shared_ptr<ScanPointWeighting>;
68 public:
70  unsigned skip_rate = 0,
71  double max_usable_range = -1)
72  : ScanProbabilityEstimator{oope}, _spw{spw}
73  , _pts_skip_rate{skip_rate}, _pt_max_usable_range{max_usable_range} {}
74 
75  LaserScan2D filter_scan(const LaserScan2D &raw_scan, const RobotPose &pose,
76  const GridMap &map) override {
77  LaserScan2D scan;
78  scan.trig_provider = raw_scan.trig_provider;
79  scan.trig_provider->set_base_angle(pose.theta);
80 
81  auto &scan_pts = scan.points();
82  const auto &raw_points = raw_scan.points();
83  for (LaserScan2D::Points::size_type i = 0; i < raw_points.size(); ++i) {
84  if (_pts_skip_rate && i % _pts_skip_rate) { continue; }
85  auto &sp = raw_points[i];
86  auto world_point = sp.move_origin(pose.x, pose.y, scan.trig_provider);
87  auto area_id = map.world_to_cell(world_point);
88  if (should_skip_point(sp, map, area_id)) { continue; }
89 
90  scan_pts.push_back(sp);
91  }
92 
93  _spw->reset(scan);
94  return scan;
95  }
96 
98  const RobotPose &pose,
99  const GridMap &map,
100  const SPEParams &params) const override {
101  auto total_weight = double{0};
102  auto total_probability = double{0};
103 
104  auto observation = expected_scan_point_observation();
105  scan.trig_provider->set_base_angle(pose.theta);
106  const auto &points = scan.points();
107  for (LaserScan2D::Points::size_type i = 0; i < points.size(); ++i) {
108  auto &sp = points[i];
109  // FIXME: assumption - sensor pose is in robot's (0,0), dir - 0
110 
111  // prepare obstacle-based AreaOccupancyObservation
112  observation.obstacle = params.scan_is_prerotated ?
113  sp.move_origin(pose.x, pose.y) :
114  sp.move_origin(pose.x, pose.y, scan.trig_provider);
115  // area around the obstacle taken into account
116  // Q: move obst_area to AOO?
117  auto obs_area = params.sp_analysis_area.move_center(observation.obstacle);
118 
119  // estimate AOO probability
120  auto aoo_prob = occupancy_observation_probability(observation,
121  obs_area, map);
122 
123  auto sp_weight = _spw->weight(points, i);
124  total_probability += aoo_prob * sp_weight * sp.factor();
125  total_weight += sp_weight;
126  }
127  if (total_weight == 0) {
128  // TODO: replace with writing to a proper logger
129  std::clog << "WARNING: unknown probability" << std::endl;
130  return unknown_probability();
131  }
132  return total_probability / total_weight;
133  }
134 
135 protected:
137  // TODO: use a strategy to convert obstacle->occupancy
138  return {true, {1.0, 1.0}, {0, 0}, 1.0};
139  }
140 
141  virtual bool should_skip_point(const ScanPoint2D &sp,
142  const GridMap &map,
143  const GridMap::Coord &area_id) const {
144  return !sp.is_occupied() || !map.has_cell(area_id) ||
145  (are_strictly_ordered(0.0, _pt_max_usable_range, sp.range()));
146  }
147 
148 private:
150  unsigned _pts_skip_rate;
152 };
153 
154 #endif
LaserScan2D::Points::size_type PointId
double weight(const LaserScan2D::Points &, PointId) const override
Coord world_to_cell(const Point2D &pt) const
LaserScan2D filter_scan(const LaserScan2D &raw_scan, const RobotPose &pose, const GridMap &map) override
double theta
Definition: robot_pose.h:131
virtual bool has_cell(const Coord &c) const
LVRect move_center(const Point2D &new_center) const
WeightedMeanPointProbabilitySPE(OOPE oope, SPW spw, unsigned skip_rate=0, double max_usable_range=-1)
virtual void reset(const LaserScan2D &scan)
virtual AreaOccupancyObservation expected_scan_point_observation() const
std::shared_ptr< OccupancyObservationProbabilityEstimator > OOPE
std::shared_ptr< ScanPointWeighting > SPW
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
bool is_occupied() const
Definition: sensor_data.h:72
double weight(const LaserScan2D::Points &pts, PointId id) const override
double estimate_scan_probability(const LaserScan2D &scan, const RobotPose &pose, const GridMap &map, const SPEParams &params) const override
void reset(const LaserScan2D &scan) override
double weight(const LaserScan2D::Points &pts, PointId id) const override
const Points & points() const
Definition: sensor_data.h:148
virtual double weight(const LaserScan2D::Points &, PointId) const =0
std::shared_ptr< TrigonometryProvider > trig_provider
Definition: sensor_data.h:171
double range() const
Definition: sensor_data.h:47
virtual bool should_skip_point(const ScanPoint2D &sp, const GridMap &map, const GridMap::Coord &area_id) const
double y
Definition: robot_pose.h:131
std::vector< ScanPoint2D > Points
Definition: sensor_data.h:146
double x
Definition: robot_pose.h:131
void reset(const LaserScan2D &scan) override
bool are_strictly_ordered(double a, double b, double c)
Definition: math_utils.h:48


slam_constructor
Author(s): JetBrains Research, OSLL team
autogenerated on Mon Jun 10 2019 15:08:25