Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00227
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 }
00239 }