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