CostmapBuilder.cpp
Go to the documentation of this file.
1/**
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @author Fabian Reister ( fabian dot reister at kit dot edu )
17 * @date 2022
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
22#include "CostmapBuilder.h"
23
24#include <algorithm>
25#include <cstddef>
26#include <functional>
27#include <memory>
28#include <optional>
29#include <string>
30#include <variant>
31#include <vector>
32
33#include <boost/geometry/algorithms/convex_hull.hpp>
34#include <boost/geometry/algorithms/disjoint.hpp>
35#include <boost/geometry/geometries/box.hpp>
36
37#include <SimoxUtility/meta/enum/EnumNames.hpp>
38#include <VirtualRobot/CollisionDetection/CollisionChecker.h>
39#include <VirtualRobot/CollisionDetection/CollisionModel.h>
40#include <VirtualRobot/Nodes/RobotNode.h> // IWYU pragma: keep
41#include <VirtualRobot/Robot.h> // IWYU pragma: keep
42#include <VirtualRobot/RobotFactory.h>
43#include <VirtualRobot/SceneObjectSet.h>
44#include <VirtualRobot/VirtualRobot.h>
45
51
59
60#include <omp.h>
61
62#if COSTMAP_BUILDER_SIMOX_CONTROL
63#include <simox/control/environment/CollisionRobot.h>
64#include <simox/control/impl/simox/robot/Robot.h>
65#include <simox/control/impl/simox/utils/conversion.h>
66
67#include <hpp/fcl/broadphase/broadphase_dynamic_AABB_tree.h>
68#endif
69
71{
72
73#if COSTMAP_BUILDER_SIMOX_CONTROL
74 namespace sc = simox::control;
75#endif
76
77
78 // helper type for the visitor
79 template <class... Ts>
80 struct overloaded : Ts...
81 {
82 using Ts::operator()...;
83 };
84 // explicit deduction guide (not needed as of C++20)
85 template <class... Ts>
86 overloaded(Ts...) -> overloaded<Ts...>;
87
88 const simox::meta::EnumNames<CostmapBuilder::DistanceCalculator>
92
94 const VirtualRobot::SceneObjectSetPtr& obstacles,
95 const std::vector<VirtualRobot::RobotPtr>& articulatedObjects,
96 const std::vector<Room>& rooms,
97 const Costmap::Parameters& parameters,
98 const std::string& robotCollisonModelName,
99 const CostmapBuilderParams& builderParameters) :
100 robot(robot),
101 obstacles(obstacles),
102 articulatedObjects(articulatedObjects),
103 rooms(rooms),
104 parameters(parameters),
105 robotCollisionModelName(robotCollisonModelName),
106 builderParameters(builderParameters)
107 {
108 ARMARX_CHECK_NOT_NULL(robot) << "Robot must be set";
109 ARMARX_CHECK_NOT_NULL(obstacles);
110 ARMARX_CHECK(robot->hasRobotNode(robotCollisionModelName));
111
112 ARMARX_CHECK_NONNEGATIVE(this->builderParameters.numThreads);
113
114 const auto& enabledRooms = this->builderParameters.roomEnableList;
115 if (not enabledRooms.empty())
116 {
117 // if roomEnableList is specified, remove all other rooms from the provided list
118 this->rooms.erase(std::remove_if(this->rooms.begin(),
119 this->rooms.end(),
120 [&enabledRooms](const Room& room)
121 {
122 const bool roomIncluded =
123 std::find(enabledRooms.cbegin(),
124 enabledRooms.cend(),
125 room.name) != enabledRooms.cend();
126 if (not roomIncluded)
127 {
128 ARMARX_VERBOSE
129 << "Room " << room.name
130 << " was found but is not included";
131 }
132 return not roomIncluded;
133 }),
134 this->rooms.end());
135 }
136
137 if (builderParameters.restrictToRooms)
138 {
140 << "No rooms enabled, even though restrict to rooms is true";
141 }
142 }
143
144 Costmap
146 {
148 [](const armarx::core::time::Duration& duration)
149 { ARMARX_INFO << "Creating costmap took " << duration; });
150
151 ARMARX_INFO << articulatedObjects.size() << " articulated objects";
152 ARMARX_INFO << obstacles->getSize() << " objects";
153
154 const auto sceneBounds = computeSceneBounds(obstacles,
155 articulatedObjects,
156 init,
157 rooms,
158 parameters.sceneBoundsMargin,
159 builderParameters.restrictToRooms);
160 const auto grid = createUniformGrid(sceneBounds, parameters);
161
162 ARMARX_VERBOSE << "Created grid";
163 Costmap costmap(grid, parameters, sceneBounds);
164
165 if (builderParameters.restrictToRooms)
166 {
167 initializeEmptyMask(costmap);
168
170 ARMARX_VERBOSE << "Restricting to rooms:";
171 for (const auto& room : rooms)
172 {
173 ARMARX_VERBOSE << " - " << room.name;
174 }
175
177
178 ARMARX_VERBOSE << "Restricted to rooms. Fraction of valid elements: "
179 << costmap.mask->cast<float>().sum() / costmap.mask->size();
180 }
181
182 {
184 [](const armarx::core::time::Duration& duration)
185 { ARMARX_INFO << "Filling costmap took " << duration; });
186
187 ARMARX_VERBOSE << "Filling grid with size (" << costmap.getGrid().rows() << "/"
188 << costmap.getGrid().cols() << ") and resolution "
189 << costmap.params().cellSize;
190 fillGridCosts(costmap);
191 ARMARX_VERBOSE << "Filled grid";
192 }
193
195 ARMARX_VERBOSE << "Initialized mask";
196
197 return costmap;
198 }
199
200 Costmap
202 {
204 [](const armarx::core::time::Duration& duration)
205 { ARMARX_INFO << "Extending costmap took " << duration; });
206
207 if (builderParameters.restrictToRooms)
208 {
209 // mask out any cell not within a room
210 ARMARX_VERBOSE << "Restricting to rooms";
212 }
213
214 {
216 [](const armarx::core::time::Duration& duration)
217 { ARMARX_INFO << "Filling costmap took " << duration; });
218
219 ARMARX_VERBOSE << "Extending grid with size (" << costmap.getGrid().rows() << "/"
220 << costmap.getGrid().cols() << ") and resolution "
221 << costmap.params().cellSize;
222 extendGridCosts(costmap);
223 ARMARX_VERBOSE << "Filled grid";
224 }
225
227 ARMARX_VERBOSE << "Initialized mask";
228
229 return costmap;
230 }
231
232 void
234 {
235 costmap.mask = costmap.grid.array() > 0.F;
236
237 ARMARX_VERBOSE << "Update mask: Fraction of valid elements: "
238 << costmap.mask->cast<float>().sum() / costmap.mask->size();
239 }
240
241 void
242 CostmapBuilder::initializeEmptyMask(Costmap& costmap)
243 {
244 costmap.mask = costmap.grid.array() >= -42.F; // FIXME: magic number, just same size
245 costmap.mask->setOnes();
246
247 ARMARX_VERBOSE << "Initializing empty mask: Fraction of valid elements: "
248 << costmap.mask->cast<float>().sum() / costmap.mask->size();
249 }
250
251 Eigen::MatrixXf
253 const Costmap::Parameters& parameters)
254 {
256
257 ARMARX_VERBOSE << "Scene bounds are " << sceneBounds.min << " and " << sceneBounds.max;
258
259 //+1 for explicit rounding up
260 size_t c_x = (sceneBounds.max.x() - sceneBounds.min.x()) / parameters.cellSize + 1;
261 size_t c_y = (sceneBounds.max.y() - sceneBounds.min.y()) / parameters.cellSize + 1;
262
263 ARMARX_VERBOSE << "Grid size: " << c_x << ", " << c_y;
264
265 ARMARX_VERBOSE << "Resetting grid";
266 Eigen::MatrixXf grid(c_x, c_y);
267 grid.setZero();
268
269 return grid;
270 }
271
272 float
273 CostmapBuilder::computeCost(const Costmap::Position& position,
274 const CollisionSetup& collisionSetupVariant)
275 {
276 float cost = std::visit(
278 [&position](const CollisionSetupSC& collisionSetup) -> float
279 {
280 // SimoxControl implementation to calculate distance
281#if COSTMAP_BUILDER_SIMOX_CONTROL
282 ARMARX_CHECK_NOT_NULL(collisionSetup.robot);
283 ARMARX_CHECK_NOT_NULL(collisionSetup.collisionRobot);
284 ARMARX_CHECK_NOT_NULL(collisionSetup.obstacleCollisionManager);
285
286 // Remember: SimoxControl uses meters.
287 const core::Pose globalPose(Eigen::Translation3f(conv::to3D(position)));
288 collisionSetup.robot->setGlobalPose(
289 sc::simox::utils::from_simox(globalPose.matrix()), true);
290
291 collisionSetup.collisionRobot->update();
292
293 for (const auto& o : collisionSetup.colObjects)
294 {
296 o->update();
297 }
298
299 collisionSetup.collisionRobot->getCollisionManager()->update();
300 collisionSetup.obstacleCollisionManager->update();
301
302 hpp::fcl::DistanceCallBackDefault defaultCallback;
303 collisionSetup.obstacleCollisionManager->distance(
304 collisionSetup.collisionRobot->getCollisionManager(), &defaultCallback);
305
306 const double minDistance = defaultCallback.data.result.min_distance;
307
308 return static_cast<float>(std::max(minDistance, 0.) * 1000);
309#else
311 << "SimoxControl distance calculation requested but not supported. "
312 "Please compile with SimoxControl to use this calculation method.";
313 return 0.F;
314#endif
315 },
316 [&position, this](const CollisionSetupSx& collisionSetup) -> float
317 {
318 const auto& collisionRobot = collisionSetup.collisionRobot;
319 const auto& robotCollisionModel = collisionSetup.robotCollisionModel;
320
322 ARMARX_CHECK_NOT_NULL(collisionRobot);
323 ARMARX_CHECK_NOT_NULL(robotCollisionModel);
325 VirtualRobot::CollisionChecker::getGlobalCollisionChecker());
326
327 const VirtualRobot::SceneObjectSetPtr& actualObstacles = [&]()
328 {
329 if (collisionSetup.filteredObstacles)
330 {
331 return collisionSetup.filteredObstacles;
332 }
333 else
334 {
335 return this->obstacles;
336 }
337 }();
338 ARMARX_CHECK_NOT_NULL(actualObstacles);
339
340 const core::Pose globalPose(Eigen::Translation3f(conv::to3D(position)));
341 collisionRobot->setGlobalPose(globalPose.matrix());
342
343 // distance to non-articulated objects
344 float distanceNonArticulated = std::numeric_limits<float>::max();
345 if (actualObstacles->getSize() > 0)
346 {
347 distanceNonArticulated =
348 VirtualRobot::CollisionChecker::getGlobalCollisionChecker()
349 ->calculateDistance(robotCollisionModel, actualObstacles);
350 }
351
352 // distance to articulated objects
353 float distanceArticulatedMin = std::numeric_limits<float>::max();
354 for (const auto& articulatedObject : articulatedObjects)
355 {
356 for (const auto& colModel : articulatedObject->getCollisionModels())
357 {
358 const float distanceArticulated =
359 VirtualRobot::CollisionChecker::getGlobalCollisionChecker()
360 ->calculateDistance(robotCollisionModel, colModel);
361 distanceArticulatedMin =
362 std::min(distanceArticulated, distanceArticulatedMin);
363 }
364 }
365
366 return std::min(distanceNonArticulated, distanceArticulatedMin);
367
368
369 // Eigen::Vector3f P1;
370 // Eigen::Vector3f P2;
371 // int id1, id2;
372
373 // float minDistance = std::numeric_limits<float>::max();
374
375 // // TODO omp...
376 // for (size_t i = 0; i < obstacles->getSize(); i++)
377 // {
378 // // cheap collision check
379 // // VirtualRobot::BoundingBox obstacleBbox =
380 // // obstacles->getSceneObject(i)->getCollisionModel()->getBoundingBox(true);
381 // // if (not intersects(robotBbox, obstacleBbox))
382 // // {
383 // // continue;
384 // // }
385
386 // // precise collision check
387 // const float dist =
388 // VirtualRobot::CollisionChecker::getGlobalCollisionChecker()->calculateDistance(
389 // robotCollisionModel,
390 // obstacles->getSceneObject(i)->getCollisionModel(),
391 // P1,
392 // P2,
393 // &id1,
394 // &id2);
395
396 // // check if objects collide
397 // if ((dist <= parameters.cellSize / 2) or
398 // VirtualRobot::CollisionChecker::getGlobalCollisionChecker()->checkCollision(
399 // robotCollisionModel, obstacles->getSceneObject(i)->getCollisionModel()))
400 // {
401 // minDistance = 0;
402 // break;
403 // }
404
405 // minDistance = std::min(minDistance, dist);
406 // }
407 // // return n->position.x() >= sceneBounds.min.x() && n->position.x() <= sceneBounds.max.x() &&
408 // // n->position.y() >= sceneBounds.min.y() && n->position.y() <= sceneBounds.max.y();
409
410 // return minDistance;
411 },
412 [](const std::monostate& _) -> float
413 {
414 ARMARX_ERROR << "Invalid collision setup";
415 return 0.F;
416 }},
417 collisionSetupVariant);
418
419 // Cap distance at maxDistance
420 cost = std::min(cost, builderParameters.maxDistance);
421 return cost;
422 }
423
424 void
425 CostmapBuilder::fillGridCosts(Costmap& costmap)
426 {
427 applyFnToCostmap(costmap,
428 [&](const CollisionSetup& collisionSetup,
429 const std::optional<float> maskOpt,
430 const float /*cost*/,
431 const Costmap::Index& index) -> float
432 {
433 const auto position = costmap.toPositionGlobal(index);
434
435 // consider mask if available and skip if not valid
436 if (maskOpt.has_value())
437 {
438 if (not maskOpt.value())
439 {
440 // important to set a value <= 0 here, so updateMask wont override mask later
441 return 0.F;
442 }
443 }
444
445 if( builderParameters.fakeModeForTesting)
446 {
447 return builderParameters.maxDistance; // similar distance everywhere
448 }
449
450 return computeCost(position, collisionSetup);
451 });
452 }
453
454 void
455 CostmapBuilder::extendGridCosts(Costmap& costmap)
456 {
457 applyFnToCostmap(
458 costmap,
459 [&](const CollisionSetup& collisionSetup,
460 const std::optional<float> maskOpt,
461 const float cost,
462 const Costmap::Index& index) -> float
463 {
464 const auto position = costmap.toPositionGlobal(index);
465
466 // consider mask if available and skip if not valid
467 // as mask is updated to respect rooms above, this will also ignore areas outside any rooms
468 if (maskOpt.has_value())
469 {
470 if (not maskOpt.value())
471 {
472 return std::min(0.F, cost);
473 }
474 }
475
476 if (cost < 0.F)
477 {
478 return cost;
479 }
480
481 return std::min(cost, computeCost(position, collisionSetup));
482 });
483 }
484
485 void
486 CostmapBuilder::applyFnToCostmap(Costmap& costmap,
487 const std::function<float(const CollisionSetup& collisionSetup,
488 const std::optional<float>,
489 const float,
490 const Costmap::Index&)>& fn)
491 {
492
493 // filter scene objects once, not in every thread
494 const VirtualRobot::SceneObjectSetPtr filteredObjects = filterObjectsForCostmap(costmap);
495
496 // called from every thread to initialize the private collision data
497 const auto initializeCollisionSetup = [&]() -> CollisionSetup
498 {
499 armarx::core::time::ScopedStopWatch sw(
500 [](const armarx::core::time::Duration& duration)
501 {
502 ARMARX_INFO << "Initializing collision setup on thread " << omp_get_thread_num()
503 << " took: " << duration;
504 });
505
506 switch (builderParameters.calculationMethod)
507 {
508 case DistanceCalculator::SimoxControl:
509 {
510#if COSTMAP_BUILDER_SIMOX_CONTROL
511 ARMARX_VERBOSE << "Initializing collision setup";
512 CollisionSetupSC collisionSetup;
513
514 using ScRobot = sc::simox::robot::Robot;
515 using ScCollisionRobot = sc::environment::CollisionRobot<hpp::fcl::OBBRSS>;
516
517 // create copy of this robot instance
518 ARMARX_DEBUG << "Copying robot";
520 VirtualRobot::RobotPtr clonedRobot =
521 robot->clone("collision_robot_" + std::to_string(omp_get_thread_num()));
522 ARMARX_CHECK_NOT_NULL(clonedRobot);
523
524 // replace the standard collision model by our custom one
525 clonedRobot->setPrimitiveApproximationModel({"navigation"}, false);
526
527 clonedRobot->setUpdateVisualization(false);
528
529 // will copy RobotPtr and keep it alive after leaving the scope
530 collisionSetup.robot = ScRobot::CREATE_SIMPLE_WRAPPER(clonedRobot);
531 ARMARX_CHECK_NOT_NULL(collisionSetup.robot);
532 collisionSetup.collisionRobot =
533 std::make_unique<ScCollisionRobot>(*collisionSetup.robot,
534 std::string(),
535 false,
536 std::vector<std::string>{"navigation"});
537
538 collisionSetup.obstacleCollisionManager =
539 std::make_unique<hpp::fcl::DynamicAABBTreeCollisionManager>();
540
541 const auto convertVRObstacle =
542 [&collisionSetup](const VirtualRobot::RobotPtr& r)
543 {
544 const auto& obstacle = collisionSetup.scObstacles.emplace_back(
545 ScRobot::CREATE_SIMPLE_WRAPPER(r));
546
547 try
548 {
549 const auto& colObject = collisionSetup.colObjects.emplace_back(
550 std::make_unique<ScCollisionRobot>(*obstacle));
551
552 // add collision objects to manager
553 for (auto& node : colObject->getNodes())
554 {
555 for (std::size_t i = 0; i < node.size(); i++)
556 {
557 collisionSetup.obstacleCollisionManager->registerObject(
558 &node.getColObject(i));
559 }
560 }
561 }
562 catch (const std::exception& ex)
563 {
564#pragma omp master
565 ARMARX_VERBOSE << "Failed to convert object `" << r->getName()
566 << "` to collision robot.\n"
567 << ex.what();
568 }
569 };
570
571 // static obstacles first have to be converted to a Robot, then converted to simox control
572 for (const auto& o : this->obstacles->getSceneObjects())
573 {
574 // Here, the scene objects are ManipulationObjects
575 const auto casted =
576 std::dynamic_pointer_cast<VirtualRobot::GraspableSensorizedObject>(o);
578 << "Scene object is not a graspable sensorized object";
579 const VirtualRobot::RobotPtr asRobot =
580 VirtualRobot::RobotFactory::createRobot(*casted);
581 convertVRObstacle(asRobot);
582 }
583
584 // articulated objects already are Robots, thus they can be immediately converted to simox control
585 for (const auto& o : this->articulatedObjects)
586 {
587 convertVRObstacle(o);
588 }
589
590 // only print once on the main thread
591#pragma omp master
592 ARMARX_INFO << "Converted " << collisionSetup.colObjects.size() << "/"
593 << (this->obstacles->getSize() + this->articulatedObjects.size())
594 << " in total";
595
596 collisionSetup.obstacleCollisionManager->setup();
597
598 return collisionSetup;
599#else
601 << "SimoxControl distance calculation requested but not supported. "
602 "Please compile with SimoxControl to use this calculation method.";
603 return {};
604#endif
605 }
606 case DistanceCalculator::Simox:
607 {
608 CollisionSetupSx collisionSetup;
609
610 ARMARX_DEBUG << "Copying robot";
612 collisionSetup.collisionRobot =
613 robot->clone("collision_robot_" + std::to_string(omp_get_thread_num()));
614
615 // replace the standard collision model by our custom one
616 collisionSetup.collisionRobot->setPrimitiveApproximationModel({"navigation"},
617 false);
618
619 collisionSetup.collisionRobot->setUpdateVisualization(false);
620 ARMARX_DEBUG << "Copying done";
621
622 ARMARX_CHECK_NOT_NULL(collisionSetup.collisionRobot);
624 collisionSetup.collisionRobot->hasRobotNode(robotCollisionModelName));
625
626 const auto collisionRobotNode =
627 collisionSetup.collisionRobot->getRobotNode(robotCollisionModelName);
628 ARMARX_CHECK_NOT_NULL(collisionRobotNode);
629
630 collisionSetup.robotCollisionModel = collisionRobotNode->getCollisionModel();
631 ARMARX_CHECK_NOT_NULL(collisionSetup.robotCollisionModel)
632 << "Collision model not available. "
633 "Make sure that you load the robot correctly!";
634
635 // scale collision model
636 collisionSetup.robotCollisionModel->scale(
637 builderParameters.collisionModelScaleFactor);
638
639 collisionSetup.filteredObstacles = filteredObjects;
640
641 ARMARX_CHECK_NOT_NULL(collisionSetup.collisionRobot);
642 ARMARX_CHECK_NOT_NULL(collisionSetup.robotCollisionModel);
643
644 return collisionSetup;
645 }
646 default:
647 ARMARX_ERROR << "Invalid distance calculator specified";
648 return {};
649 }
650 };
651
652 if (costmap.mask.has_value())
653 {
654 ARMARX_VERBOSE << "Costmap provides mask.";
655 }
656
657 const std::size_t c_x = costmap.grid.rows();
658 const std::size_t c_y = costmap.grid.cols();
659
660 robot->setUpdateVisualization(false);
661
662 // a per-thread local variable (through `private` directive below)
663 CollisionSetup collisionSetup;
664
665 const int threadNumDefault = omp_get_max_threads();
666 const int actualThreads = this->builderParameters.numThreads == 0
667 ? threadNumDefault
668 : this->builderParameters.numThreads;
669 ARMARX_INFO << "Using " << actualThreads << " threads.";
670
671
672#pragma omp parallel for num_threads(actualThreads) \
673 schedule(static) private(collisionSetup) default(shared)
674 for (unsigned int x = 0; x < c_x; x++)
675 {
676 // any exception (like those generated by ARMARX_CHECK) need to be caught in the executing thread
677 try
678 {
679
680 // we have to initialize the collision setup for each thread
681 if (std::holds_alternative<std::monostate>(collisionSetup))
682 {
683 collisionSetup = initializeCollisionSetup();
684 ARMARX_VERBOSE << "Collision setup created successfully";
685 }
686 ARMARX_CHECK(not std::holds_alternative<std::monostate>(collisionSetup));
687
688
689 for (unsigned int y = 0; y < c_y; y++)
690 {
691 const Costmap::Index index{x, y};
692
693 const auto maskVal = costmap.mask.has_value()
694 ? std::make_optional(costmap.mask.value()(x, y))
695 : std::nullopt;
696 costmap.grid(x, y) = fn(collisionSetup, maskVal, costmap.grid(x, y), index);
697 }
698 }
699 catch (const std::exception& e)
700 {
701 ARMARX_ERROR << "Error during costmap calculation: " << e.what();
702 }
703 }
704 }
705
706 VirtualRobot::SceneObjectSetPtr
707 CostmapBuilder::filterObjectsForCostmap(const Costmap& costmap)
708 {
709 armarx::core::time::ScopedStopWatch sw(
710 [](const armarx::core::time::Duration& duration)
711 { ARMARX_INFO << "Filtering objects took " << duration; });
712
713 VirtualRobot::SceneObjectSetPtr filtered(new VirtualRobot::SceneObjectSet);
714
716 using Box = boost::geometry::model::box<Point>;
718
719 const auto toPoint = [](const Eigen::Vector3f& vec) { return Point(vec.x(), vec.y()); };
720 const auto toBox = [&toPoint](const VirtualRobot::BoundingBox& bb)
721 { return Box(toPoint(bb.getMin()), toPoint(bb.getMax())); };
722
723 Polygon costmapBB;
724 {
725 Polygon cornerPoints = util::geometry::toPolygon(std::vector<Eigen::Vector2f>{
726 costmap.toPositionGlobal(Costmap::Index(0, 0)),
727 costmap.toPositionGlobal(Costmap::Index(0, costmap.grid.cols() - 1)),
728 costmap.toPositionGlobal(Costmap::Index(costmap.grid.rows() - 1, 0)),
729 costmap.toPositionGlobal(
730 Costmap::Index(costmap.grid.rows() - 1, costmap.grid.cols() - 1))});
731 boost::geometry::convex_hull(cornerPoints, costmapBB);
732 }
733
734
735 for (const auto& object : this->obstacles->getSceneObjects())
736 {
737 const auto& colModel = object->getCollisionModel();
738
739 if (colModel)
740 {
741 Box bb = toBox(colModel->getGlobalBoundingBox());
742
743 // if bb of object is disjoint to bb of costmap we check the distance between them
744 // otherwise, we always include the object
745 if (boost::geometry::disjoint(costmapBB, bb))
746 {
747 float distance = boost::geometry::distance(costmapBB, bb);
748 if (distance > builderParameters.maxFilterDistance)
749 {
750 // if the distance is greater than configured, we skip this object
751 continue;
752 }
753 }
754
755 filtered->addSceneObject(object);
756 }
757 }
758 const std::size_t prevSize = this->obstacles->getSize();
759 const std::size_t filteredSize = filtered->getSize();
760
761 ARMARX_INFO << "Remaining objects for costmap calculation: " << filteredSize << "/"
762 << prevSize << " ("
763 << static_cast<float>(filteredSize) * 100.f / static_cast<float>(prevSize)
764 << "%)";
765
766 for (const auto& object : filtered->getSceneObjects())
767 {
768 ARMARX_VERBOSE << "- " << object->getName();
769 }
770
771
772 return filtered;
773 }
774
775} // namespace armarx::navigation::algorithms
uint8_t index
#define ARMARX_CHECK_NOT_EMPTY(c)
Represents a duration.
Definition Duration.h:17
Measures the time this stop watch was inside the current scope.
static const simox::meta::EnumNames< DistanceCalculator > DistanceCalculatorNames
static Eigen::MatrixXf createUniformGrid(const SceneBounds &sceneBounds, const Costmap::Parameters &parameters)
CostmapBuilder(const VirtualRobot::RobotPtr &robot, const VirtualRobot::SceneObjectSetPtr &obstacles, const std::vector< VirtualRobot::RobotPtr > &articulatedObjects, const std::vector< Room > &rooms, const Costmap::Parameters &parameters, const std::string &robotCollisonModelName, const CostmapBuilderParams &builderParameters)
Costmap create(const SceneBounds &init=SceneBounds())
#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_NONNEGATIVE(number)
Check whether number is nonnegative (>= 0).
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
This file is part of ArmarX.
overloaded(Ts...) -> overloaded< Ts... >
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)
Definition util.cpp:62
void invalidateOutsideRooms(const std::vector< Room > &rooms, Costmap &costmap)
Definition util.cpp:493
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition eigen.cpp:14
Eigen::Isometry3f Pose
Definition basic_types.h:31
boost::geometry::model::d2::point_xy< float > point_type
Definition geometry.h:35
point_type toPoint(const Eigen::Vector2f &pt)
Definition geometry.cpp:43
polygon_type toPolygon(const std::vector< Eigen::Vector2f > &hull)
Definition geometry.cpp:31
boost::geometry::model::polygon< point_type > polygon_type
Definition geometry.h:36
objpose::ObjectPoseSeq articulatedObjects(objpose::ObjectPoseSeq objects)
Definition util.cpp:94
::wykobi::polygon< float, 2 > Polygon
Eigen::Vector3f Point
double distance(const Point &a, const Point &b)
Definition point.hpp:95
#define ARMARX_TRACE
Definition trace.h:77