fast_correlative_scan_matcher_3d_test.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 <random>
22 #include <string>
23 
29 #include "gtest/gtest.h"
30 
31 namespace cartographer {
32 namespace mapping {
33 namespace scan_matching {
34 namespace {
35 
36 class FastCorrelativeScanMatcher3DTest : public ::testing::Test {
37  protected:
38  FastCorrelativeScanMatcher3DTest()
39  : range_data_inserter_(CreateRangeDataInserterTestOptions3D()),
40  options_(CreateFastCorrelativeScanMatcher3DTestOptions3D(6)) {}
41 
42  void SetUp() override {
43  point_cloud_ = {
44  Eigen::Vector3f(4.f, 0.f, 0.f), Eigen::Vector3f(4.5f, 0.f, 0.f),
45  Eigen::Vector3f(5.f, 0.f, 0.f), Eigen::Vector3f(5.5f, 0.f, 0.f),
46  Eigen::Vector3f(0.f, 4.f, 0.f), Eigen::Vector3f(0.f, 4.5f, 0.f),
47  Eigen::Vector3f(0.f, 5.f, 0.f), Eigen::Vector3f(0.f, 5.5f, 0.f),
48  Eigen::Vector3f(0.f, 0.f, 4.f), Eigen::Vector3f(0.f, 0.f, 4.5f),
49  Eigen::Vector3f(0.f, 0.f, 5.f), Eigen::Vector3f(0.f, 0.f, 5.5f)};
50  }
51 
52  transform::Rigid3f GetRandomPose() {
53  const float x = 0.7f * distribution_(prng_);
54  const float y = 0.7f * distribution_(prng_);
55  const float z = 0.7f * distribution_(prng_);
56  const float theta = 0.2f * distribution_(prng_);
57  return transform::Rigid3f::Translation(Eigen::Vector3f(x, y, z)) *
59  Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()));
60  }
61 
62  static proto::FastCorrelativeScanMatcherOptions3D
63  CreateFastCorrelativeScanMatcher3DTestOptions3D(
64  const int branch_and_bound_depth) {
65  auto parameter_dictionary = common::MakeDictionary(
66  "return {"
67  "branch_and_bound_depth = " +
68  std::to_string(branch_and_bound_depth) +
69  ", "
70  "full_resolution_depth = " +
71  std::to_string(branch_and_bound_depth) +
72  ", "
73  "min_rotational_score = 0.1, "
74  // Unknown space has kMinProbability = 0.1, so we need to make sure here
75  // to pick a larger number otherwise we always find matches.
76  "min_low_resolution_score = 0.15, "
77  "linear_xy_search_window = 0.8, "
78  "linear_z_search_window = 0.8, "
79  "angular_search_window = 0.3, "
80  "}");
82  parameter_dictionary.get());
83  }
84 
85  static mapping::proto::RangeDataInserterOptions3D
86  CreateRangeDataInserterTestOptions3D() {
87  auto parameter_dictionary = common::MakeDictionary(
88  "return { "
89  "hit_probability = 0.7, "
90  "miss_probability = 0.4, "
91  "num_free_space_voxels = 5, "
92  "}");
93  return CreateRangeDataInserterOptions3D(parameter_dictionary.get());
94  }
95 
96  std::unique_ptr<FastCorrelativeScanMatcher3D> GetFastCorrelativeScanMatcher(
97  const proto::FastCorrelativeScanMatcherOptions3D& options,
98  const transform::Rigid3f& pose) {
99  hybrid_grid_ = common::make_unique<HybridGrid>(0.05f);
100  range_data_inserter_.Insert(
101  sensor::RangeData{pose.translation(),
103  {}},
104  hybrid_grid_.get());
105  hybrid_grid_->FinishUpdate();
106 
107  return common::make_unique<FastCorrelativeScanMatcher3D>(
108  *hybrid_grid_, hybrid_grid_.get(),
109  std::vector<TrajectoryNode>(
110  {{std::make_shared<const TrajectoryNode::Data>(
111  CreateConstantData(point_cloud_)),
112  pose.cast<double>()}}),
113  options);
114  }
115 
116  TrajectoryNode::Data CreateConstantData(
117  const sensor::PointCloud& low_resolution_point_cloud) {
118  return TrajectoryNode::Data{common::FromUniversal(0),
119  Eigen::Quaterniond::Identity(),
120  {},
121  point_cloud_,
122  low_resolution_point_cloud,
123  Eigen::VectorXf::Zero(10)};
124  }
125 
126  std::mt19937 prng_ = std::mt19937(42);
127  std::uniform_real_distribution<float> distribution_ =
128  std::uniform_real_distribution<float>(-1.f, 1.f);
129  RangeDataInserter3D range_data_inserter_;
130  const proto::FastCorrelativeScanMatcherOptions3D options_;
132  std::unique_ptr<HybridGrid> hybrid_grid_;
133 };
134 
135 constexpr float kMinScore = 0.1f;
136 
137 TEST_F(FastCorrelativeScanMatcher3DTest, CorrectPoseForMatch) {
138  for (int i = 0; i != 20; ++i) {
139  const auto expected_pose = GetRandomPose();
140 
141  std::unique_ptr<FastCorrelativeScanMatcher3D> fast_correlative_scan_matcher(
142  GetFastCorrelativeScanMatcher(options_, expected_pose));
143 
144  const std::unique_ptr<FastCorrelativeScanMatcher3D::Result> result =
145  fast_correlative_scan_matcher->Match(
147  CreateConstantData(point_cloud_), kMinScore);
148  EXPECT_THAT(result, testing::NotNull());
149  EXPECT_LT(kMinScore, result->score);
150  EXPECT_LT(0.09f, result->rotational_score);
151  EXPECT_LT(0.14f, result->low_resolution_score);
152  EXPECT_THAT(expected_pose,
153  transform::IsNearly(result->pose_estimate.cast<float>(), 0.05f))
154  << "Actual: " << transform::ToProto(result->pose_estimate).DebugString()
155  << "\nExpected: " << transform::ToProto(expected_pose).DebugString();
156 
157  const std::unique_ptr<FastCorrelativeScanMatcher3D::Result>
158  low_resolution_result = fast_correlative_scan_matcher->Match(
160  CreateConstantData({Eigen::Vector3f(42.f, 42.f, 42.f)}), kMinScore);
161  EXPECT_THAT(low_resolution_result, testing::IsNull())
162  << low_resolution_result->low_resolution_score;
163  }
164 }
165 
166 TEST_F(FastCorrelativeScanMatcher3DTest, CorrectPoseForMatchFullSubmap) {
167  const auto expected_pose = GetRandomPose();
168 
169  std::unique_ptr<FastCorrelativeScanMatcher3D> fast_correlative_scan_matcher(
170  GetFastCorrelativeScanMatcher(options_, expected_pose));
171 
172  const std::unique_ptr<FastCorrelativeScanMatcher3D::Result> result =
173  fast_correlative_scan_matcher->MatchFullSubmap(
174  Eigen::Quaterniond::Identity(), Eigen::Quaterniond::Identity(),
175  CreateConstantData(point_cloud_), kMinScore);
176  EXPECT_THAT(result, testing::NotNull());
177  EXPECT_LT(kMinScore, result->score);
178  EXPECT_LT(0.09f, result->rotational_score);
179  EXPECT_LT(0.14f, result->low_resolution_score);
180  EXPECT_THAT(expected_pose,
181  transform::IsNearly(result->pose_estimate.cast<float>(), 0.05f))
182  << "Actual: " << transform::ToProto(result->pose_estimate).DebugString()
183  << "\nExpected: " << transform::ToProto(expected_pose).DebugString();
184 
185  const std::unique_ptr<FastCorrelativeScanMatcher3D::Result>
186  low_resolution_result = fast_correlative_scan_matcher->MatchFullSubmap(
187  Eigen::Quaterniond::Identity(), Eigen::Quaterniond::Identity(),
188  CreateConstantData({Eigen::Vector3f(42.f, 42.f, 42.f)}), kMinScore);
189  EXPECT_THAT(low_resolution_result, testing::IsNull())
190  << low_resolution_result->low_resolution_score;
191 }
192 
193 } // namespace
194 } // namespace scan_matching
195 } // namespace mapping
196 } // namespace cartographer
PointCloud TransformPointCloud(const PointCloud &point_cloud, const transform::Rigid3f &transform)
Definition: point_cloud.cc:25
std::unique_ptr< HybridGrid > hybrid_grid_
static Rigid3 Rotation(const AngleAxis &angle_axis)
proto::RangeDataInserterOptions3D CreateRangeDataInserterOptions3D(common::LuaParameterDictionary *parameter_dictionary)
std::unique_ptr< LuaParameterDictionary > MakeDictionary(const std::string &code)
Time FromUniversal(const int64 ticks)
Definition: time.cc:34
proto::Rigid2d ToProto(const transform::Rigid2d &transform)
Definition: transform.cc:48
sensor::PointCloud point_cloud_
const proto::FastCorrelativeScanMatcherOptions3D options_
std::uniform_real_distribution< float > distribution_
std::vector< Eigen::Vector3f > PointCloud
Definition: point_cloud.h:32
RangeDataInserter3D range_data_inserter_
proto::FastCorrelativeScanMatcherOptions3D CreateFastCorrelativeScanMatcherOptions3D(common::LuaParameterDictionary *const parameter_dictionary)
transform::Rigid3d pose
static Rigid3 Translation(const Vector &vector)


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