1 #ifndef SLAM_CTOR_CORE_M3RSM_ENGINE_H 2 #define SLAM_CTOR_CORE_M3RSM_ENGINE_H 10 #include "../geometry_primitives.h" 18 using SPEPtr = std::shared_ptr<ScanProbabilityEstimator>;
39 std::shared_ptr<LaserScan2D> filtered_lscan,
bool is_rotated,
41 : rotation{rot}, translation_drift{tdrift}, spe{scan_prob_est}
42 , filtered_scan{filtered_lscan}, scan_is_prerotated{is_rotated}
43 , pose{&robot_pose}, map{&grid_map}
47 Point2D avg_drift = translation_drift.center();
49 auto drifted_pose = *
pose;
50 if (scan_is_prerotated) {
51 drifted_pose = {pose->
x + avg_drift.
x, pose->
y + avg_drift.
y, 0};
56 map->
rescale(translation_drift.side());
57 prob_upper_bound = spe->estimate_scan_probability(
58 *filtered_scan, drifted_pose, *map,
63 :
Match(that.rotation, tdrift, that.spe, that.filtered_scan,
64 that.scan_is_prerotated, *that.pose, *that.map, false) {}
66 bool is_valid()
const {
return !std::isnan(prob_upper_bound); }
86 Match(
double prob) : prob_upper_bound{prob} {}
141 : _max_finest_prob_diff{max_finest_prob_diff} {
142 reset_engine_state();
147 _best_finest_probability = 0.0;
151 _max_x_error = max_x_error;
152 _max_y_error = max_y_error;
156 _rotation_sector = sector;
157 _rotation_resolution = step;
161 double match_prob = match.prob_upper_bound;
162 if (match_prob < _best_finest_probability) {
return; }
164 if (match.is_finest()) {
165 _best_finest_probability = std::max(_best_finest_probability,
166 match_prob - _max_finest_prob_diff);
168 _matches.push(std::move(match));
174 bool prerotate_scan =
false) {
176 const auto empty_trs_range =
Rect{0, 0, 0, 0};
177 const auto entire_trs_range =
Rect{-_max_y_error, _max_y_error,
178 -_max_x_error, _max_x_error};
180 double rotation_drift = 0;
181 auto fscan = std::make_shared<LaserScan2D>(spe->filter_scan(raw_scan, pose,
183 auto rotation_resolution = _rotation_resolution;
184 while (
less_or_equal(2 * rotation_drift, _rotation_sector)) {
185 for (
auto &rot : std::set<double>{rotation_drift, -rotation_drift}) {
186 auto scan = prerotate_scan ?
187 std::make_shared<LaserScan2D>(fscan->to_cartesian(rot + pose.
theta))
189 add_match(
Match{rot, empty_trs_range,
spe,
190 scan, prerotate_scan,
pose, map});
191 add_match(
Match{rot, entire_trs_range,
spe,
192 scan, prerotate_scan,
pose, map});
194 rotation_drift += rotation_resolution;
199 while (!_matches.empty()) {
200 auto best_match = _matches.top();
203 auto should_branch_horz =
less(translation_step,
204 coarse_drift.hside_len());
205 auto should_branch_vert =
less(translation_step,
206 coarse_drift.vside_len());
207 if (!should_branch_horz && !should_branch_vert) {
210 branch(best_match, should_branch_horz, should_branch_vert);
217 void branch(
const Match &coarse_match,
bool is_horz,
bool is_vert) {
219 auto finer_drifts = std::vector<Rect>{};
221 if (is_horz && is_vert) {
222 finer_drifts = coarse_drift.split4_evenly();
223 }
else if (is_horz) {
224 finer_drifts = coarse_drift.split_horz();
225 }
else if (is_vert) {
226 finer_drifts = coarse_drift.split_vert();
230 for (
auto& finer_drift : finer_drifts) {
231 auto finer_match =
Match{finer_drift, coarse_match};
233 coarse_match.prob_upper_bound) &&
234 "BUG: Bounding assumption is violated");
235 add_match(std::move(finer_match));
void branch(const Match &coarse_match, bool is_horz, bool is_vert)
void set_translation_lookup_range(double max_x_error, double max_y_error)
CONSTEXPR bool are_equal(const T &a, const T &b, const T &eps)
static Match invalid_match()
void set_rotation_lookup_range(double sector, double step)
M3RSMEngine(double max_finest_prob_diff=0)
Match next_best_match(double translation_step)
std::priority_queue< Match > _matches
std::priority_queue< Match > Matches
LightWeightRectangle sp_analysis_area
std::shared_ptr< ScanProbabilityEstimator > SPEPtr
Match(double rot, const Rect &tdrift, SPEPtr scan_prob_est, std::shared_ptr< LaserScan2D > filtered_lscan, bool is_rotated, const RobotPose &robot_pose, GridMap &grid_map, bool is_root=true)
void add_match(Match &&match)
std::ostream & operator<<(std::ostream &os, const Match &match)
double is_finest(double threashold=0) const
constexpr double rad2deg(double angle_rad)
void filter_prerotated_scan()
decltype(SPEParams{}.sp_analysis_area) Rect
bool less_or_equal(double a, double b)
void add_scan_matching_request(std::shared_ptr< ScanProbabilityEstimator > spe, const RobotPose &pose, const LaserScan2D &raw_scan, GridMap &map, bool prerotate_scan=false)
CONSTEXPR bool less(double a, double b)
decltype(SPEParams{}.sp_analysis_area) Rect
bool operator<(const Match &that) const
void reset_engine_state()
std::shared_ptr< LaserScan2D > filtered_scan
virtual void rescale(double)
double _best_finest_probability
double _max_finest_prob_diff
Match(const Rect &tdrift, const Match &that)