inflation.cpp
Go to the documentation of this file.
1 
6 #include "filters.hpp"
7 
8 #include <ros/ros.h>
9 
12 
13 namespace mitre_fast_layered_map
14 {
16 {
17 }
18 
20 {
21 }
22 
24 {
25  if (!Inflation::getParam(std::string("layer"), layer_))
26  {
27  ROS_ERROR("Unable to find nonground_layer parameter.");
28  return false;
29  }
30 
31  if (!Inflation::getParam(std::string("inflation_side_len_m"), inflationSideLen_m_))
32  {
33  ROS_ERROR("Unable to find inflation radius parameter.");
34  return false;
35  }
36 
37  ROS_INFO("Running inflation filter with layer: %s, and inflation radius: %f", layer_.c_str(), inflationSideLen_m_);
38 
39  return true;
40 }
41 
43 {
44  if (!_mapIn.exists(layer_))
45  {
46  ROS_ERROR("Layer %s does not exist within the map.", layer_.c_str());
47  return false;
48  }
49 
50  _mapOut = _mapIn;
51 
52  grid_map::Matrix &inflateLayer = _mapOut[layer_];
53  // We will set inflation on the inflate layer then add it into the layer above at the end
54  grid_map::Matrix layer = _mapOut[layer_];
55 
56  int sideLen = _mapOut.getLength().x(); // We assume a square map
57  int cellSideLen = _mapOut.getSize()(0);
58  double resolution = _mapOut.getResolution();
59 
60  // Rim is the outermost ring of cells
61  double distToRim = sideLen / 2;
62 
63  grid_map::Position pos = _mapOut.getPosition();
64 
65  double posXMax = pos.x() + distToRim;
66  double posXMin = pos.x() - distToRim;
67  double posYMax = pos.y() + distToRim;
68  double posYMin = pos.y() - distToRim;
69 
70  // Cells to inflate to unless hitting edge of map
71  int numCellsForInflation = (int)floor(inflationSideLen_m_ / resolution);
72 
73  for (grid_map::GridMapIterator mapIt(_mapOut); !mapIt.isPastEnd(); ++mapIt)
74  {
75  const grid_map::Index index(*mapIt);
76 
77  // Use the original layer to find obstacles, they may have been wiped out on inflate layer
78  if (layer(index(0), index(1)) != 100)
79  {
80  continue;
81  }
82 
83  // We want to select a block of matrix cells for inflation
84  // to make it as fast as possible. We will calculate +x and +y to
85  // determine where the block will start, and then use -x and -y
86  // to calculate the size of the block
87 
88  grid_map::Position cellPos;
89  _mapOut.getPosition(index, cellPos);
90 
91  // Calculate cells from edge in +x direction
92  int xCells = (int)floor((posXMax - cellPos.x()) / resolution);
93  int yCells = (int)floor((posYMax - cellPos.y()) / resolution);
94 
95  //
96  // CALCULATE INFLATION BOX START CELL
97  //
98 
99  int rowStartIdx;
100  int colStartIdx;
101 
102  // If there are more cells than needed for inflation size
103  if (xCells > numCellsForInflation)
104  {
105  // Use inflation size, +x so subtract from current idx
106  rowStartIdx = index.x() - numCellsForInflation;
107  }
108  else
109  {
110  // Otherwise, use the max number of cells before hitting boundary
111  rowStartIdx = index.x() - xCells;
112  }
113 
114  // If there are more cells than needed for inflation size
115  if (yCells > numCellsForInflation)
116  {
117  // Use inflation size, +y so subtract from current idx
118  colStartIdx = index.y() - numCellsForInflation;
119  }
120  else
121  {
122  // Otherwise, use the max number of cells before hitting boundary
123  colStartIdx = index.y() - yCells;
124  }
125 
126  //
127  // CALCULATE HEIGHT AND WIDTH OF BOX
128  //
129 
130  int blockXSize;
131  int blockYSize;
132 
133  // Do the same for minimum
134  xCells = (int)floor((cellPos.x() - posXMin) / resolution);
135  yCells = (int)floor((cellPos.y() - posYMin) / resolution);
136 
137  if (xCells > numCellsForInflation)
138  {
139  // Calculate size of block in x direction
140  // index.x() - rowStartIdx gives num cells going up, num cells for inflation
141  // adds on for the number of cells going down, and +1 is to include the
142  // starting cell
143  blockXSize = (index.x() - rowStartIdx) + numCellsForInflation + 1;
144  }
145  else
146  {
147  blockXSize = (index.x() - rowStartIdx) + xCells + 1;
148  }
149 
150  if (yCells > numCellsForInflation)
151  {
152  blockYSize = (index.y() - colStartIdx) + numCellsForInflation + 1;
153  }
154  else
155  {
156  blockYSize = (index.y() - colStartIdx) + yCells + 1;
157  }
158 
159  // Two cases of wrapping.
160  // 1. Either start index of x or y is negative, which means that
161  // the obstacle is near enough to 0 in the matrix that inflation in the map needs
162  // to be placed in the higher rows of the matrix.
163  // 2. The start index + inflation wraps back over to 0.
164  // These are both essentially the same problem, so we should map one to the other.
165 
166  if (rowStartIdx < 0)
167  {
168  rowStartIdx = cellSideLen + rowStartIdx;
169  }
170 
171  if (colStartIdx < 0)
172  {
173  colStartIdx = cellSideLen + colStartIdx;
174  }
175 
176  /*
177  * Below is a potential worst case scenario, where we need to break up into 4 matrices.
178  * The numbers within the cells of the bottom matrix correspond to where the case gets taken
179  * care of.
180  *
181  * [2,3], [2,4], [2,0], [2,1], [2,2],
182  * [3,3], [3,4], [3,0], [3,1], [3,2],
183  * [4,3], [4,4], [4,0], [4,1], [4,2],
184  * [0,3], [0,4], [0,0], [0,1], [0,2],
185  * [1,3], [1,4], [1,0], [1,1], [1,2],
186  *
187  * [2], [2], [1], [1], [1],
188  * [2], [2], [1], [1], [1],
189  * [3], [3], [4], [4], [4],
190  * [3], [3], [4], [4], [4],
191  * [3], [3], [4], [4], [4],
192  */
193 
194  // If our block matrix is wrapping on both rows and columns
195  if (rowStartIdx + blockXSize > cellSideLen && colStartIdx + blockYSize > cellSideLen)
196  {
197  int rowsBeforeWrap = cellSideLen - rowStartIdx;
198  int rowsAfterWrap = blockXSize - rowsBeforeWrap;
199 
200  int colsBeforeWrap = cellSideLen - colStartIdx;
201  int colsAfterWrap = blockYSize - colsBeforeWrap;
202 
203  // Case 1: Need to wrap the rows back around
204  inflateLayer.block(rowStartIdx, 0, rowsBeforeWrap, colsAfterWrap).array() = 30;
205 
206  // Case 2: Get wrapped around columns
207  inflateLayer.block(rowStartIdx, colStartIdx, rowsBeforeWrap, colsBeforeWrap).array() = 30;
208 
209  // Case 3: Get positive wrapped around rows
210  inflateLayer.block(0, colStartIdx, rowsAfterWrap, colsBeforeWrap).array() = 30;
211 
212  // Case 4: Get regular row matrix
213  inflateLayer.block(0, 0, rowsAfterWrap, colsAfterWrap).array() = 30;
214  }
215  else if (rowStartIdx + blockXSize > cellSideLen)
216  {
217  int rowsBeforeWrap = cellSideLen - rowStartIdx;
218  int rowsAfterWrap = blockXSize - rowsBeforeWrap;
219 
220  // The top wrapped around matrix
221  inflateLayer.block(rowStartIdx, colStartIdx, rowsBeforeWrap, blockYSize).array() = 30;
222 
223  // Unwrapped bit
224  inflateLayer.block(0, colStartIdx, rowsAfterWrap, blockYSize).array() = 30;
225  }
226  else if (colStartIdx + blockYSize > cellSideLen)
227  {
228  int colsBeforeWrap = cellSideLen - colStartIdx;
229  int colsAfterWrap = blockYSize - colsBeforeWrap;
230 
231  // Wrapped around columns
232  inflateLayer.block(rowStartIdx, colStartIdx, blockXSize, colsBeforeWrap).array() = 30;
233 
234  // Unwrapped bit
235  inflateLayer.block(rowStartIdx, 0, blockXSize, colsAfterWrap).array() = 30;
236  }
237  else
238  {
239  // No wrapping required
240  inflateLayer.block(rowStartIdx, colStartIdx, blockXSize, blockYSize).array() = 30;
241  }
242  }
243 
244  // Replace any overwritten obstacles
245  for (grid_map::GridMapIterator it(_mapOut); !it.isPastEnd(); ++it)
246  {
247  const grid_map::Index index(*it);
248 
249  if (layer(index(0), index(1)) == 100)
250  {
251  inflateLayer(index(0), index(1)) = 100;
252  }
253  }
254 
255  return true;
256 }
257 
258 
259 } // namespace mitre_fast_layered_map
260 
const Length & getLength() const
Eigen::Array2i Index
PLUGINLIB_EXPORT_CLASS(mitre_fast_layered_map::Inflation, filters::FilterBase< grid_map::GridMap >)
bool getPosition(const Index &index, Position &position) const
Eigen::MatrixXf Matrix
double inflationSideLen_m_
Determines length of side of square to inflate around an obstacle.
Definition: filters.hpp:48
virtual bool update(const grid_map::GridMap &_mapIn, grid_map::GridMap &_mapOut)
Definition: inflation.cpp:42
bool getParam(const std::string &name, std::string &value)
bool exists(const std::string &layer) const
double getResolution() const
Eigen::Vector2d Position
#define ROS_INFO(...)
std::string layer_
Layer of grid map to perform outlier removal on.
Definition: filters.hpp:47
Filters that operate on a grid map instance.
#define ROS_ERROR(...)
const Size & getSize() const


mitre_fast_layered_map
Author(s):
autogenerated on Thu Mar 11 2021 03:06:49