Go to the documentation of this file.00001
00011 #ifndef __MONTE_CARLO_SCAN_MATCHER_H
00012 #define __MONTE_CARLO_SCAN_MATCHER_H
00013
00014 #include <functional>
00015 #include <limits>
00016 #include <memory>
00017
00018 #include "state_data.h"
00019 #include "sensor_data.h"
00020 #include "grid_scan_matcher.h"
00021
00022
00023
00030 class MonteCarloScanMatcher : public GridScanMatcher {
00031 public:
00032 using ObsPtr = std::shared_ptr<GridScanMatcherObserver>;
00033 public:
00034
00042 MonteCarloScanMatcher(std::shared_ptr<ScanCostEstimator> estimator,
00043 unsigned failed_iter, unsigned max_iter):
00044 GridScanMatcher{estimator},
00045 _failed_tries_limit(failed_iter), _total_tries_limit(max_iter) {}
00046
00056 virtual double process_scan(const RobotState &init_pose,
00057 const TransformedLaserScan &scan,
00058 const GridMap &map,
00059 RobotState &pose_delta) override {
00060 do_for_each_observer([init_pose, scan, map](ObsPtr obs) {
00061 obs->on_matching_start(init_pose, scan, map);
00062 });
00063
00064 unsigned failed_tries = 0, total_tries = 0;
00065 std::shared_ptr<ScanCostEstimator> sce = GridScanMatcher::cost_estimator();
00066 double min_scan_cost = std::numeric_limits<double>::max();
00067 RobotState optimal_pose = init_pose;
00068
00069 min_scan_cost = sce->estimate_scan_cost(optimal_pose, scan,
00070 map, min_scan_cost);
00071
00072 do_for_each_observer([optimal_pose, scan, min_scan_cost](ObsPtr obs) {
00073 obs->on_scan_test(optimal_pose, scan, min_scan_cost);
00074 obs->on_pose_update(optimal_pose, scan, min_scan_cost);
00075 });
00076
00077 while (failed_tries < _failed_tries_limit &&
00078 total_tries < _total_tries_limit) {
00079 total_tries++;
00080
00081 RobotState sampled_pose = optimal_pose;
00082 sample_pose(sampled_pose);
00083 double sampled_scan_cost = sce->estimate_scan_cost(sampled_pose, scan,
00084 map, min_scan_cost);
00085 do_for_each_observer([sampled_pose, scan, sampled_scan_cost](ObsPtr obs) {
00086 obs->on_scan_test(sampled_pose, scan, sampled_scan_cost);
00087 });
00088
00089 if (min_scan_cost <= sampled_scan_cost) {
00090 failed_tries++;
00091 continue;
00092 }
00093
00094 min_scan_cost = sampled_scan_cost;
00095 optimal_pose = sampled_pose;
00096 failed_tries = on_estimate_update(failed_tries, _failed_tries_limit);
00097
00098 do_for_each_observer([optimal_pose, scan, min_scan_cost](ObsPtr obs) {
00099 obs->on_pose_update(optimal_pose, scan, min_scan_cost);
00100 });
00101 }
00102
00103 pose_delta.x = optimal_pose.x - init_pose.x;
00104 pose_delta.y = optimal_pose.y - init_pose.y;
00105 pose_delta.theta = optimal_pose.theta - init_pose.theta;
00106
00107 do_for_each_observer([pose_delta, min_scan_cost](ObsPtr obs) {
00108 obs->on_matching_end(pose_delta, min_scan_cost);
00109 });
00110 return min_scan_cost;
00111 }
00112
00113 protected:
00118 virtual void sample_pose(RobotState &base_pose) = 0;
00119
00125 virtual unsigned on_estimate_update(unsigned sample_num,
00126 unsigned sample_limit) = 0;
00127
00128 private:
00129 void do_for_each_observer(std::function<void(ObsPtr)> op) {
00130 for (auto &obs : GridScanMatcher::observers()) {
00131 if (auto obs_ptr = obs.lock()) {
00132 op(obs_ptr);
00133 }
00134 }
00135 }
00136
00137 private:
00138 unsigned _failed_tries_limit;
00139 unsigned _total_tries_limit;
00140 };
00141
00142 #endif