MarkerSelector.cpp
Go to the documentation of this file.
00001 
00019 #include <urdf2graspit/MarkerSelector.h>
00020 #include <urdf2inventor/IVHelpers.h>
00021 
00022 #include <Inventor/SoDB.h>  // for file reading
00023 #include <Inventor/SoInput.h>   // for file reading
00024 #include <Inventor/nodes/SoPerspectiveCamera.h>
00025 #include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
00026 #include <Inventor/events/SoMouseButtonEvent.h>
00027 #include <Inventor/SoPickedPoint.h>
00028 
00029 #include <Inventor/nodes/SoMatrixTransform.h>
00030 #include <Inventor/nodes/SoEventCallback.h>
00031 #include <Inventor/nodes/SoCone.h>
00032 #include <Inventor/nodes/SoSphere.h>
00033 #include <Inventor/nodes/SoMaterial.h>
00034 #include <Inventor/nodes/SoCoordinate3.h>
00035 #include <Inventor/actions/SoSearchAction.h>
00036 #include <Inventor/details/SoFaceDetail.h>
00037 
00038 #include <vector>
00039 #include <map>
00040 #include <fstream>
00041 #include <iostream>
00042 #include <sstream>
00043 #include <string>
00044 #include <algorithm>
00045 
00046 #include <ros/ros.h>  // only needed for ROS prints, e.g. ROS_ERROR
00047 
00048 using urdf2graspit::markerselector::MarkerSelector;
00049 
00050 std::string MarkerSelector::Marker::toSoBaseName(const std::string& name)
00051 {
00052   // same behaviour as in SoBase::setName() copied in this function.
00053   std::string goodstring;
00054 
00055   // check for bad characters
00056   const char * str = name.c_str();
00057   bool isbad = !SbName::isBaseNameStartChar(name[0]);
00058 
00059   int i;
00060   const int namelen = name.size();
00061   for (i = 1; i < namelen && !isbad; i++)
00062   {
00063     isbad = !SbName::isBaseNameChar(name[i]);
00064   }
00065 
00066   if (isbad)
00067   {
00068     // replace bad characters
00069     if (!SbName::isBaseNameStartChar(name[0])) goodstring += '_';
00070 
00071     for (i = 0; i < namelen; i++)
00072     {
00073       goodstring += SbName::isBaseNameChar(name[i]) ? name[i] : '_';
00074     }
00075   }
00076   else
00077   {
00078     goodstring = name;
00079   }
00080   return goodstring;
00081 }
00082 
00083 
00084 bool MarkerSelector::writeResults(const std::string& outputFile)
00085 {
00086     // Now let the user click on the points, and as soon as the window is closed,
00087     // we save the marker selections:
00088     if (markers.empty())
00089     {
00090         ROS_INFO("No markers selected, so no file written");
00091         return true;
00092     }
00093 
00094     ROS_INFO_STREAM("Finished marker selection, now writing marker files to " << outputFile);
00095     // first, group all markers of all links together
00096     MarkerMap markerMap = getMarkers();
00097     std::stringstream str;
00098     for (MarkerMap::iterator it = markerMap.begin(); it != markerMap.end(); ++it)
00099     {
00100         str << it->first << std::endl;
00101         str << it->second.size() << std::endl;
00102         for (std::vector<Marker>::iterator m = it->second.begin(); m != it->second.end(); ++m)
00103         {
00104             str << m->visualNum << " " << m->coords.x() << " " << m->coords.y() << " " << m->coords.z();
00105             str << " " << m->normal.x() << " " << m->normal.y() << " " << m->normal.z() << std::endl;
00106         }
00107     }
00108 
00109     if (!writeToFile(str.str(), outputFile))
00110     {
00111         ROS_ERROR("Could not write to output file.");
00112         return false;
00113     }
00114 
00115     return true;
00116 }
00117 
00118 MarkerSelector::MarkerMap MarkerSelector::getMarkers()
00119 {
00120     MarkerMap markerMap;
00121     for (std::vector<Marker>::iterator it = markers.begin(); it != markers.end(); ++it)
00122     {
00123         // std::cout<<*it<<std::endl;
00124         MarkerMap::iterator mapit = markerMap.find(it->linkName);
00125         if (mapit == markerMap.end())
00126             mapit = markerMap.insert(std::make_pair(it->linkName, std::vector<Marker>())).first;
00127         mapit->second.push_back(*it);
00128     }
00129     for (MarkerMap::iterator it = markerMap.begin(); it != markerMap.end(); ++it)
00130     {
00131         std::sort(it->second.begin(), it->second.end(), MarkerSelector::sortMarker);
00132     }
00133     return markerMap;
00134 }
00135 
00136 std::string MarkerSelector::toString()
00137 {
00138     std::stringstream str;
00139     for (std::vector<Marker>::iterator it = markers.begin(); it != markers.end(); ++it)
00140     {
00141         str << *it << std::endl;
00142     }
00143     /*MarkerMap markerMap=getMarkers();
00144     for (MarkerMap::iterator it=markerMap.begin(); it!=markerMap.end(); ++it) {
00145         str<<it->first<<std::endl;
00146         str<<it->second.size()<<std::endl;
00147         for (std::vector<Marker>::iterator m=it->second.begin(); m!=it->second.end(); ++m) {
00148             str<<m->visualNum<<" "<<m->x<<" "<<m->y<<" "<<m->z;
00149             str<<" "<<m->nx<<" "<<m->ny<<" "<<m->nz<<std::endl;
00150         }
00151     }*/
00152     return str.str();
00153 }
00154 
00155 bool MarkerSelector::sortMarker(const Marker& i, const Marker& j)
00156 {
00157     return (i.visualNum < j.visualNum);
00158 }
00159 
00160 bool MarkerSelector::writeToFile(const std::string& content, const std::string& filename)
00161 {
00162     std::ofstream outf(filename.c_str());
00163     if (!outf)
00164     {
00165         ROS_ERROR_STREAM(filename << "could not be opened for writing!");
00166         return false;
00167     }
00168     outf << content;
00169     outf.close();
00170     return true;
00171 }
00172 
00173 
00177 bool getTransform(const SoPath* p, unsigned int fromIdx, unsigned int toIdx, urdf2inventor::EigenTransform& transform)
00178 {
00179     SbMatrix sbTransform;
00180     sbTransform.makeIdentity();
00181 
00182     if ((toIdx >= p->getLength()) || (toIdx <0))
00183     {
00184         ROS_ERROR_STREAM("Cannot compute transform for end index out of bounds ("<<toIdx<<")");
00185         return false;
00186     }
00187     if ((fromIdx >= p->getLength()) || (fromIdx <0))
00188     {
00189         ROS_ERROR_STREAM("Cannot compute transform for start index out of bounds ("<<fromIdx<<")");
00190         return false;
00191     }
00192 
00193     for (int i = fromIdx; i <= toIdx;  ++i)
00194     {
00195         SoNode * n = p->getNode(i);
00196         std::string name = n->getName().getString();
00197         //ROS_INFO("Path[%i]: %s, type %s",i,name.c_str(),n->getTypeId().getName().getString());
00198         SoSeparator * nSep = dynamic_cast<SoSeparator*>(n);
00199         if (!nSep) continue; // only separators may have children which are transforms
00200         for (int c=0; c<nSep->getNumChildren(); ++c)
00201         {
00202             SoNode * child = nSep->getChild(c);
00203             if (!child) continue;
00204             //ROS_INFO_STREAM("Child: "<<child->getTypeId().getName().getString());
00205             SoTransformation * trNode = dynamic_cast<SoTransformation*>(child);
00206             if (trNode)
00207             {
00208                 SoTransform * tNode = dynamic_cast<SoTransform*>(child);
00209                 if (!tNode)
00210                 {
00211                     ROS_ERROR_STREAM("Transformation node was found in MarkerSelector::getTransform() "
00212                             <<"(type "<<child->getTypeId().getName().getString()
00213                             <<") which still needs to be implemented (line "<<__LINE__<<")");
00214                     continue;
00215                 }
00216                 SbMatrix tmpMat;
00217                 
00218                 /*float x,y,z,w;
00219                 tNode->center.getValue().getValue(x,y,z);
00220                 ROS_INFO_STREAM("Center " <<x<<","<<y<<","<<z);
00221                 tNode->scaleFactor.getValue().getValue(x,y,z);
00222                 ROS_INFO_STREAM("ScaleFactor " <<x<<","<<y<<","<<z);
00223                 tNode->scaleOrientation.getValue().getValue(x,y,z,w);
00224                 ROS_INFO_STREAM("ScaleOri " <<x<<","<<y<<","<<z<<","<<w);
00225                 tNode->rotation.getValue().getValue(x,y,z,w);
00226                 ROS_INFO_STREAM("Rot " <<x<<","<<y<<","<<z<<","<<w);
00227                 tmpMat.makeIdentity();
00228                 tmpMat.setTranslate(tNode->translation.getValue());
00229                 sbTransform.multRight(tmpMat);
00230                 tmpMat.makeIdentity();
00231                 tmpMat.setRotate(tNode->rotation.getValue());
00232                 sbTransform.multRight(tmpMat);*/
00233 
00234                 tmpMat.setTransform(tNode->translation.getValue(), tNode->rotation.getValue(), 
00235                         tNode->scaleFactor.getValue());//, tNode->scaleOrientation.getValue(), tNode->center.getValue());
00236                 sbTransform.multRight(tmpMat);
00237             }
00238         }
00239     }
00240     
00241     urdf2inventor::EigenTransform egTransform=urdf2inventor::getEigenTransform(sbTransform);
00242 
00243     // for some reason I haven't gotten to the bottom of yet, the matrix is *not* the same when
00244     // we build it again from scratch, even if there is no shearing in the original sbTransform.
00245     // i.e. even if *only* a rotation was explicitly set for sbTransform above, and we do an
00246     // additional  
00247     //      egTransform=urdf2inventor::EigenTransform(egTransform.rotation());
00248     // the matrix vary still! For now, work around this by only using translation and rotation.
00249     // XXX TODO this has to be done properly at some stage.
00250     //ROS_INFO_STREAM(std::endl<<urdf2inventor::printMatrix(egTransform));
00251     transform.setIdentity();
00252     transform.translate(egTransform.translation());
00253     transform=transform*urdf2inventor::EigenTransform(egTransform.rotation());
00254     //ROS_INFO_STREAM(std::endl<<urdf2inventor::printMatrix(transform));
00255     return true;
00256 }
00257 
00258 
00264 #define VISUAL_SCANF "_visual_%i_%s"
00265 
00269 #define MARKER_SCANF "contact_marker_%i_%s"
00270 
00271 
00272 void MarkerSelector::onClickModel(const SoPickedPoint * pPickedPt)
00273 {
00274     SoPath *pPickPath = pPickedPt->getPath();
00275 
00276     // First, see if a marker was clidked.
00277     int mId, mPos;
00278     std::string mLinkName;
00279     SoNode * markerNode = getIntStr(MARKER_SCANF, pPickPath, mLinkName, mId, mPos);
00280     if (markerNode)
00281     {
00282         ROS_INFO_STREAM("Marker "<<mId<<", name "<<mLinkName<<" clicked! Removing...");
00283         MarkerNodeMap::iterator mpIt=markerParentNodes.find(mId);
00284         if (mpIt==markerParentNodes.end())
00285         {
00286             ROS_ERROR("Marker was not found in the existing map, it should have been!");
00287             return;
00288         }
00289         bool markerRemoved=false;
00290         for (std::vector<Marker>::iterator mIt=markers.begin(); mIt!=markers.end(); ++mIt)
00291         {
00292             if (mIt->markerID==mId)
00293             {
00294                 markerRemoved=true;
00295                 markers.erase(mIt);
00296                 break;
00297             }
00298         }
00299         if (!markerRemoved)
00300         {
00301             ROS_ERROR("Could not find marker in the list. Will not remove it.");
00302             return;
00303         }
00304         SoSeparator * _mSep = dynamic_cast<SoSeparator*>(mpIt->second);
00305         if (!_mSep)
00306         {
00307             ROS_ERROR("Marker parent node is not a separator, can't remove it");
00308             return;
00309         }
00310         _mSep->removeChild(markerNode);
00311         return;
00312     }
00313 
00314     mId=markerParentNodes.size();
00315     Marker marker(mId);
00316     int linkIdx;
00317     SoNode * linkNode = getIntStr(VISUAL_SCANF, pPickPath, marker.linkName, marker.visualNum, linkIdx);
00318     if (!linkNode)
00319     {
00320         ROS_INFO("No link or marker was clicked.");
00321         return;
00322     }
00323 
00324     float x, y, z;
00325     pPickedPt->getObjectPoint(linkNode).getValue(x, y, z);
00326     // pPickedPt->getObjectNormal(linkNode).getValue(nx,ny,nz);
00327     ROS_INFO_STREAM("Clicked link "<<marker.linkName<<", point "<<","<<x<<","<<y<<","<<z);
00328 
00329     marker.setCoords(x, y, z);
00330 
00331     int shapeIdx;
00332     if (!computeCorrectFaceNormal(pPickedPt, isFacesCCW(), marker.normal, shapeIdx))
00333     {
00334         ROS_WARN("No face normal correction possible. Using default normal.");
00335     }
00336     
00337 
00338     // get the transform from the link to the shape form: we have to consider this transform for the normal as well. 
00339     // ROS_INFO_STREAM("Index of link in path: "<<linkIdx<<" / "<<(pPickPath->getLength()-1)<<" and shape in path: "<<shapeIdx);
00340     urdf2inventor::EigenTransform link2VertexTransform;
00341     if (!getTransform(pPickPath, linkIdx, shapeIdx, link2VertexTransform))
00342     {
00343         ROS_WARN("Cannot get transform between link and geometry node, normals may be off.");
00344     }
00345         
00346     SoSeparator * _nodeSep = dynamic_cast<SoSeparator*>(linkNode);
00347     if (!_nodeSep)
00348     {
00349         ROS_WARN_STREAM("The node for link "<<marker.linkName
00350             <<" is not a separator, so cannot add visual marker sphere");
00351     }
00352     else 
00353     {
00354         // ROS_INFO_STREAM("Adding marker "<<marker);
00355         //urdf2inventor::addSphere(_nodeSep, marker.coords, marker_size, 1, 0, 0);
00356         // compute rotation from z to normal
00357         Eigen::Vector3d zAxis(0,0,1);
00358         urdf2inventor::EigenTransform toZ(Eigen::Quaterniond::FromTwoVectors(zAxis,marker.normal));
00359         urdf2inventor::EigenTransform cylTrans;
00360         cylTrans.setIdentity();
00361         cylTrans.translate(marker.coords);
00362         cylTrans=cylTrans*link2VertexTransform*toZ;
00363         float radius = marker_size;
00364         float height = radius*4;
00365         std::stringstream str;
00366         str<<"contact_marker_"<<mId<<"_"<<marker.linkName;
00367         ROS_INFO_STREAM("Adding a new marker named "<<str.str());
00368         urdf2inventor::addCylinder(_nodeSep, cylTrans, radius, height, 1, 0, 0, 0, str.str().c_str());
00369         markerParentNodes.insert(std::make_pair(mId,_nodeSep));
00370     }
00371 
00372     marker.normal = link2VertexTransform.rotation() * marker.normal;
00373     markers.push_back(marker);
00374 }


urdf2graspit
Author(s): Jennifer Buehler
autogenerated on Wed May 8 2019 02:53:45