30 #include <unordered_map>
31 #include <unordered_set>
33 #include <VirtualRobot/CollisionDetection/CDManager.h>
34 #include <VirtualRobot/CollisionDetection/CollisionModel.h>
35 #include <VirtualRobot/RobotFactory.h>
36 #include <VirtualRobot/RobotNodeSet.h>
37 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
38 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.h>
39 #include <VirtualRobot/XML/RobotIO.h>
47 #include "../util/Metrics.h"
54 #include <MotionPlanning/CSpace/CSpaceSampled.h>
80 static Initializer init;
81 return init.doStuff();
85 bool loadVisualizationModel,
86 float stationaryObjectMargin) :
89 this->stationaryObjectMargin = stationaryObjectMargin;
109 commonStorage = commonStoragePrx;
114 throw std::invalid_argument{
"SimoxCSpace ctor: commonStorage == null"};
125 for (
const auto& obj : stationaryObjects)
127 cloned->addStationaryObject(obj);
129 cloned->agentInfo = agentInfo;
136 Saba::CSpaceSampledPtr
141 VirtualRobot::CDManagerPtr tmpCd =
142 VirtualRobot::CDManagerPtr(
new VirtualRobot::CDManager(
cd));
148 Saba::CSpaceSampledPtr result(
new Saba::CSpaceSampled(
151 agentInfo.kinemaicChainNames.size() > 0
152 ?
agentSceneObj->getRobotNodeSet(agentInfo.kinemaicChainNames.at(0))
153 : VirtualRobot::RobotNodeSetPtr()));
163 stationaryObjects.emplace_back(obj);
169 stationaryObjects = objList;
175 this->agentInfo = agentInfo;
186 jointValues[agentJoint->getName()] = *it;
187 agentJoint->setJointValueNoUpdate(*(it++));
205 return !
cd.isInCollision();
224 TIMING_END(CSpaceInit_ensureCoinIsInitialized)
242 new VirtualRobot::SceneObjectSet{
"StationaryObjectSet",
cd.getCollisionChecker()});
246 for (std::size_t i = 0; i < stationaryObjects.size(); ++i)
249 const auto& obj = stationaryObjects.at(i);
253 sceneObj->setUpdateVisualization(
false);
259 VirtualRobot::CoinVisualizationNodePtr visu(
new VirtualRobot::CoinVisualizationNode(
260 (SoNode*)VirtualRobot::CoinVisualizationFactory::CreatePolygonVisualization(
265 VirtualRobot::CollisionModelPtr(
new VirtualRobot::CollisionModel(visu)),
266 VirtualRobot::SceneObject::Physics{},
267 cd.getCollisionChecker()));
277 { return obj->getName(); });
288 if (agentInfo.agentPose)
290 agentData.
agent->setGlobalPose(
291 armarx::PosePtr::dynamicCast(agentInfo.agentPose)->toEigen());
298 const std::size_t numberOfJoints = agentData.
joints.size();
309 cd.addCollisionModel(std::move(colMod));
321 auto packageNames = agentInfo.agentProjectNames;
322 if (!agentInfo.agentProjectName.empty())
324 packageNames.emplace_back(agentInfo.agentProjectName);
327 std::string absoluteFilePath;
328 std::vector<std::string> paths;
329 for (
const auto& package : packageNames)
333 std::vector<std::string> packagePaths =
Split(pathStr,
";,",
false,
true);
335 paths.reserve(paths.size() + packagePaths.size());
336 std::move(packagePaths.begin(), packagePaths.end(), std::back_inserter(paths));
340 agentInfo.agentRelativeFilePath, absoluteFilePath, paths))
343 s <<
"could not find file " << agentInfo.agentRelativeFilePath <<
" in project "
344 << agentInfo.agentProjectName;
346 throw std::invalid_argument{
s.str()};
353 : VirtualRobot::RobotIO::eCollisionModel)
354 : VirtualRobot::RobotIO::eStructure;
355 auto pair = std::make_pair(loadType, absoluteFilePath);
359 agent = VirtualRobot::RobotIO::loadRobot(absoluteFilePath, loadType);
361 ARMARX_DEBUG <<
"Robot Cache MISS! Path: " << absoluteFilePath
362 <<
" load type: " << (int)loadType;
364 agent = pool->getRobot();
370 ARMARX_DEBUG <<
"Robot Cache hit! load type: " << (int)loadType;
388 s <<
"Can't load agent from: " << absoluteFilePath;
390 throw std::invalid_argument{
s.str()};
403 data.agent = robotPtr;
410 std::unordered_map<std::string, std::vector<VirtualRobot::RobotNodePtr>>
411 toCollSetAssociatedObjects;
412 toCollSetAssociatedObjects.reserve(agentInfo.collisionSetNames.size());
414 for (std::size_t i = 0; i < agentInfo.attachedObjects.size(); ++i)
416 const auto& attached = agentInfo.attachedObjects.at(i);
418 attached.objectClassBase,
fileManager,
false, robotPtr->getCollisionChecker());
419 std::stringstream sceneObjName;
420 sceneObjName <<
"attached_obj_" << i <<
"_" << sceneObj->getName();
421 sceneObj->setName(sceneObjName.str());
424 if (!
data.agent->hasRobotNode(attached.attachedToRobotNodeName))
427 s <<
"Agent " <<
data.agent->getName() <<
" has no node "
428 << attached.attachedToRobotNodeName <<
"to attach object "
429 << attached.objectClassBase->getName();
431 throw std::invalid_argument{
s.str()};
434 VirtualRobot::RobotNodePtr nodeToAttachTo =
435 data.agent->getRobotNode(attached.attachedToRobotNodeName);
436 VirtualRobot::RobotFactory::attach(
440 armarx::PosePtr::dynamicCast(attached.relativeObjectPose)->toEigen());
443 if (attached.associatedCollisionSetName.empty())
446 data.collisionSets.emplace_back(
new VirtualRobot::SceneObjectSet{
447 sceneObjName.str(),
data.agent->getCollisionChecker()});
448 data.collisionSets.back()->addSceneObject(
449 data.agent->getRobotNode(sceneObjName.str()));
454 if (
std::find(agentInfo.collisionSetNames.begin(),
455 agentInfo.collisionSetNames.end(),
456 attached.associatedCollisionSetName) ==
457 agentInfo.collisionSetNames.end())
460 s <<
"Agent " <<
data.agent->getName() <<
" has no set "
461 << attached.associatedCollisionSetName
462 <<
" to use as associated collision set for attached object "
463 << attached.objectClassBase->getName();
465 throw std::invalid_argument{
s.str()};
468 toCollSetAssociatedObjects[attached.associatedCollisionSetName].emplace_back(
469 data.agent->getRobotNode(sceneObjName.str()));
473 for (
const auto& name : agentInfo.collisionSetNames)
475 if (!
data.agent->hasRobotNodeSet(name))
478 s <<
"Agent " <<
data.agent->getName() <<
" has no collision model " << name;
480 throw std::invalid_argument{
s.str()};
484 data.collisionSets.emplace_back(
485 new VirtualRobot::SceneObjectSet{name,
data.agent->getCollisionChecker()});
486 data.collisionSets.back()->addSceneObjects(
data.agent->getRobotNodeSet(name));
488 for (
auto& obj : toCollSetAssociatedObjects[name])
490 data.collisionSets.back()->addSceneObject(std::move(obj));
493 if (!agentInfo.collisionObjectNames.empty())
495 data.collisionSets.emplace_back(
new VirtualRobot::SceneObjectSet{
496 "collisionObjects",
data.agent->getCollisionChecker()});
497 for (
const auto& name : agentInfo.collisionObjectNames)
499 if (!
data.agent->hasRobotNode(name))
502 s <<
"Agent " <<
data.agent->getName() <<
" has no collision model "
505 throw std::invalid_argument{
s.str()};
509 data.collisionSets.back()->addSceneObject(
data.agent->getRobotNode(name));
511 for (
auto& obj : toCollSetAssociatedObjects[name])
513 data.collisionSets.back()->addSceneObject(std::move(obj));
521 std::set<std::string> blacklist(agentInfo.jointsExcludedFromPlanning.begin(),
522 agentInfo.jointsExcludedFromPlanning.end());
524 for (
const auto& name : agentInfo.kinemaicChainNames)
526 if (!
data.agent->hasRobotNodeSet(name))
529 s <<
"Agent " <<
data.agent->getName() <<
" has no kinematic chain " << name;
531 throw std::invalid_argument{
s.str()};
535 for (
auto& node : *(
data.agent->getRobotNodeSet(name)))
537 auto nodeIt = blacklist.find(node->getName());
538 if (nodeIt != blacklist.end())
543 if (!(node->isTranslationalJoint() || node->isRotationalJoint()))
546 s <<
"The node " << node->getName() <<
" in the kinematic chain " << name
547 <<
" of agent " <<
data.agent->getName()
548 <<
" is neither rotational nor tranlational";
550 throw std::invalid_argument{
s.str()};
553 data.joints.emplace_back(node);
554 blacklist.emplace_hint(nodeIt, node->getName());
558 for (
const auto& name : agentInfo.additionalJointsForPlanning)
560 if (!
data.agent->hasRobotNode(name))
563 s <<
"Agent " <<
data.agent->getName() <<
" has no node " << name;
565 throw std::invalid_argument{
s.str()};
567 auto node =
data.agent->getRobotNode(name);
569 auto nodeIt = blacklist.find(node->getName());
570 if (nodeIt != blacklist.end())
575 if (!(node->isTranslationalJoint() || node->isRotationalJoint()))
578 s <<
"The node " << node->getName() <<
" of agent " <<
data.agent->getName()
579 <<
" is neither rotational nor tranlational";
581 throw std::invalid_argument{
s.str()};
584 data.joints.emplace_back(node);
585 blacklist.emplace_hint(nodeIt, node->getName());
590 VirtualRobot::ManipulationObjectPtr
592 const memoryx::ObjectClassBasePtr&
object,
595 VirtualRobot::CollisionCheckerPtr
const& colChecker)
const
601 VirtualRobot::ManipulationObjectPtr mo;
605 s <<
"Can't use object class with ice id " <<
object->ice_id();
607 throw armarx::InvalidArgumentException{
s.str()};
611 auto pair = std::make_pair((
int)(stationaryObjectMargin * 1000), object->getId());
612 auto pairZeroMargin = std::make_pair(0, object->getId());
618 mo = tmpMo->clone(tmpMo->getName(), colChecker,
true);
620 ARMARX_DEBUG <<
"mesh Cache hit for " << tmpMo->getName() <<
" - Cloning took "
621 << (end - start).toMilliSeconds();
628 ARMARX_DEBUG <<
"mesh Cache HALFMISS - mesh inflation needed for "
630 mo = tmpMo->clone(tmpMo->getName(), colChecker,
true);
635 fileManager, VirtualRobot::RobotIO::eCollisionModel));
636 VirtualRobot::ManipulationObjectPtr orgMo = sw->getManipulationObject();
637 ARMARX_DEBUG <<
"mesh Cache MISS for " << orgMo->getName();
639 std::string moName = orgMo->getName();
640 mo = orgMo->clone(moName, colChecker,
true);
642 if (this->stationaryObjectMargin != 0.0f && inflate)
645 << stationaryObjectMargin <<
" as margin";
647 mo->getCollisionModel()->inflateModel(this->stationaryObjectMargin);
657 VirtualRobot::ManipulationObjectPtr
659 const PoseBasePtr& pose,
666 const_cast<VirtualRobot::CDManager*
>(&
cd)->getCollisionChecker());
669 const auto objectPose = armarx::PosePtr::dynamicCast(pose);
674 s <<
"Can't convert pose of " << memoryx::ObjectClassPtr::dynamicCast(
object)->getName()
675 <<
" to armarx::Pose.";
677 throw armarx::InvalidArgumentException{
s.str()};
680 mo->setGlobalPose(objectPose->toEigen());
686 memoryx::WorkingMemoryInterfacePrx workingMemoryPrx,
687 const std::vector<std::string>& excludedInstancesIds )
691 auto objInstPrx = workingMemoryPrx->getObjectInstancesSegment();
692 const auto objs = objInstPrx->getAllEntities();
693 auto agentSeg = workingMemoryPrx->getAgentInstancesSegment();
695 for (
const auto& entityBase : objs)
697 auto id = entityBase->getId();
698 if (
std::find(excludedInstancesIds.cbegin(), excludedInstancesIds.cend(),
id) !=
699 excludedInstancesIds.cend())
705 memoryx::ObjectInstancePtr::dynamicCast(entityBase);
706 auto objPose =
object->getPose();
707 if (objPose->frame !=
GlobalFrame && !objPose->frame.empty())
709 objPose = FramedPosePtr::dynamicCast(
710 agentSeg->convertToWorldPose(objPose->agent, objPose));
715 const std::string className =
object->getMostProbableClass();
717 memoryx::ObjectClassList classes = workingMemoryPrx->getPriorKnowledge()
718 ->getObjectClassesSegment()
719 ->getClassWithSubclasses(className);
723 ARMARX_INFO_S <<
"No classes for most probable class '" << className
724 <<
"' of object '" <<
object->getName() <<
"' with id " << id;
735 memoryx::CommonStorageInterfacePrx commonStoragePrx,
740 AgentPlanningInformation agentData;
741 agentData.agentProjectNames = rsc->getArmarXPackages();
742 agentData.agentRelativeFilePath = rsc->getRobotFilename();
744 cspace->setAgent(agentData);
746 cspace->addObjectsFromWorkingMemory(workingMemoryPrx);
747 cspace->initCollisionTest();
762 ARMARX_ERROR_S <<
"SimoxCSpace ice_postUnmarshal: commonStorage == null";
763 throw std::invalid_argument{
"SimoxCSpace ice_postUnmarshal: commonStorage == null"};
770 template <
class T,
class Thrower>
771 std::vector<std::vector<T>>
772 transpose(
const std::vector<std::vector<T>>& src, Thrower thrower)
774 std::size_t numDatapoints = src.size();
779 std::size_t numDimensions = src.at(0).size();
780 std::vector<std::vector<T>> transposed(numDimensions, std::vector<T>(numDatapoints));
781 for (std::size_t i = 0; i < numDatapoints; ++i)
783 auto& datapoint = src.at(i);
784 if (datapoint.size() !=
static_cast<std::size_t
>(numDimensions))
786 thrower(i, datapoint.size(), numDimensions);
788 for (std::size_t dim = 0; dim < numDimensions; ++dim)
790 transposed.at(dim).at(i) = datapoint.at(dim);
797 std::vector<std::vector<T>>
801 [](std::size_t idx, std::size_t szi, std::size_t numDim)
803 std::stringstream ss;
804 ss <<
"transpose: Element " << idx <<
" has " << szi
805 <<
" dimensions. The Element 0 has " << numDim <<
"dimensions.";
806 throw std::invalid_argument{ss.str()};
817 auto thrower = [](std::size_t idx, std::size_t szi, std::size_t numDim)
819 std::stringstream ss;
820 ss <<
"SimoxCSpace::pathToTrajectory: The datapoint " << idx <<
" has " << szi
821 <<
" dimensions. The CSpace has " << numDim <<
"dimensions.";
822 throw std::invalid_argument{ss.str()};
830 LimitlessStateSeq limitlessStates;
833 LimitlessState state;
834 state.enabled = joint->isLimitless();
835 state.limitHi = joint->getJointLimitHigh();
836 state.limitLo = joint->getJointLimitLow();
837 limitlessStates.push_back(state);
839 traj->setLimitless(limitlessStates);
850 std::back_inserter(dims),
851 [](
const VirtualRobot::RobotNodePtr& joint) {
852 return FloatRange{joint->getJointLimitLo(), joint->getJointLimitHi()};
858 SimoxCSpace::getAgentJointNames()
const
860 Ice::StringSeq result;
861 result.reserve(getAgentJoints().size());
862 for (
const auto& e : getAgentJoints())
864 result.emplace_back(e->getName());
870 SimoxCSpace::jointMapToVector(
const std::map<std::string, float>& jointMap,
871 bool checkForNonexistenJointsInCspace)
const
873 VectorXf result(getDimensionality(), 0.f);
874 std::size_t valuesFromMapUsed = 0;
875 auto jointNames = getAgentJointNames();
876 for (std::size_t i = 0; i < jointNames.size(); ++i)
878 auto it = jointMap.find(jointNames.at(i));
879 if (it != jointMap.end())
881 result.at(i) = it->second;
885 if (checkForNonexistenJointsInCspace && (valuesFromMapUsed != jointMap.size()))
887 throw std::invalid_argument{
888 "the joint map contained a joint not contained by the cspace!"};
893 SimoxCSpaceWith2DPose::SimoxCSpaceWith2DPose(
894 memoryx::CommonStorageInterfacePrx commonStoragePrx,
895 bool loadVisualizationModel,
896 float stationaryObjectMargin) :
897 SimoxCSpace(commonStoragePrx, loadVisualizationModel, stationaryObjectMargin)
907 for (
const auto& obj : stationaryObjects)
909 cloned->addStationaryObject(obj);
911 cloned->poseBounds = poseBounds;
912 cloned->agentInfo = agentInfo;
921 bounds.at(0).min = poseBounds.min.e0;
922 bounds.at(0).max = poseBounds.max.e0;
924 bounds.at(1).min = poseBounds.min.e1;
925 bounds.at(1).max = poseBounds.max.e1;
927 bounds.at(2).min = poseBounds.min.e2;
928 bounds.at(2).max = poseBounds.max.e2;
931 std::move(parentBounds.begin(), parentBounds.end(), bounds.begin() + 3);
939 joints.resize(joints.size() + 3);
940 std::move_backward(joints.begin(), joints.end() - 3, joints.end());
943 joints.at(2) =
"alpha";
953 const auto rot = *(it++);
955 const auto crot = std::cos(rot);
956 const auto srot = std::sin(rot);
971 memoryx::CommonStorageInterfacePrx commonStoragePrx,
972 bool loadVisualizationModel,
973 float stationaryObjectMargin) :
974 SimoxCSpace(commonStoragePrx, loadVisualizationModel, stationaryObjectMargin)
984 for (
const auto& obj : stationaryObjects)
986 cloned->addStationaryObject(obj);
988 cloned->poseBounds = poseBounds;
989 cloned->agentInfo = agentInfo;
998 bounds.at(0).min = poseBounds.min.e0;
999 bounds.at(0).max = poseBounds.max.e0;
1001 bounds.at(1).min = poseBounds.min.e1;
1002 bounds.at(1).max = poseBounds.max.e1;
1004 bounds.at(2).min = poseBounds.min.e2;
1005 bounds.at(2).max = poseBounds.max.e2;
1007 bounds.at(3).min = poseBounds.min.e3;
1008 bounds.at(3).max = poseBounds.max.e3;
1010 bounds.at(4).min = poseBounds.min.e4;
1011 bounds.at(4).max = poseBounds.max.e4;
1013 bounds.at(5).min = poseBounds.min.e5;
1014 bounds.at(5).max = poseBounds.max.e5;
1016 std::move(parentBounds.begin(), parentBounds.end(), bounds.begin() + 6);
1027 const auto roll = *(it++);
1028 const auto pitch = *(it++);
1029 const auto yaw = *(it++);
1031 const auto croll = std::cos(roll);
1032 const auto sroll = std::sin(roll);
1034 const auto cpitch = std::cos(pitch);
1035 const auto spitch = std::sin(pitch);
1037 const auto cyaw = std::cos(yaw);
1038 const auto syaw = std::sin(yaw);
1062 joints.resize(joints.size() + 6);
1063 std::move_backward(joints.begin(), joints.end() - 6, joints.end());
1067 joints.at(3) =
"alpha";
1068 joints.at(4) =
"betha";
1069 joints.at(5) =
"gamma";
1073 std::vector<armarx::DebugDrawerLineSet>
1075 const std::vector<std::string>& nodeNames,
1076 float traceStepSize)
1078 if (traceStepSize <= 0)
1080 throw std::invalid_argument{
"SimoxCSpace::getTraces: traceStepSize <= 0"};
1082 std::vector<armarx::DebugDrawerLineSet> traces;
1083 if (nodeNames.empty())
1087 traces.resize(nodeNames.size());
1088 if (vecs.size() < 2)
1092 auto addPoints = [&]
1094 for (std::size_t i = 0; i < nodeNames.size(); ++i)
1096 const auto& name = nodeNames.at(i);
1097 armarx::DebugDrawerLineSet&
trace = traces.at(i);
1099 trace.points.emplace_back(
1100 DebugDrawerPointCloudElement{pose(0, 3), pose(1, 3), pose(2, 3)});
1103 for (std::size_t vecI = 0; vecI < vecs.size() - 1; ++vecI)
1105 const auto& vecStart = vecs.at(vecI);
1106 const auto& vecEnd = vecs.at(vecI + 1);
1107 assert(vecStart.size() == vecEnd.size());
1109 auto dist =
euclideanDistance(vecStart.begin(), vecStart.end(), vecEnd.begin());
1110 if (dist > traceStepSize)
1112 VectorXf vecCfg = vecStart;
1117 Eigen::VectorXf eStep = (eEnd - eStart).normalized() * traceStepSize;
1119 while (dist > traceStepSize)
1125 dist -= traceStepSize;