00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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
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
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
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
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
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
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
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
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
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 }
00348 }
00349 }