real_time_correlative_scan_matcher_2d.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2016 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #include <algorithm>
20 #include <cmath>
21 #include <functional>
22 #include <limits>
23 
24 #include "Eigen/Geometry"
30 #include "glog/logging.h"
31 
32 namespace cartographer {
33 namespace mapping {
34 namespace scan_matching {
35 
37  const proto::RealTimeCorrelativeScanMatcherOptions& options)
38  : options_(options) {}
39 
40 std::vector<Candidate2D>
42  const SearchParameters& search_parameters) const {
43  int num_candidates = 0;
44  for (int scan_index = 0; scan_index != search_parameters.num_scans;
45  ++scan_index) {
46  const int num_linear_x_candidates =
47  (search_parameters.linear_bounds[scan_index].max_x -
48  search_parameters.linear_bounds[scan_index].min_x + 1);
49  const int num_linear_y_candidates =
50  (search_parameters.linear_bounds[scan_index].max_y -
51  search_parameters.linear_bounds[scan_index].min_y + 1);
52  num_candidates += num_linear_x_candidates * num_linear_y_candidates;
53  }
54  std::vector<Candidate2D> candidates;
55  candidates.reserve(num_candidates);
56  for (int scan_index = 0; scan_index != search_parameters.num_scans;
57  ++scan_index) {
58  for (int x_index_offset = search_parameters.linear_bounds[scan_index].min_x;
59  x_index_offset <= search_parameters.linear_bounds[scan_index].max_x;
60  ++x_index_offset) {
61  for (int y_index_offset =
62  search_parameters.linear_bounds[scan_index].min_y;
63  y_index_offset <= search_parameters.linear_bounds[scan_index].max_y;
64  ++y_index_offset) {
65  candidates.emplace_back(scan_index, x_index_offset, y_index_offset,
66  search_parameters);
67  }
68  }
69  }
70  CHECK_EQ(candidates.size(), num_candidates);
71  return candidates;
72 }
73 
75  const transform::Rigid2d& initial_pose_estimate,
76  const sensor::PointCloud& point_cloud,
77  const ProbabilityGrid& probability_grid,
78  transform::Rigid2d* pose_estimate) const {
79  CHECK_NOTNULL(pose_estimate);
80 
81  const Eigen::Rotation2Dd initial_rotation = initial_pose_estimate.rotation();
82  const sensor::PointCloud rotated_point_cloud = sensor::TransformPointCloud(
83  point_cloud,
84  transform::Rigid3f::Rotation(Eigen::AngleAxisf(
85  initial_rotation.cast<float>().angle(), Eigen::Vector3f::UnitZ())));
86  const SearchParameters search_parameters(
87  options_.linear_search_window(), options_.angular_search_window(),
88  rotated_point_cloud, probability_grid.limits().resolution());
89 
90  const std::vector<sensor::PointCloud> rotated_scans =
91  GenerateRotatedScans(rotated_point_cloud, search_parameters);
92  const std::vector<DiscreteScan2D> discrete_scans = DiscretizeScans(
93  probability_grid.limits(), rotated_scans,
94  Eigen::Translation2f(initial_pose_estimate.translation().x(),
95  initial_pose_estimate.translation().y()));
96  std::vector<Candidate2D> candidates =
97  GenerateExhaustiveSearchCandidates(search_parameters);
98  ScoreCandidates(probability_grid, discrete_scans, search_parameters,
99  &candidates);
100 
101  const Candidate2D& best_candidate =
102  *std::max_element(candidates.begin(), candidates.end());
103  *pose_estimate = transform::Rigid2d(
104  {initial_pose_estimate.translation().x() + best_candidate.x,
105  initial_pose_estimate.translation().y() + best_candidate.y},
106  initial_rotation * Eigen::Rotation2Dd(best_candidate.orientation));
107  return best_candidate.score;
108 }
109 
111  const ProbabilityGrid& probability_grid,
112  const std::vector<DiscreteScan2D>& discrete_scans,
113  const SearchParameters& search_parameters,
114  std::vector<Candidate2D>* const candidates) const {
115  for (Candidate2D& candidate : *candidates) {
116  candidate.score = 0.f;
117  for (const Eigen::Array2i& xy_index :
118  discrete_scans[candidate.scan_index]) {
119  const Eigen::Array2i proposed_xy_index(
120  xy_index.x() + candidate.x_index_offset,
121  xy_index.y() + candidate.y_index_offset);
122  const float probability =
123  probability_grid.GetProbability(proposed_xy_index);
124  candidate.score += probability;
125  }
126  candidate.score /=
127  static_cast<float>(discrete_scans[candidate.scan_index].size());
128  candidate.score *=
129  std::exp(-common::Pow2(std::hypot(candidate.x, candidate.y) *
130  options_.translation_delta_cost_weight() +
131  std::abs(candidate.orientation) *
132  options_.rotation_delta_cost_weight()));
133  CHECK_GT(candidate.score, 0.f);
134  }
135 }
136 
137 } // namespace scan_matching
138 } // namespace mapping
139 } // namespace cartographer
std::vector< DiscreteScan2D > DiscretizeScans(const MapLimits &map_limits, const std::vector< sensor::PointCloud > &scans, const Eigen::Translation2f &initial_translation)
void ScoreCandidates(const ProbabilityGrid &probability_grid, const std::vector< DiscreteScan2D > &discrete_scans, const SearchParameters &search_parameters, std::vector< Candidate2D > *candidates) const
PointCloud TransformPointCloud(const PointCloud &point_cloud, const transform::Rigid3f &transform)
Definition: point_cloud.cc:25
static Rigid3 Rotation(const AngleAxis &angle_axis)
constexpr T Pow2(T a)
Definition: math.h:50
std::vector< Candidate2D > GenerateExhaustiveSearchCandidates(const SearchParameters &search_parameters) const
Rigid2< double > Rigid2d
std::vector< sensor::PointCloud > GenerateRotatedScans(const sensor::PointCloud &point_cloud, const SearchParameters &search_parameters)
proto::ProbabilityGridRangeDataInserterOptions2D options_
RealTimeCorrelativeScanMatcher2D(const proto::RealTimeCorrelativeScanMatcherOptions &options)
float GetProbability(const Eigen::Array2i &cell_index) const
std::vector< Eigen::Vector3f > PointCloud
Definition: point_cloud.h:32
const Vector & translation() const
const MapLimits & limits() const
Definition: grid_2d.h:41
double Match(const transform::Rigid2d &initial_pose_estimate, const sensor::PointCloud &point_cloud, const ProbabilityGrid &probability_grid, transform::Rigid2d *pose_estimate) const


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58