submap_2d.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/2d/submap_2d.h"
00018 
00019 #include <cinttypes>
00020 #include <cmath>
00021 #include <cstdlib>
00022 #include <fstream>
00023 #include <limits>
00024 
00025 #include "Eigen/Geometry"
00026 #include "absl/memory/memory.h"
00027 #include "cartographer/common/port.h"
00028 #include "cartographer/mapping/2d/probability_grid_range_data_inserter_2d.h"
00029 #include "cartographer/mapping/2d/tsdf_range_data_inserter_2d.h"
00030 #include "cartographer/mapping/range_data_inserter_interface.h"
00031 #include "glog/logging.h"
00032 
00033 namespace cartographer {
00034 namespace mapping {
00035 
00036 proto::SubmapsOptions2D CreateSubmapsOptions2D(
00037     common::LuaParameterDictionary* const parameter_dictionary) {
00038   proto::SubmapsOptions2D options;
00039   options.set_num_range_data(
00040       parameter_dictionary->GetNonNegativeInt("num_range_data"));
00041   *options.mutable_grid_options_2d() = CreateGridOptions2D(
00042       parameter_dictionary->GetDictionary("grid_options_2d").get());
00043   *options.mutable_range_data_inserter_options() =
00044       CreateRangeDataInserterOptions(
00045           parameter_dictionary->GetDictionary("range_data_inserter").get());
00046 
00047   bool valid_range_data_inserter_grid_combination = false;
00048   const proto::GridOptions2D_GridType& grid_type =
00049       options.grid_options_2d().grid_type();
00050   const proto::RangeDataInserterOptions_RangeDataInserterType&
00051       range_data_inserter_type =
00052           options.range_data_inserter_options().range_data_inserter_type();
00053   if (grid_type == proto::GridOptions2D::PROBABILITY_GRID &&
00054       range_data_inserter_type ==
00055           proto::RangeDataInserterOptions::PROBABILITY_GRID_INSERTER_2D) {
00056     valid_range_data_inserter_grid_combination = true;
00057   }
00058   if (grid_type == proto::GridOptions2D::TSDF &&
00059       range_data_inserter_type ==
00060           proto::RangeDataInserterOptions::TSDF_INSERTER_2D) {
00061     valid_range_data_inserter_grid_combination = true;
00062   }
00063   CHECK(valid_range_data_inserter_grid_combination)
00064       << "Invalid combination grid_type " << grid_type
00065       << " with range_data_inserter_type " << range_data_inserter_type;
00066   CHECK_GT(options.num_range_data(), 0);
00067   return options;
00068 }
00069 
00070 Submap2D::Submap2D(const Eigen::Vector2f& origin, std::unique_ptr<Grid2D> grid,
00071                    ValueConversionTables* conversion_tables)
00072     : Submap(transform::Rigid3d::Translation(
00073           Eigen::Vector3d(origin.x(), origin.y(), 0.))),
00074       conversion_tables_(conversion_tables) {
00075   grid_ = std::move(grid);
00076 }
00077 
00078 Submap2D::Submap2D(const proto::Submap2D& proto,
00079                    ValueConversionTables* conversion_tables)
00080     : Submap(transform::ToRigid3(proto.local_pose())),
00081       conversion_tables_(conversion_tables) {
00082   if (proto.has_grid()) {
00083     if (proto.grid().has_probability_grid_2d()) {
00084       grid_ =
00085           absl::make_unique<ProbabilityGrid>(proto.grid(), conversion_tables_);
00086     } else if (proto.grid().has_tsdf_2d()) {
00087       grid_ = absl::make_unique<TSDF2D>(proto.grid(), conversion_tables_);
00088     } else {
00089       LOG(FATAL) << "proto::Submap2D has grid with unknown type.";
00090     }
00091   }
00092   set_num_range_data(proto.num_range_data());
00093   set_insertion_finished(proto.finished());
00094 }
00095 
00096 proto::Submap Submap2D::ToProto(const bool include_grid_data) const {
00097   proto::Submap proto;
00098   auto* const submap_2d = proto.mutable_submap_2d();
00099   *submap_2d->mutable_local_pose() = transform::ToProto(local_pose());
00100   submap_2d->set_num_range_data(num_range_data());
00101   submap_2d->set_finished(insertion_finished());
00102   if (include_grid_data) {
00103     CHECK(grid_);
00104     *submap_2d->mutable_grid() = grid_->ToProto();
00105   }
00106   return proto;
00107 }
00108 
00109 void Submap2D::UpdateFromProto(const proto::Submap& proto) {
00110   CHECK(proto.has_submap_2d());
00111   const auto& submap_2d = proto.submap_2d();
00112   set_num_range_data(submap_2d.num_range_data());
00113   set_insertion_finished(submap_2d.finished());
00114   if (proto.submap_2d().has_grid()) {
00115     if (proto.submap_2d().grid().has_probability_grid_2d()) {
00116       grid_ = absl::make_unique<ProbabilityGrid>(proto.submap_2d().grid(),
00117                                                  conversion_tables_);
00118     } else if (proto.submap_2d().grid().has_tsdf_2d()) {
00119       grid_ = absl::make_unique<TSDF2D>(proto.submap_2d().grid(),
00120                                         conversion_tables_);
00121     } else {
00122       LOG(FATAL) << "proto::Submap2D has grid with unknown type.";
00123     }
00124   }
00125 }
00126 
00127 void Submap2D::ToResponseProto(
00128     const transform::Rigid3d&,
00129     proto::SubmapQuery::Response* const response) const {
00130   if (!grid_) return;
00131   response->set_submap_version(num_range_data());
00132   proto::SubmapQuery::Response::SubmapTexture* const texture =
00133       response->add_textures();
00134   grid()->DrawToSubmapTexture(texture, local_pose());
00135 }
00136 
00137 void Submap2D::InsertRangeData(
00138     const sensor::RangeData& range_data,
00139     const RangeDataInserterInterface* range_data_inserter) {
00140   CHECK(grid_);
00141   CHECK(!insertion_finished());
00142   range_data_inserter->Insert(range_data, grid_.get());
00143   set_num_range_data(num_range_data() + 1);
00144 }
00145 
00146 void Submap2D::Finish() {
00147   CHECK(grid_);
00148   CHECK(!insertion_finished());
00149   grid_ = grid_->ComputeCroppedGrid();
00150   set_insertion_finished(true);
00151 }
00152 
00153 ActiveSubmaps2D::ActiveSubmaps2D(const proto::SubmapsOptions2D& options)
00154     : options_(options), range_data_inserter_(CreateRangeDataInserter()) {}
00155 
00156 std::vector<std::shared_ptr<const Submap2D>> ActiveSubmaps2D::submaps() const {
00157   return std::vector<std::shared_ptr<const Submap2D>>(submaps_.begin(),
00158                                                       submaps_.end());
00159 }
00160 
00161 std::vector<std::shared_ptr<const Submap2D>> ActiveSubmaps2D::InsertRangeData(
00162     const sensor::RangeData& range_data) {
00163   if (submaps_.empty() ||
00164       submaps_.back()->num_range_data() == options_.num_range_data()) {
00165     AddSubmap(range_data.origin.head<2>());
00166   }
00167   for (auto& submap : submaps_) {
00168     submap->InsertRangeData(range_data, range_data_inserter_.get());
00169   }
00170   if (submaps_.front()->num_range_data() == 2 * options_.num_range_data()) {
00171     submaps_.front()->Finish();
00172   }
00173   return submaps();
00174 }
00175 
00176 std::unique_ptr<RangeDataInserterInterface>
00177 ActiveSubmaps2D::CreateRangeDataInserter() {
00178   switch (options_.range_data_inserter_options().range_data_inserter_type()) {
00179     case proto::RangeDataInserterOptions::PROBABILITY_GRID_INSERTER_2D:
00180       return absl::make_unique<ProbabilityGridRangeDataInserter2D>(
00181           options_.range_data_inserter_options()
00182               .probability_grid_range_data_inserter_options_2d());
00183     case proto::RangeDataInserterOptions::TSDF_INSERTER_2D:
00184       return absl::make_unique<TSDFRangeDataInserter2D>(
00185           options_.range_data_inserter_options()
00186               .tsdf_range_data_inserter_options_2d());
00187     default:
00188       LOG(FATAL) << "Unknown RangeDataInserterType.";
00189   }
00190 }
00191 
00192 std::unique_ptr<GridInterface> ActiveSubmaps2D::CreateGrid(
00193     const Eigen::Vector2f& origin) {
00194   constexpr int kInitialSubmapSize = 100;
00195   float resolution = options_.grid_options_2d().resolution();
00196   switch (options_.grid_options_2d().grid_type()) {
00197     case proto::GridOptions2D::PROBABILITY_GRID:
00198       return absl::make_unique<ProbabilityGrid>(
00199           MapLimits(resolution,
00200                     origin.cast<double>() + 0.5 * kInitialSubmapSize *
00201                                                 resolution *
00202                                                 Eigen::Vector2d::Ones(),
00203                     CellLimits(kInitialSubmapSize, kInitialSubmapSize)),
00204           &conversion_tables_);
00205     case proto::GridOptions2D::TSDF:
00206       return absl::make_unique<TSDF2D>(
00207           MapLimits(resolution,
00208                     origin.cast<double>() + 0.5 * kInitialSubmapSize *
00209                                                 resolution *
00210                                                 Eigen::Vector2d::Ones(),
00211                     CellLimits(kInitialSubmapSize, kInitialSubmapSize)),
00212           options_.range_data_inserter_options()
00213               .tsdf_range_data_inserter_options_2d()
00214               .truncation_distance(),
00215           options_.range_data_inserter_options()
00216               .tsdf_range_data_inserter_options_2d()
00217               .maximum_weight(),
00218           &conversion_tables_);
00219     default:
00220       LOG(FATAL) << "Unknown GridType.";
00221   }
00222 }
00223 
00224 void ActiveSubmaps2D::AddSubmap(const Eigen::Vector2f& origin) {
00225   if (submaps_.size() >= 2) {
00226     // This will crop the finished Submap before inserting a new Submap to
00227     // reduce peak memory usage a bit.
00228     CHECK(submaps_.front()->insertion_finished());
00229     submaps_.erase(submaps_.begin());
00230   }
00231   submaps_.push_back(absl::make_unique<Submap2D>(
00232       origin,
00233       std::unique_ptr<Grid2D>(
00234           static_cast<Grid2D*>(CreateGrid(origin).release())),
00235       &conversion_tables_));
00236 }
00237 
00238 }  // namespace mapping
00239 }  // namespace cartographer


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