00001
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
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
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;
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
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 }
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
00152
00153
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
00197
00198
00199
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
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;
00222 bool never_collide = true;
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
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;
00251 bool never_collide = true;
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
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
00277
00278
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
00286
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
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
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
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
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 }