31 #include <boost/regex.hpp>
33 #include <SimoxUtility/algorithm/string/string_tools.h>
34 #include <VirtualRobot/CollisionDetection/CollisionChecker.h>
35 #include <VirtualRobot/RobotNodeSet.h>
36 #include <VirtualRobot/SceneObjectSet.h>
59 interval = getProperty<int>(
"interval").getValue();
61 useWorkingMemory = getProperty<bool>(
"UseWorkingMemory").getValue();
64 workingMemoryName = getProperty<std::string>(
"WorkingMemoryName").getValue();
65 ARMARX_INFO <<
"Using WorkingMemory \"" << workingMemoryName <<
"\" to get SceneObjects."
68 usingTopic(getProperty<std::string>(
"WorkingMemoryListenerTopicName").getValue());
72 robotStateComponentName = getProperty<std::string>(
"RobotStateComponentName").getValue();
73 ARMARX_INFO <<
"Using RobotStateComponent \"" << robotStateComponentName
74 <<
"\" to get SceneObjects." << std::endl;
78 std::string collisionPairsString = getProperty<std::string>(
"CollisionPairs").getValue();
79 boost::regex regexCollisionPair(
80 "[\\[\\{\\(](([^:,\\[\\{\\(\\]\\}\\)]+:)?([^,\\[\\{\\(\\]\\}\\)]+,|[\\[\\{\\(]([^,\\[\\{\\("
81 "\\]\\}\\)]+,)*[^,\\[\\{\\(\\]\\}\\)]+[\\]\\}\\)],)){2}[0-9]*[.]?[0-9]*[\\]\\}\\)]");
83 boost::sregex_token_iterator iterCollisionPair(
84 collisionPairsString.begin(), collisionPairsString.end(), regexCollisionPair, 0);
85 boost::sregex_token_iterator end;
87 for (; iterCollisionPair != end; ++iterCollisionPair)
89 std::string collisionPairString = *iterCollisionPair;
90 while ((collisionPairString[0] ==
'{' &&
91 collisionPairString[collisionPairString.size() - 1] ==
'}') ||
92 (collisionPairString[0] ==
'(' &&
93 collisionPairString[collisionPairString.size() - 1] ==
')') ||
94 (collisionPairString[0] ==
'[' &&
95 collisionPairString[collisionPairString.size() - 1] ==
']'))
97 collisionPairString = collisionPairString.substr(1, collisionPairString.size() - 2);
100 if ((collisionPairString[0] ==
'{' || collisionPairString[0] ==
'(' ||
101 collisionPairString[0] ==
'[') &&
102 (collisionPairString[collisionPairString.size() - 1] ==
'}' ||
103 collisionPairString[collisionPairString.size() - 1] ==
')' ||
104 collisionPairString[collisionPairString.size() - 1] ==
']'))
106 ARMARX_ERROR <<
"Could not parse collision pair: " << *iterCollisionPair
107 <<
". Ignoring..." << std::endl;
111 boost::regex regex(
"([^:,\\[\\{\\(\\]\\}\\)]+:)?([\\{\\[\\(][^\\{\\[\\(\\]\\}\\)]+[\\]\\}"
112 "\\)]|[^\\{\\[\\(\\]\\}\\),]+)");
114 boost::sregex_token_iterator iter(
115 collisionPairString.begin(), collisionPairString.end(), regex, 0);
116 boost::sregex_token_iterator end;
120 std::string robotName1;
121 std::vector<std::string> nodeNames1;
123 std::string nodeSetName1;
124 parseNodeSet(*iter, robotName1, nodeNames1, usesNodeSet1, nodeSetName1);
129 std::string robotName2;
130 std::vector<std::string> nodeNames2;
132 std::string nodeSetName2;
133 parseNodeSet(*iter, robotName2, nodeNames2, usesNodeSet2, nodeSetName2);
146 std::atof(((std::string)*iter).c_str()));
151 collisionChecker = VirtualRobot::CollisionChecker::getGlobalCollisionChecker();
153 offeringTopic(getProperty<std::string>(
"CollisionListenerTopicName").getValue());
154 offeringTopic(getProperty<std::string>(
"DistanceListenerTopicName").getValue());
156 useDebugDrawer = getProperty<bool>(
"UseDebugDrawer").getValue();
163 std::scoped_lock lockData(dataMutex);
167 if (useWorkingMemory)
169 workingMemoryPrx = getProxy<memoryx::WorkingMemoryInterfacePrx>(workingMemoryName);
170 objectInstancesPrx = workingMemoryPrx->getObjectInstancesSegment();
171 agentInstancesPrx = workingMemoryPrx->getAgentInstancesSegment();
173 for (memoryx::AgentInstanceBasePtr& agent : agentInstancesPrx->getAllAgentInstances())
176 agent->getSharedRobot()->getRobotStateComponent();
180 robots.push_back({robot, robotStateComponentPrx});
186 getProxy<RobotStateComponentInterfacePrx>(robotStateComponentName);
191 RobotPair r = {robot, robotStateComponentPrx};
196 std::unique_lock lock(connectedMutex);
201 for (SceneObjectPair& pair : sceneObjectPairs)
203 if (!resolveCollisionPair(pair))
205 std::ostringstream nodeNames1Str;
207 pair.nodeNames1.end() - 1,
208 std::ostream_iterator<std::string>(nodeNames1Str,
","));
209 nodeNames1Str << pair.nodeNames1.back();
211 std::ostringstream nodeNames2Str;
213 pair.nodeNames2.end() - 1,
214 std::ostream_iterator<std::string>(nodeNames2Str,
","));
215 nodeNames2Str << pair.nodeNames2.back();
216 ARMARX_WARNING <<
"Could not resolve collision pair: {" << pair.robotName1
217 << (pair.robotName1 ==
"" ?
"" :
":") <<
"(" << nodeNames1Str.str()
218 <<
")," << pair.robotName2 << (pair.robotName2 ==
"" ?
"" :
":")
219 <<
"(" << nodeNames2Str.str() <<
")," << pair.warningDistance <<
"}"
225 collisionListenerPrx = getTopic<CollisionListenerPrx>(
226 getProperty<std::string>(
"CollisionListenerTopicName").getValue());
227 distanceListenerPrx = getTopic<DistanceListenerPrx>(
228 getProperty<std::string>(
"DistanceListenerTopicName").getValue());
234 &CollisionCheckerComponent::reportDistancesAndCollisions,
237 "ReportCollisionsTask");
244 debugDrawerTopicPrx = getTopic<DebugDrawerInterfacePrx>(
245 getProperty<std::string>(
"DebugDrawerTopicName").getValue());
247 if (!debugDrawerTopicPrx)
249 ARMARX_ERROR <<
"Failed to obtain debug drawer proxy." << std::endl;
250 useDebugDrawer =
false;
259 std::unique_lock lock(connectedMutex);
264 std::scoped_lock lockData(dataMutex);
265 for (SceneObjectPair& pair : sceneObjectPairs)
267 pair.objects1 = VirtualRobot::SceneObjectSetPtr();
268 pair.objects2 = VirtualRobot::SceneObjectSetPtr();
272 if (useDebugDrawer && debugDrawerTopicPrx)
274 debugDrawerTopicPrx->clearLayer(
"distanceVisu");
275 debugDrawerTopicPrx->removeLayer(
"distanceVisu");
292 armarx::CollisionCheckerComponent::resolveCollisionPair(SceneObjectPair& pair)
294 std::shared_lock lockConnected(connectedMutex);
300 if (pair.usesNodeSet1 && pair.nodeSetName1 !=
"")
302 pair.nodeNames1.clear();
303 if (pair.robotName1 !=
"")
305 for (RobotPair& robotPair :
robots)
307 if (robotPair.robot->getName() == pair.robotName1)
309 VirtualRobot::SceneObjectSetPtr
set =
310 robotPair.robot->getRobotNodeSet(pair.nodeSetName1);
315 pair.nodeNames1.push_back(
so->getName());
321 <<
"\" has no set with name \"" << pair.nodeSetName1 <<
"\""
330 ARMARX_WARNING <<
"No robot name given for RobotNodeSet \"" << pair.nodeSetName1 <<
"\""
335 VirtualRobot::SceneObjectSetPtr objects1(
new VirtualRobot::SceneObjectSet());
336 for (std::string& nodeName : pair.nodeNames1)
341 ARMARX_DEBUG <<
"failed to get object: \"" << pair.robotName1 <<
"\" : \"" << nodeName
342 <<
"\"" << std::endl;
345 if (!sc->getCollisionModel())
347 ARMARX_WARNING << pair.robotName1 << (pair.robotName1 ==
"" ?
"" :
".") << nodeName
348 <<
" does not have a collision model. Ignoring..." << std::endl;
351 objects1->addSceneObject(sc);
354 if (pair.usesNodeSet2 && pair.nodeSetName2 !=
"")
356 pair.nodeNames2.clear();
357 if (pair.robotName2 !=
"")
359 for (RobotPair& robotPair :
robots)
361 if (robotPair.robot->getName() == pair.robotName2)
363 VirtualRobot::SceneObjectSetPtr
set =
364 robotPair.robot->getRobotNodeSet(pair.nodeSetName2);
369 pair.nodeNames2.push_back(
so->getName());
375 <<
"\" has no set with name \"" << pair.nodeSetName2 <<
"\""
384 ARMARX_WARNING <<
"No robot name given for RobotNodeSet \"" << pair.nodeSetName2 <<
"\""
389 VirtualRobot::SceneObjectSetPtr objects2(
new VirtualRobot::SceneObjectSet());
390 for (std::string& nodeName : pair.nodeNames2)
395 ARMARX_DEBUG <<
"failed to get object: \"" << pair.robotName2 <<
"\" : \"" << nodeName
396 <<
"\"" << std::endl;
399 if (!sc->getCollisionModel())
401 ARMARX_WARNING << pair.robotName2 << (pair.robotName2 ==
"" ?
"" :
".") << nodeName
402 <<
" does not have a collision model. Ignoring..." << std::endl;
405 objects2->addSceneObject(sc);
408 if (!objects1 || !objects2 || objects1->getSize() == 0 || objects2->getSize() == 0)
413 pair.objects1 = objects1;
414 pair.objects2 = objects2;
419 armarx::CollisionCheckerComponent::getSceneObject(
const std::string& robotName,
420 const std::string& nodeName)
422 if (robotName.size() == 0 && useWorkingMemory)
424 ARMARX_DEBUG <<
"Get object from WorkingMemory: " << nodeName << std::endl;
425 return getSceneObjectFromWorkingMemory(nodeName);
427 else if (robotName.size() == 0)
430 ARMARX_DEBUG <<
"Get object from first robot: " << nodeName << std::endl;
431 return robots[0].robot->getRobotNode(nodeName);
435 ARMARX_DEBUG <<
"Searching for matching robot: " << robotName << std::endl;
436 for (RobotPair& r :
robots)
438 if (r.robot->getName() == robotName)
440 ARMARX_DEBUG <<
"Get object from robot: " << nodeName << std::endl;
441 return r.robot->getRobotNode(nodeName);
445 ARMARX_DEBUG << r.robot->getName() <<
" != " << robotName << std::endl;
454 armarx::CollisionCheckerComponent::parseNodeSet(
const std::string& setAsString,
455 std::string& robotName,
456 std::vector<std::string>& nodeNames,
458 std::string& nodeSetName)
462 std::string nodeNamesString;
463 switch (
split.size())
467 nodeNamesString =
split[0];
470 robotName =
split[0];
471 nodeNamesString =
split[1];
477 if (nodeNamesString[0] !=
'{' && nodeNamesString[0] !=
'(' && nodeNamesString[0] !=
'[')
480 nodeSetName = nodeNamesString;
487 while ((nodeNamesString[0] ==
'{' && nodeNamesString[nodeNamesString.size() - 1] ==
'}') ||
488 (nodeNamesString[0] ==
'(' && nodeNamesString[nodeNamesString.size() - 1] ==
')') ||
489 (nodeNamesString[0] ==
'[' && nodeNamesString[nodeNamesString.size() - 1] ==
']'))
491 nodeNamesString = nodeNamesString.substr(1, nodeNamesString.size() - 2);
502 armarx::CollisionCheckerComponent::getSceneObjectFromWorkingMemory(
const std::string& name)
506 if (sc->getName() == name)
511 const memoryx::EntityBasePtr entityBase = objectInstancesPrx->getEntityByName(name);
512 const memoryx::ObjectInstanceBasePtr
object =
513 memoryx::ObjectInstancePtr::dynamicCast(entityBase);
517 ARMARX_ERROR <<
"Could not get object with name " << name << std::endl;
521 const std::string className =
object->getMostProbableClass();
523 memoryx::ObjectClassList classes =
524 workingMemoryPrx->getPriorKnowledge()->getObjectClassesSegment()->getClassWithSubclasses(
529 ARMARX_INFO_S <<
"No classes for most probable class '" << className <<
"' of object '"
530 <<
object->getName() <<
"' with name " << name;
535 const PosePtr objectPose = armarx::PosePtr::dynamicCast(armarx::PoseBasePtr{
536 new armarx::Pose{
object->getPositionBase(), object->getOrientationBase()}});
540 ARMARX_ERROR <<
"Can't use object class with ice id " << classes.at(0)->ice_id()
547 VirtualRobot::ManipulationObjectPtr orgMo = sw->getManipulationObject();
549 std::string moName = orgMo->getName();
550 VirtualRobot::ManipulationObjectPtr mo = orgMo->clone(moName);
555 ARMARX_ERROR <<
"Can't convert pose of " << objectClass->getName() <<
" to armarx::Pose."
559 mo->setGlobalPose(objectPose->toEigen());
562 workingMemorySceneObjects.push_back(mo);
567 armarx::CollisionCheckerComponent::synchronizeObjectsFromWorkingMemory()
569 std::scoped_lock lockPosition(wmPositionMutex);
572 auto it = currentPositions.find(sc->getName());
573 if (it != currentPositions.end())
575 sc->setGlobalPose(it->second->toEigen());
581 armarx::CollisionCheckerComponent::reportDistancesAndCollisions()
583 std::scoped_lock lockData(dataMutex);
584 for (RobotPair& r :
robots)
587 r.robot, r.robotStateComponentPrx->getSynchronizedRobot());
589 synchronizeObjectsFromWorkingMemory();
591 for (SceneObjectPair& pair : sceneObjectPairs)
593 if (!pair.objects1 || !pair.objects2)
598 if (useDebugDrawer && debugDrawerTopicPrx)
600 std::ostringstream nodeNames1Str;
602 pair.nodeNames1.end() - 1,
603 std::ostream_iterator<std::string>(nodeNames1Str,
","));
604 nodeNames1Str << pair.nodeNames1.back();
606 std::ostringstream nodeNames2Str;
608 pair.nodeNames2.end() - 1,
609 std::ostream_iterator<std::string>(nodeNames2Str,
","));
610 nodeNames2Str << pair.nodeNames2.back();
612 Eigen::Vector3f p1, p2;
613 distance = collisionChecker->calculateDistance(pair.objects1, pair.objects2, p1, p2);
616 if (
distance <= pair.warningDistance)
628 debugDrawerTopicPrx->setLineVisu(
"distanceVisu",
629 pair.robotName1 + (pair.robotName1 ==
"" ?
"" :
": ") +
630 nodeNames1Str.str() +
" - " + pair.robotName2 +
631 (pair.robotName2 ==
"" ?
"" :
": ") +
640 distance = collisionChecker->calculateDistance(pair.objects1, pair.objects2);
643 distanceListenerPrx->reportDistance(
644 pair.robotName1, pair.nodeNames1, pair.robotName2, pair.nodeNames2,
distance);
646 if (
distance <= pair.warningDistance)
648 collisionListenerPrx->reportCollisionWarning(
649 pair.robotName1, pair.nodeNames1, pair.robotName2, pair.nodeNames2,
distance);
652 if (collisionChecker->checkCollision(pair.objects1, pair.objects2))
654 collisionListenerPrx->reportCollision(
655 pair.robotName1, pair.nodeNames1, pair.robotName2, pair.nodeNames2,
distance);
662 const std::vector<std::string>& nodeNames1,
663 const std::string& robotName2,
664 const std::vector<std::string>& nodeNames2,
665 double warningDistance,
669 robotName1, nodeNames1,
false,
"", robotName2, nodeNames2,
false,
"", warningDistance);
674 const std::vector<std::string>& nodeNames1,
675 const bool usesNodeSet1,
676 const std::string& nodeSetName1,
677 const std::string& robotName2,
678 const std::vector<std::string>& nodeNames2,
679 const bool usesNodeSet2,
680 const std::string& nodeSetName2,
681 double warningDistance)
687 SceneObjectPair pair = {VirtualRobot::SceneObjectSetPtr(),
692 VirtualRobot::SceneObjectSetPtr(),
698 std::scoped_lock lockData(dataMutex);
699 resolveCollisionPair(pair);
700 sceneObjectPairs.push_back(pair);
705 const std::vector<std::string>& nodeNames1,
706 const std::string& robotName2,
707 const std::vector<std::string>& nodeNames2,
710 std::scoped_lock lockData(dataMutex);
711 for (
auto it = sceneObjectPairs.begin(); it != sceneObjectPairs.end(); it++)
713 if ((it->robotName1 == robotName1 && it->nodeNames1 == nodeNames1 &&
714 it->robotName2 == robotName2 && it->nodeNames2 == nodeNames2) ||
715 (it->robotName1 == robotName2 && it->nodeNames1 == nodeNames2 &&
716 it->robotName2 == robotName1 && it->nodeNames2 == nodeNames1))
718 sceneObjectPairs.erase(it);
726 const std::vector<std::string>& nodeNames1,
727 const std::string& robotName2,
728 const std::vector<std::string>& nodeNames2,
729 const Ice::Current&)
const
731 std::scoped_lock lockData(dataMutex);
732 for (
const SceneObjectPair& pair : sceneObjectPairs)
734 if ((pair.robotName1 == robotName1 && pair.nodeNames1 == nodeNames1 &&
735 pair.robotName2 == robotName2 && pair.nodeNames2 == nodeNames2) ||
736 (pair.robotName1 == robotName2 && pair.nodeNames1 == nodeNames2 &&
737 pair.robotName2 == robotName1 && pair.nodeNames2 == nodeNames1))
747 const std::vector<std::string>& nodeNames1,
748 const std::string& robotName2,
749 const std::vector<std::string>& nodeNames2,
750 double warningDistance,
753 std::scoped_lock lockData(dataMutex);
754 for (SceneObjectPair& pair : sceneObjectPairs)
756 if ((pair.robotName1 == robotName1 && pair.nodeNames1 == nodeNames1 &&
757 pair.robotName2 == robotName2 && pair.nodeNames2 == nodeNames2) ||
758 (pair.robotName1 == robotName2 && pair.nodeNames1 == nodeNames2 &&
759 pair.robotName2 == robotName1 && pair.nodeNames2 == nodeNames1))
761 pair.warningDistance = warningDistance;
769 const std::vector<std::string>& nodeNames1,
770 const std::string& robotName2,
771 const std::vector<std::string>& nodeNames2,
772 const Ice::Current&)
const
774 std::scoped_lock lockData(dataMutex);
775 for (
const SceneObjectPair& pair : sceneObjectPairs)
777 if ((pair.robotName1 == robotName1 && pair.nodeNames1 == nodeNames1 &&
778 pair.robotName2 == robotName2 && pair.nodeNames2 == nodeNames2) ||
779 (pair.robotName1 == robotName2 && pair.nodeNames1 == nodeNames2 &&
780 pair.robotName2 == robotName1 && pair.nodeNames2 == nodeNames1))
782 return pair.warningDistance;
791 std::scoped_lock lockData(dataMutex);
792 CollisionPairList
list;
793 for (
const SceneObjectPair& pair : sceneObjectPairs)
795 armarx::CollisionPair p = {pair.robotName1,
799 pair.warningDistance};
814 std::shared_lock lockConnected(connectedMutex);
816 if (connected && reportTask && reportTask->isRunning())
821 &CollisionCheckerComponent::reportDistancesAndCollisions,
824 "ReportCollisionsTask");
831 &CollisionCheckerComponent::reportDistancesAndCollisions,
834 "ReportCollisionsTask");
839 CollisionCheckerComponent::reportEntityCreated(
const std::string& segmentName,
840 const memoryx::EntityBasePtr& entity,
843 if (segmentName == objectInstancesPrx->getSegmentName())
845 std::scoped_lock lockData(dataMutex);
846 for (SceneObjectPair& pair : sceneObjectPairs)
848 if ((!pair.objects1 || !pair.objects2) &&
849 ((pair.robotName1 ==
"" &&
850 std::find(pair.nodeNames1.begin(), pair.nodeNames1.end(), entity->getName()) !=
851 pair.nodeNames1.end()) ||
852 (pair.robotName2 ==
"" &&
853 std::find(pair.nodeNames2.begin(), pair.nodeNames2.end(), entity->getName()) !=
854 pair.nodeNames2.end())))
856 resolveCollisionPair(pair);
860 else if (segmentName == agentInstancesPrx->getSegmentName())
862 std::scoped_lock lockData(dataMutex);
863 memoryx::AgentInstanceBasePtr agent =
864 agentInstancesPrx->getAgentInstanceById(entity->getId());
866 agent->getSharedRobot()->getRobotStateComponent();
870 robots.push_back({robot, robotStateComponentPrx});
873 for (SceneObjectPair& pair : sceneObjectPairs)
875 if ((!pair.objects1 || !pair.objects2) &&
876 (pair.robotName1 == entity->getName() || pair.robotName2 == entity->getName()))
878 resolveCollisionPair(pair);
885 CollisionCheckerComponent::reportEntityUpdated(
const std::string& segmentName,
886 const memoryx::EntityBasePtr& entityOld,
887 const memoryx::EntityBasePtr& entityNew,
890 if (segmentName == objectInstancesPrx->getSegmentName())
892 std::scoped_lock lockPosition(wmPositionMutex);
893 const memoryx::ObjectInstanceBasePtr
object =
894 memoryx::ObjectInstancePtr::dynamicCast(entityNew);
895 currentPositions[entityNew->getName()] = armarx::PosePtr::dynamicCast(armarx::PoseBasePtr{
896 new armarx::Pose{
object->getPositionBase(), object->getOrientationBase()}});
901 CollisionCheckerComponent::reportEntityRemoved(
const std::string& segmentName,
902 const memoryx::EntityBasePtr& entity,
905 if (segmentName == objectInstancesPrx->getSegmentName())
907 std::scoped_lock lockData(dataMutex);
908 for (SceneObjectPair& pair : sceneObjectPairs)
910 if ((pair.robotName1 ==
"" &&
911 std::find(pair.nodeNames1.begin(), pair.nodeNames1.end(), entity->getName()) !=
912 pair.nodeNames1.end()) ||
913 (pair.robotName2 ==
"" &&
914 std::find(pair.nodeNames2.begin(), pair.nodeNames2.end(), entity->getName()) !=
915 pair.nodeNames2.end()))
917 pair.objects1.reset();
918 pair.objects2.reset();
921 for (
auto it = workingMemorySceneObjects.begin(); it != workingMemorySceneObjects.end();
924 if ((*it)->getName() == entity->getName())
926 workingMemorySceneObjects.erase(it);
931 else if (segmentName == agentInstancesPrx->getSegmentName())
933 std::scoped_lock lockData(dataMutex);
934 for (
auto it =
robots.begin(); it !=
robots.end(); ++it)
936 if ((*it).robot->getName() == entity->getName())
943 for (SceneObjectPair& pair : sceneObjectPairs)
945 if (pair.robotName1 == entity->getName() || pair.robotName2 == entity->getName())
947 pair.objects1.reset();
948 pair.objects2.reset();
955 CollisionCheckerComponent::reportSnapshotLoaded(
const std::string& segmentName,
const Ice::Current&)
957 if (segmentName == objectInstancesPrx->getSegmentName())
959 std::scoped_lock lockData(dataMutex);
960 for (SceneObjectPair& pair : sceneObjectPairs)
962 if (!pair.objects1 || !pair.objects2)
964 resolveCollisionPair(pair);
971 CollisionCheckerComponent::reportSnapshotCompletelyLoaded(
const Ice::Current&
c)
976 CollisionCheckerComponent::reportMemoryCleared(
const std::string& segmentName,
const Ice::Current&)
978 if (segmentName == objectInstancesPrx->getSegmentName())
980 std::scoped_lock lockData(dataMutex);
981 for (SceneObjectPair& pair : sceneObjectPairs)
983 if (pair.robotName1 ==
"" || pair.robotName2 ==
"")
985 pair.objects1.reset();
986 pair.objects2.reset();