14#include <boost/geometry.hpp>
15#include <boost/geometry/algorithms/append.hpp>
16#include <boost/geometry/geometries/multi_point.hpp>
19#include <Eigen/Geometry>
21#include <range/v3/algorithm/all_of.hpp>
22#include <range/v3/algorithm/min.hpp>
23#include <range/v3/all.hpp>
24#include <range/v3/numeric/accumulate.hpp>
25#include <range/v3/range/conversion.hpp>
26#include <range/v3/view/drop.hpp>
27#include <range/v3/view/enumerate.hpp>
28#include <range/v3/view/filter.hpp>
29#include <range/v3/view/reverse.hpp>
30#include <range/v3/view/transform.hpp>
31#include <range/v3/view/zip_with.hpp>
33#include <SimoxUtility/color/Color.h>
34#include <SimoxUtility/color/cmaps/colormaps.h>
35#include <SimoxUtility/shapes/OrientedBox.h>
36#include <VirtualRobot/Nodes/RobotNode.h>
37#include <VirtualRobot/Robot.h>
57#include <armarx/navigation/safety_guard/aron/LaserBasedProximityParams.aron.generated.h>
62namespace rv = ::ranges::views;
70 inline core::TwistLimits
71 mergeSafetyLimits(
const std::vector<std::optional<core::TwistLimits>>& resultsAll)
73 const auto isValidFn =
74 [](
const std::optional<core::TwistLimits>& result)
noexcept ->
bool
75 {
return result.has_value(); };
77 const std::vector<core::TwistLimits> validResults =
78 resultsAll | rv::filter(isValidFn) |
80 [](
const std::optional<core::TwistLimits>& result)
noexcept -> core::TwistLimits
81 {
return result.value(); }) |
85 if (validResults.empty())
90 const std::vector<float> linearLimits =
92 rv::transform([](
const core::TwistLimits& result)
noexcept ->
float
93 {
return result.linear; }) |
96 const std::vector<float> angularLimits =
98 rv::transform([](
const core::TwistLimits& result)
noexcept ->
float
99 {
return result.angular; }) |
102 const core::TwistLimits combinedResult{.linear = ranges::min(linearLimits),
103 .angular = ranges::min(angularLimits)};
105 return combinedResult;
114 return simox::Color::white();
116 return simox::Color::gray();
118 return simox::Color::magenta();
120 return simox::Color::cyan();
122 return simox::Color::yellow();
124 return simox::Color::blue();
126 return simox::Color::green();
128 return simox::Color::orange();
131 return simox::Color::black();
144 return "IgnoredRegion";
146 return "AttachedObject";
148 return "NearFieldArtifact";
171 arondto::LaserBasedProximityParams dto;
181 arondto::LaserBasedProximityParams dto;
196 generalConfig(generalConfig),
197 humanColorMap_(
simox::color::cmaps::BuPu().reversed()),
198 laserColorMap_(
simox::color::cmaps::OrRd().reversed())
207 auto layer =
viz.layer(
"safety_guard");
210 auto clusterLayer =
viz.layer(
"safety_guard_clusters");
211 auto filteredLayer =
viz.layer(
"safety_guard_filtered");
213 const std::optional<core::TwistLimits> resultHumans = safetyLimitsHumans(layer);
214 const std::optional<core::TwistLimits> resultLaserScanners =
215 safetyLimitsLaserScanners(layer, clusterLayer, filteredLayer, global_V_movement);
218 viz.commit(std::vector<viz::Layer>{layer, clusterLayer, filteredLayer});
221 mergeSafetyLimits({resultHumans, resultLaserScanners});
228 std::optional<core::TwistLimits>
229 LaserBasedProximity::safetyLimitsLaserScanners(
viz::Layer& layer,
232 const Eigen::Vector2f& global_V_movement)
const
249 debugObserver.setDebugObserverDatafield(
"numLaserScannerFeatures",
251 debugObserver.setDebugObserverDatafield(
252 "numFirstLaserScannerFeatures",
260 std::size_t smallestClusterSize = std::numeric_limits<std::size_t>::max();
264 std::size_t numFeaturesWithoutPoints = 0;
268 for (
const auto& feature : features.features)
270 smallestClusterSize = std::min(smallestClusterSize, feature.points.size());
272 if (feature.points.empty())
274 numFeaturesWithoutPoints++;
279 if (smallestClusterSize != std::numeric_limits<std::size_t>::max())
281 debugObserver.setDebugObserverDatafield(
"smallestClusterSize", smallestClusterSize);
284 debugObserver.setDebugObserverDatafield(
"numFeaturesWithoutPoints",
285 numFeaturesWithoutPoints);
295 const core::Pose robot_T_global{global_T_robot.inverse()};
300 boost::geometry::model::multi_point<util::geometry::point_type> robotNodes;
301 for (
const auto& node :
scene.robot->getRobotNodes())
304 boost::geometry::append(robotNodes,
307 boost::geometry::convex_hull(robotNodes, robotConvexHull);
311 const auto minDistanceFn =
312 [
this, &robotConvexHull, &robot_T_global](
const memory::LaserScannerFeatures& features)
313 -> std::vector<DistanceAndClosestPoint>
315 const core::Pose& global_T_sensor = features.frameGlobalPose;
318 const auto minDistanceFnInner =
319 [
this, &robotConvexHull, &global_T_sensor, &robot_T_global](
320 const memory::LaserScannerFeature& feature) -> DistanceAndClosestPoint
323 const std::vector<Eigen::Vector3f> points3dGlobal =
325 rv::transform([&global_T_sensor](
const Eigen::Vector2f& pt) -> Eigen::Vector3f
326 {
return global_T_sensor *
conv::to3D(pt); }) |
329 return calculateMinDistance(robotConvexHull, robot_T_global, points3dGlobal);
334 const std::vector<DistanceAndClosestPoint> distances =
335 features.features | rv::transform(minDistanceFnInner) | ranges::to_vector;
340 laserScannerFeatureHistory_.push_back(
scene.dynamicScene->laserScannerFeatures);
342 const std::vector<memory::LaserScannerFeatures> accumulatedLaserScannerFeatures =
343 laserScannerFeatureHistory_ | ranges::views::join |
344 ranges::to<std::vector<memory::LaserScannerFeatures>>;
347 std::vector<DistanceAndClosestPoint> minDistanceToObstacles =
348 accumulatedLaserScannerFeatures | rv::transform(minDistanceFn) | ranges::views::join |
351 const auto result = [&]() -> std::optional<InternalVelocityLimitResult>
353 switch (
params.laserScannerProximityField.mode)
358 return velocityLimitsDirectionDependent(
359 global_V_movement, minDistanceToObstacles, global_T_robot);
361 return velocityLimitsDirectionIndependent(minDistanceToObstacles);
365 <<
static_cast<int>(
params.laserScannerProximityField.mode);
374 simox::color::Color color = simox::Color::blue();
375 viz::Polygon vizPoly(
"robot_convex_hull");
376 for (
const auto& p : rv::reverse(robotConvexHull.outer()))
378 Eigen::Vector2f pt(p.x(), p.y());
381 layer.
add(vizPoly.color(color).lineColor(color));
384 layer.
add(viz::Line(
"robot_movement_Dir")
385 .fromTo(global_T_robot.translation(),
386 global_T_robot.translation() +
387 conv::to3D(global_V_movement).normalized() * 1000)
389 .color(simox::Color::blue()));
392 for (
const auto& [i, region] : ranges::views::enumerate(
params.ignoredRegions))
394 viz::Polygon vizRegion(
"ignored_region_" + std::to_string(i));
395 vizRegion.addPoint(Eigen::Vector3f(region.min().x(), region.min().y(), 15));
396 vizRegion.addPoint(Eigen::Vector3f(region.max().x(), region.min().y(), 15));
397 vizRegion.addPoint(Eigen::Vector3f(region.max().x(), region.max().y(), 15));
398 vizRegion.addPoint(Eigen::Vector3f(region.min().x(), region.max().y(), 15));
399 layer.
add(vizRegion.color(simox::Color::magenta()));
403 for (
const auto& [i, obj] :
404 ranges::views::enumerate(
scene.dynamicScene->attachedObjects))
406 const auto& oobb = obj->oobbGlobal();
409 simox::OrientedBoxf inflatedOobb{
410 oobb->transformation_centered(),
411 oobb->dimensions() + Eigen::Vector3f::Ones() *
params.attachedObjectsInflation};
413 viz::Box vizObj(
"attached_object_" + std::to_string(i));
414 vizObj.set(inflatedOobb);
415 layer.
add(vizObj.color(simox::Color::magenta()));
425 const std::size_t numCurrentFrameFeatures = ranges::accumulate(
426 scene.dynamicScene->laserScannerFeatures |
427 rv::transform([](
const memory::LaserScannerFeatures& features) noexcept -> std::size_t
428 { return features.features.size(); }),
434 const auto currentFrameFeatures =
435 minDistanceToObstacles |
436 rv::drop(minDistanceToObstacles.size() - numCurrentFrameFeatures);
438 const float sphereRadius = 50.F;
439 const float textScale = 3.F;
440 const Eigen::Vector3f sphereOffset{0, 0, 50};
441 const Eigen::Vector3f sizeTextOffset{0, 0, 200};
442 const Eigen::Vector3f reasonTextOffset{0, 0, 350};
444 for (
const auto& [i, obstacle] : ranges::views::enumerate(currentFrameFeatures))
452 const std::string suffix = std::to_string(i);
453 const Eigen::Vector3f position =
conv::to3D(obstacle.centroid);
455 clusterLayer.
add(viz::Sphere(
"cluster_" + suffix)
456 .position(position + sphereOffset)
457 .radius(sphereRadius)
458 .color(simox::Color::white()));
459 clusterLayer.
add(viz::Text(
"cluster_size_" + suffix)
460 .position(position + sizeTextOffset)
461 .text(std::to_string(obstacle.clusterSize))
463 .color(simox::Color::white()));
470 const simox::color::Color color = filterReasonColor(obstacle.filterReason);
472 filteredLayer.
add(viz::Sphere(
"filtered_" + suffix)
473 .position(position + sphereOffset)
474 .radius(sphereRadius)
476 filteredLayer.
add(viz::Text(
"filtered_reason_" + suffix)
477 .position(position + reasonTextOffset)
478 .text(filterReasonName(obstacle.filterReason))
484 if (not result.has_value())
490 if (result->closestPoint.has_value())
493 const auto color = laserColorMap_.at(
494 std::abs(result->twistLimits.linear), 0, generalConfig.maxVel.linear);
497 viz::Line(
"nearest_obstacle")
498 .fromTo(global_T_robot.translation(),
conv::to3D(result->closestPoint.value()))
503 return result->twistLimits;
506 std::optional<core::TwistLimits>
507 LaserBasedProximity::safetyLimitsHumans(viz::Layer& layer)
const
509 if (not
params.enableHumans)
518 const auto minimalSegmentDistanceToRobot =
519 [&global_T_robot](
const human::Human& human) ->
float
521 const Eigen::Isometry3f global_T_human =
conv::to3D(human.pose);
522 const Eigen::Isometry3f robot_T_human = global_T_robot.inverse() * global_T_human;
525 return robot_T_human.translation().norm();
528 if (
scene.dynamicScene->humans.empty())
534 const auto distanceRobotToHumans =
scene.dynamicScene->humans |
535 rv::transform(minimalSegmentDistanceToRobot) |
538 const std::optional<float> minDistanceToHumans =
scene.dynamicScene->humans.empty()
539 ? std::optional<float>{std::nullopt}
540 : ranges::min(distanceRobotToHumans);
543 if (not minDistanceToHumans.has_value())
549 evaluateProximityField(
params.humanProximityField, minDistanceToHumans.value());
553 const auto color = humanColorMap_(result.second).with_alpha(1 - result.second + 0.1);
555 layer.
add(viz::Cylinder(
"distance_humans")
556 .position(global_T_robot.translation() + Eigen::Vector3f{0, 0, 10})
557 .direction(Eigen::Vector3f::UnitZ())
558 .radius(minDistanceToHumans.value())
566 LaserBasedProximity::DistanceAndClosestPoint
567 LaserBasedProximity::calculateMinDistance(
570 const std::vector<Eigen::Vector3f>& globalPoints)
const
575 const std::vector<Eigen::Vector2f> points2dGlobal =
577 rv::transform([](
const Eigen::Vector3f& pt) -> Eigen::Vector2f
582 const auto ignoredResult = [&globalPoints](
const Eigen::Vector2f& centroid,
584 -> DistanceAndClosestPoint
586 return {.distance = std::numeric_limits<float>::max(),
587 .closestPoint = Eigen::Vector2f::Zero(),
588 .clusterSize = globalPoints.size(),
589 .centroid = centroid,
590 .filterReason = filterReason};
593 if (globalPoints.empty())
599 const Eigen::Vector2f centroid =
600 ranges::accumulate(points2dGlobal,
601 Eigen::Vector2f{Eigen::Vector2f::Zero()},
602 [](
const Eigen::Vector2f& lhs,
const Eigen::Vector2f& rhs)
603 -> Eigen::Vector2f {
return lhs + rhs; }) /
604 static_cast<float>(points2dGlobal.size());
607 featureIgnoreReason(globalPoints, points2dGlobal, centroid);
611 return ignoredResult(centroid, ignoreReason);
615 const std::vector<float> pointsDistanceRobotCenter =
617 rv::transform([&robot_T_global](
const Eigen::Vector3f& pt) ->
float
618 {
return conv::to2D(robot_T_global * pt).norm(); }) |
624 if (
params.enableLaserScannerFiltering and
625 globalPoints.size() <=
static_cast<std::size_t
>(
params.laserScannerFilteringThreshold))
627 const auto isCloseToRobot = [
this](
const float distanceToCenter)
noexcept ->
bool
629 return std::max(distanceToCenter -
params.robotRadius, 0.F) <
630 params.laserScannerMaxFilteringDistance;
634 const float minSurfaceDistance =
635 std::max(ranges::min(pointsDistanceRobotCenter) -
params.robotRadius, 0.F);
637 if (ranges::all_of(pointsDistanceRobotCenter, isCloseToRobot))
641 ARMARX_VERBOSE <<
"Ignoring small feature with " << globalPoints.size()
642 <<
" points (<= laserScannerFilteringThreshold "
643 <<
params.laserScannerFilteringThreshold
644 <<
"): all points are within laserScannerMaxFilteringDistance "
645 <<
params.laserScannerMaxFilteringDistance
646 <<
" mm of the robot surface (closest point at "
647 << minSurfaceDistance
648 <<
" mm). Distances to robot center: " << pointsDistanceRobotCenter;
652 ARMARX_VERBOSE <<
"Keeping small feature with " << globalPoints.size()
653 <<
" points: not all points are within "
654 <<
params.laserScannerMaxFilteringDistance
655 <<
" mm of the robot surface (closest point at " << minSurfaceDistance
659 const auto distancesAndClosestPoint =
661 [
this, &convexHull, &globalPoints, ¢roid](
662 const Eigen::Vector2f& pt,
float distanceToCenter) -> DistanceAndClosestPoint
664 const auto distanceToRobotConvexHull =
665 static_cast<float>(boost::geometry::distance(
668 const float distanceUsingRobotRadius =
669 std::max(distanceToCenter -
params.robotRadius, 0.F);
672 std::min(distanceToRobotConvexHull, distanceUsingRobotRadius),
674 .clusterSize = globalPoints.size(),
675 .centroid = centroid,
679 pointsDistanceRobotCenter) |
683 distancesAndClosestPoint, std::less{}, &DistanceAndClosestPoint::distance);
686 std::pair<core::TwistLimits, float>
688 float minDistance)
const
690 if (minDistance < proximityField.safetyDistance)
695 if (minDistance > proximityField.influenceDistance)
701 const float proximityRange =
702 proximityField.influenceDistance - proximityField.safetyDistance;
703 const float clippedDistance =
704 std::min(minDistance, proximityField.influenceDistance) - proximityField.safetyDistance;
706 const float fractionalDistance = std::clamp(clippedDistance / proximityRange, 0.F, 1.F);
708 if (not proximityField.reduceVelocity)
713 const float d_s = std::pow(1 - fractionalDistance, proximityField.k);
715 const auto permissibleVelocity = [&proximityField](
const float d_s,
716 const float v_max) ->
float
717 {
return v_max / (1 + proximityField.lambda * d_s); };
719 const core::TwistLimits result{
720 .linear = permissibleVelocity(d_s, generalConfig.maxVel.linear),
721 .angular = permissibleVelocity(d_s, generalConfig.maxVel.angular)};
723 return {result, fractionalDistance};
726 template <
class T,
class Func>
728 allPointsInside(
const std::vector<T>& points, Func isInsideFunc)
730 for (
const auto& p : points)
732 if (not isInsideFunc(p))
742 LaserBasedProximity::featureIgnoreReason(
743 const std::vector<Eigen::Vector3f>& featurePoints3DGlobal,
744 const std::vector<Eigen::Vector2f>& featurePoints2DGlobal,
745 const Eigen::Vector2f& centroid)
const
752 const auto featureInfo = [&]() -> std::string
754 return "feature with " + std::to_string(featurePoints3DGlobal.size()) +
755 " points around global (" + std::to_string(centroid.x()) +
", " +
756 std::to_string(centroid.y()) +
")";
760 for (
const auto& [i, region] : ranges::views::enumerate(
params.ignoredRegions))
764 if (allPointsInside(featurePoints2DGlobal,
765 [®ion](
const Eigen::Vector2f& p) {
return region.contains(p); }))
768 ARMARX_VERBOSE <<
"Ignoring " << featureInfo() <<
": lies fully inside ignored "
769 <<
"region " << i <<
" [" << region.min().transpose() <<
"; "
770 << region.max().transpose() <<
"]";
776 if (not
params.ignoreAttachedObjects)
779 <<
"Not checking features against attached objects "
780 "(params.ignoreAttachedObjects is false)";
784 for (
const auto& [i, o] : ranges::views::enumerate(
scene.dynamicScene->attachedObjects))
786 const auto& oobbGlobal = o->oobbGlobal();
789 simox::OrientedBoxf inflatedOobb{oobbGlobal->transformation_centered(),
790 oobbGlobal->dimensions() +
791 Eigen::Vector3f::Ones() *
792 params.attachedObjectsInflation};
794 if (allPointsInside(featurePoints3DGlobal,
795 [&inflatedOobb](
const Eigen::Vector3f& p)
796 {
return inflatedOobb.contains(p); }))
799 ARMARX_VERBOSE <<
"Ignoring " << featureInfo() <<
": lies fully inside the "
800 <<
"(inflated by " <<
params.attachedObjectsInflation
801 <<
" mm) OOBB of attached object " << i;
806 ARMARX_VERBOSE <<
"Keeping " << featureInfo() <<
": neither inside one of the "
807 <<
params.ignoredRegions.size() <<
" ignored regions nor inside one of the "
808 <<
scene.dynamicScene->attachedObjects.size() <<
" attached objects";
813 LaserBasedProximity::InternalVelocityLimitResult
814 LaserBasedProximity::velocityLimitsDirectionDependent(
815 const Eigen::Vector2f& global_V_movement,
816 std::vector<DistanceAndClosestPoint>& minDistanceToObstacles,
817 const Eigen::Isometry3f& global_T_robot)
const
820 float maxPermissibleRelativeVelocityLinear = generalConfig.maxVel.linear;
822 std::optional<Eigen::Vector2f> minPoint = std::nullopt;
823 std::optional<float> minDistance = std::nullopt;
825 const Eigen::Isometry3f robot_T_global = global_T_robot.inverse();
828 auto& debugObserver = *
context.debugObserver;
830 debugObserver.setDebugObserverDatafield(
"numObstacles", minDistanceToObstacles.size());
832 std::size_t closestClusterSize = 0;
837 bool mustStop =
false;
841 const Eigen::Vector2f global_V_movementDirection =
842 global_V_movement.norm() > 1e-6F ? global_V_movement.normalized().eval()
843 : Eigen::Vector2f::Zero();
846 std::size_t numFiltered = 0;
847 std::size_t numTooFarAway = 0;
848 std::size_t numMovingAway = 0;
849 std::size_t numTangential = 0;
850 std::size_t numConstraining = 0;
852 for (
auto& obstacle : minDistanceToObstacles)
854 const float distance = obstacle.distance;
855 const Eigen::Vector2f& global_P_obstacle_pt = obstacle.closestPoint;
856 const std::size_t clusterSize = obstacle.clusterSize;
858 const float ds =
params.laserScannerProximityField.safetyDistance;
859 const float di =
params.laserScannerProximityField.influenceDistance;
866 if (d >= std::numeric_limits<float>::max())
875 ARMARX_VERBOSE <<
"Obstacle (cluster size " << clusterSize <<
") at distance "
876 << d <<
" mm is outside the influence distance " << di <<
" mm";
881 float velocity_damper = generalConfig.maxVel.linear * (d - ds) / (di - ds);
885 const Eigen::Vector2f minPointGlobal = global_P_obstacle_pt;
890 const Eigen::Vector2f directionRobotToObstacle =
891 (minPointGlobal - global_T_robot.translation().head<2>()).normalized();
898 const float relativeVelocityScaling =
899 directionRobotToObstacle.dot(global_V_movementDirection);
905 if (relativeVelocityScaling < 0)
909 ARMARX_VERBOSE <<
"Obstacle (cluster size " << clusterSize <<
") at distance " << d
910 <<
" mm does not constrain the velocity: the robot is moving away "
912 <<
VAROUT(relativeVelocityScaling) <<
")";
919 maxPermissibleRelativeVelocityLinear = 0;
921 ARMARX_VERBOSE <<
"Obstacle (cluster size " << clusterSize <<
") at distance " << d
922 <<
" mm is within the safety distance " << ds
923 <<
" mm -> the robot must stop";
926 if (not mustStop or d < minDistance.value())
929 minPoint = minPointGlobal;
931 closestClusterSize = clusterSize;
937 if (std::abs(relativeVelocityScaling) > 1e-4)
941 const float thisMaxPermissibileRelVelLinear =
942 velocity_damper / relativeVelocityScaling;
945 if (thisMaxPermissibileRelVelLinear < maxPermissibleRelativeVelocityLinear)
947 ARMARX_VERBOSE <<
"New most constraining obstacle (cluster size " << clusterSize
948 <<
") at distance " << d <<
" mm: limiting the linear velocity "
949 <<
"to " << thisMaxPermissibileRelVelLinear <<
" mm/s";
951 maxPermissibleRelativeVelocityLinear = thisMaxPermissibileRelVelLinear;
952 minPoint = minPointGlobal;
954 closestClusterSize = clusterSize;
961 ARMARX_VERBOSE <<
"Obstacle (cluster size " << clusterSize <<
") at distance " << d
962 <<
" mm does not constrain the velocity: the robot passes it "
964 <<
VAROUT(relativeVelocityScaling) <<
")";
968 ARMARX_VERBOSE <<
"Of " << minDistanceToObstacles.size() <<
" obstacles (accumulated over "
969 <<
"the feature history): " << numFiltered <<
" filtered out, "
970 << numTooFarAway <<
" too far away, " << numMovingAway <<
" moving away, "
971 << numTangential <<
" tangential, " << numConstraining <<
" constraining";
973 debugObserver.setDebugObserverDatafield(
"maxPermissibleRelativeVelocityLinear",
974 maxPermissibleRelativeVelocityLinear);
975 debugObserver.setDebugObserverDatafield(
"numObstaclesFiltered", numFiltered);
976 debugObserver.setDebugObserverDatafield(
"numObstaclesTooFarAway", numTooFarAway);
977 debugObserver.setDebugObserverDatafield(
"numObstaclesMovingAway", numMovingAway);
978 debugObserver.setDebugObserverDatafield(
"numObstaclesTangential", numTangential);
979 debugObserver.setDebugObserverDatafield(
"numObstaclesConstraining", numConstraining);
981 if (minDistance.has_value())
983 debugObserver.setDebugObserverDatafield(
"minDistance", minDistance.value());
984 debugObserver.setDebugObserverDatafield(
"closestClusterSize", closestClusterSize);
987 core::TwistLimits result{.linear = std::max<float>(0, maxPermissibleRelativeVelocityLinear),
988 .angular = generalConfig.maxVel.angular};
989 return {.twistLimits = result, .minDistance = minDistance, .closestPoint = minPoint};
992 LaserBasedProximity::InternalVelocityLimitResult
993 LaserBasedProximity::velocityLimitsDirectionIndependent(
994 const std::vector<DistanceAndClosestPoint>& minDistanceToObstacles)
const
996 const DistanceAndClosestPoint minDistance =
997 ranges::min(minDistanceToObstacles, std::less{}, &DistanceAndClosestPoint::distance);
1000 evaluateProximityField(
params.laserScannerProximityField, minDistance.distance);
1002 return {.twistLimits = result.first,
1003 .minDistance = minDistance.distance,
1004 .closestPoint = minDistance.closestPoint};
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
SafetyGuardResult computeSafetyLimits(const Eigen::Vector2f &global_V_movement) override
LaserBasedProximityParams Params
LaserBasedProximity(const Params ¶ms, const core::GeneralConfig &generalConfig, const core::Scene &scene, const Context &ctx)
SafetyGuard(const core::Scene &scene, const Context &ctx)
const core::Scene & scene
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
#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_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_VERBOSE
The logging level for verbose information.
std::shared_ptr< Dict > DictPtr
std::vector< Eigen::Vector2f > to2D(const std::vector< Eigen::Vector3f > &v)
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
This file is part of ArmarX.
void fromAron(const arondto::ProximityFieldParams &dto, ProximityFieldParams &bo)
void toAron(arondto::ProximityFieldParams &dto, const ProximityFieldParams &bo)
FilterReason
Why a laser scanner feature does not constrain the velocity.
@ TooFarAway
The feature is outside the influence distance.
@ MovingAway
The robot is moving away from the feature.
@ None
The feature constrains, or is a candidate to constrain, the velocity.
@ NoPoints
The feature has no points.
@ NearFieldArtifact
Small feature close to the robot, most likely a measuring artifact of the sensor.
@ AttachedObject
The feature lies fully inside the inflated OOBB of an attached object.
@ IgnoredRegion
The feature lies fully inside one of the ignored regions.
@ Tangential
The robot passes the feature exactly tangentially.
boost::geometry::model::d2::point_xy< float > point_type
boost::geometry::model::polygon< point_type > polygon_type
This file is part of ArmarX.
double distance(const Point &a, const Point &b)
std::optional< core::DynamicScene > dynamicScene
static TwistLimits ZeroLimits()
static TwistLimits NoLimits()
static LaserBasedProximityParams FromAron(const aron::data::DictPtr &dict)
aron::data::DictPtr toAron() const override
Algorithms algorithm() const override
std::experimental::observer_ptr< DebugObserverComponentPluginUser > debugObserver
void add(ElementT const &element)