real_time_correlative_scan_matcher_2d_test.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2016 The Cartographer Authors
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "cartographer/mapping/internal/2d/scan_matching/real_time_correlative_scan_matcher_2d.h"
00018 
00019 #include <cmath>
00020 #include <memory>
00021 
00022 #include "Eigen/Geometry"
00023 #include "absl/memory/memory.h"
00024 #include "cartographer/common/lua_parameter_dictionary_test_helpers.h"
00025 #include "cartographer/mapping/2d/probability_grid.h"
00026 #include "cartographer/mapping/2d/probability_grid_range_data_inserter_2d.h"
00027 #include "cartographer/mapping/2d/tsdf_2d.h"
00028 #include "cartographer/mapping/2d/tsdf_range_data_inserter_2d.h"
00029 #include "cartographer/mapping/internal/scan_matching/real_time_correlative_scan_matcher.h"
00030 #include "cartographer/sensor/point_cloud.h"
00031 #include "cartographer/transform/transform.h"
00032 #include "gtest/gtest.h"
00033 
00034 namespace cartographer {
00035 namespace mapping {
00036 namespace scan_matching {
00037 namespace {
00038 
00039 proto::RealTimeCorrelativeScanMatcherOptions
00040 CreateRealTimeCorrelativeScanMatcherTestOptions2D() {
00041   auto parameter_dictionary = common::MakeDictionary(
00042       "return {"
00043       "linear_search_window = 0.6, "
00044       "angular_search_window = 0.16, "
00045       "translation_delta_cost_weight = 0., "
00046       "rotation_delta_cost_weight = 0., "
00047       "}");
00048   return CreateRealTimeCorrelativeScanMatcherOptions(
00049       parameter_dictionary.get());
00050 }
00051 
00052 class RealTimeCorrelativeScanMatcherTest : public ::testing::Test {
00053  protected:
00054   RealTimeCorrelativeScanMatcherTest() {
00055     point_cloud_.push_back({Eigen::Vector3f{0.025f, 0.175f, 0.f}});
00056     point_cloud_.push_back({Eigen::Vector3f{-0.025f, 0.175f, 0.f}});
00057     point_cloud_.push_back({Eigen::Vector3f{-0.075f, 0.175f, 0.f}});
00058     point_cloud_.push_back({Eigen::Vector3f{-0.125f, 0.175f, 0.f}});
00059     point_cloud_.push_back({Eigen::Vector3f{-0.125f, 0.125f, 0.f}});
00060     point_cloud_.push_back({Eigen::Vector3f{-0.125f, 0.075f, 0.f}});
00061     point_cloud_.push_back({Eigen::Vector3f{-0.125f, 0.025f, 0.f}});
00062     real_time_correlative_scan_matcher_ =
00063         absl::make_unique<RealTimeCorrelativeScanMatcher2D>(
00064             CreateRealTimeCorrelativeScanMatcherTestOptions2D());
00065   }
00066 
00067   void SetUpTSDF() {
00068     grid_ = absl::make_unique<TSDF2D>(
00069         MapLimits(0.05, Eigen::Vector2d(0.3, 0.5), CellLimits(20, 20)), 0.3,
00070         1.0, &conversion_tables_);
00071     {
00072       auto parameter_dictionary = common::MakeDictionary(R"text(
00073       return {
00074         truncation_distance = 0.3,
00075         maximum_weight = 10.,
00076         update_free_space = false,
00077         normal_estimation_options = {
00078           num_normal_samples = 4,
00079           sample_radius = 0.5,
00080         },
00081         project_sdf_distance_to_scan_normal = true,
00082         update_weight_range_exponent = 0,
00083         update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0.5,
00084         update_weight_distance_cell_to_hit_kernel_bandwidth = 0.5,
00085       })text");
00086       range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(
00087           CreateTSDFRangeDataInserterOptions2D(parameter_dictionary.get()));
00088     }
00089     range_data_inserter_->Insert(
00090         sensor::RangeData{Eigen::Vector3f(0.5f, -0.5f, 0.f), point_cloud_, {}},
00091         grid_.get());
00092     grid_->FinishUpdate();
00093   }
00094 
00095   void SetUpProbabilityGrid() {
00096     grid_ = absl::make_unique<ProbabilityGrid>(
00097         MapLimits(0.05, Eigen::Vector2d(0.05, 0.25), CellLimits(6, 6)),
00098         &conversion_tables_);
00099     {
00100       auto parameter_dictionary = common::MakeDictionary(
00101           "return { "
00102           "insert_free_space = true, "
00103           "hit_probability = 0.7, "
00104           "miss_probability = 0.4, "
00105           "}");
00106       range_data_inserter_ =
00107           absl::make_unique<ProbabilityGridRangeDataInserter2D>(
00108               CreateProbabilityGridRangeDataInserterOptions2D(
00109                   parameter_dictionary.get()));
00110     }
00111     range_data_inserter_->Insert(
00112         sensor::RangeData{Eigen::Vector3f::Zero(), point_cloud_, {}},
00113         grid_.get());
00114     grid_->FinishUpdate();
00115   }
00116 
00117   ValueConversionTables conversion_tables_;
00118   std::unique_ptr<Grid2D> grid_;
00119   std::unique_ptr<RangeDataInserterInterface> range_data_inserter_;
00120   sensor::PointCloud point_cloud_;
00121   std::unique_ptr<RealTimeCorrelativeScanMatcher2D>
00122       real_time_correlative_scan_matcher_;
00123 };
00124 
00125 TEST_F(RealTimeCorrelativeScanMatcherTest,
00126        ScorePerfectHighResolutionCandidateProbabilityGrid) {
00127   SetUpProbabilityGrid();
00128   const std::vector<sensor::PointCloud> scans =
00129       GenerateRotatedScans(point_cloud_, SearchParameters(0, 0, 0., 0.));
00130   const std::vector<DiscreteScan2D> discrete_scans =
00131       DiscretizeScans(grid_->limits(), scans, Eigen::Translation2f::Identity());
00132   std::vector<Candidate2D> candidates;
00133   candidates.emplace_back(0, 0, 0, SearchParameters(0, 0, 0., 0.));
00134   real_time_correlative_scan_matcher_->ScoreCandidates(
00135       *grid_, discrete_scans, SearchParameters(0, 0, 0., 0.), &candidates);
00136   EXPECT_EQ(0, candidates[0].scan_index);
00137   EXPECT_EQ(0, candidates[0].x_index_offset);
00138   EXPECT_EQ(0, candidates[0].y_index_offset);
00139   // Every point should align perfectly.
00140   EXPECT_NEAR(0.7, candidates[0].score, 1e-2);
00141 }
00142 
00143 TEST_F(RealTimeCorrelativeScanMatcherTest,
00144        ScorePerfectHighResolutionCandidateTSDF) {
00145   SetUpTSDF();
00146   const std::vector<sensor::PointCloud> scans =
00147       GenerateRotatedScans(point_cloud_, SearchParameters(0, 0, 0., 0.));
00148   const std::vector<DiscreteScan2D> discrete_scans =
00149       DiscretizeScans(grid_->limits(), scans, Eigen::Translation2f::Identity());
00150   std::vector<Candidate2D> candidates;
00151   candidates.emplace_back(0, 0, 0, SearchParameters(0, 0, 0., 0.));
00152   real_time_correlative_scan_matcher_->ScoreCandidates(
00153       *grid_, discrete_scans, SearchParameters(0, 0, 0., 0.), &candidates);
00154   EXPECT_EQ(0, candidates[0].scan_index);
00155   EXPECT_EQ(0, candidates[0].x_index_offset);
00156   EXPECT_EQ(0, candidates[0].y_index_offset);
00157   // Every point should align perfectly.
00158   EXPECT_NEAR(1.0, candidates[0].score, 1e-1);
00159   EXPECT_LT(0.95, candidates[0].score);
00160 }
00161 
00162 TEST_F(RealTimeCorrelativeScanMatcherTest,
00163        ScorePartiallyCorrectHighResolutionCandidateProbabilityGrid) {
00164   SetUpProbabilityGrid();
00165   const std::vector<sensor::PointCloud> scans =
00166       GenerateRotatedScans(point_cloud_, SearchParameters(0, 0, 0., 0.));
00167   const std::vector<DiscreteScan2D> discrete_scans =
00168       DiscretizeScans(grid_->limits(), scans, Eigen::Translation2f::Identity());
00169   std::vector<Candidate2D> candidates;
00170   candidates.emplace_back(0, 0, 1, SearchParameters(0, 0, 0., 0.));
00171   real_time_correlative_scan_matcher_->ScoreCandidates(
00172       *grid_, discrete_scans, SearchParameters(0, 0, 0., 0.), &candidates);
00173   EXPECT_EQ(0, candidates[0].scan_index);
00174   EXPECT_EQ(0, candidates[0].x_index_offset);
00175   EXPECT_EQ(1, candidates[0].y_index_offset);
00176   // 3 points should align perfectly.
00177   EXPECT_LT(0.7 * 3. / 7., candidates[0].score);
00178   EXPECT_GT(0.7, candidates[0].score);
00179 }
00180 
00181 TEST_F(RealTimeCorrelativeScanMatcherTest,
00182        ScorePartiallyCorrectHighResolutionCandidateTSDF) {
00183   SetUpTSDF();
00184   const std::vector<sensor::PointCloud> scans =
00185       GenerateRotatedScans(point_cloud_, SearchParameters(0, 0, 0., 0.));
00186   const std::vector<DiscreteScan2D> discrete_scans =
00187       DiscretizeScans(grid_->limits(), scans, Eigen::Translation2f::Identity());
00188   std::vector<Candidate2D> candidates;
00189   candidates.emplace_back(0, 0, 1, SearchParameters(0, 0, 0., 0.));
00190   real_time_correlative_scan_matcher_->ScoreCandidates(
00191       *grid_, discrete_scans, SearchParameters(0, 0, 0., 0.), &candidates);
00192   EXPECT_EQ(0, candidates[0].scan_index);
00193   EXPECT_EQ(0, candidates[0].x_index_offset);
00194   EXPECT_EQ(1, candidates[0].y_index_offset);
00195   // 3 points should align perfectly.
00196   EXPECT_LT(1.0 - 4. / (7. * 6.), candidates[0].score);
00197   EXPECT_GT(1.0, candidates[0].score);
00198 }
00199 
00200 }  // namespace
00201 }  // namespace scan_matching
00202 }  // namespace mapping
00203 }  // namespace cartographer


cartographer
Author(s): The Cartographer Authors
autogenerated on Thu May 9 2019 02:27:35