tsdf_match_cost_function_2d_test.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2018 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/tsdf_match_cost_function_2d.h"
00018 
00019 #include "cartographer/common/lua_parameter_dictionary.h"
00020 #include "cartographer/common/lua_parameter_dictionary_test_helpers.h"
00021 #include "cartographer/mapping/2d/tsdf_2d.h"
00022 #include "cartographer/mapping/2d/tsdf_range_data_inserter_2d.h"
00023 #include "gmock/gmock.h"
00024 #include "gtest/gtest.h"
00025 
00026 namespace cartographer {
00027 namespace mapping {
00028 namespace scan_matching {
00029 namespace {
00030 
00031 using ::testing::DoubleNear;
00032 using ::testing::ElementsAre;
00033 
00034 class TSDFSpaceCostFunction2DTest : public ::testing::Test {
00035  protected:
00036   TSDFSpaceCostFunction2DTest()
00037       : tsdf_(MapLimits(0.1, Eigen::Vector2d(2.05, 2.05), CellLimits(40, 40)),
00038               0.3, 1.0, &conversion_tables_) {
00039     auto parameter_dictionary = common::MakeDictionary(
00040         "return { "
00041         "truncation_distance = 0.3,"
00042         "maximum_weight = 1.0,"
00043         "update_free_space = false,"
00044         "normal_estimation_options = {"
00045         "num_normal_samples = 2,"
00046         "sample_radius = 10.,"
00047         "},"
00048         "project_sdf_distance_to_scan_normal = true,"
00049         "update_weight_range_exponent = 0,"
00050         "update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0,"
00051         "update_weight_distance_cell_to_hit_kernel_bandwidth = 0,"
00052         "}");
00053     options_ = CreateTSDFRangeDataInserterOptions2D(parameter_dictionary.get());
00054     range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00055   }
00056 
00057   void InsertPointcloud() {
00058     auto range_data = sensor::RangeData();
00059     for (float x = -.5; x < 0.5f; x += 0.1) {
00060       range_data.returns.push_back({Eigen::Vector3f{x, 1.0f, 0.f}});
00061     }
00062     range_data.origin.x() = -0.5f;
00063     range_data.origin.y() = -0.5f;
00064     range_data_inserter_->Insert(range_data, &tsdf_);
00065     tsdf_.FinishUpdate();
00066   }
00067 
00068   ValueConversionTables conversion_tables_;
00069   proto::TSDFRangeDataInserterOptions2D options_;
00070   TSDF2D tsdf_;
00071   std::unique_ptr<TSDFRangeDataInserter2D> range_data_inserter_;
00072 };
00073 
00074 TEST_F(TSDFSpaceCostFunction2DTest, MatchEmptyTSDF) {
00075   const sensor::PointCloud matching_cloud = {{Eigen::Vector3f{0.f, 0.f, 0.f}}};
00076   std::unique_ptr<ceres::CostFunction> cost_function(
00077       CreateTSDFMatchCostFunction2D(1.f, matching_cloud, tsdf_));
00078   const std::array<double, 3> pose_estimate{{0., 0., 0.}};
00079   const std::array<const double*, 1> parameter_blocks{{pose_estimate.data()}};
00080   std::array<double, 1> residuals;
00081   std::array<std::array<double, 3>, 1> jacobians;
00082   std::array<double*, 1> jacobians_ptrs;
00083   for (int i = 0; i < 1; ++i) jacobians_ptrs[i] = jacobians[i].data();
00084   bool valid_result = cost_function->Evaluate(
00085       parameter_blocks.data(), residuals.data(), jacobians_ptrs.data());
00086   EXPECT_FALSE(valid_result);
00087 }
00088 
00089 TEST_F(TSDFSpaceCostFunction2DTest, ExactInitialPose) {
00090   InsertPointcloud();
00091   const sensor::PointCloud matching_cloud = {{Eigen::Vector3f{0.f, 1.0f, 0.f}}};
00092   std::unique_ptr<ceres::CostFunction> cost_function(
00093       CreateTSDFMatchCostFunction2D(1.f, matching_cloud, tsdf_));
00094   const std::array<double, 3> pose_estimate{{0., 0., 0.}};
00095   const std::array<const double*, 1> parameter_blocks{{pose_estimate.data()}};
00096   std::array<double, 1> residuals;
00097   std::array<std::array<double, 3>, 1> jacobians;
00098   std::array<double*, 1> jacobians_ptrs;
00099   for (int i = 0; i < 1; ++i) jacobians_ptrs[i] = jacobians[i].data();
00100   const bool valid_result = cost_function->Evaluate(
00101       parameter_blocks.data(), residuals.data(), jacobians_ptrs.data());
00102   EXPECT_TRUE(valid_result);
00103   EXPECT_THAT(residuals, ElementsAre(DoubleNear(0., 1e-3)));
00104   EXPECT_THAT(jacobians[0],
00105               ElementsAre(DoubleNear(0., 1e-3), DoubleNear(-1., 1e-3),
00106                           DoubleNear(0., 1e-3)));
00107 }
00108 
00109 TEST_F(TSDFSpaceCostFunction2DTest, PertubatedInitialPose) {
00110   InsertPointcloud();
00111   sensor::PointCloud matching_cloud = {{Eigen::Vector3f{0.f, 1.0f, 0.f}}};
00112   std::unique_ptr<ceres::CostFunction> cost_function(
00113       CreateTSDFMatchCostFunction2D(1.f, matching_cloud, tsdf_));
00114   std::array<double, 3> pose_estimate{{0., 0.1, 0.}};
00115   std::array<const double*, 1> parameter_blocks{{pose_estimate.data()}};
00116   std::array<double, 1> residuals;
00117   std::array<std::array<double, 3>, 1> jacobians;
00118   std::array<double*, 1> jacobians_ptrs;
00119   for (int i = 0; i < 1; ++i) jacobians_ptrs[i] = jacobians[i].data();
00120 
00121   bool valid_result = cost_function->Evaluate(
00122       parameter_blocks.data(), residuals.data(), jacobians_ptrs.data());
00123   EXPECT_TRUE(valid_result);
00124   EXPECT_THAT(residuals, ElementsAre(DoubleNear(-0.1, 1e-3)));
00125   EXPECT_THAT(jacobians[0],
00126               ElementsAre(DoubleNear(0., 1e-3), DoubleNear(-1., 1e-3),
00127                           DoubleNear(0., 1e-3)));
00128 
00129   pose_estimate[1] = -0.1;
00130   parameter_blocks = {{pose_estimate.data()}};
00131   valid_result = cost_function->Evaluate(
00132       parameter_blocks.data(), residuals.data(), jacobians_ptrs.data());
00133   EXPECT_TRUE(valid_result);
00134   EXPECT_THAT(residuals, ElementsAre(DoubleNear(0.1, 1e-3)));
00135   EXPECT_THAT(jacobians[0],
00136               ElementsAre(DoubleNear(0., 1e-3), DoubleNear(-1., 1e-3),
00137                           DoubleNear(0., 1e-3)));
00138 }
00139 
00140 TEST_F(TSDFSpaceCostFunction2DTest, InvalidInitialPose) {
00141   InsertPointcloud();
00142   sensor::PointCloud matching_cloud = {{Eigen::Vector3f{0.f, 1.0f, 0.f}}};
00143   std::unique_ptr<ceres::CostFunction> cost_function(
00144       CreateTSDFMatchCostFunction2D(1.f, matching_cloud, tsdf_));
00145   std::array<double, 3> pose_estimate{{0., 0.4, 0.}};
00146   std::array<const double*, 1> parameter_blocks{{pose_estimate.data()}};
00147   std::array<double, 1> residuals;
00148   std::array<std::array<double, 3>, 1> jacobians;
00149   std::array<double*, 1> jacobians_ptrs;
00150   for (int i = 0; i < 1; ++i) jacobians_ptrs[i] = jacobians[i].data();
00151 
00152   bool valid_result = cost_function->Evaluate(
00153       parameter_blocks.data(), residuals.data(), jacobians_ptrs.data());
00154   EXPECT_FALSE(valid_result);
00155 
00156   pose_estimate[1] = -0.4;
00157   parameter_blocks = {{pose_estimate.data()}};
00158   valid_result = cost_function->Evaluate(
00159       parameter_blocks.data(), residuals.data(), jacobians_ptrs.data());
00160   EXPECT_FALSE(valid_result);
00161 }
00162 
00163 }  // namespace
00164 }  // namespace scan_matching
00165 }  // namespace mapping
00166 }  // namespace cartographer


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