tsdf_range_data_inserter_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/2d/tsdf_range_data_inserter_2d.h"
00018 
00019 #include "cartographer/common/lua_parameter_dictionary.h"
00020 #include "cartographer/common/lua_parameter_dictionary_test_helpers.h"
00021 #include "gmock/gmock.h"
00022 
00023 namespace cartographer {
00024 namespace mapping {
00025 namespace {
00026 
00027 class RangeDataInserterTest2DTSDF : public ::testing::Test {
00028  protected:
00029   RangeDataInserterTest2DTSDF()
00030       : tsdf_(MapLimits(1., Eigen::Vector2d(0., 7.), CellLimits(8, 1)), 2.0,
00031               10.0, &conversion_tables_) {
00032     auto parameter_dictionary = common::MakeDictionary(
00033         "return { "
00034         "truncation_distance = 2.0,"
00035         "maximum_weight = 10.,"
00036         "update_free_space = false,"
00037         "normal_estimation_options = {"
00038         "num_normal_samples = 2,"
00039         "sample_radius = 10.,"
00040         "},"
00041         "project_sdf_distance_to_scan_normal = false,"
00042         "update_weight_range_exponent = 0,"
00043         "update_weight_angle_scan_normal_to_ray_kernel_bandwidth = 0,"
00044         "update_weight_distance_cell_to_hit_kernel_bandwidth = 0,"
00045         "}");
00046     options_ = CreateTSDFRangeDataInserterOptions2D(parameter_dictionary.get());
00047     range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00048   }
00049 
00050   void InsertPoint() {
00051     auto range_data = sensor::RangeData();
00052     range_data.returns.push_back({Eigen::Vector3f{-0.5f, 3.5f, 0.f}});
00053     range_data.origin.x() = -0.5f;
00054     range_data.origin.y() = -0.5f;
00055     range_data_inserter_->Insert(range_data, &tsdf_);
00056     tsdf_.FinishUpdate();
00057   }
00058 
00059   ValueConversionTables conversion_tables_;
00060   proto::TSDFRangeDataInserterOptions2D options_;
00061   TSDF2D tsdf_;
00062   std::unique_ptr<TSDFRangeDataInserter2D> range_data_inserter_;
00063 };
00064 
00065 class MockCellProperties {
00066  public:
00067   MockCellProperties(const Eigen::Array2i& cell_index, const TSDF2D& tsdf)
00068       : is_known_(tsdf.IsKnown(cell_index)),
00069         tsd_(tsdf.GetTSD(cell_index)),
00070         weight_(tsdf.GetWeight(cell_index)){};
00071 
00072   bool is_known_;
00073   float tsd_;
00074   float weight_;
00075 };
00076 
00077 ::std::ostream& operator<<(::std::ostream& os, const MockCellProperties& bar) {
00078   return os << std::to_string(bar.is_known_) + "\t" + std::to_string(bar.tsd_) +
00079                    "\t" + std::to_string(bar.weight_);
00080 }
00081 
00082 MATCHER_P3(EqualCellProperties, expected_is_known, expected_tsd,
00083            expected_weight,
00084            std::string("Expected ") + std::to_string(expected_is_known) + "\t" +
00085                std::to_string(expected_tsd) + "\t" +
00086                std::to_string(expected_weight)) {
00087   bool result = expected_is_known == arg.is_known_;
00088   result = result && (std::abs(expected_tsd - arg.tsd_) < 1e-4);
00089   result = result && (std::abs(expected_weight - arg.weight_) < 1e-2);
00090   return result;
00091 }
00092 
00093 TEST_F(RangeDataInserterTest2DTSDF, InsertPoint) {
00094   InsertPoint();
00095   const float truncation_distance =
00096       static_cast<float>(options_.truncation_distance());
00097   const float maximum_weight = static_cast<float>(options_.maximum_weight());
00098 
00099   for (float y = 1.5; y < 6.; ++y) {
00100     // Cell intersects with ray.
00101     float x = -0.5f;
00102     Eigen::Array2i cell_index =
00103         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00104     float expected_tsdf =
00105         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00106     float expected_weight = 1.f;
00107     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00108                 EqualCellProperties(true, expected_tsdf, expected_weight));
00109     // Cells don't intersect with ray.
00110     x = 0.5f;
00111     cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00112     expected_tsdf = -truncation_distance;
00113     expected_weight = 0.;
00114     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00115                 EqualCellProperties(false, expected_tsdf, expected_weight));
00116     x = 1.5f;
00117     cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00118     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00119                 EqualCellProperties(false, expected_tsdf, expected_weight));
00120   }
00121 
00122   // Cells don't intersect with ray.
00123   Eigen::Array2i cell_index =
00124       tsdf_.limits().GetCellIndex(Eigen::Vector2f(0.5, 6.5));
00125   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00126               EqualCellProperties(false, -truncation_distance, 0.));
00127   cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(-0.5, -1.5));
00128   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00129               EqualCellProperties(false, -truncation_distance, 0.));
00130   for (int i = 0; i < 1000; ++i) {
00131     InsertPoint();
00132   }
00133   for (float y = 1.5; y < 6.; ++y) {
00134     // Cell intersects with ray.
00135     float x = -0.5f;
00136     Eigen::Array2i cell_index =
00137         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00138     float expected_tsdf =
00139         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00140     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00141                 EqualCellProperties(true, expected_tsdf, maximum_weight));
00142   }
00143 }
00144 
00145 TEST_F(RangeDataInserterTest2DTSDF, InsertPointWithFreeSpaceUpdate) {
00146   options_.set_update_free_space(true);
00147   range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00148   InsertPoint();
00149   const float truncation_distance =
00150       static_cast<float>(options_.truncation_distance());
00151   const float maximum_weight = static_cast<float>(options_.maximum_weight());
00152 
00153   for (float y = -0.5; y < 6.; ++y) {
00154     // Cells intersect with ray.
00155     float x = -0.5f;
00156     Eigen::Array2i cell_index =
00157         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00158     float expected_tsdf =
00159         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00160     float expected_weight = 1.f;
00161     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00162                 EqualCellProperties(true, expected_tsdf, expected_weight));
00163     // Cells don't intersect with ray.
00164     x = 0.5f;
00165     cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00166     expected_tsdf = -truncation_distance;
00167     expected_weight = 0.;
00168     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00169                 EqualCellProperties(false, expected_tsdf, expected_weight));
00170     x = 1.5f;
00171     cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00172     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00173                 EqualCellProperties(false, expected_tsdf, expected_weight));
00174   }
00175 
00176   // Cells don't intersect with the ray.
00177   Eigen::Array2i cell_index =
00178       tsdf_.limits().GetCellIndex(Eigen::Vector2f(-0.5, 6.5));
00179   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00180               EqualCellProperties(false, -truncation_distance, 0.));
00181   cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(-0.5, -1.5));
00182   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00183               EqualCellProperties(false, -truncation_distance, 0.));
00184   for (int i = 0; i < 1000; ++i) {
00185     InsertPoint();
00186   }
00187   for (float y = -0.5; y < 6.; ++y) {
00188     // Cell intersects with ray.
00189     float x = -0.5f;
00190     Eigen::Array2i cell_index =
00191         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00192     float expected_tsdf =
00193         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00194     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00195                 EqualCellProperties(true, expected_tsdf, maximum_weight));
00196   }
00197 }
00198 
00199 TEST_F(RangeDataInserterTest2DTSDF, InsertPointLinearWeight) {
00200   options_.set_update_weight_range_exponent(1);
00201   range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00202   InsertPoint();
00203   const float truncation_distance =
00204       static_cast<float>(options_.truncation_distance());
00205   for (float y = 1.5; y < 6.; ++y) {
00206     // Cell intersects with ray.
00207     float x = -0.5f;
00208     Eigen::Array2i cell_index =
00209         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00210     float expected_tsdf =
00211         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00212     float expected_weight = 1.f / 4.f;
00213     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00214                 EqualCellProperties(true, expected_tsdf, expected_weight));
00215   }
00216 }
00217 
00218 TEST_F(RangeDataInserterTest2DTSDF, InsertPointQuadraticWeight) {
00219   options_.set_update_weight_range_exponent(2);
00220   range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00221   InsertPoint();
00222   const float truncation_distance =
00223       static_cast<float>(options_.truncation_distance());
00224   for (float y = 1.5; y < 6.; ++y) {
00225     // Cell intersects with ray.
00226     float x = -0.5f;
00227     Eigen::Array2i cell_index =
00228         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00229     float expected_tsdf =
00230         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00231     float expected_weight = 1.f / std::pow(4.f, 2);
00232     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00233                 EqualCellProperties(true, expected_tsdf, expected_weight));
00234   }
00235 }
00236 
00237 TEST_F(RangeDataInserterTest2DTSDF,
00238        InsertSmallAnglePointWithoutNormalProjection) {
00239   auto range_data = sensor::RangeData();
00240   range_data.returns.push_back({Eigen::Vector3f{-0.5f, 3.5f, 0.f}});
00241   range_data.returns.push_back({Eigen::Vector3f{5.5f, 3.5f, 0.f}});
00242   range_data.returns.push_back({Eigen::Vector3f{10.5f, 3.5f, 0.f}});
00243   range_data.origin.x() = -0.5f;
00244   range_data.origin.y() = -0.5f;
00245   range_data_inserter_->Insert(range_data, &tsdf_);
00246   tsdf_.FinishUpdate();
00247   float x = 4.5f;
00248   float y = 2.5f;
00249   Eigen::Array2i cell_index =
00250       tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00251   Eigen::Vector2f ray =
00252       Eigen::Vector2f(-0.5f, -0.5f) - Eigen::Vector2f(5.5f, 3.5f);
00253   float ray_length = ray.norm();
00254   Eigen::Vector2f origin_to_cell =
00255       Eigen::Vector2f(x, y) - Eigen::Vector2f(-0.5f, -0.5f);
00256   float distance_origin_to_cell = origin_to_cell.norm();
00257   float expected_tsdf = ray_length - distance_origin_to_cell;
00258   float expected_weight = 1.f;
00259   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00260               EqualCellProperties(true, expected_tsdf, expected_weight));
00261 }
00262 
00263 TEST_F(RangeDataInserterTest2DTSDF, InsertSmallAnglePointWitNormalProjection) {
00264   options_.set_project_sdf_distance_to_scan_normal(true);
00265   range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00266   auto range_data = sensor::RangeData();
00267   range_data.returns.push_back({Eigen::Vector3f{-0.5f, 3.5f, 0.f}});
00268   range_data.returns.push_back({Eigen::Vector3f{5.5f, 3.5f, 0.f}});
00269   range_data.origin.x() = -0.5f;
00270   range_data.origin.y() = -0.5f;
00271   range_data_inserter_->Insert(range_data, &tsdf_);
00272   tsdf_.FinishUpdate();
00273   float x = 4.5f;
00274   float y = 2.5f;
00275   Eigen::Array2i cell_index =
00276       tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00277   float expected_tsdf = 1.f;
00278   float expected_weight = 1.f;
00279   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00280               EqualCellProperties(true, expected_tsdf, expected_weight));
00281   x = 6.5f;
00282   y = 4.5f;
00283   cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00284   expected_tsdf = -1.f;
00285   expected_weight = 1.f;
00286   EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00287               EqualCellProperties(true, expected_tsdf, expected_weight));
00288 }
00289 
00290 TEST_F(RangeDataInserterTest2DTSDF,
00291        InsertPointsWithAngleScanNormalToRayWeight) {
00292   float bandwidth = 10.f;
00293   options_.set_update_weight_angle_scan_normal_to_ray_kernel_bandwidth(
00294       bandwidth);
00295   range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00296   auto range_data = sensor::RangeData();
00297   range_data.returns.push_back({Eigen::Vector3f{-0.5f, 3.5f, 0.f}});
00298   range_data.returns.push_back({Eigen::Vector3f{5.5f, 3.5f, 0.f}});
00299   range_data.origin.x() = -0.5f;
00300   range_data.origin.y() = -0.5f;
00301   range_data_inserter_->Insert(range_data, &tsdf_);
00302   tsdf_.FinishUpdate();
00303   float x = -0.5f;
00304   float y = 3.5f;
00305   // Ray is perpendicular to surface.
00306   Eigen::Array2i cell_index =
00307       tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00308   float expected_weight = 1.f / (std::sqrt(2 * M_PI) * bandwidth);
00309   EXPECT_NEAR(expected_weight, tsdf_.GetWeight(cell_index), 1e-3);
00310   x = 6.5f;
00311   y = 4.5f;
00312   cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00313   EXPECT_NEAR(expected_weight, tsdf_.GetWeight(cell_index), 1e-3);
00314   // Ray is inclined relative to surface.
00315   cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00316   float angle = std::atan(7.f / 5.f);
00317   expected_weight = 1.f / (std::sqrt(2 * M_PI) * bandwidth) *
00318                     std::exp(angle * angle / (2 * std::pow(bandwidth, 2)));
00319   EXPECT_NEAR(expected_weight, tsdf_.GetWeight(cell_index), 1e-3);
00320   x = 6.5f;
00321   y = 4.5f;
00322   cell_index = tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00323   EXPECT_NEAR(expected_weight, tsdf_.GetWeight(cell_index), 1e-3);
00324 }
00325 
00326 TEST_F(RangeDataInserterTest2DTSDF, InsertPointsWithDistanceCellToHit) {
00327   float bandwidth = 10.f;
00328   options_.set_update_weight_distance_cell_to_hit_kernel_bandwidth(bandwidth);
00329   range_data_inserter_ = absl::make_unique<TSDFRangeDataInserter2D>(options_);
00330   InsertPoint();
00331   const float truncation_distance =
00332       static_cast<float>(options_.truncation_distance());
00333   for (float y = 1.5; y < 6.; ++y) {
00334     float x = -0.5f;
00335     Eigen::Array2i cell_index =
00336         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y));
00337     float expected_tsdf =
00338         std::max(std::min(3.5f - y, truncation_distance), -truncation_distance);
00339     float expected_weight =
00340         1.f / (std::sqrt(2 * M_PI) * bandwidth) *
00341         std::exp(std::pow(expected_tsdf, 2) / (2 * std::pow(bandwidth, 2)));
00342     EXPECT_THAT(MockCellProperties(cell_index, tsdf_),
00343                 EqualCellProperties(true, expected_tsdf, expected_weight));
00344   }
00345 }
00346 
00347 }  // namespace
00348 }  // namespace mapping
00349 }  // namespace cartographer


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