GridMap.cpp
Go to the documentation of this file.
1 /*
2  * GridMap.cpp
3  *
4  * Created on: Jul 14, 2014
5  * Author: Péter Fankhauser
6  * Institute: ETH Zurich, ANYbotics
7  */
8 
10 
15 
16 #include <Eigen/Dense>
17 
18 #include <math.h>
19 #include <algorithm>
20 #include <cassert>
21 #include <iostream>
22 #include <stdexcept>
23 
24 using namespace std;
25 using namespace grid_map;
26 
27 namespace grid_map {
28 
29 GridMap::GridMap(const std::vector<std::string>& layers) {
30  position_.setZero();
31  length_.setZero();
32  resolution_ = 0.0;
33  size_.setZero();
34  startIndex_.setZero();
35  timestamp_ = 0;
36  layers_ = layers;
37 
38  for (auto& layer : layers_) {
39  data_.insert(std::pair<std::string, Matrix>(layer, Matrix()));
40  }
41 }
42 
43 GridMap::GridMap() : GridMap(std::vector<std::string>()) {}
44 
45 void GridMap::setGeometry(const Length& length, const double resolution, const Position& position) {
46  assert(length(0) > 0.0);
47  assert(length(1) > 0.0);
48  assert(resolution > 0.0);
49 
50  Size size;
51  size(0) = static_cast<int>(round(length(0) / resolution)); // There is no round() function in Eigen.
52  size(1) = static_cast<int>(round(length(1) / resolution));
53  resize(size);
54  clearAll();
55 
56  resolution_ = resolution;
57  length_ = (size_.cast<double>() * resolution_).matrix();
58  position_ = position;
59  startIndex_.setZero();
60 
61  return;
62 }
63 
64 void GridMap::setGeometry(const SubmapGeometry& geometry) {
65  setGeometry(geometry.getLength(), geometry.getResolution(), geometry.getPosition());
66 }
67 
68 void GridMap::setBasicLayers(const std::vector<std::string>& basicLayers) {
69  basicLayers_ = basicLayers;
70 }
71 
72 const std::vector<std::string>& GridMap::getBasicLayers() const {
73  return basicLayers_;
74 }
75 
77  return basicLayers_.size() > 0;
78 }
79 
80 bool GridMap::hasSameLayers(const GridMap& other) const {
81  for (const auto& layer : layers_) {
82  if (!other.exists(layer)) {
83  return false;
84  }
85  }
86  return true;
87 }
88 
89 void GridMap::add(const std::string& layer, const double value) {
90  add(layer, Matrix::Constant(size_(0), size_(1), value));
91 }
92 
93 void GridMap::add(const std::string& layer, const Matrix& data) {
94  assert(size_(0) == data.rows());
95  assert(size_(1) == data.cols());
96 
97  if (exists(layer)) {
98  // Type exists already, overwrite its data.
99  data_.at(layer) = data;
100  } else {
101  // Type does not exist yet, add type and data.
102  data_.insert(std::pair<std::string, Matrix>(layer, data));
103  layers_.push_back(layer);
104  }
105 }
106 
107 bool GridMap::exists(const std::string& layer) const {
108  return !(data_.find(layer) == data_.end());
109 }
110 
111 const Matrix& GridMap::get(const std::string& layer) const {
112  try {
113  return data_.at(layer);
114  } catch (const std::out_of_range& exception) {
115  throw std::out_of_range("GridMap::get(...) : No map layer '" + layer + "' available.");
116  }
117 }
118 
119 Matrix& GridMap::get(const std::string& layer) {
120  try {
121  return data_.at(layer);
122  } catch (const std::out_of_range& exception) {
123  throw std::out_of_range("GridMap::get(...) : No map layer of type '" + layer + "' available.");
124  }
125 }
126 
127 const Matrix& GridMap::operator[](const std::string& layer) const {
128  return get(layer);
129 }
130 
131 Matrix& GridMap::operator[](const std::string& layer) {
132  return get(layer);
133 }
134 
135 bool GridMap::erase(const std::string& layer) {
136  const auto dataIterator = data_.find(layer);
137  if (dataIterator == data_.end()) {
138  return false;
139  }
140  data_.erase(dataIterator);
141 
142  const auto layerIterator = std::find(layers_.begin(), layers_.end(), layer);
143  if (layerIterator == layers_.end()) {
144  return false;
145  }
146  layers_.erase(layerIterator);
147 
148  const auto basicLayerIterator = std::find(basicLayers_.begin(), basicLayers_.end(), layer);
149  if (basicLayerIterator != basicLayers_.end()) {
150  basicLayers_.erase(basicLayerIterator);
151  }
152 
153  return true;
154 }
155 
156 const std::vector<std::string>& GridMap::getLayers() const {
157  return layers_;
158 }
159 
160 float& GridMap::atPosition(const std::string& layer, const Position& position) {
161  Index index;
162  if (getIndex(position, index)) {
163  return at(layer, index);
164  }
165  throw std::out_of_range("GridMap::atPosition(...) : Position is out of range.");
166 }
167 
168 float GridMap::atPosition(const std::string& layer, const Position& position, InterpolationMethods interpolationMethod) const {
169 
170  bool skipNextSwitchCase = false;
171  switch (interpolationMethod) {
173  float value;
174  if (atPositionBicubicConvolutionInterpolated(layer, position, value)) {
175  return value;
176  } else {
177  interpolationMethod = InterpolationMethods::INTER_LINEAR;
178  skipNextSwitchCase = true;
179  }
180  [[fallthrough]];
181  }
183  if (!skipNextSwitchCase) {
184  float value;
185  if (atPositionBicubicInterpolated(layer, position, value)) {
186  return value;
187  } else {
188  interpolationMethod = InterpolationMethods::INTER_LINEAR;
189  }
190  }
191  [[fallthrough]];
192  }
194  float value;
195  if (atPositionLinearInterpolated(layer, position, value))
196  return value;
197  else {
198  interpolationMethod = InterpolationMethods::INTER_NEAREST;
199  }
200  [[fallthrough]];
201  }
203  Index index;
204  if (getIndex(position, index)) {
205  return at(layer, index);
206  } else
207  throw std::out_of_range("GridMap::atPosition(...) : Position is out of range.");
208  break;
209  }
210  default:
211  throw std::runtime_error(
212  "GridMap::atPosition(...) : Specified "
213  "interpolation method not implemented.");
214  }
215 }
216 
217 float& GridMap::at(const std::string& layer, const Index& index) {
218  try {
219  return data_.at(layer)(index(0), index(1));
220  } catch (const std::out_of_range& exception) {
221  throw std::out_of_range("GridMap::at(...) : No map layer '" + layer + "' available.");
222  }
223 }
224 
225 float GridMap::at(const std::string& layer, const Index& index) const {
226  try {
227  return data_.at(layer)(index(0), index(1));
228  } catch (const std::out_of_range& exception) {
229  throw std::out_of_range("GridMap::at(...) : No map layer '" + layer + "' available.");
230  }
231 }
232 
233 bool GridMap::getIndex(const Position& position, Index& index) const {
234  return getIndexFromPosition(index, position, length_, position_, resolution_, size_, startIndex_);
235 }
236 
237 bool GridMap::getPosition(const Index& index, Position& position) const {
238  return getPositionFromIndex(position, index, length_, position_, resolution_, size_, startIndex_);
239 }
240 
241 bool GridMap::isInside(const Position& position) const {
242  return checkIfPositionWithinMap(position, length_, position_);
243 }
244 
245 bool GridMap::isValid(DataType value) const {
246  return isfinite(value);
247 }
248 
249 bool GridMap::isValid(const Index& index) const {
250  return isValid(index, basicLayers_);
251 }
252 
253 bool GridMap::isValid(const Index& index, const std::string& layer) const {
254  return isValid(at(layer, index));
255 }
256 
257 bool GridMap::isValid(const Index& index, const std::vector<std::string>& layers) const {
258  if (layers.empty()) {
259  return false;
260  }
261  for (const auto& layer : layers) {
262  if (!isValid(index, layer)) {
263  return false;
264  }
265  }
266  return true;
267 }
268 
269 bool GridMap::getPosition3(const std::string& layer, const Index& index, Position3& position) const {
270  const auto value = at(layer, index);
271  if (!isValid(value)) {
272  return false;
273  }
274  Position position2d;
275  getPosition(index, position2d);
276  position.head(2) = position2d;
277  position.z() = value;
278  return true;
279 }
280 
281 bool GridMap::getVector(const std::string& layerPrefix, const Index& index, Eigen::Vector3d& vector) const {
282  Eigen::Vector3d temp{at(layerPrefix + "x", index), at(layerPrefix + "y", index), at(layerPrefix + "z", index)};
283  if (!isValid(temp[0]) || !isValid(temp[1]) || !isValid(temp[2])) {
284  return false;
285  } else {
286  vector = temp;
287  return true;
288  }
289 }
290 
291 GridMap GridMap::getSubmap(const Position& position, const Length& length, bool& isSuccess) const {
292  Index index;
293  return getSubmap(position, length, index, isSuccess);
294 }
295 
296 GridMap GridMap::getSubmap(const Position& position, const Length& length, Index& /*indexInSubmap*/, bool& isSuccess) const {
297  // Submap the generate.
298  GridMap submap(layers_);
300  submap.setTimestamp(timestamp_);
301  submap.setFrameId(frameId_);
302 
303  // Get submap geometric information.
304  SubmapGeometry submapInformation(*this, position, length, isSuccess);
305  if (!isSuccess) {
306  return GridMap(layers_);
307  }
308  submap.setGeometry(submapInformation);
309  submap.startIndex_.setZero(); // Because of the way we copy the data below.
310 
311  // Copy data.
312  std::vector<BufferRegion> bufferRegions;
313 
314  if (!getBufferRegionsForSubmap(bufferRegions, submapInformation.getStartIndex(), submap.getSize(), size_, startIndex_)) {
315  cout << "Cannot access submap of this size." << endl;
316  isSuccess = false;
317  return GridMap(layers_);
318  }
319 
320  for (const auto& data : data_) {
321  for (const auto& bufferRegion : bufferRegions) {
322  Index index = bufferRegion.getStartIndex();
323  Size size = bufferRegion.getSize();
324 
325  if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::TopLeft) {
326  submap.data_[data.first].topLeftCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
327  } else if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::TopRight) {
328  submap.data_[data.first].topRightCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
329  } else if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::BottomLeft) {
330  submap.data_[data.first].bottomLeftCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
331  } else if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::BottomRight) {
332  submap.data_[data.first].bottomRightCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
333  }
334  }
335  }
336 
337  isSuccess = true;
338  return submap;
339 }
340 
341 GridMap GridMap::getTransformedMap(const Eigen::Isometry3d& transform, const std::string& heightLayerName, const std::string& newFrameId,
342  const double sampleRatio) const {
343  // Check if height layer is valid.
344  if (!exists(heightLayerName)) {
345  throw std::out_of_range("GridMap::getTransformedMap(...) : No map layer '" + heightLayerName + "' available.");
346  }
347 
348  // Initialization.
349  std::vector<Position3> positionSamples;
350  Position3 center;
351  Index newIndex;
352 
353  const double sampleLength = resolution_ * sampleRatio;
354 
355  // Find edges in new coordinate frame.
356  const double halfLengthX = length_.x() * 0.5;
357  const double halfLengthY = length_.y() * 0.5;
358  const Position3 topLeftCorner(position_.x() + halfLengthX, position_.y() + halfLengthY, 0.0);
359  const Position3 topRightCorner(position_.x() + halfLengthX, position_.y() - halfLengthY, 0.0);
360  const Position3 bottomLeftCorner(position_.x() - halfLengthX, position_.y() + halfLengthY, 0.0);
361  const Position3 bottomRightCorner(position_.x() - halfLengthX, position_.y() - halfLengthY, 0.0);
362 
363  std::vector<Position3> newEdges;
364  newEdges.reserve(4);
365  newEdges.push_back(transform * topLeftCorner);
366  newEdges.push_back(transform * topRightCorner);
367  newEdges.push_back(transform * bottomLeftCorner);
368  newEdges.push_back(transform * bottomRightCorner);
369 
370  // Find new grid center.
371  Position3 newCenter = Position3::Zero();
372  for (const auto& newEdge : newEdges) {
373  newCenter += newEdge;
374  }
375  newCenter *= 0.25;
376 
377  // Find new grid length.
378  Length maxLengthFromCenter = Length(0.0, 0.0);
379  for (const auto& newEdge : newEdges) {
380  Position3 positionCenterToEdge = newEdge - newCenter;
381  maxLengthFromCenter.x() = std::fmax(std::fabs(positionCenterToEdge.x()), maxLengthFromCenter.x());
382  maxLengthFromCenter.y() = std::fmax(std::fabs(positionCenterToEdge.y()), maxLengthFromCenter.y());
383  }
384  Length newLength = 2.0 * maxLengthFromCenter;
385 
386  // Create new grid map.
387  GridMap newMap(layers_);
389  newMap.setTimestamp(timestamp_);
390  newMap.setFrameId(newFrameId);
391  newMap.setGeometry(newLength, resolution_, Position(newCenter.x(), newCenter.y()));
392  newMap.startIndex_.setZero();
393 
394  for (GridMapIterator iterator(*this); !iterator.isPastEnd(); ++iterator) {
395  // Get position at current index.
396  if (!getPosition3(heightLayerName, *iterator, center)) {
397  continue;
398  }
399 
400  // Sample four points around the center cell.
401  positionSamples.clear();
402 
403  if (sampleRatio > 0.0) {
404  positionSamples.reserve(5);
405  positionSamples.push_back(center);
406  positionSamples.push_back(Position3(center.x() - sampleLength, center.y(), center.z()));
407  positionSamples.push_back(Position3(center.x() + sampleLength, center.y(), center.z()));
408  positionSamples.push_back(Position3(center.x(), center.y() - sampleLength, center.z()));
409  positionSamples.push_back(Position3(center.x(), center.y() + sampleLength, center.z()));
410  } else {
411  positionSamples.push_back(center);
412  }
413 
414  // Transform the sampled points and register to the new map.
415  for (const auto& position : positionSamples) {
416  const Position3 transformedPosition = transform * position;
417 
418  // Get new index.
419  if (!newMap.getIndex(Position(transformedPosition.x(), transformedPosition.y()), newIndex)) {
420  continue;
421  }
422 
423  // Check if we have already assigned a value (preferably larger height
424  // values -> inpainting).
425  const auto newExistingValue = newMap.at(heightLayerName, newIndex);
426  if (!std::isnan(newExistingValue) && newExistingValue > transformedPosition.z()) {
427  continue;
428  }
429 
430  // Copy the layers.
431  for (const auto& layer : layers_) {
432  const auto currentValueInOldGrid = at(layer, *iterator);
433  auto& newValue = newMap.at(layer, newIndex);
434  if (layer == heightLayerName) {
435  newValue = transformedPosition.z();
436  } // adjust height
437  else {
438  newValue = currentValueInOldGrid;
439  } // re-assign
440  }
441  }
442  }
443 
444  return newMap;
445 }
446 
447 void GridMap::setPosition(const Position& position) {
448  position_ = position;
449 }
450 
451 bool GridMap::move(const Position& position, std::vector<BufferRegion>& newRegions) {
452  Index indexShift;
453  Position positionShift = position - position_;
454  getIndexShiftFromPositionShift(indexShift, positionShift, resolution_);
455  Position alignedPositionShift;
456  getPositionShiftFromIndexShift(alignedPositionShift, indexShift, resolution_);
457 
458  // Delete fields that fall out of map (and become empty cells).
459  for (int i = 0; i < indexShift.size(); i++) {
460  if (indexShift(i) != 0) {
461  if (abs(indexShift(i)) >= getSize()(i)) {
462  // Entire map is dropped.
463  clearAll();
464  newRegions.push_back(BufferRegion(Index(0, 0), getSize(), BufferRegion::Quadrant::Undefined));
465  } else {
466  // Drop cells out of map.
467  int sign = (indexShift(i) > 0 ? 1 : -1);
468  int startIndex = startIndex_(i) - (sign < 0 ? 1 : 0);
469  int endIndex = startIndex - sign + indexShift(i);
470  int nCells = abs(indexShift(i));
471  int index = (sign > 0 ? startIndex : endIndex);
472  wrapIndexToRange(index, getSize()(i));
473 
474  if (index + nCells <= getSize()(i)) {
475  // One region to drop.
476  if (i == 0) {
477  clearRows(index, nCells);
478  newRegions.push_back(BufferRegion(Index(index, 0), Size(nCells, getSize()(1)), BufferRegion::Quadrant::Undefined));
479  } else if (i == 1) {
480  clearCols(index, nCells);
481  newRegions.push_back(BufferRegion(Index(0, index), Size(getSize()(0), nCells), BufferRegion::Quadrant::Undefined));
482  }
483  } else {
484  // Two regions to drop.
485  int firstIndex = index;
486  int firstNCells = getSize()(i) - firstIndex;
487  if (i == 0) {
488  clearRows(firstIndex, firstNCells);
489  newRegions.push_back(BufferRegion(Index(firstIndex, 0), Size(firstNCells, getSize()(1)), BufferRegion::Quadrant::Undefined));
490  } else if (i == 1) {
491  clearCols(firstIndex, firstNCells);
492  newRegions.push_back(BufferRegion(Index(0, firstIndex), Size(getSize()(0), firstNCells), BufferRegion::Quadrant::Undefined));
493  }
494 
495  int secondIndex = 0;
496  int secondNCells = nCells - firstNCells;
497  if (i == 0) {
498  clearRows(secondIndex, secondNCells);
499  newRegions.push_back(BufferRegion(Index(secondIndex, 0), Size(secondNCells, getSize()(1)), BufferRegion::Quadrant::Undefined));
500  } else if (i == 1) {
501  clearCols(secondIndex, secondNCells);
502  newRegions.push_back(BufferRegion(Index(0, secondIndex), Size(getSize()(0), secondNCells), BufferRegion::Quadrant::Undefined));
503  }
504  }
505  }
506  }
507  }
508 
509  // Update information.
510  startIndex_ += indexShift;
512  position_ += alignedPositionShift;
513 
514  // Check if map has been moved at all.
515  return (indexShift.any() != 0);
516 }
517 
518 bool GridMap::move(const Position& position) {
519  std::vector<BufferRegion> newRegions;
520  return move(position, newRegions);
521 }
522 
523 bool GridMap::addDataFrom(const GridMap& other, bool extendMap, bool overwriteData, bool copyAllLayers, std::vector<std::string> layers) {
524  // Set the layers to copy.
525  if (copyAllLayers) layers = other.getLayers();
526 
527  // Resize map.
528  if (extendMap) extendToInclude(other);
529 
530  // Check if all layers to copy exist and add missing layers.
531  for (const auto& layer : layers) {
532  if (std::find(layers_.begin(), layers_.end(), layer) == layers_.end()) {
533  add(layer);
534  }
535  }
536  // Copy data.
537  for (GridMapIterator iterator(*this); !iterator.isPastEnd(); ++iterator) {
538  if (isValid(*iterator) && !overwriteData) continue;
539  Position position;
540  getPosition(*iterator, position);
541  Index index;
542  if (!other.isInside(position)) continue;
543  other.getIndex(position, index);
544  for (const auto& layer : layers) {
545  if (!other.isValid(index, layer)) continue;
546  at(layer, *iterator) = other.at(layer, index);
547  }
548  }
549 
550  return true;
551 }
552 
553 bool GridMap::extendToInclude(const GridMap& other) {
554  // Get dimension of maps.
555  Position topLeftCorner(position_.x() + length_.x() / 2.0, position_.y() + length_.y() / 2.0);
556  Position bottomRightCorner(position_.x() - length_.x() / 2.0, position_.y() - length_.y() / 2.0);
557  Position topLeftCornerOther(other.getPosition().x() + other.getLength().x() / 2.0, other.getPosition().y() + other.getLength().y() / 2.0);
558  Position bottomRightCornerOther(other.getPosition().x() - other.getLength().x() / 2.0,
559  other.getPosition().y() - other.getLength().y() / 2.0);
560  // Check if map needs to be resized.
561  bool resizeMap = false;
562  Position extendedMapPosition = position_;
563  Length extendedMapLength = length_;
564  if (topLeftCornerOther.x() > topLeftCorner.x()) {
565  extendedMapPosition.x() += (topLeftCornerOther.x() - topLeftCorner.x()) / 2.0;
566  extendedMapLength.x() += topLeftCornerOther.x() - topLeftCorner.x();
567  resizeMap = true;
568  }
569  if (topLeftCornerOther.y() > topLeftCorner.y()) {
570  extendedMapPosition.y() += (topLeftCornerOther.y() - topLeftCorner.y()) / 2.0;
571  extendedMapLength.y() += topLeftCornerOther.y() - topLeftCorner.y();
572  resizeMap = true;
573  }
574  if (bottomRightCornerOther.x() < bottomRightCorner.x()) {
575  extendedMapPosition.x() -= (bottomRightCorner.x() - bottomRightCornerOther.x()) / 2.0;
576  extendedMapLength.x() += bottomRightCorner.x() - bottomRightCornerOther.x();
577  resizeMap = true;
578  }
579  if (bottomRightCornerOther.y() < bottomRightCorner.y()) {
580  extendedMapPosition.y() -= (bottomRightCorner.y() - bottomRightCornerOther.y()) / 2.0;
581  extendedMapLength.y() += bottomRightCorner.y() - bottomRightCornerOther.y();
582  resizeMap = true;
583  }
584  // Resize map and copy data to new map.
585  if (resizeMap) {
586  GridMap mapCopy = *this;
587  setGeometry(extendedMapLength, resolution_, extendedMapPosition);
588  // Align new map with old one.
589  Vector shift = position_ - mapCopy.getPosition();
590  shift.x() = std::fmod(shift.x(), resolution_);
591  shift.y() = std::fmod(shift.y(), resolution_);
592  if (std::abs(shift.x()) < resolution_ / 2.0) {
593  position_.x() -= shift.x();
594  } else {
595  position_.x() += resolution_ - shift.x();
596  }
597  if (size_.x() % 2 != mapCopy.getSize().x() % 2) {
598  position_.x() += -std::copysign(resolution_ / 2.0, shift.x());
599  }
600  if (std::abs(shift.y()) < resolution_ / 2.0) {
601  position_.y() -= shift.y();
602  } else {
603  position_.y() += resolution_ - shift.y();
604  }
605  if (size_.y() % 2 != mapCopy.getSize().y() % 2) {
606  position_.y() += -std::copysign(resolution_ / 2.0, shift.y());
607  }
608  // Copy data.
609  for (GridMapIterator iterator(*this); !iterator.isPastEnd(); ++iterator) {
610  if (isValid(*iterator)) continue;
611  Position position;
612  getPosition(*iterator, position);
613  Index index;
614  if (!mapCopy.isInside(position)) continue;
615  mapCopy.getIndex(position, index);
616  for (const auto& layer : layers_) {
617  at(layer, *iterator) = mapCopy.at(layer, index);
618  }
619  }
620  }
621  return true;
622 }
623 
624 void GridMap::setTimestamp(const Time timestamp) {
625  timestamp_ = timestamp;
626 }
627 
629  return timestamp_;
630 }
631 
633  timestamp_ = 0.0;
634 }
635 
636 void GridMap::setFrameId(const std::string& frameId) {
637  frameId_ = frameId;
638 }
639 
640 const std::string& GridMap::getFrameId() const {
641  return frameId_;
642 }
643 
644 const Length& GridMap::getLength() const {
645  return length_;
646 }
647 
649  return position_;
650 }
651 
652 double GridMap::getResolution() const {
653  return resolution_;
654 }
655 
656 const Size& GridMap::getSize() const {
657  return size_;
658 }
659 
660 void GridMap::setStartIndex(const Index& startIndex) {
661  startIndex_ = startIndex;
662 }
663 
665  return startIndex_;
666 }
667 
669  return (startIndex_ == 0).all();
670 }
671 
673  if (isDefaultStartIndex()) return;
674 
675  std::vector<BufferRegion> bufferRegions;
676  if (!getBufferRegionsForSubmap(bufferRegions, startIndex_, size_, size_, startIndex_)) {
677  throw std::out_of_range("Cannot access submap of this size.");
678  }
679 
680  for (auto& data : data_) {
681  auto tempData(data.second);
682  for (const auto& bufferRegion : bufferRegions) {
683  Index index = bufferRegion.getStartIndex();
684  Size size = bufferRegion.getSize();
685 
686  if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::TopLeft) {
687  tempData.topLeftCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
688  } else if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::TopRight) {
689  tempData.topRightCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
690  } else if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::BottomLeft) {
691  tempData.bottomLeftCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
692  } else if (bufferRegion.getQuadrant() == BufferRegion::Quadrant::BottomRight) {
693  tempData.bottomRightCorner(size(0), size(1)) = data.second.block(index(0), index(1), size(0), size(1));
694  }
695  }
696  data.second = tempData;
697  }
698 
699  startIndex_.setZero();
700 }
701 
703  if (getSize().x() < 1 || getSize().y() < 1) {
704  return position_;
705  }
706 
707  if (isInside(position)) {
708  return position;
709  }
710 
711  Position positionInMap = position;
712 
713  // Find edges.
714  const double halfLengthX = length_.x() * 0.5;
715  const double halfLengthY = length_.y() * 0.5;
716  const Position3 topLeftCorner(position_.x() + halfLengthX, position_.y() + halfLengthY, 0.0);
717  const Position3 topRightCorner(position_.x() + halfLengthX, position_.y() - halfLengthY, 0.0);
718  const Position3 bottomLeftCorner(position_.x() - halfLengthX, position_.y() + halfLengthY, 0.0);
719  const Position3 bottomRightCorner(position_.x() - halfLengthX, position_.y() - halfLengthY, 0.0);
720 
721  // Find constraints.
722  const double maxX = topRightCorner.x();
723  const double minX = bottomRightCorner.x();
724  const double maxY = bottomLeftCorner.y();
725  const double minY = bottomRightCorner.y();
726 
727  // Clip to box constraints and correct for indexing precision.
728  // Points on the border can lead to invalid indices because the cells represent half open intervals, i.e. [...).
729  positionInMap.x() = std::fmin(positionInMap.x(), maxX - std::numeric_limits<double>::epsilon());
730  positionInMap.y() = std::fmin(positionInMap.y(), maxY - std::numeric_limits<double>::epsilon());
731 
732  positionInMap.x() = std::fmax(positionInMap.x(), minX + std::numeric_limits<double>::epsilon());
733  positionInMap.y() = std::fmax(positionInMap.y(), minY + std::numeric_limits<double>::epsilon());
734 
735  return positionInMap;
736 }
737 
738 void GridMap::clear(const std::string& layer) {
739  try {
740  data_.at(layer).setConstant(NAN);
741  } catch (const std::out_of_range& exception) {
742  throw std::out_of_range("GridMap::clear(...) : No map layer '" + layer + "' available.");
743  }
744 }
745 
747  for (auto& layer : basicLayers_) {
748  clear(layer);
749  }
750 }
751 
753  for (auto& data : data_) {
754  data.second.setConstant(NAN);
755  }
756 }
757 
758 void GridMap::clearRows(unsigned int index, unsigned int nRows) {
759  for (auto& layer : layers_) {
760  data_.at(layer).block(index, 0, nRows, getSize()(1)).setConstant(NAN);
761  }
762 }
763 
764 void GridMap::clearCols(unsigned int index, unsigned int nCols) {
765  for (auto& layer : layers_) {
766  data_.at(layer).block(0, index, getSize()(0), nCols).setConstant(NAN);
767  }
768 }
769 
770 bool GridMap::atPositionLinearInterpolated(const std::string& layer, const Position& position, float& value) const {
771  Position point;
772  Index indices[4];
773  bool idxTempDir;
774  size_t idxShift[4];
775 
776  getIndex(position, indices[0]);
777  getPosition(indices[0], point);
778 
779  if (position.x() >= point.x()) {
780  indices[1] = indices[0] + Index(-1, 0); // Second point is above first point.
781  idxTempDir = true;
782  } else {
783  indices[1] = indices[0] + Index(+1, 0);
784  idxTempDir = false;
785  }
786  if (position.y() >= point.y()) {
787  indices[2] = indices[0] + Index(0, -1); // Third point is right of first point.
788  if (idxTempDir) {
789  idxShift[0] = 0;
790  idxShift[1] = 1;
791  idxShift[2] = 2;
792  idxShift[3] = 3;
793  } else {
794  idxShift[0] = 1;
795  idxShift[1] = 0;
796  idxShift[2] = 3;
797  idxShift[3] = 2;
798  }
799 
800  } else {
801  indices[2] = indices[0] + Index(0, +1);
802  if (idxTempDir) {
803  idxShift[0] = 2;
804  idxShift[1] = 3;
805  idxShift[2] = 0;
806  idxShift[3] = 1;
807  } else {
808  idxShift[0] = 3;
809  idxShift[1] = 2;
810  idxShift[2] = 1;
811  idxShift[3] = 0;
812  }
813  }
814  indices[3].x() = indices[1].x();
815  indices[3].y() = indices[2].y();
816 
817  const Size& mapSize = getSize();
818  const size_t bufferSize = mapSize(0) * mapSize(1);
819  const size_t startIndexLin = getLinearIndexFromIndex(startIndex_, mapSize);
820  const size_t endIndexLin = startIndexLin + bufferSize;
821  const auto& layerMat = operator[](layer);
822  float f[4];
823 
824  for (size_t i = 0; i < 4; ++i) {
825  const size_t indexLin = getLinearIndexFromIndex(indices[idxShift[i]], mapSize);
826  if ((indexLin < startIndexLin) || (indexLin > endIndexLin)) return false;
827  f[i] = layerMat(indexLin);
828  }
829 
830  getPosition(indices[idxShift[0]], point);
831  const Position positionRed = (position - point) / resolution_;
832  const Position positionRedFlip = Position(1., 1.) - positionRed;
833 
834  value = f[0] * positionRedFlip.x() * positionRedFlip.y() + f[1] * positionRed.x() * positionRedFlip.y() +
835  f[2] * positionRedFlip.x() * positionRed.y() + f[3] * positionRed.x() * positionRed.y();
836  return true;
837 }
838 
839 void GridMap::resize(const Index& size) {
840  size_ = size;
841  for (auto& data : data_) {
842  data.second.resize(size_(0), size_(1));
843  }
844 }
845 
846 
847 bool GridMap::atPositionBicubicConvolutionInterpolated(const std::string& layer, const Position& position,
848  float& value) const
849 {
850  double interpolatedValue = 0.0;
851  if (!bicubic_conv::evaluateBicubicConvolutionInterpolation(*this, layer, position, &interpolatedValue)) {
852  return false;
853  }
854 
855  if (!std::isfinite(interpolatedValue)) {
856  return false;
857  }
858  value = interpolatedValue;
859 
860  return true;
861 }
862 
863 bool GridMap::atPositionBicubicInterpolated(const std::string& layer, const Position& position,
864  float& value) const
865 {
866  double interpolatedValue = 0.0;
867  if (!bicubic::evaluateBicubicInterpolation(*this, layer, position, &interpolatedValue)) {
868  return false;
869  }
870 
871  if (!std::isfinite(interpolatedValue)) {
872  return false;
873  }
874  value = interpolatedValue;
875 
876  return true;
877 
878 }
879 
880 
881 } // namespace grid_map
const Length & getLength() const
Definition: GridMap.cpp:644
double getResolution() const
Eigen::Array2i Index
Definition: TypeDefs.hpp:22
void setGeometry(const Length &length, const double resolution, const Position &position=Position::Zero())
Definition: GridMap.cpp:45
Time getTimestamp() const
Definition: GridMap.cpp:628
bool atPositionBicubicConvolutionInterpolated(const std::string &layer, const Position &position, float &value) const
Definition: GridMap.cpp:847
Size size_
Size of the buffer (rows and cols of the data structure).
Definition: GridMap.hpp:581
void setPosition(const Position &position)
Definition: GridMap.cpp:447
float & atPosition(const std::string &layer, const Position &position)
Definition: GridMap.cpp:160
Eigen::Vector2d Vector
Definition: TypeDefs.hpp:19
const Index & getStartIndex() const
Definition: GridMap.cpp:664
void clear(const std::string &layer)
Definition: GridMap.cpp:738
bool getPosition(const Index &index, Position &position) const
Definition: GridMap.cpp:237
void wrapIndexToRange(Index &index, const Size &bufferSize)
bool getBufferRegionsForSubmap(std::vector< BufferRegion > &submapBufferRegions, const Index &submapIndex, const Size &submapBufferSize, const Size &bufferSize, const Index &bufferStartIndex=Index::Zero())
void setBasicLayers(const std::vector< std::string > &basicLayers)
Definition: GridMap.cpp:68
const Position & getPosition() const
Definition: GridMap.cpp:648
Eigen::Array2i Size
Definition: TypeDefs.hpp:23
const std::string & getFrameId() const
Definition: GridMap.cpp:640
double resolution_
Map resolution in xy plane [m/cell].
Definition: GridMap.hpp:575
GridMap getTransformedMap(const Eigen::Isometry3d &transform, const std::string &heightLayerName, const std::string &newFrameId, const double sampleRatio=0.0) const
Definition: GridMap.cpp:341
std::vector< std::string > basicLayers_
Definition: GridMap.hpp:569
std::unordered_map< std::string, Matrix > data_
Grid map data stored as layers of matrices.
Definition: GridMap.hpp:561
Position getClosestPositionInMap(const Position &position) const
Definition: GridMap.cpp:702
Eigen::MatrixXf Matrix
Definition: TypeDefs.hpp:16
grid_map::DataType DataType
Definition: GridMap.hpp:44
bool getVector(const std::string &layerPrefix, const Index &index, Eigen::Vector3d &vector) const
Definition: GridMap.cpp:281
std::string frameId_
Frame id of the grid map.
Definition: GridMap.hpp:555
const Matrix & operator[](const std::string &layer) const
Definition: GridMap.cpp:127
grid_map::Matrix Matrix
Definition: GridMap.hpp:45
bool atPositionBicubicInterpolated(const std::string &layer, const Position &position, float &value) const
Definition: GridMap.cpp:863
bool move(const Position &position, std::vector< BufferRegion > &newRegions)
Definition: GridMap.cpp:451
void convertToDefaultStartIndex()
Definition: GridMap.cpp:672
InterpolationMethods
Definition: TypeDefs.hpp:39
bool getIndexFromPosition(Index &index, const Position &position, const Length &mapLength, const Position &mapPosition, const double &resolution, const Size &bufferSize, const Index &bufferStartIndex=Index::Zero())
bool addDataFrom(const GridMap &other, bool extendMap, bool overwriteData, bool copyAllLayers, std::vector< std::string > layers=std::vector< std::string >())
Definition: GridMap.cpp:523
GridMap getSubmap(const Position &position, const Length &length, bool &isSuccess) const
Definition: GridMap.cpp:291
bool isValid(const Index &index) const
Definition: GridMap.cpp:249
const Length & getLength() const
Eigen::Vector3d Position3
Definition: TypeDefs.hpp:20
bool exists(const std::string &layer) const
Definition: GridMap.cpp:107
bool extendToInclude(const GridMap &other)
Definition: GridMap.cpp:553
bool checkIfPositionWithinMap(const Position &position, const Length &mapLength, const Position &mapPosition)
double getResolution() const
Definition: GridMap.cpp:652
const std::vector< std::string > & getLayers() const
Definition: GridMap.cpp:156
bool getPositionShiftFromIndexShift(Vector &positionShift, const Index &indexShift, const double &resolution)
std::vector< std::string > layers_
Names of the data layers.
Definition: GridMap.hpp:564
bool isInside(const Position &position) const
Definition: GridMap.cpp:241
Eigen::Vector2d Position
Definition: TypeDefs.hpp:18
bool isDefaultStartIndex() const
Definition: GridMap.cpp:668
const Matrix & get(const std::string &layer) const
Definition: GridMap.cpp:111
void resetTimestamp()
Definition: GridMap.cpp:632
const Position & getPosition() const
void setStartIndex(const Index &startIndex)
Definition: GridMap.cpp:660
uint64_t Time
Definition: TypeDefs.hpp:25
Position position_
Map position in the grid map frame [m].
Definition: GridMap.hpp:578
float & at(const std::string &layer, const Index &index)
Definition: GridMap.cpp:217
bool hasSameLayers(const grid_map::GridMap &other) const
Definition: GridMap.cpp:80
Time timestamp_
Timestamp of the grid map (nanoseconds).
Definition: GridMap.hpp:558
bool hasBasicLayers() const
Definition: GridMap.cpp:76
Index startIndex_
Circular buffer start indeces.
Definition: GridMap.hpp:584
void add(const std::string &layer, const double value=NAN)
Definition: GridMap.cpp:89
size_t getLinearIndexFromIndex(const Index &index, const Size &bufferSize, const bool rowMajor=false)
bool evaluateBicubicConvolutionInterpolation(const GridMap &gridMap, const std::string &layer, const Position &queriedPosition, double *interpolatedValue)
bool atPositionLinearInterpolated(const std::string &layer, const Position &position, float &value) const
Definition: GridMap.cpp:770
bool getPositionFromIndex(Position &position, const Index &index, const Length &mapLength, const Position &mapPosition, const double &resolution, const Size &bufferSize, const Index &bufferStartIndex=Index::Zero())
void clearCols(unsigned int index, unsigned int nCols)
Definition: GridMap.cpp:764
void clearRows(unsigned int index, unsigned int nRows)
Definition: GridMap.cpp:758
Length length_
Side length of the map in x- and y-direction [m].
Definition: GridMap.hpp:572
bool getIndexShiftFromPositionShift(Index &indexShift, const Vector &positionShift, const double &resolution)
void setFrameId(const std::string &frameId)
Definition: GridMap.cpp:636
const Index & getStartIndex() const
void setTimestamp(const Time timestamp)
Definition: GridMap.cpp:624
bool erase(const std::string &layer)
Definition: GridMap.cpp:135
bool getIndex(const Position &position, Index &index) const
Definition: GridMap.cpp:233
bool getPosition3(const std::string &layer, const Index &index, Position3 &position) const
Definition: GridMap.cpp:269
bool evaluateBicubicInterpolation(const GridMap &gridMap, const std::string &layer, const Position &queriedPosition, double *interpolatedValue)
Eigen::Array2d Length
Definition: TypeDefs.hpp:24
void resize(const Index &bufferSize)
Definition: GridMap.cpp:839
const std::vector< std::string > & getBasicLayers() const
Definition: GridMap.cpp:72
const Size & getSize() const
Definition: GridMap.cpp:656


grid_map_core
Author(s): Péter Fankhauser
autogenerated on Tue Jun 1 2021 02:13:27