9 #include <Eigen/Geometry>
11 #include <IceUtil/Time.h>
13 #include <VirtualRobot/BoundingBox.h>
14 #include <VirtualRobot/CollisionDetection/CollisionChecker.h>
15 #include <VirtualRobot/CollisionDetection/CollisionModel.h>
16 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
17 #include <VirtualRobot/XML/ObjectIO.h>
26 #include "range/v3/view/zip.hpp"
35 const std::optional<Mask>& mask,
39 sceneBounds(sceneBounds),
40 parameters(parameters),
41 global_T_costmap(origin)
47 Costmap::validateSizes()
const
61 Eigen::Vector2f posLocal;
74 return global_T_costmap * costmap_P_pos;
85 if (
index.x() >= grid.rows() ||
index.y() >= grid.cols())
101 const auto localPosition = global_T_costmap.inverse() * globalPosition;
103 const float vX = (localPosition.x() - parameters.
cellSize / 2 - sceneBounds.
min.x()) /
105 const float vY = (localPosition.y() - parameters.
cellSize / 2 - sceneBounds.
min.y()) /
108 const int iX = std::round(vX - 0.01);
109 const int iY = std::round(vY - 0.01);
111 const int iXSan = std::clamp<int>(iX, 0, grid.rows() - 1);
112 const int iYSan = std::clamp<int>(iY, 0, grid.cols() - 1);
136 if (mask.has_value())
139 <<
"At least one element has to be valid. Here, all elements are masked out!";
149 for (
int r = 0; r < grid.rows(); r++)
151 for (
int c = 0;
c < grid.cols();
c++)
153 if (mask.has_value())
155 if (not mask.value()(r,
c))
160 const float currentVal = grid(r,
c);
161 if (currentVal < minVal)
171 return {.value = minVal, .index = {row, col}, .position =
toPositionGlobal({row, col})};
181 if (mask.has_value())
184 <<
"At least one element has to be valid. Here, all elements are masked out!";
187 Grid newGrid(grid.rows(), grid.cols());
188 const double max = grid.maxCoeff();
189 newGrid.setConstant(
max);
190 for (
int r = 0; r < grid.rows(); r++)
192 for (
int c = 0;
c < grid.cols();
c++)
194 if (mask.has_value())
196 if (not mask.value()(r,
c))
201 Eigen::MatrixXf valueMatrix(
filter.matrix.rows(),
filter.matrix.cols());
202 const int radius_r = (
filter.matrix.rows() - 1) / 2;
203 const int radius_c = (
filter.matrix.cols() - 1) / 2;
204 valueMatrix.setConstant(
max);
205 for (
int i = -radius_r; i <= radius_r; i++)
207 for (
int j = -radius_c; j <= radius_c; j++)
209 const int ri = r + i;
210 const int cj =
c + j;
211 if (ri > 0 and ri < grid.rows() and cj > 0 and cj < grid.cols() and mask.value()(ri, cj))
213 valueMatrix(radius_r + i, radius_c + j) = grid(ri, cj);
217 const double sum =
filter.matrix.sum();
220 const float filteredValue = (valueMatrix.cwiseProduct(
filter.matrix)).sum() / sum;
221 newGrid(r,
c) =
filter.useMinimum ?
std::min(grid(r,
c), filteredValue) : filteredValue;
245 return grid(
v.index.x(),
v.index.y()) == 0.F;
255 other.validateSizes();
257 const auto startIdx =
toVertex(other.sceneBounds.
min);
263 const int rows =
std::min(other.grid.rows(), grid.rows() - startIdx.index.x());
264 const int cols =
std::min(other.grid.cols(), grid.cols() - startIdx.index.y());
266 ARMARX_VERBOSE <<
"Adding other grid to region (" << startIdx.index.x() <<
", "
267 << startIdx.index.y() <<
"), "
268 <<
" (" << startIdx.index.x() + rows <<
", " << startIdx.index.y() + cols
274 grid.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array() +=
275 weight * other.grid.block(0, 0, rows, cols).array();
277 if (not mask.has_value())
279 mask =
Mask(grid.rows(), grid.cols());
284 << mask->array().cast<
float>().sum() / mask->size();
286 Mask otherMask(grid.rows(), grid.cols());
288 otherMask.block(startIdx.index.x(), startIdx.index.y(), rows, cols).setOnes();
290 if (other.mask.has_value())
296 otherMask.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array() *=
297 other.mask->block(0, 0, rows, cols).array();
301 mask->array() *= otherMask.array();
304 << mask->array().cast<
float>().sum() / mask->size();
308 grid.array() *= mask->cast<
float>().array();
319 other.validateSizes();
321 const auto startIdx =
toVertex(other.sceneBounds.
min);
327 const int rows =
std::min(other.grid.rows(), grid.rows() - startIdx.index.x());
328 const int cols =
std::min(other.grid.cols(), grid.cols() - startIdx.index.y());
330 ARMARX_VERBOSE <<
"Adding other grid to region (" << startIdx.index.x() <<
", "
331 << startIdx.index.y() <<
"), "
332 <<
" (" << startIdx.index.x() + rows <<
", " << startIdx.index.y() + cols
341 grid.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array() =
342 other.grid.block(0, 0, rows, cols)
345 grid.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array());
349 grid.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array() =
350 other.grid.block(0, 0, rows, cols)
353 grid.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array());
358 if (not mask.has_value())
360 mask =
Mask(grid.rows(), grid.cols());
364 Mask otherMask(grid.rows(), grid.cols());
366 otherMask.block(startIdx.index.x(), startIdx.index.y(), rows, cols).setOnes();
368 if (other.mask.has_value())
374 otherMask.block(startIdx.index.x(), startIdx.index.y(), rows, cols).array() *=
375 other.mask->block(0, 0, rows, cols).array();
379 mask->array() *= otherMask.array();
382 << mask->array().cast<
float>().sum() / mask->size();
386 grid.array() *= mask->cast<
float>().array();
391 const std::optional<Costmap::Mask>&
397 std::optional<Costmap::Mask>&
426 const std::vector<float>& weights)
const
430 const std::vector<float> costmapWeights(weights.begin(), weights.end() - 1);
439 for (
int x = 0; x < mergedCostmap.
getGrid().rows(); x++)
441 for (
int y = 0; y < mergedCostmap.
getGrid().cols(); y++)
447 for (
const auto& costmap : costmaps)
450 mergedCostmap.mask.value()(x, y) &=
451 costmap.isValid(costmap.toVertex(position).index);
457 for (
const auto& [weight, costmap] :
458 ranges::views::zip(costmapWeights, costmaps))
460 const auto otherCostmapVal = costmap.value(position);
463 newVal += weight * otherCostmapVal.value();
466 newVal += weights.back() * mergedCostmap.grid(x, y);
467 mergedCostmap.grid(x, y) = newVal;
471 mergedCostmap.grid(x, y) = 0;
476 return mergedCostmap;
483 .
matrix = Eigen::MatrixXf::Zero(radius * 2 + 1, radius * 2 + 1)
485 for (
int i = -radius; i <= radius; i++) {
486 for (
int j = -radius; j <= radius; j++) {
487 gaussianFilter.matrix(radius + i, radius + j) =
488 std::exp(-0.5 * (std::pow(i / sigma, 2.0) +
489 std::pow(j / sigma, 2.0))) /
490 (2 *
M_PI * sigma * sigma);
493 return gaussianFilter;
499 if(not mask.has_value())
501 return grid.cols() * grid.rows();
504 return mask->array().cast<
int>().sum();