00001
00019 #include <urdf2graspit/MarkerSelector.h>
00020 #include <urdf2inventor/IVHelpers.h>
00021
00022 #include <Inventor/SoDB.h>
00023 #include <Inventor/SoInput.h>
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>
00047
00048 using urdf2graspit::markerselector::MarkerSelector;
00049
00050 std::string MarkerSelector::Marker::toSoBaseName(const std::string& name)
00051 {
00052
00053 std::string goodstring;
00054
00055
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
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
00087
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
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
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
00144
00145
00146
00147
00148
00149
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
00198 SoSeparator * nSep = dynamic_cast<SoSeparator*>(n);
00199 if (!nSep) continue;
00200 for (int c=0; c<nSep->getNumChildren(); ++c)
00201 {
00202 SoNode * child = nSep->getChild(c);
00203 if (!child) continue;
00204
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
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 tmpMat.setTransform(tNode->translation.getValue(), tNode->rotation.getValue(),
00235 tNode->scaleFactor.getValue());
00236 sbTransform.multRight(tmpMat);
00237 }
00238 }
00239 }
00240
00241 urdf2inventor::EigenTransform egTransform=urdf2inventor::getEigenTransform(sbTransform);
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 transform.setIdentity();
00252 transform.translate(egTransform.translation());
00253 transform=transform*urdf2inventor::EigenTransform(egTransform.rotation());
00254
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
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
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
00339
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
00355
00356
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 }