SetupCollisionPair.cpp
Go to the documentation of this file.
00001 // -*- C++ -*-
00010 #include <iomanip>
00011 #include <hrpModel/Link.h>
00012 #include <hrpModel/ModelLoaderUtil.h>
00013 #include <hrpModel/JointPath.h>
00014 #include <hrpUtil/Eigen3d.h>
00015 #include <hrpUtil/Eigen4d.h>
00016 #include <hrpCollision/ColdetModel.h>
00017 #include "CollisionDetector.h"
00018 extern "C" {
00019 #include <qhull/qhull_a.h>
00020 }
00021 
00022 #define deg2rad(x)      ((x)*M_PI/180)
00023 #define rad2deg(x)      ((x)*180/M_PI)
00024 
00025 std::vector<hrp::ColdetLinkPairPtr> m_pair;
00026 std::vector<std::string> blacklist;
00027 hrp::BodyPtr m_robot;
00028 
00029 RTC::ReturnCode_t setupCollisionModel(hrp::BodyPtr m_robot, const char *url, OpenHRP::BodyInfo_var binfo) {
00030     // do qhull
00031     OpenHRP::ShapeInfoSequence_var sis = binfo->shapes();
00032     OpenHRP::LinkInfoSequence_var lis = binfo->links();
00033     for(unsigned int i = 0; i < m_robot->numLinks(); i++ ) {
00034         const OpenHRP::LinkInfo& i_li = lis[i];
00035         const OpenHRP::TransformedShapeIndexSequence& tsis = i_li.shapeIndices;
00036         // setup
00037         int numTriangles = 0;
00038         for (unsigned int l=0; l<tsis.length(); l++) {
00039             OpenHRP::ShapeInfo& si = sis[tsis[l].shapeIndex];
00040             const OpenHRP::LongSequence& triangles = si.triangles;
00041             numTriangles += triangles.length();
00042         }
00043         double points[numTriangles*3];
00044         int points_i = 0;
00045         hrp::Matrix44 Rs44; // inv
00046         hrp::Matrix33 Rs33 = m_robot->link(i)->Rs;
00047 
00048         Rs44 << Rs33(0,0),Rs33(0,1), Rs33(0,2), 0,
00049             Rs33(1,0),Rs33(1,1), Rs33(1,2), 0,
00050             Rs33(2,0),Rs33(2,1), Rs33(2,2), 0,
00051             0.0,      0.0,       0.0,    1.0;
00052         for (unsigned int l=0; l<tsis.length(); l++) {
00053             const OpenHRP::DblArray12& M = tsis[l].transformMatrix;
00054             hrp::Matrix44 T0;
00055             T0 << M[0], M[1], M[2],  M[3],
00056                 M[4], M[5], M[6],  M[7],
00057                 M[8], M[9], M[10], M[11],
00058                 0.0,  0.0,  0.0,   1.0;
00059             hrp::Matrix44 T(Rs44 * T0);
00060             const OpenHRP::ShapeInfo& si = sis[tsis[l].shapeIndex];
00061             const OpenHRP::LongSequence& triangles = si.triangles;
00062             const float *vertices = si.vertices.get_buffer();
00063 
00064             for(unsigned int j=0; j < triangles.length() / 3; ++j){
00065                 for(int k=0; k < 3; ++k){
00066                     long orgVertexIndex = si.triangles[j * 3 + k];
00067                     int p = orgVertexIndex * 3;
00068 
00069                     hrp::Vector4 v(T * hrp::Vector4(vertices[p+0], vertices[p+1], vertices[p+2], 1.0));
00070                     points[points_i++] =  v[0];
00071                     points[points_i++] =  v[1];
00072                     points[points_i++] =  v[2];
00073                 }
00074             }
00075         }
00076 
00077         hrp::ColdetModelPtr coldetModel(new hrp::ColdetModel());
00078         coldetModel->setName(std::string(i_li.name));
00079         // qhull
00080         int vertexIndex = 0;
00081         int triangleIndex = 0;
00082         int num = 0;
00083         char flags[250];
00084         boolT ismalloc = False;
00085         sprintf(flags,"qhull Qt Tc");
00086         if (! qh_new_qhull (3,numTriangles,points,ismalloc,flags,NULL,stderr) ) {
00087 
00088             qh_triangulate();
00089             qh_vertexneighbors();
00090 
00091             vertexT *vertex,**vertexp;
00092             coldetModel->setNumVertices(qh num_vertices);
00093             coldetModel->setNumTriangles(qh num_facets);
00094             int index[qh num_vertices];
00095             FORALLvertices {
00096                 int p = qh_pointid(vertex->point);
00097                 index[p] = vertexIndex;
00098                 coldetModel->setVertex(vertexIndex++, points[p*3+0], points[p*3+1], points[p*3+2]);
00099             }
00100             facetT *facet;
00101             num = qh num_facets;;
00102             {
00103                 FORALLfacets {
00104                     int j = 0, p[3];
00105                     setT *vertices = qh_facet3vertex (facet);
00106                     FOREACHvertexreverse12_ (vertices) {
00107                         if (j<3) {
00108                             p[j] = index[qh_pointid(vertex->point)];
00109                         } else {
00110                             fprintf(stderr, "extra vertex %d\n",j);
00111                         }
00112                         j++;
00113                     }
00114                     coldetModel->setTriangle(triangleIndex++, p[0], p[1], p[2]);
00115                 }
00116             }
00117         } // qh_new_qhull
00118 
00119         coldetModel->build();
00120         m_robot->link(i)->coldetModel =  coldetModel;
00121 
00122         qh_freeqhull(!qh_ALL);
00123         int curlong, totlong;
00124         qh_memfreeshort (&curlong, &totlong);
00125         if (curlong || totlong) {
00126             fprintf(stderr, "convhulln: did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
00127         }
00128         //
00129         std::cerr << std::setw(16) << i_li.name << " reduce triangles from " << std::setw(5) << numTriangles << " to " << std::setw(4) << num << std::endl;
00130     }
00131 
00132     return RTC::RTC_OK;
00133 }
00134 
00135 bool checkCollisionForAllJointRange(int i, hrp::JointPathPtr jointPath, std::vector<hrp::ColdetLinkPairPtr> &collisionPairs)
00136 {
00137     if ( i >= (int)jointPath->numJoints() ) return false;
00138     if ( collisionPairs.size() == 0 ) return true;
00139     hrp::Link *l = jointPath->joint(i);
00140 
00141     if ( l->jointType == hrp::Link::FIXED_JOINT ) {
00142         checkCollisionForAllJointRange(i+1, jointPath, collisionPairs);
00143     } else {
00144         double step = (l->ulimit - l->llimit)/2;
00145         for(float angle = l->llimit; angle <= l->ulimit; angle += step)
00146         {
00147             l->q = angle;
00148             m_robot->calcForwardKinematics(false,false);
00149             m_robot->updateLinkColdetModelPositions();
00150 
00151             //std::cerr << "    " << collisionPair->link(0)->name << ":" << collisionPair->link(1)->name << " ";
00152             //for(int j = 0; j < jointPath->numJoints(); j++) std::cerr << rad2deg(jointPath->joint(j)->q) << " ";
00153             // std::cerr << "id = " << i << "/" << jointPath->numJoints() << ", " << l->name << " " << rad2deg(angle) << " (" << rad2deg(l->llimit) << "," << rad2deg(l->ulimit) << ") " << collisionPair->detectIntersection() << " " << collisionPair->link(0)->name << ":" << collisionPair->link(1)->name << std::endl;
00154             for(std::vector<hrp::ColdetLinkPairPtr>::iterator it = collisionPairs.begin(); it != collisionPairs.end(); ) {
00155                 if ( (*it)->detectIntersection() ) {
00156                     std::cerr << "Find collision for " << (*it)->link(0)->name << " " << (*it)->link(1)->name << std::endl;
00157                     it = collisionPairs.erase(it);
00158                     continue;
00159                 }
00160                 it++;
00161             }
00162             checkCollisionForAllJointRange(i+1, jointPath, collisionPairs);
00163         }
00164     }
00165     return false;
00166 }
00167 
00168 bool checkBlackListJoint(hrp::Link *l) {
00169     for(std::vector<std::string>::iterator it = blacklist.begin(); it != blacklist.end(); it++ ) {
00170             if (l->name == (*it)) return true;
00171     }
00172     return false;
00173 }
00174 
00175 bool checkBlackListJointPair(hrp::Link *l1, hrp::Link *l2) {
00176     for(std::vector<std::string>::iterator it = blacklist.begin(); it != blacklist.end(); it++ ) {
00177             if ((l1->name + ":" + l2->name) == (*it) ||
00178                 (l2->name + ":" + l1->name) == (*it)) return true;
00179     }
00180     return false;
00181 }
00182 
00183 bool compare_joint_path_length(const hrp::ColdetLinkPairPtr& p1, const hrp::ColdetLinkPairPtr& p2) {
00184     return (m_robot->getJointPath(p1->link(0),p1->link(1))->numJoints()) > (m_robot->getJointPath(p2->link(0),p2->link(1))->numJoints());
00185 }
00186 
00187 void setupCollisionLinkPair()
00188 {
00189     std::vector<hrp::ColdetLinkPairPtr> tmp_pair;
00190 
00191     std::cerr << "Setup Initial collision pair without " << std::endl;
00192     for(std::vector<std::string>::iterator it = blacklist.begin(); it != blacklist.end(); it++ ) {
00193         std::cerr << *it << " ";
00194     }
00195     std::cerr << std::endl;
00196     // find link to be ignored as the link is included in the parent link
00197     // need AABBCollision?
00198     //
00199     // set all collisoin pair
00200     for (unsigned int i=0; i<m_robot->numLinks(); i++) {
00201         hrp::Link *l1 = m_robot->link(i);
00202         for (unsigned int j=i+1; j<m_robot->numLinks(); j++) {
00203             hrp::Link *l2 = m_robot->link(j);
00204             if ( l1->coldetModel && l2->coldetModel
00205                  &&  (!(checkBlackListJoint(l1) ||  checkBlackListJoint(l2) || checkBlackListJointPair(l1, l2)))
00206                 ) {
00207                 tmp_pair.push_back(new hrp::ColdetLinkPair(l1, l2));
00208             }
00209         }
00210     }
00211 
00212     std::cerr << "Initial collision pair size " << tmp_pair.size() << std::endl;
00213     std::vector<hrp::ColdetLinkPairPtr>::iterator it;
00214     // Remove collision pair if the pair always collides
00215     std::cerr << "step 0: Remove collision pair if they are adjacent pair" << std::endl;
00216     it = tmp_pair.begin();
00217     while ( it != tmp_pair.end() ) {
00218         hrp::JointPathPtr jointPath = m_robot->getJointPath((*it)->link(0),(*it)->link(1));
00219         if ( jointPath->numJoints() == 1 ) {
00220             hrp::Link *l = jointPath->joint(0);
00221             bool always_collide = true; // true if always collide
00222             bool never_collide = true;  // true if never collide ( crrect )
00223             l->llimit = -M_PI;l->ulimit = M_PI;
00224             std::cerr << l->name << " ulimit - " << l->llimit << " " << l->ulimit << std::endl;
00225             for(float angle = l->llimit; angle <= l->ulimit; angle += deg2rad(5)) {
00226                 l->q = angle;
00227                 m_robot->calcForwardKinematics(false,false);
00228                 m_robot->updateLinkColdetModelPositions();
00229                 if ( (*it)->detectIntersection() ) {
00230                     never_collide = false;
00231                 } else {
00232                     always_collide = false;
00233                 }
00234                 //std::cerr << l->name << " " << deg2rad(l->q) << " intersect:" << (*it)->detectIntersection() <<  " check:" << (*it)->checkCollision() << std::endl;
00235                 (*it)->clearCollisions();
00236             }
00237             std::cerr << "  pair (" << jointPath->numJoints() << ") " << (*it)->link(0)->name << "/" << (*it)->link(1)->name << (always_collide?" always collide":"") << (never_collide?" never collide":"") << std::endl;
00238             it = tmp_pair.erase(it);
00239             continue;
00240         }
00241         it++;
00242     }
00243     //
00244     std::cerr << "step 1: Remove complex (2 or 3 distance) collision pair if they never/always collide" << std::endl;
00245     it = tmp_pair.begin();
00246     while ( it != tmp_pair.end() ) {
00247         hrp::JointPathPtr jointPath = m_robot->getJointPath((*it)->link(0),(*it)->link(1));
00248         if ( jointPath->numJoints() == 2 || jointPath->numJoints() == 3 ) {
00249             hrp::Link *l = jointPath->joint(0);
00250             bool always_collide = true; // true if always collide
00251             bool never_collide = true;  // true if never collide ( crrect )
00252             for(float angle = l->llimit; angle <= l->ulimit; angle += deg2rad(5)) {
00253                 l->q = angle;
00254                 m_robot->calcForwardKinematics(false,false);
00255                 m_robot->updateLinkColdetModelPositions();
00256                 if ( (*it)->detectIntersection() ) {
00257                     never_collide = false;
00258                 } else {
00259                     always_collide = false;
00260                 }
00261                 //std::cerr << l->name << " " << deg2rad(l->q) << " intersect:" << (*it)->detectIntersection() <<  " check:" << (*it)->checkCollision() << std::endl;
00262                 (*it)->clearCollisions();
00263             }
00264             std::cerr << "  pair (" << jointPath->numJoints() << ") " << (*it)->link(0)->name << "/" << (*it)->link(1)->name << " always:" << always_collide << ", never:" << never_collide << " " << (( always_collide || never_collide )?"remove from list":"") << std::endl;
00265             if ( always_collide || never_collide ) {
00266                 it = tmp_pair.erase(it);
00267                 continue;
00268             } else {
00269                 m_pair.push_back(*it);
00270             }
00271         }
00272         it++;
00273     }
00274     std::cerr << "  Remove always/never collide pair for a length of 1,2,3 ... " << tmp_pair.size() << std::endl;
00275 
00276     // setup data structure for check collision pair
00277     // pair_tree[<pair:L1,L2,L3,L4>, [ <pair:L1,L2,L3,L4>, <pair:L1,L2,L3>, <pair:L1,L2> ]]
00278     // pair_tree[<pair:L2,L3,L4,L5>, [ <pair:L2,L3,L4,L5>, <pair:L2,L3,L4>, <pair:L2,L3> ]]
00279     std::map<hrp::ColdetLinkPairPtr, std::vector<hrp::ColdetLinkPairPtr> > pair_tree;
00280     std::sort(tmp_pair.begin(), tmp_pair.end(), compare_joint_path_length);
00281     int i = 0;
00282     it = tmp_pair.begin();
00283     while ( it != tmp_pair.end() ) {
00284         hrp::JointPathPtr jointPath1 = m_robot->getJointPath((*it)->link(0),(*it)->link(1));
00285         //std::cerr << "  " << i << "/" << tmp_pair.size() << "  pair (" << jointPath1->numJoints() << ") " << (*it)->link(0)->name << " " << (*it)->link(1)->name <<std::endl;
00286         // check if JointPath1 is included in some of the pair_tree (jointPath2)
00287         bool is_new_key = true;
00288         for (std::map<hrp::ColdetLinkPairPtr, std::vector<hrp::ColdetLinkPairPtr> >::iterator ii=pair_tree.begin(); ii != pair_tree.end(); ++ii) {
00289             hrp::JointPathPtr jointPath2 = m_robot->getJointPath(((*ii).first)->link(0),((*ii).first)->link(1));
00290             // check if JointPath1 is included in jointPath2
00291             bool find_key = true;
00292             for (unsigned int j = 0; j < jointPath1->numJoints() ; j++ ) {
00293                 if ( jointPath1->joint(j)->name != jointPath2->joint(j)->name ) {
00294                     find_key = false;
00295                     break;
00296                 }
00297             }
00298             if ( find_key ) {
00299                 (*ii).second.push_back(*it);
00300                 is_new_key = false;
00301             }
00302         }
00303         if (is_new_key) {
00304             pair_tree[*it] = std::vector<hrp::ColdetLinkPairPtr>(1,*it)
00305 ;
00306         }
00307         it++; i++;
00308     }
00309     // remove non-collisin pair from tmp_pair
00310     std::cerr << "step 2: Remove collision pair if they never collide" << std::endl;
00311     i = 0;
00312     for (std::map<hrp::ColdetLinkPairPtr, std::vector<hrp::ColdetLinkPairPtr> >::iterator ii=pair_tree.begin(); ii != pair_tree.end(); ++ii) {
00313         hrp::ColdetLinkPairPtr key_pair = (*ii).first;
00314         std::vector<hrp::ColdetLinkPairPtr> sub_pairs = (*ii).second;
00315         hrp::JointPathPtr jointPath = m_robot->getJointPath(key_pair->link(0),key_pair->link(1));
00316         std::sort(sub_pairs.begin(), sub_pairs.end(), compare_joint_path_length);
00317         //
00318         std::cerr << "  " << i << "/" << tmp_pair.size() << "  pair (" << jointPath->numJoints() << ") " << (*ii).first->link(0)->name << " " << (*ii).first->link(1)->name <<std::endl;
00319         i += (*ii).second.size();
00320         for(std::vector<hrp::ColdetLinkPairPtr>::iterator it = sub_pairs.begin(); it != sub_pairs.end(); it++ ) {
00321             hrp::JointPathPtr jointPath = m_robot->getJointPath((*it)->link(0),(*it)->link(1));
00322             for ( unsigned int j = 0; j < jointPath->numJoints(); j++ ) {
00323                 std::cerr << jointPath->joint(j)->name << " ";
00324             }
00325             std::cerr << std::endl;
00326         }
00327         // rmeove non-collision pair from sub_paris
00328         checkCollisionForAllJointRange(0, jointPath, sub_pairs);
00329         for(std::vector<hrp::ColdetLinkPairPtr>::iterator p = sub_pairs.begin(); p != sub_pairs.end(); p++ ) {
00330             for(std::vector<hrp::ColdetLinkPairPtr>::iterator it = tmp_pair.begin(); it != tmp_pair.end(); ) {
00331                 if ( (*p)->link(0) == (*it)->link(0) &&  (*p)->link(1) == (*it)->link(1) ) {
00332                     tmp_pair.erase(it);
00333                     continue;
00334                 }
00335                 it++;
00336             }
00337             //tmp_pair.erase(it); // does not work???
00338         }
00339     }
00340     it = tmp_pair.begin();
00341     while ( it != tmp_pair.end() ) {
00342         m_pair.push_back(*it);
00343         it++;
00344     }
00345     std::cerr << "Reduced collision pair size " << m_pair.size() << std::endl;
00346 }
00347 
00348 int main (int argc, char** argv)
00349 {
00350     std::string url;
00351 
00352     for (int i = 1; i < argc; ++ i) {
00353         std::string arg(argv[i]);
00354         coil::normalize(arg);
00355         if ( arg == "--model" ) {
00356             if (++i < argc) url = argv[i];
00357         } else if ( arg == "-o" ) {
00358             ++i;
00359         } else if ( arg[0] == '-' ||  arg[0] == '_'  ) {
00360             std::cerr << argv[0] << " : Unknwon arguments " << arg << std::endl;
00361         } else {
00362             blacklist.push_back(argv[i]);
00363         }
00364     }
00365     if (argc < 2) {
00366         std::cerr << "usage: " << argv[0] << " --model <model file> <blacklist : R_HAND_J0 L_HAND_J0 EYEBROW_P EYELID_P EYE_Y EYE_P MOUTH_P UPPERLIP_P LOWERLIP_P CHEEK_P>" << std::endl;
00367         exit(1);
00368     }
00369 
00370     m_robot = hrp::BodyPtr(new hrp::Body());
00371     OpenHRP::BodyInfo_var binfo = hrp::loadBodyInfo(url.c_str(), argc, argv);
00372     if (CORBA::is_nil(binfo)){
00373         std::cerr << "failed to load model[" << url << "]" << std::endl;
00374         return 1;
00375     }
00376     if (!loadBodyFromBodyInfo(m_robot, binfo)) {
00377         std::cerr << "failed to load model[" << url << "]" << std::endl;
00378         return 1;
00379     }
00380     setupCollisionModel(m_robot, url.c_str(), binfo);
00381     setupCollisionLinkPair();
00382 
00383     std::string fname = "/tmp/"+m_robot->name()+"collision_pair.conf";
00384     std::ofstream ofs(fname.c_str());
00385     ofs << "collision_pair:";
00386     for (std::vector<hrp::ColdetLinkPairPtr>::iterator it = m_pair.begin(); it != m_pair.end(); it++) {
00387         ofs << " " << (*it)->link(0)->name << ":" << (*it)->link(1)->name;
00388         std::cerr << (*it)->link(0)->name << ":" << (*it)->link(1)->name << std::endl;
00389     }
00390     ofs << std::endl;
00391     ofs.close();
00392     std::cerr << "Write collision pair conf file to " << fname << std::endl;
00393 
00394     return 0;
00395 }


hrpsys
Author(s): AIST, Fumio Kanehiro
autogenerated on Wed Sep 6 2017 02:35:56