real_time_correlative_scan_matcher_3d.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 <cmath>
20 
21 #include "Eigen/Geometry"
24 #include "glog/logging.h"
25 
26 namespace cartographer {
27 namespace mapping {
28 namespace scan_matching {
29 
31  const proto::RealTimeCorrelativeScanMatcherOptions& options)
32  : options_(options) {}
33 
34 float RealTimeCorrelativeScanMatcher3D::Match(
35  const transform::Rigid3d& initial_pose_estimate,
36  const sensor::PointCloud& point_cloud, const HybridGrid& hybrid_grid,
37  transform::Rigid3d* pose_estimate) const {
38  CHECK_NOTNULL(pose_estimate);
39  float best_score = -1.f;
40  for (const transform::Rigid3f& transform : GenerateExhaustiveSearchTransforms(
41  hybrid_grid.resolution(), point_cloud)) {
42  const transform::Rigid3f candidate =
43  initial_pose_estimate.cast<float>() * transform;
44  const float score = ScoreCandidate(
45  hybrid_grid, sensor::TransformPointCloud(point_cloud, candidate),
46  transform);
47  if (score > best_score) {
48  best_score = score;
49  *pose_estimate = candidate.cast<double>();
50  }
51  }
52  return best_score;
53 }
54 
55 std::vector<transform::Rigid3f>
56 RealTimeCorrelativeScanMatcher3D::GenerateExhaustiveSearchTransforms(
57  const float resolution, const sensor::PointCloud& point_cloud) const {
58  std::vector<transform::Rigid3f> result;
59  const int linear_window_size =
60  common::RoundToInt(options_.linear_search_window() / resolution);
61  // We set this value to something on the order of resolution to make sure that
62  // the std::acos() below is defined.
63  float max_scan_range = 3.f * resolution;
64  for (const Eigen::Vector3f& point : point_cloud) {
65  const float range = point.norm();
66  max_scan_range = std::max(range, max_scan_range);
67  }
68  const float kSafetyMargin = 1.f - 1e-3f;
69  const float angular_step_size =
70  kSafetyMargin * std::acos(1.f - common::Pow2(resolution) /
71  (2.f * common::Pow2(max_scan_range)));
72  const int angular_window_size =
73  common::RoundToInt(options_.angular_search_window() / angular_step_size);
74  for (int z = -linear_window_size; z <= linear_window_size; ++z) {
75  for (int y = -linear_window_size; y <= linear_window_size; ++y) {
76  for (int x = -linear_window_size; x <= linear_window_size; ++x) {
77  for (int rz = -angular_window_size; rz <= angular_window_size; ++rz) {
78  for (int ry = -angular_window_size; ry <= angular_window_size; ++ry) {
79  for (int rx = -angular_window_size; rx <= angular_window_size;
80  ++rx) {
81  const Eigen::Vector3f angle_axis(rx * angular_step_size,
82  ry * angular_step_size,
83  rz * angular_step_size);
84  result.emplace_back(
85  Eigen::Vector3f(x * resolution, y * resolution,
86  z * resolution),
88  }
89  }
90  }
91  }
92  }
93  }
94  return result;
95 }
96 
97 float RealTimeCorrelativeScanMatcher3D::ScoreCandidate(
98  const HybridGrid& hybrid_grid,
99  const sensor::PointCloud& transformed_point_cloud,
100  const transform::Rigid3f& transform) const {
101  float score = 0.f;
102  for (const Eigen::Vector3f& point : transformed_point_cloud) {
103  score += hybrid_grid.GetProbability(hybrid_grid.GetCellIndex(point));
104  }
105  score /= static_cast<float>(transformed_point_cloud.size());
106  const float angle = transform::GetAngle(transform);
107  score *=
108  std::exp(-common::Pow2(transform.translation().norm() *
109  options_.translation_delta_cost_weight() +
110  angle * options_.rotation_delta_cost_weight()));
111  CHECK_GT(score, 0.f);
112  return score;
113 }
114 
115 } // namespace scan_matching
116 } // namespace mapping
117 } // namespace cartographer
PointCloud TransformPointCloud(const PointCloud &point_cloud, const transform::Rigid3f &transform)
Definition: point_cloud.cc:25
Eigen::Quaternion< T > AngleAxisVectorToRotationQuaternion(const Eigen::Matrix< T, 3, 1 > &angle_axis)
Definition: transform.h:86
constexpr T Pow2(T a)
Definition: math.h:50
RealTimeCorrelativeScanMatcher3D(const scan_matching::proto::RealTimeCorrelativeScanMatcherOptions &options)
int RoundToInt(const float x)
Definition: port.h:41
Rigid3< OtherType > cast() const
float GetProbability(const Eigen::Array3i &index) const
Definition: hybrid_grid.h:521
proto::ProbabilityGridRangeDataInserterOptions2D options_
const Vector & translation() const
std::vector< Eigen::Vector3f > PointCloud
Definition: point_cloud.h:32
Eigen::Array3i GetCellIndex(const Eigen::Vector3f &point) const
Definition: hybrid_grid.h:428
FloatType GetAngle(const Rigid3< FloatType > &transform)
Definition: transform.h:34


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