grid_2d.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 #include "cartographer/mapping/2d/grid_2d.h"
00017 
00018 namespace cartographer {
00019 namespace mapping {
00020 namespace {
00021 
00022 float MinCorrespondenceCostFromProto(const proto::Grid2D& proto) {
00023   if (proto.min_correspondence_cost() == 0.f &&
00024       proto.max_correspondence_cost() == 0.f) {
00025     LOG(WARNING) << "proto::Grid2D: min_correspondence_cost "
00026                     "is initialized with 0 indicating an older version of the "
00027                     "protobuf format. Loading default values.";
00028     return kMinCorrespondenceCost;
00029   } else {
00030     return proto.min_correspondence_cost();
00031   }
00032 }
00033 
00034 float MaxCorrespondenceCostFromProto(const proto::Grid2D& proto) {
00035   if (proto.min_correspondence_cost() == 0.f &&
00036       proto.max_correspondence_cost() == 0.f) {
00037     LOG(WARNING) << "proto::Grid2D: max_correspondence_cost "
00038                     "is initialized with 0 indicating an older version of the "
00039                     "protobuf format. Loading default values.";
00040     return kMaxCorrespondenceCost;
00041   } else {
00042     return proto.max_correspondence_cost();
00043   }
00044 }
00045 }  // namespace
00046 
00047 proto::GridOptions2D CreateGridOptions2D(
00048     common::LuaParameterDictionary* const parameter_dictionary) {
00049   proto::GridOptions2D options;
00050   const std::string grid_type_string =
00051       parameter_dictionary->GetString("grid_type");
00052   proto::GridOptions2D_GridType grid_type;
00053   CHECK(proto::GridOptions2D_GridType_Parse(grid_type_string, &grid_type))
00054       << "Unknown GridOptions2D_GridType kind: " << grid_type_string;
00055   options.set_grid_type(grid_type);
00056   options.set_resolution(parameter_dictionary->GetDouble("resolution"));
00057   return options;
00058 }
00059 
00060 Grid2D::Grid2D(const MapLimits& limits, float min_correspondence_cost,
00061                float max_correspondence_cost,
00062                ValueConversionTables* conversion_tables)
00063     : limits_(limits),
00064       correspondence_cost_cells_(
00065           limits_.cell_limits().num_x_cells * limits_.cell_limits().num_y_cells,
00066           kUnknownCorrespondenceValue),
00067       min_correspondence_cost_(min_correspondence_cost),
00068       max_correspondence_cost_(max_correspondence_cost),
00069       value_to_correspondence_cost_table_(conversion_tables->GetConversionTable(
00070           max_correspondence_cost, min_correspondence_cost,
00071           max_correspondence_cost)) {
00072   CHECK_LT(min_correspondence_cost_, max_correspondence_cost_);
00073 }
00074 
00075 Grid2D::Grid2D(const proto::Grid2D& proto,
00076                ValueConversionTables* conversion_tables)
00077     : limits_(proto.limits()),
00078       correspondence_cost_cells_(),
00079       min_correspondence_cost_(MinCorrespondenceCostFromProto(proto)),
00080       max_correspondence_cost_(MaxCorrespondenceCostFromProto(proto)),
00081       value_to_correspondence_cost_table_(conversion_tables->GetConversionTable(
00082           max_correspondence_cost_, min_correspondence_cost_,
00083           max_correspondence_cost_)) {
00084   CHECK_LT(min_correspondence_cost_, max_correspondence_cost_);
00085   if (proto.has_known_cells_box()) {
00086     const auto& box = proto.known_cells_box();
00087     known_cells_box_ =
00088         Eigen::AlignedBox2i(Eigen::Vector2i(box.min_x(), box.min_y()),
00089                             Eigen::Vector2i(box.max_x(), box.max_y()));
00090   }
00091   correspondence_cost_cells_.reserve(proto.cells_size());
00092   for (const auto& cell : proto.cells()) {
00093     CHECK_LE(cell, std::numeric_limits<uint16>::max());
00094     correspondence_cost_cells_.push_back(cell);
00095   }
00096 }
00097 
00098 // Finishes the update sequence.
00099 void Grid2D::FinishUpdate() {
00100   while (!update_indices_.empty()) {
00101     DCHECK_GE(correspondence_cost_cells_[update_indices_.back()],
00102               kUpdateMarker);
00103     correspondence_cost_cells_[update_indices_.back()] -= kUpdateMarker;
00104     update_indices_.pop_back();
00105   }
00106 }
00107 
00108 // Fills in 'offset' and 'limits' to define a subregion of that contains all
00109 // known cells.
00110 void Grid2D::ComputeCroppedLimits(Eigen::Array2i* const offset,
00111                                   CellLimits* const limits) const {
00112   if (known_cells_box_.isEmpty()) {
00113     *offset = Eigen::Array2i::Zero();
00114     *limits = CellLimits(1, 1);
00115     return;
00116   }
00117   *offset = known_cells_box_.min().array();
00118   *limits = CellLimits(known_cells_box_.sizes().x() + 1,
00119                        known_cells_box_.sizes().y() + 1);
00120 }
00121 
00122 // Grows the map as necessary to include 'point'. This changes the meaning of
00123 // these coordinates going forward. This method must be called immediately
00124 // after 'FinishUpdate', before any calls to 'ApplyLookupTable'.
00125 void Grid2D::GrowLimits(const Eigen::Vector2f& point) {
00126   GrowLimits(point, {mutable_correspondence_cost_cells()},
00127              {kUnknownCorrespondenceValue});
00128 }
00129 
00130 void Grid2D::GrowLimits(const Eigen::Vector2f& point,
00131                         const std::vector<std::vector<uint16>*>& grids,
00132                         const std::vector<uint16>& grids_unknown_cell_values) {
00133   CHECK(update_indices_.empty());
00134   while (!limits_.Contains(limits_.GetCellIndex(point))) {
00135     const int x_offset = limits_.cell_limits().num_x_cells / 2;
00136     const int y_offset = limits_.cell_limits().num_y_cells / 2;
00137     const MapLimits new_limits(
00138         limits_.resolution(),
00139         limits_.max() +
00140             limits_.resolution() * Eigen::Vector2d(y_offset, x_offset),
00141         CellLimits(2 * limits_.cell_limits().num_x_cells,
00142                    2 * limits_.cell_limits().num_y_cells));
00143     const int stride = new_limits.cell_limits().num_x_cells;
00144     const int offset = x_offset + stride * y_offset;
00145     const int new_size = new_limits.cell_limits().num_x_cells *
00146                          new_limits.cell_limits().num_y_cells;
00147 
00148     for (size_t grid_index = 0; grid_index < grids.size(); ++grid_index) {
00149       std::vector<uint16> new_cells(new_size,
00150                                     grids_unknown_cell_values[grid_index]);
00151       for (int i = 0; i < limits_.cell_limits().num_y_cells; ++i) {
00152         for (int j = 0; j < limits_.cell_limits().num_x_cells; ++j) {
00153           new_cells[offset + j + i * stride] =
00154               (*grids[grid_index])[j + i * limits_.cell_limits().num_x_cells];
00155         }
00156       }
00157       *grids[grid_index] = new_cells;
00158     }
00159     limits_ = new_limits;
00160     if (!known_cells_box_.isEmpty()) {
00161       known_cells_box_.translate(Eigen::Vector2i(x_offset, y_offset));
00162     }
00163   }
00164 }
00165 
00166 proto::Grid2D Grid2D::ToProto() const {
00167   proto::Grid2D result;
00168   *result.mutable_limits() = mapping::ToProto(limits_);
00169   *result.mutable_cells() = {correspondence_cost_cells_.begin(),
00170                              correspondence_cost_cells_.end()};
00171   CHECK(update_indices().empty()) << "Serializing a grid during an update is "
00172                                      "not supported. Finish the update first.";
00173   if (!known_cells_box().isEmpty()) {
00174     auto* const box = result.mutable_known_cells_box();
00175     box->set_max_x(known_cells_box().max().x());
00176     box->set_max_y(known_cells_box().max().y());
00177     box->set_min_x(known_cells_box().min().x());
00178     box->set_min_y(known_cells_box().min().y());
00179   }
00180   result.set_min_correspondence_cost(min_correspondence_cost_);
00181   result.set_max_correspondence_cost(max_correspondence_cost_);
00182   return result;
00183 }
00184 
00185 }  // namespace mapping
00186 }  // namespace cartographer


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