30#include <opencv2/core/eigen.hpp>
31#include <opencv2/core/mat.hpp>
32#include <opencv2/core/types.hpp>
33#include <opencv2/imgproc.hpp>
35#include <VirtualRobot/BoundingBox.h>
36#include <VirtualRobot/CollisionDetection/CollisionModel.h>
37#include <VirtualRobot/Random.h>
38#include <VirtualRobot/Robot.h>
39#include <VirtualRobot/SceneObjectSet.h>
40#include <VirtualRobot/VirtualRobot.h>
41#include <VirtualRobot/Workspace/WorkspaceGrid.h>
54#include <range/v3/algorithm/for_each.hpp>
55#include <range/v3/view/zip.hpp>
63 const std::vector<VirtualRobot::RobotPtr>& articulatedObjects,
65 const std::vector<Room>&
rooms,
67 const bool restrictToRooms)
77 for (
const auto& room :
rooms)
79 for (
const auto& point : room.polygon)
81 bounds.
min.x() = std::min(point.x(), bounds.
min.x());
82 bounds.
min.y() = std::min(point.y(), bounds.
min.y());
83 bounds.
max.x() = std::max(point.x(), bounds.
max.x());
84 bounds.
max.y() = std::max(point.y(), bounds.
max.y());
96 ARMARX_CHECK((not obstacles->getCollisionModels().empty()) or
97 (not articulatedObjects.empty()));
99 const auto expandBounds = [&bounds](
const VirtualRobot::BoundingBox&& bb)
101 if (!bb.getMin().allFinite() || !bb.getMax().allFinite())
107 bounds.
min.x() = std::min(bb.getMin().x(), bounds.
min.x());
108 bounds.
min.y() = std::min(bb.getMin().y(), bounds.
min.y());
109 bounds.
max.x() = std::max(bb.getMax().x(), bounds.
max.x());
110 bounds.
max.y() = std::max(bb.getMax().y(), bounds.
max.y());
114 for (
const auto& colModel : obstacles->getCollisionModels())
116 expandBounds(colModel->getBoundingBox());
119 ARMARX_VERBOSE <<
"non-articulated objects: scene bounds: " << bounds.
min <<
" and "
123 for (
const auto& articulatedObject : articulatedObjects)
125 if (articulatedObject->getCollisionModels().empty())
127 ARMARX_WARNING <<
"The articulated object `" << articulatedObject->getType()
128 <<
"/" << articulatedObject->getName()
129 <<
"` does not provide any collision model!";
132 ARMARX_DEBUG <<
"Articulated object `" << articulatedObject->getType() <<
"/"
133 << articulatedObject->getName();
135 for (
const auto& colModel : articulatedObject->getCollisionModels())
137 expandBounds(colModel->getBoundingBox());
139 <<
VAROUT(colModel->getBoundingBox().getMax());
149 bounds.
min.x() -= margin;
150 bounds.
min.y() -= margin;
151 bounds.
max.x() += margin;
152 bounds.
max.y() += margin;
164 for (
const auto& point : points)
166 bounds.
min.x() = std::min(point.x(), bounds.
min.x());
167 bounds.
min.y() = std::min(point.y(), bounds.
min.y());
168 bounds.
max.x() = std::max(point.x(), bounds.
max.x());
169 bounds.
max.y() = std::max(point.y(), bounds.
max.y());
173 bounds.
min.x() -= margin;
174 bounds.
min.y() -= margin;
175 bounds.
max.x() += margin;
176 bounds.
max.y() += margin;
184 return {.min = Eigen::Vector2f{extends.minX, extends.minY},
185 .max = Eigen::Vector2f{extends.maxX, extends.maxY}};
189 merge(
const std::vector<SceneBounds>& sceneBounds)
193 const auto expandBounds = [&bounds](
const SceneBounds& sb)
195 bounds.
min.x() = std::min(bounds.
min.x(), sb.min.x());
196 bounds.
min.y() = std::min(bounds.
min.y(), sb.min.y());
198 bounds.
max.x() = std::max(bounds.
max.x(), sb.max.x());
199 bounds.
max.y() = std::max(bounds.
max.y(), sb.max.y());
204 ranges::for_each(sceneBounds, expandBounds);
210 toCostmap(
const VirtualRobot::WorkspaceGrid& workspaceGrid)
212 const Costmap::Grid grid(workspaceGrid.getCells().x, workspaceGrid.getCells().y);
216 .cellSize = workspaceGrid.getDiscretizeSize()};
218 return {grid, parameters, sceneBounds};
305 ranges::for_each(costmaps, assertSameSize);
318 const std::vector<float> weights(costmaps.size(), 1.F / costmaps.size());
323 costmaps.front().params());
334 ARMARX_CHECK(
false) <<
"This case should already be handled.";
347 ranges::for_each(costmaps,
348 [&mergedCostmap, &addMode](
const auto&
costmap)
351 return mergedCostmap;
355 mergeAligned(
const std::vector<Costmap>& costmaps,
const std::vector<float>& weights)
363 costmaps.front().params());
368 ranges::for_each(ranges::views::zip(costmaps, weights),
369 [&mergedCostmap](
const auto& p)
371 const auto& [
costmap, weight] = p;
375 return mergedCostmap;
381 const float scale =
costmap.params().cellSize / cellSize;
385 cv::eigen2cv(
costmap.getGrid(), src);
388 cv::resize(src, dst, cv::Size{0, 0}, scale, scale);
390 Eigen::MatrixXf scaledGrid;
391 cv::cv2eigen(dst, scaledGrid);
394 std::optional<Costmap::Mask> scaledMask;
395 if (
costmap.getMask().has_value())
402 constexpr int someInt = 100;
405 someInt *
costmap.getMask().value().cast<std::uint8_t>();
408 cv::eigen2cv(mask, maskMat);
411 cv::resize(maskMat, maskScaled, cv::Size{0, 0}, scale, scale);
417 Eigen::MatrixXi scaledMaskInt;
418 cv::cv2eigen(maskScaled, scaledMaskInt);
426 <<
costmap.getGrid().cols() <<
")";
427 ARMARX_VERBOSE <<
"Resized to (" << scaledGrid.rows() <<
", " << scaledGrid.cols() <<
")";
436 std::optional<core::Pose2D>
439 const auto sizeX =
costmap.getGrid().cols();
440 const auto sizeY =
costmap.getGrid().rows();
442 constexpr std::size_t maxIterations = 1000;
446 for (std::size_t iteration = 0; iteration < maxIterations; iteration++)
448 const float iX = VirtualRobot::RandomFloat() *
static_cast<float>(sizeX);
449 const float iY = VirtualRobot::RandomFloat() *
static_cast<float>(sizeY);
459 pose.translation() =
costmap.toPositionGlobal(idx);
468 invalidateOutsideRoomsImpl(
469 const std::vector<Room>&
rooms,
472 const float footprintRadius)
474 const std::size_t c_x = mask.rows();
475 const std::size_t c_y = mask.cols();
477 const auto isInsideRoom = [&
rooms, footprintRadius](
const Eigen::Vector2f& pos) ->
bool
479 return std::any_of(
rooms.begin(),
481 [&pos, footprintRadius](
const Room& room) ->
bool
482 { return room.isInside(pos, footprintRadius); });
485 for (
unsigned int x = 0;
x < c_x;
x++)
487 for (
unsigned int y = 0; y < c_y; y++)
492 if (not isInsideRoom(position))
503 const float footprintRadius)
506 const auto indexToGlobal = [&
costmap](
auto idx) {
return costmap.toPositionGlobal(idx); };
508 invalidateOutsideRoomsImpl(
509 rooms, indexToGlobal,
costmap.getMutableMask().value(), -1.F);
514 static_cast<int>(std::max(
515 1.F,
costmap.params().sceneBoundsMargin /
costmap.params().cellSize)));
518 if (footprintRadius > 0.F)
520 invalidateOutsideRoomsImpl(
521 rooms, indexToGlobal,
costmap.getMutableMask().value(), footprintRadius);
528 const float footprintRadius)
531 invalidateOutsideRoomsImpl(
534 costmap.getMutableMask().value(),
542 cv::eigen2cv(mask, cvMask);
544 cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
545 cv::dilate(cvMask, cvMask, kernel, cv::Point(-1, -1), numIterations);
548 cv::cv2eigen(cvMask, dst);
#define ARMARX_CHECK_NOT_EMPTY(c)
static Eigen::MatrixXf createUniformGrid(const SceneBounds &sceneBounds, const Costmap::Parameters ¶meters)
static Costmap WithSameDimsAs(const Costmap &other, const Grid &grid, const std::optional< Mask > &mask=std::nullopt)
Create a costmap with the same dimensions and parameters as the given one.
Eigen::Matrix< bool, Eigen::Dynamic, Eigen::Dynamic > Mask
bool add(const Costmap &other, float weight=1.0)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
This file is part of ArmarX.
This file is part of ArmarX.
Costmap::Mask dilateMask(const Costmap::Mask &mask, int numIterations)
Costmap toCostmap(const VirtualRobot::WorkspaceGrid &workspaceGrid)
SceneBounds merge(const std::vector< SceneBounds > &sceneBounds)
Costmap scaleCostmap(const Costmap &costmap, float cellSize)
std::optional< core::Pose2D > sampleValidPositionInMap(const algorithms::Costmap &costmap)
void invalidateOutsideRooms(const std::vector< Room > &rooms, Costmap &costmap, const float footprintRadius)
CostmapMergeMode
Defines how the.
SceneBounds computeSceneBounds(const VirtualRobot::SceneObjectSetPtr &obstacles, const std::vector< VirtualRobot::RobotPtr > &articulatedObjects, const SceneBounds &init, const std::vector< Room > &rooms, const float margin, const bool restrictToRooms)
SceneBounds toSceneBounds(const VirtualRobot::WorkspaceGrid::Extends &extends)
Costmap mergeAligned(const std::vector< Costmap > &costmaps, CostmapMergeMode mode)
void checkSameSize(const std::vector< Costmap > &costmaps)
This file offers overloads of toIce() and fromIce() functions for STL container types.