35 #include <VirtualRobot/XML/ObjectIO.h>
36 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.h>
38 #include <SimoxUtility/algorithm/string/string_tools.h>
41 #include <Inventor/nodes/SoSeparator.h>
42 #include <Inventor/nodes/SoNode.h>
43 #include <Inventor/nodes/SoGroup.h>
44 #include <Inventor/nodes/SoSeparator.h>
45 #include <Inventor/nodes/SoImage.h>
46 #include <Inventor/nodes/SoFile.h>
47 #include <Inventor/nodes/SoTexture2.h>
48 #include <Inventor/nodes/SoTexture3.h>
49 #include <Inventor/VRMLnodes/SoVRMLImageTexture.h>
50 #include <Inventor/actions/SoSearchAction.h>
53 #include <Eigen/Eigenvalues>
63 namespace fs = std::filesystem;
83 uncertaintyVisuType(eEllipse)
85 coinVisFactory.reset(
new VirtualRobot::CoinVisualizationFactory());
96 throw armarx::LocalException(
"Loadmode must either be eFull oder eCollisionModel");
98 this->loadMode = loadMode;
114 return simoxObject->getVisualization();
119 const std::string ivFName = cacheAttributeFile(
ATTR_IV_FILE,
true);
120 return coinVisFactory->getVisualizationFromFile(ivFName);
128 return simoxObject->getCollisionModel();
134 return VirtualRobot::CollisionModelPtr(
new VirtualRobot::CollisionModel(coinVisFactory->getVisualizationFromFile(ivFName)));
153 const std::string ivFName = cacheAttributeFile(
ATTR_IV_FILE,
true);
164 return storeManipulationObject(mo, filesDBName);
175 if (!xmlFName.empty())
177 VirtualRobot::ManipulationObjectPtr mo = loadManipulationObjectFile(xmlFName);
179 ARMARX_INFO_S <<
" Saved manipulation object file: " << xmlFName <<
" (Id: " << fileId <<
")";
189 if (!xmlFName.empty())
192 VirtualRobot::ManipulationObjectPtr mo = loadManipulationObjectFile(xmlFName);
198 const std::string& filesDBName)
200 VirtualRobot::ManipulationObjectPtr mo = createManipulationObjectFromIvFiles(
getEntity()->
getName(), ivFNameVis, ivFNameCollision);
202 ARMARX_INFO_S <<
" Saved IV model file: " << ivFNameVis <<
" (Id: " << ivFileId <<
")";
207 VirtualRobot::ManipulationObjectPtr mo = createManipulationObjectFromIvFiles(
getEntity()->
getName(), ivFNameVis, ivFNameCollision);
213 this->uncertaintyVisuType = visuType;
217 float heatmapDensityThreshold,
int heatmapGridSize)
219 this->ellipseRadiusInSigmas = ellipseRadiusInSigmas;
220 this->heatmapMinVariance = heatmapMinVariance;
221 this->heatmapDensityThreshold = heatmapDensityThreshold;
222 this->heatmapGridSize = heatmapGridSize;
225 VirtualRobot::ColorMap SimoxObjectWrapper::getUncertaintyColorMap()
231 if (mapName ==
"eHot")
233 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eHot);
235 else if (mapName ==
"eIntensity")
237 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eIntensity);
239 else if (mapName ==
"eRed")
241 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eRed);
243 else if (mapName ==
"eGreen")
245 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eGreen);
247 else if (mapName ==
"eBlue")
249 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eBlue);
251 else if (mapName ==
"eHotAlpha")
253 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eHotAlpha);
255 else if (mapName ==
"eRedAlpha")
257 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eRedAlpha);
259 else if (mapName ==
"eGreenAlpha")
261 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eGreenAlpha);
263 else if (mapName ==
"eBlueAlpha")
265 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eBlueAlpha);
269 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eHot);
274 return VirtualRobot::ColorMap(VirtualRobot::ColorMap::eHot);
278 float SimoxObjectWrapper::getUncertaintyEllipseTransparency()
317 m.block(0, 3, 3, 1) = objPos->toEigen();
325 m.block(0, 0, 3, 3) = objOrient->toEigen();
336 mo->setGlobalPose(m);
341 EntityAttributeBasePtr posAttr = obj->getPositionAttribute();
342 ProbabilityMeasureBasePtr posDist = posAttr->getUncertainty();
346 static const std::string UNCERTAINTY_VISU_NAME =
"positionUncertainty";
347 VirtualRobot::VisualizationNodePtr moVis;
351 moVis = mo->getVisualization();
355 moVis->detachVisualization(UNCERTAINTY_VISU_NAME);
369 VirtualRobot::VisualizationNodePtr posDistVisu;
373 const VirtualRobot::ColorMap cmap = getUncertaintyColorMap();
375 switch (uncertaintyVisuType)
378 posDistVisu = getUncertaintyEllipsesVisu(posGM, objPos->toEigen(), cmap, getUncertaintyEllipseTransparency());
382 posDistVisu = getUncertaintyHeatVisu(posGM, objPos->toEigen(),
false, cmap);
386 posDistVisu = getUncertaintyHeatVisu(posGM, objPos->toEigen(),
true, cmap);
400 dm.block(0, 0, 3, 3) = objOrientInv;
401 posDistVisu->setGlobalPose(dm);
405 moVis->attachVisualization(UNCERTAINTY_VISU_NAME, posDistVisu);
416 VirtualRobot::VisualizationNodePtr SimoxObjectWrapper::getUncertaintyEllipsesVisu(GaussianMixtureDistributionBasePtr posGM,
const Eigen::Vector3f& objPos,
417 const VirtualRobot::ColorMap& cmap,
float transparency)
419 static float COV_SCALE_FACTOR = 1.f;
421 std::vector<VirtualRobot::VisualizationNodePtr> compVisuList;
423 for (
int i = 0; i < posGM->size(); ++i)
425 GaussianMixtureComponent comp = posGM->getComponent(i);
428 Eigen::Matrix3f cov = gaussian->toEigenCovariance() * COV_SCALE_FACTOR;
430 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> es(cov);
431 Eigen::Vector3f eval = es.eigenvalues();
437 SoMaterial* matBody =
new SoMaterial;
438 matBody->diffuseColor.setValue(color.r, color.b, color.g);
439 matBody->ambientColor.setValue(color.r, color.b, color.g);
440 matBody->transparency.setValue(transparency);
442 VirtualRobot::VisualizationNodePtr compVisu(
new VirtualRobot::CoinVisualizationNode(coinVisFactory->CreateEllipse(
443 ellipseRadiusInSigmas *
sqrt(eval(0)) / 1000.,
444 ellipseRadiusInSigmas *
sqrt(eval(1)) / 1000.,
445 ellipseRadiusInSigmas *
sqrt(eval(2)) / 1000.,
452 dm.block(0, 0, 3, 3) = evec;
453 dm.block(0, 3, 3, 1) = gaussian->toEigenMean() - objPos;
454 compVisu->setGlobalPose(dm);
456 compVisuList.push_back(compVisu);
459 return coinVisFactory->createUnitedVisualization(compVisuList);
462 VirtualRobot::VisualizationNodePtr SimoxObjectWrapper::getUncertaintyHeatVisu(GaussianMixtureDistributionBasePtr posGM,
const Eigen::Vector3f& objPos,
bool heatSurface,
463 const VirtualRobot::ColorMap& cmap)
465 const float SCALE_FACTOR =
sqrt(2 *
M_PI * heatmapMinVariance);
466 const float COV_SCALE_FACTOR = 1.f;
467 const float LOG_PROB_CUTOFF = -logf(heatmapDensityThreshold);
468 const float MAX_CLUSTER_VARIANCE = 100;
470 std::vector<VirtualRobot::VisualizationNodePtr> clusterVisuList;
472 WestGMMReducer reducer;
473 GaussianMixtureDistributionBasePtr reducedGMM = reducer.reduceByMaxAABB(posGM, MAX_CLUSTER_VARIANCE);
476 for (
int k = 0; k < reducedGMM->size(); ++k)
497 NormalDistributionPtr compGaussian = NormalDistributionPtr::dynamicCast(reducedGMM->getComponent(k).gaussian);
498 Eigen::Vector3f clusterCenter = compGaussian->toEigenMean();
500 std::cout <<
"Cluster mean: " << clusterCenter << std::endl;
503 clusterCenter /= SCALE_FACTOR;
505 float sx = 6. * sqrtf(compGaussian->getCovariance(0, 0));
506 float sy = 6. * sqrtf(compGaussian->getCovariance(1, 1));
507 int GRID_SIZE_X = (int) round(
sqrt(sx / sy) * (
float) heatmapGridSize);
508 int GRID_SIZE_Y = (int) round(
sqrt(sy / sx) * (
float) heatmapGridSize);
509 float CELL_SIZE_X = sx / (
float) GRID_SIZE_X / SCALE_FACTOR;
510 float CELL_SIZE_Y = sy / (
float) GRID_SIZE_Y / SCALE_FACTOR;
512 Eigen::MatrixXf grid = Eigen::MatrixXf::Zero(GRID_SIZE_X, GRID_SIZE_Y);
514 for (
int i = 0; i < posGM->size(); ++i)
516 GaussianMixtureComponent comp = posGM->getComponent(i);
520 Eigen::Vector2f
mean;
521 mean << meanVec[0], meanVec[1];
522 mean /= SCALE_FACTOR;
525 Eigen::Matrix2f cov = cov3D.block(0, 0, 2, 2) * COV_SCALE_FACTOR / (SCALE_FACTOR * SCALE_FACTOR);
527 float covDet = cov.determinant();
528 float covDetSqrtInv = powf(covDet, -0.5f);
531 pos(0) = clusterCenter(0) - (
float)(GRID_SIZE_X * CELL_SIZE_X) / 2.;
533 for (
int xc = 0; xc < GRID_SIZE_X; ++xc)
535 pos(1) = clusterCenter(1) - (
float)(GRID_SIZE_Y * CELL_SIZE_Y) / 2.;
537 for (
int yc = 0; yc < GRID_SIZE_Y; ++yc)
539 float pdfValue = (LOG_PROB_CUTOFF + log(evaluate2DGaussian(pos,
mean, covInv, covDetSqrtInv))) / LOG_PROB_CUTOFF * comp.weight;
548 else if (pdfValue > 1.)
554 grid(xc, yc) += pdfValue;
557 pos(1) += CELL_SIZE_Y;
560 pos(0) += CELL_SIZE_X;
564 VirtualRobot::VisualizationNodePtr clusterVisu;
568 clusterVisu.reset(
new VirtualRobot::CoinVisualizationNode(coinVisFactory->Create2DHeightMap(
570 CELL_SIZE_X * SCALE_FACTOR,
571 CELL_SIZE_Y * SCALE_FACTOR,
581 clusterVisu.reset(
new VirtualRobot::CoinVisualizationNode(coinVisFactory->Create2DMap(
583 CELL_SIZE_X * SCALE_FACTOR,
584 CELL_SIZE_Y * SCALE_FACTOR,
593 dm.block(0, 3, 3, 1) = clusterCenter * SCALE_FACTOR - objPos;
594 clusterVisu->setGlobalPose(dm);
596 clusterVisuList.push_back(clusterVisu);
599 return coinVisFactory->createUnitedVisualization(clusterVisuList);;
602 float SimoxObjectWrapper::evaluate2DGaussian(
const Eigen::Vector2f& point,
const Eigen::Vector2f&
mean,
const Eigen::Matrix2f& covInv,
float covDetSqrtInv)
605 float e = exp(inner(0, 0));
607 static const float c = 1. / 2 *
M_PI;
609 return c * covDetSqrtInv * e;
612 float SimoxObjectWrapper::evaluate3DGaussian(
const Eigen::Vector3f& point,
const Eigen::Vector3f&
mean,
const Eigen::Matrix3f& covInv,
float covDet)
615 float e = exp(inner(0, 0));
617 return pow(2 *
M_PI, -3.0f / 2.0f) * pow(covDet, -0.5) * e;
636 void SimoxObjectWrapper::loadSimoxObject()
const
639 if (loadMode != VirtualRobot::RobotIO::eStructure)
653 if (moFName.empty() && ivFName.empty() && ivFNameCollision.empty())
655 ARMARX_WARNING_S <<
"SimoxWrapper was not able to find ManipulationObjectFile or an ivFile an ivCollision of ObjectInstance " <<
getEntity()->getName() << std::endl;
659 ARMARX_WARNING_S <<
"SimoxWrapper was not able to find IvFile Attribute of ObjectInstance " <<
getEntity()->getName() << std::endl;
661 else if (ivFNameCollision.empty() && loadMode == VirtualRobot::RobotIO::eCollisionModel)
663 ARMARX_WARNING_S <<
"SimoxWrapper was not able to find ivFNameCollision Attribute of ObjectInstance " <<
getEntity()->getName() << std::endl;
666 if (!moFName.empty())
670 simoxObject = loadManipulationObjectFile(moFName);
675 simoxObject = createManipulationObjectFromIvFiles(
getEntity()->
getName(), ivFName, ivFNameCollision);
679 std::string SimoxObjectWrapper::cacheAttributeFile(
const std::string& attrName,
bool preserveOriginalFName )
const
682 std::string result =
"";
687 ARMARX_DEBUG_S <<
"Caching file(s) from attribute \"" << attrName <<
"\"";
689 fileManager->ensureFileInCache(
getEntity()->getAttribute(attrName), result, preserveOriginalFName);
693 ARMARX_DEBUG_S <<
"Attribute \"" << attrName <<
"\" not available";
699 bool SimoxObjectWrapper::cacheAttributeFiles(
const std::string& attrName,
bool preserveOriginalFName )
const
705 return fileManager->ensureFilesInCache(
getEntity()->getAttribute(attrName), preserveOriginalFName);
713 VirtualRobot::ManipulationObjectPtr SimoxObjectWrapper::loadManipulationObjectFile(
const std::string& xmlFName)
const
715 return VirtualRobot::ObjectIO::loadManipulationObject(xmlFName);
718 VirtualRobot::ManipulationObjectPtr SimoxObjectWrapper::createManipulationObjectFromIvFiles(
const std::string& objName,
719 const std::string& ivFNameVis,
const std::string& ivFNameCollision)
const
721 VirtualRobot::ManipulationObjectPtr mo(
new VirtualRobot::ManipulationObject(objName));
723 mo->setFilename(objName +
".xml");
725 VirtualRobot::VisualizationNodePtr visFull = (!ivFNameVis.empty()) ? coinVisFactory->getVisualizationFromFile(ivFNameVis) : VirtualRobot::VisualizationNodePtr();
729 mo->setVisualization(visFull);
732 VirtualRobot::VisualizationNodePtr visCollision = ivFNameCollision.empty() ? VirtualRobot::VisualizationNodePtr() : coinVisFactory->getVisualizationFromFile(ivFNameCollision);
736 VirtualRobot::CollisionModelPtr collisionModel(
new VirtualRobot::CollisionModel(visCollision));
737 mo->setCollisionModel(collisionModel);
744 std::string SimoxObjectWrapper::storeManipulationObject(
const VirtualRobot::ManipulationObjectPtr mo,
const std::string& filesDBName)
755 fs::path visuFName = mo->getVisualization()->getFilename();
756 fs::path collisionFName = mo->getCollisionModel()->getVisualization()->getFilename();
757 storeEntityIVFiles(visuFName.string(), collisionFName.string(), filesDBName);
761 const std::string onlyFilenameVisu = visuFName.filename().string();
762 mo->getVisualization()->setFilename(onlyFilenameVisu, mo->getVisualization()->usedBoundingBoxVisu());
764 const std::string onlyFilenameCol = collisionFName.filename().string();
765 mo->getCollisionModel()->getVisualization()->setFilename(onlyFilenameCol,
766 mo->getCollisionModel()->getVisualization()->usedBoundingBoxVisu());
768 VirtualRobot::ObjectIO::saveManipulationObject(mo, moTempFile);
773 std::string fileId =
fileManager->storeFileToAttr(filesDBName, moTempFile, moAttr, fs::path(mo->getFilename()).filename().string());
778 fs::remove(moTempFile);
782 void SimoxObjectWrapper::storeEntityIVFiles(
const std::string& visuFName,
const std::string& collisionFName,
const std::string& filesDBName,
bool processTextures)
785 NameList::const_iterator itTex;
791 EntityAttributeBasePtr visuAttr =
new EntityAttribute(
ATTR_IV_FILE);
793 std::string visu_filename = visuFName;
794 if (!visu_filename.empty())
797 if (std::filesystem::path(visu_filename).is_relative())
799 visu_filename = (cachePath / visu_filename).
string();
802 ARMARX_INFO <<
" Saving visualization iv file: " << visu_filename;
803 fileManager->storeFileToAttr(filesDBName, visu_filename, visuAttr);
813 std::string col_filename = collisionFName;
814 if (!col_filename.empty())
817 if (std::filesystem::path(col_filename).is_relative())
819 col_filename = (cachePath / col_filename).
string();
827 if (col_filename == visu_filename)
829 collisionAttr->addValue(visuAttr->getValue());
833 fileManager->storeFileToAttr(filesDBName, col_filename, collisionAttr);
842 getEntity()->putAttribute(collisionAttr);
846 if (!textures.empty())
851 for (itTex = textures.begin(); itTex != textures.end(); ++itTex)
854 fileManager->storeFileToAttr(filesDBName, *itTex, texAttr);
860 else if (oldTextureFileAttr)
863 getEntity()->removeAttribute(oldTextureFileAttr->getName());
873 if (!in.openFile(ivFName.c_str()))
879 SoNode* n = SoDB::readAll(&in);
888 Eigen::Vector3f result = {0, 0, 0};
895 if (attr->size() > 0)
897 armarx::Vector3BasePtr vecBase = armarx::VariantPtr::dynamicCast(attr->getValueAt(0))->getClass<armarx::Vector3Base>();
898 result(0) = vecBase->x;
899 result(1) = vecBase->y;
900 result(2) = vecBase->z;
924 if (node->getTypeId() == SoFile::getClassTypeId())
927 SoFile* fileNode = (SoFile*)node;
928 SbString fileNodeName = fileNode->getFullName();
933 SbString s2 = fileNode->name.getValue();
941 storeFilenames.push_back(s2.getString());
946 storeFilenames.push_back(fileNodeName.getString());
950 SoGroup* fileChildren = fileNode->copyChildren();
953 else if (node->getTypeId().isDerivedFrom(SoGroup::getClassTypeId()))
955 SoGroup* groupNode = (SoGroup*)node;
958 for (
int i = 0; i < groupNode->getNumChildren(); i++)
963 else if (node->getTypeId() == SoImage::getClassTypeId())
966 SbString imageFilename = ((SoImage*)node)->filename.getValue();
969 else if (node->getTypeId() == SoTexture2::getClassTypeId())
972 SbString texture2Filename = ((SoTexture2*)node)->filename.getValue();
975 else if (node->getTypeId() == SoTexture3::getClassTypeId())
982 sa.setType(SoVRMLImageTexture::getClassTypeId());
984 sa.setSearchingAll(TRUE);
987 SoPathList& pathList = sa.getPaths();
988 if (pathList.getLength() <= 0)
992 SoFullPath* p = (SoFullPath*)pathList[0];
993 if (!p->getTail()->isOfType(SoVRMLImageTexture::getClassTypeId()))
997 SoVRMLImageTexture* texture = (SoVRMLImageTexture*) p->getTail();
998 if (texture->url.getNum() <= 0)
1002 for (
int i = 0; i < texture->url.getNum(); ++i)
1005 if (!path.empty() && fs::exists(path))
1007 storeFilenames.push_back(path);
1010 if (i == texture->url.getNum() - 1)
1012 Ice::StringSeq textures;
1013 for (
int j = 0; j < texture->url.getNum(); ++j)
1015 textures.push_back(texture->url[j].getString());
1017 ARMARX_ERROR <<
"Could not make any of the texture paths absolute: " << simox::alg::join(textures,
", ");
1032 return std::string();
1037 fs::path absOrigFileDirPath;
1038 std::string resultPathStr;
1039 if (!origFile.empty())
1043 if (filepath.is_absolute())
1051 return std::string();
1054 else if (!filepath.has_parent_path())
1056 return (absOrigFileDirPath / filepath).string();
1060 return resultPathStr;
1065 return std::string();