00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00037 #include "collision_space/environmentODE.h"
00038 #include <geometric_shapes/shape_operations.h>
00039 #include <ros/console.h>
00040 #include <cassert>
00041 #include <cstdio>
00042 #include <cmath>
00043 #include <algorithm>
00044 #include <map>
00045 
00046 #include <boost/thread.hpp>
00047 static int          ODEInitCount = 0;
00048 static boost::mutex ODEInitCountLock;
00049 
00050 static std::map<boost::thread::id, int> ODEThreadMap;
00051 static boost::mutex                     ODEThreadMapLock;
00052 
00053 
00054 
00055 static const int MAX_ODE_CONTACTS = 128;
00056 static const int TEST_FOR_ALLOWED_NUM = 1;
00057 
00058 static const std::string CONTACT_ONLY_NAME="contact_only";
00059 
00060 collision_space::EnvironmentModelODE::EnvironmentModelODE(void) : EnvironmentModel()
00061 {
00062   ODEInitCountLock.lock();
00063   if (ODEInitCount == 0)
00064   {
00065     int res = dInitODE2(0);
00066     ROS_DEBUG_STREAM("Calling ODE Init res " << res);
00067   }
00068   ODEInitCount++;
00069   ODEInitCountLock.unlock();
00070     
00071   checkThreadInit();
00072 
00073   ROS_DEBUG("Initializing ODE");
00074 
00075   model_geom_.env_space = dSweepAndPruneSpaceCreate(0, dSAP_AXES_XZY);
00076   model_geom_.self_space = dSweepAndPruneSpaceCreate(0, dSAP_AXES_XZY);
00077   
00078   previous_set_robot_model_ = false;
00079 }
00080 
00081 collision_space::EnvironmentModelODE::~EnvironmentModelODE(void)
00082 {
00083   freeMemory();
00084   ODEInitCountLock.lock();
00085   ODEInitCount--;
00086   boost::thread::id id = boost::this_thread::get_id();
00087   ODEThreadMapLock.lock();
00088   ODEThreadMap.erase(id);
00089   ODEThreadMapLock.unlock();
00090   if (ODEInitCount == 0)
00091   {
00092     ODEThreadMap.clear();
00093     ROS_DEBUG("Closing ODE");
00094     dCloseODE();
00095   }
00096   ODEInitCountLock.unlock();
00097 }
00098 
00099 void collision_space::EnvironmentModelODE::freeMemory(void)
00100 { 
00101   for (unsigned int j = 0 ; j < model_geom_.link_geom.size() ; ++j)
00102     delete model_geom_.link_geom[j];
00103   model_geom_.link_geom.clear();
00104   if (model_geom_.env_space)
00105     dSpaceDestroy(model_geom_.env_space);
00106   if (model_geom_.self_space)
00107     dSpaceDestroy(model_geom_.self_space);
00108   for (std::map<std::string, CollisionNamespace*>::iterator it = coll_namespaces_.begin() ; it != coll_namespaces_.end() ; ++it) {
00109     delete it->second;
00110   }
00111   model_geom_.storage.clear();
00112   coll_namespaces_.clear();
00113 }
00114 
00115 void collision_space::EnvironmentModelODE::checkThreadInit(void) const
00116 {
00117   boost::thread::id id = boost::this_thread::get_id();
00118   ODEThreadMapLock.lock();
00119   if (ODEThreadMap.find(id) == ODEThreadMap.end())
00120   {
00121     ODEThreadMap[id] = 1;
00122     ROS_DEBUG("Initializing new thread (%d total)", (int)ODEThreadMap.size());
00123     int res = dAllocateODEDataForThread(dAllocateMaskAll);
00124     ROS_DEBUG_STREAM("Init says " << res);
00125   } 
00126   ODEThreadMapLock.unlock();
00127 }
00128 
00129 void collision_space::EnvironmentModelODE::setRobotModel(const planning_models::KinematicModel* model, 
00130                                                          const AllowedCollisionMatrix& allowed_collision_matrix,
00131                                                          const std::map<std::string, double>& link_padding_map,
00132                                                          double default_padding,
00133                                                          double scale) 
00134 {
00135   collision_space::EnvironmentModel::setRobotModel(model, allowed_collision_matrix, link_padding_map, default_padding, scale);
00136   if(previous_set_robot_model_) {
00137     for (unsigned int j = 0 ; j < model_geom_.link_geom.size() ; ++j)
00138       delete model_geom_.link_geom[j];
00139     model_geom_.link_geom.clear();
00140     dSpaceDestroy(model_geom_.env_space);
00141     dSpaceDestroy(model_geom_.self_space);
00142     model_geom_.env_space = dSweepAndPruneSpaceCreate(0, dSAP_AXES_XZY);
00143     model_geom_.self_space = dSweepAndPruneSpaceCreate(0, dSAP_AXES_XZY);
00144     attached_bodies_in_collision_matrix_.clear();
00145     geom_lookup_map_.clear();
00146   }
00147   createODERobotModel();
00148   previous_set_robot_model_ = true;
00149 }
00150 
00151 void collision_space::EnvironmentModelODE::getAttachedBodyPoses(std::map<std::string, std::vector<tf::Transform> >& pose_map) const
00152 {
00153   pose_map.clear();
00154 
00155   const unsigned int n = model_geom_.link_geom.size();    
00156   for (unsigned int i = 0 ; i < n ; ++i)
00157   {
00158     LinkGeom *lg = model_geom_.link_geom[i];
00159     
00160          
00161     const unsigned int nab = lg->att_bodies.size();
00162     std::vector<tf::Transform> nbt;
00163     for (unsigned int j = 0 ; j < nab ; ++j)
00164     {
00165       for(unsigned int k = 0; k < lg->att_bodies[j]->geom.size(); k++) {
00166         const dReal *pos = dGeomGetPosition(lg->att_bodies[j]->geom[k]);
00167         dQuaternion q;
00168         dGeomGetQuaternion(lg->att_bodies[j]->geom[k], q);
00169         
00170         nbt.push_back(tf::Transform(tf::Quaternion(q[1], q[2], q[3], q[0]), tf::Vector3(pos[0], pos[1], pos[2])));
00171       }
00172       pose_map[lg->att_bodies[j]->att->getName()] = nbt;
00173     }
00174   }
00175 }
00176 
00177 void collision_space::EnvironmentModelODE::createODERobotModel()
00178 {
00179   for (unsigned int i = 0 ; i < robot_model_->getLinkModels().size() ; ++i)
00180   {
00181     
00182 
00183 
00184     const planning_models::KinematicModel::LinkModel *link = robot_model_->getLinkModels()[i];
00185     if (!link || !link->getLinkShape())
00186       continue;
00187         
00188     LinkGeom *lg = new LinkGeom(model_geom_.storage);
00189     lg->link = link;
00190     if(!default_collision_matrix_.getEntryIndex(link->getName(), lg->index)) {
00191       ROS_WARN_STREAM("Link " << link->getName() << " not in provided collision matrix");
00192     } 
00193     double padd = default_robot_padding_;
00194     if(default_link_padding_map_.find(link->getName()) != default_link_padding_map_.end()) {
00195       padd = default_link_padding_map_.find(link->getName())->second;
00196     }
00197     ROS_DEBUG_STREAM("Link " << link->getName() << " padding " << padd);
00198 
00199     dGeomID unpadd_g = createODEGeom(model_geom_.self_space, model_geom_.storage, link->getLinkShape(), 1.0, 0.0);
00200     assert(unpadd_g);
00201     lg->geom.push_back(unpadd_g);
00202     geom_lookup_map_[unpadd_g] = std::pair<std::string, BodyType>(link->getName(), LINK);
00203 
00204     dGeomID padd_g = createODEGeom(model_geom_.env_space, model_geom_.storage, link->getLinkShape(), robot_scale_, padd);
00205     assert(padd_g);
00206     lg->padded_geom.push_back(padd_g);
00207     geom_lookup_map_[padd_g] = std::pair<std::string, BodyType>(link->getName(), LINK);
00208     const std::vector<planning_models::KinematicModel::AttachedBodyModel*>& attached_bodies = link->getAttachedBodyModels();
00209     for (unsigned int j = 0 ; j < attached_bodies.size() ; ++j) {
00210       padd = default_robot_padding_;
00211       if(default_link_padding_map_.find(attached_bodies[j]->getName()) != default_link_padding_map_.end()) {
00212         padd = default_link_padding_map_.find(attached_bodies[j]->getName())->second;
00213       } else if (default_link_padding_map_.find("attached") != default_link_padding_map_.end()) {
00214         padd = default_link_padding_map_.find("attached")->second;
00215       }
00216       addAttachedBody(lg, attached_bodies[j], padd);
00217     }
00218     model_geom_.link_geom.push_back(lg);
00219   } 
00220 }
00221 
00222 dGeomID collision_space::EnvironmentModelODE::createODEGeom(dSpaceID space, ODEStorage &storage, const shapes::StaticShape *shape)
00223 {
00224   dGeomID g = NULL;
00225   switch (shape->type)
00226   {
00227   case shapes::PLANE:
00228     {
00229       const shapes::Plane *p = static_cast<const shapes::Plane*>(shape);
00230       g = dCreatePlane(space, p->a, p->b, p->c, p->d);
00231     }
00232     break;
00233   default:
00234     break;
00235   }
00236   return g;
00237 }
00238 
00239 dGeomID collision_space::EnvironmentModelODE::createODEGeom(dSpaceID space, ODEStorage &storage, const shapes::Shape *shape, double scale, double padding)
00240 {
00241   dGeomID g = NULL;
00242   switch (shape->type)
00243   {
00244   case shapes::SPHERE:
00245     {
00246       g = dCreateSphere(space, static_cast<const shapes::Sphere*>(shape)->radius * scale + padding);
00247     }
00248     break;
00249   case shapes::BOX:
00250     {
00251       const double *size = static_cast<const shapes::Box*>(shape)->size;
00252       g = dCreateBox(space, size[0] * scale + padding * 2.0, size[1] * scale + padding * 2.0, size[2] * scale + padding * 2.0);
00253     }   
00254     break;
00255   case shapes::CYLINDER:
00256     {
00257       g = dCreateCylinder(space, static_cast<const shapes::Cylinder*>(shape)->radius * scale + padding,
00258                           static_cast<const shapes::Cylinder*>(shape)->length * scale + padding * 2.0);
00259     }
00260     break;
00261   case shapes::MESH:
00262     {
00263       const shapes::Mesh *mesh = static_cast<const shapes::Mesh*>(shape);
00264       if (mesh->vertexCount > 0 && mesh->triangleCount > 0)
00265       {         
00266         
00267         int icount = mesh->triangleCount * 3;
00268         dTriIndex *indices = new dTriIndex[icount];
00269         for (int i = 0 ; i < icount ; ++i)
00270           indices[i] = mesh->triangles[i];
00271                 
00272         
00273         double *vertices = new double[mesh->vertexCount* 3];
00274         double sx = 0.0, sy = 0.0, sz = 0.0;
00275         for (unsigned int i = 0 ; i < mesh->vertexCount ; ++i)
00276         {
00277           unsigned int i3 = i * 3;
00278           vertices[i3] = mesh->vertices[i3];
00279           vertices[i3 + 1] = mesh->vertices[i3 + 1];
00280           vertices[i3 + 2] = mesh->vertices[i3 + 2];
00281           sx += vertices[i3];
00282           sy += vertices[i3 + 1];
00283           sz += vertices[i3 + 2];
00284         }
00285         
00286         sx /= (double)mesh->vertexCount;
00287         sy /= (double)mesh->vertexCount;
00288         sz /= (double)mesh->vertexCount;
00289 
00290         
00291         for (unsigned int i = 0 ; i < mesh->vertexCount ; ++i)
00292         {
00293           unsigned int i3 = i * 3;
00294                     
00295           
00296           double dx = vertices[i3] - sx;
00297           double dy = vertices[i3 + 1] - sy;
00298           double dz = vertices[i3 + 2] - sz;
00299                     
00300           
00301           
00302                     
00303           double ndx = ((dx > 0) ? dx+padding : dx-padding);
00304           double ndy = ((dy > 0) ? dy+padding : dy-padding);
00305           double ndz = ((dz > 0) ? dz+padding : dz-padding);
00306 
00307           
00308           
00309           vertices[i3] = sx + ndx; 
00310           vertices[i3 + 1] = sy + ndy; 
00311           vertices[i3 + 2] = sz + ndz; 
00312         }
00313                 
00314         dTriMeshDataID data = dGeomTriMeshDataCreate();
00315         dGeomTriMeshDataBuildDouble(data, vertices, sizeof(double) * 3, mesh->vertexCount, indices, icount, sizeof(dTriIndex) * 3);
00316         g = dCreateTriMesh(space, data, NULL, NULL, NULL);
00317         ODEStorage::Element& e = storage.meshes[g];
00318         e.vertices = vertices;
00319         e.indices = indices;
00320         e.data = data;
00321         e.n_vertices = mesh->vertexCount;
00322         e.n_indices = icount;
00323       }
00324     }
00325         
00326   default:
00327     break;
00328   }
00329   return g;
00330 }
00331 
00332 void collision_space::EnvironmentModelODE::updateGeom(dGeomID geom,  const tf::Transform &pose) const
00333 {
00334   tf::Vector3 pos = pose.getOrigin();
00335   dGeomSetPosition(geom, pos.getX(), pos.getY(), pos.getZ());
00336   tf::Quaternion quat = pose.getRotation();
00337   dQuaternion q; 
00338   q[0] = quat.getW(); q[1] = quat.getX(); q[2] = quat.getY(); q[3] = quat.getZ();
00339   dGeomSetQuaternion(geom, q);
00340 }
00341 
00342 void collision_space::EnvironmentModelODE::updateAttachedBodies()
00343 {
00344   updateAttachedBodies(default_link_padding_map_);
00345 }
00346 
00347 void collision_space::EnvironmentModelODE::updateAttachedBodies(const std::map<std::string, double>& link_padding_map)
00348 {
00349   
00350   for(std::map<std::string, bool>::iterator it = attached_bodies_in_collision_matrix_.begin();
00351       it != attached_bodies_in_collision_matrix_.end();
00352       it++) {
00353     if(!default_collision_matrix_.removeEntry(it->first)) {
00354       ROS_WARN_STREAM("No entry in default collision matrix for attached body " << it->first <<
00355                       " when there really should be.");
00356     }
00357   }
00358   attached_bodies_in_collision_matrix_.clear();
00359   for (unsigned int i = 0 ; i < model_geom_.link_geom.size() ; ++i) {
00360     LinkGeom *lg = model_geom_.link_geom[i];
00361 
00362     for(unsigned int j = 0; j < lg->att_bodies.size(); j++) {
00363       for(unsigned int k = 0; k < lg->att_bodies[j]->geom.size(); k++) {
00364         geom_lookup_map_.erase(lg->att_bodies[j]->geom[k]);
00365       }
00366       for(unsigned int k = 0; k < lg->att_bodies[j]->padded_geom.size(); k++) {
00367         geom_lookup_map_.erase(lg->att_bodies[j]->padded_geom[k]);
00368       }
00369     }
00370     lg->deleteAttachedBodies();
00371 
00372     
00373     const std::vector<planning_models::KinematicModel::AttachedBodyModel*>& attached_bodies = lg->link->getAttachedBodyModels();
00374     for (unsigned int j = 0 ; j < attached_bodies.size(); ++j) {
00375       double padd = default_robot_padding_;
00376       if(link_padding_map.find(attached_bodies[j]->getName()) != link_padding_map.end()) {
00377         padd = link_padding_map.find(attached_bodies[j]->getName())->second;
00378       } else if (link_padding_map.find("attached") != link_padding_map.end()) {
00379         padd = link_padding_map.find("attached")->second;
00380       }
00381       ROS_DEBUG_STREAM("Updating attached body " << attached_bodies[j]->getName());      
00382       addAttachedBody(lg, attached_bodies[j], padd);
00383     }
00384   }
00385 }
00386 
00387 void collision_space::EnvironmentModelODE::addAttachedBody(LinkGeom* lg, 
00388                                                            const planning_models::KinematicModel::AttachedBodyModel* attm,
00389                                                            double padd) {
00390 
00391   AttGeom* attg = new AttGeom(model_geom_.storage);
00392   attg->att = attm;
00393 
00394   if(!default_collision_matrix_.addEntry(attm->getName(), false)) {
00395     ROS_WARN_STREAM("Must already have an entry in allowed collision matrix for " << attm->getName());
00396   } else {
00397     ROS_DEBUG_STREAM("Adding entry for " << attm->getName());
00398   } 
00399   attached_bodies_in_collision_matrix_[attm->getName()] = true;
00400   default_collision_matrix_.getEntryIndex(attm->getName(), attg->index);
00401   
00402   for(unsigned int i = 0; i < attm->getTouchLinks().size(); i++) {
00403     if(default_collision_matrix_.hasEntry(attm->getTouchLinks()[i])) {
00404       if(!default_collision_matrix_.changeEntry(attm->getName(), attm->getTouchLinks()[i], true)) {
00405         ROS_WARN_STREAM("No entry in allowed collision matrix for " << attm->getName() << " and " << attm->getTouchLinks()[i]);
00406       } else {
00407         ROS_DEBUG_STREAM("Adding touch link for " << attm->getName() << " and " << attm->getTouchLinks()[i]);
00408       }
00409     }
00410   }
00411   for(unsigned int i = 0; i < attm->getShapes().size(); i++) {
00412     dGeomID ga = createODEGeom(model_geom_.self_space, model_geom_.storage, attm->getShapes()[i], 1.0, 0.0);
00413     assert(ga);
00414     attg->geom.push_back(ga);
00415     geom_lookup_map_[ga] = std::pair<std::string, BodyType>(attm->getName(), ATTACHED);    
00416 
00417     dGeomID padd_ga = createODEGeom(model_geom_.env_space, model_geom_.storage, attm->getShapes()[i], robot_scale_, padd);
00418     assert(padd_ga);
00419     attg->padded_geom.push_back(padd_ga);
00420     geom_lookup_map_[padd_ga] = std::pair<std::string, BodyType>(attm->getName(), ATTACHED);    
00421   }
00422   lg->att_bodies.push_back(attg);
00423 }
00424 
00425 void collision_space::EnvironmentModelODE::setAttachedBodiesLinkPadding() {
00426   for (unsigned int i = 0 ; i < model_geom_.link_geom.size() ; ++i) {
00427     LinkGeom *lg = model_geom_.link_geom[i];
00428     
00429     const std::vector<planning_models::KinematicModel::AttachedBodyModel*>& attached_bodies = lg->link->getAttachedBodyModels();
00430     for (unsigned int j = 0 ; j < attached_bodies.size(); ++j) {
00431       double new_padd = -1.0;
00432       if(altered_link_padding_map_.find(attached_bodies[j]->getName()) != altered_link_padding_map_.end()) {
00433         new_padd = altered_link_padding_map_.find(attached_bodies[j]->getName())->second;
00434       } else if (altered_link_padding_map_.find("attached") != altered_link_padding_map_.end()) {
00435         new_padd = altered_link_padding_map_.find("attached")->second;
00436       }
00437       if(new_padd != -1.0) {
00438         for(unsigned int k = 0; k < attached_bodies[j]->getShapes().size(); k++) {
00439           geom_lookup_map_.erase(lg->att_bodies[j]->padded_geom[k]);
00440           dGeomDestroy(lg->att_bodies[j]->padded_geom[k]);
00441           model_geom_.storage.remove(lg->att_bodies[j]->padded_geom[k]);
00442           dGeomID padd_ga = createODEGeom(model_geom_.env_space, model_geom_.storage, attached_bodies[j]->getShapes()[k], robot_scale_, new_padd);
00443           assert(padd_ga);
00444           lg->att_bodies[j]->padded_geom[k] = padd_ga;
00445           geom_lookup_map_[padd_ga] = std::pair<std::string, BodyType>(attached_bodies[j]->getName(), ATTACHED);
00446         }
00447       }
00448     }
00449   }
00450 }
00451 
00452 void collision_space::EnvironmentModelODE::revertAttachedBodiesLinkPadding() {
00453   for (unsigned int i = 0 ; i < model_geom_.link_geom.size() ; ++i) {
00454     LinkGeom *lg = model_geom_.link_geom[i];
00455     
00456     const std::vector<planning_models::KinematicModel::AttachedBodyModel*>& attached_bodies = lg->link->getAttachedBodyModels();
00457     for (unsigned int j = 0 ; j < attached_bodies.size(); ++j) {
00458       double new_padd = -1.0;
00459       if(altered_link_padding_map_.find(attached_bodies[j]->getName()) != altered_link_padding_map_.end()) {
00460         new_padd = default_link_padding_map_.find(attached_bodies[j]->getName())->second;
00461       } else if (altered_link_padding_map_.find("attached") != altered_link_padding_map_.end()) {
00462         new_padd = default_link_padding_map_.find("attached")->second;
00463       }
00464       if(new_padd != -1.0) {
00465         for(unsigned int k = 0; k < attached_bodies[j]->getShapes().size(); k++) {
00466           geom_lookup_map_.erase(lg->att_bodies[j]->padded_geom[k]);
00467           dGeomDestroy(lg->att_bodies[j]->padded_geom[k]);
00468           model_geom_.storage.remove(lg->att_bodies[j]->padded_geom[k]);
00469           dGeomID padd_ga = createODEGeom(model_geom_.env_space, model_geom_.storage, attached_bodies[j]->getShapes()[k], robot_scale_, new_padd);
00470           assert(padd_ga);
00471           lg->att_bodies[j]->padded_geom[k] = padd_ga;
00472           geom_lookup_map_[padd_ga] = std::pair<std::string, BodyType>(attached_bodies[j]->getName(), ATTACHED);
00473         }
00474       }
00475     }
00476   }
00477 }
00478 
00479 void collision_space::EnvironmentModelODE::updateRobotModel(const planning_models::KinematicState* state)
00480 { 
00481   const unsigned int n = model_geom_.link_geom.size();
00482     
00483   for (unsigned int i = 0 ; i < n ; ++i) {
00484     const planning_models::KinematicState::LinkState* link_state = state->getLinkState(model_geom_.link_geom[i]->link->getName());
00485     if(link_state == NULL) {
00486       ROS_WARN_STREAM("No link state for link " << model_geom_.link_geom[i]->link->getName());
00487       continue;
00488     }
00489     updateGeom(model_geom_.link_geom[i]->geom[0], link_state->getGlobalCollisionBodyTransform());
00490     updateGeom(model_geom_.link_geom[i]->padded_geom[0], link_state->getGlobalCollisionBodyTransform());
00491     const std::vector<planning_models::KinematicState::AttachedBodyState*>& attached_bodies = link_state->getAttachedBodyStateVector();
00492     for (unsigned int j = 0 ; j < attached_bodies.size(); ++j) {
00493       for(unsigned int k = 0; k < attached_bodies[j]->getGlobalCollisionBodyTransforms().size(); k++) {
00494         updateGeom(model_geom_.link_geom[i]->att_bodies[j]->geom[k], attached_bodies[j]->getGlobalCollisionBodyTransforms()[k]);
00495         updateGeom(model_geom_.link_geom[i]->att_bodies[j]->padded_geom[k], attached_bodies[j]->getGlobalCollisionBodyTransforms()[k]);
00496       }
00497     }
00498   }    
00499 }
00500 
00501 void collision_space::EnvironmentModelODE::setAlteredLinkPadding(const std::map<std::string, double>& new_link_padding) {
00502   
00503   
00504   collision_space::EnvironmentModel::setAlteredLinkPadding(new_link_padding);
00505 
00506   for(unsigned int i = 0; i < model_geom_.link_geom.size(); i++) {
00507 
00508     LinkGeom *lg = model_geom_.link_geom[i];
00509 
00510     if(altered_link_padding_map_.find(lg->link->getName()) != altered_link_padding_map_.end()) {
00511       double new_padding = altered_link_padding_map_.find(lg->link->getName())->second;
00512       const planning_models::KinematicModel::LinkModel *link = lg->link;
00513       if (!link || !link->getLinkShape()) {
00514         ROS_WARN_STREAM("Can't get kinematic model for link " << link->getName() << " to make new padding");
00515         continue;
00516       }
00517       ROS_DEBUG_STREAM("Setting padding for link " << lg->link->getName() << " from " 
00518                        << default_link_padding_map_[lg->link->getName()] 
00519                        << " to " << new_padding);
00520       
00521       for (unsigned int j = 0 ; j < lg->padded_geom.size() ; ++j) {
00522         geom_lookup_map_.erase(lg->padded_geom[j]);
00523         dGeomDestroy(lg->padded_geom[j]);
00524         model_geom_.storage.remove(lg->padded_geom[j]);
00525       }
00526       lg->padded_geom.clear();
00527       dGeomID g = createODEGeom(model_geom_.env_space, model_geom_.storage, link->getLinkShape(), robot_scale_, new_padding);
00528       assert(g);
00529       lg->padded_geom.push_back(g);
00530       geom_lookup_map_[g] = std::pair<std::string, BodyType>(link->getName(), LINK);
00531     }
00532   }
00533   
00534   setAttachedBodiesLinkPadding();  
00535 }
00536 
00537 void collision_space::EnvironmentModelODE::revertAlteredLinkPadding() {
00538   for(unsigned int i = 0; i < model_geom_.link_geom.size(); i++) {
00539     
00540     LinkGeom *lg = model_geom_.link_geom[i];
00541 
00542     if(altered_link_padding_map_.find(lg->link->getName()) != altered_link_padding_map_.end()) {
00543       double old_padding = default_link_padding_map_.find(lg->link->getName())->second;
00544       const planning_models::KinematicModel::LinkModel *link = lg->link;
00545       if (!link || !link->getLinkShape()) {
00546         ROS_WARN_STREAM("Can't get kinematic model for link " << link->getName() << " to revert to old padding");
00547         continue;
00548       }
00549       
00550       for (unsigned int j = 0 ; j < lg->padded_geom.size() ; ++j) {
00551         geom_lookup_map_.erase(lg->padded_geom[j]);
00552         dGeomDestroy(lg->padded_geom[j]);
00553         model_geom_.storage.remove(lg->padded_geom[j]);
00554       }
00555       ROS_DEBUG_STREAM("Reverting padding for link " << lg->link->getName() << " from " << altered_link_padding_map_[lg->link->getName()]
00556                       << " to " << old_padding);
00557       lg->padded_geom.clear();
00558       dGeomID g = createODEGeom(model_geom_.env_space, model_geom_.storage, link->getLinkShape(), robot_scale_, old_padding);
00559       assert(g);
00560       dGeomSetData(g, reinterpret_cast<void*>(lg));
00561       lg->padded_geom.push_back(g);
00562       geom_lookup_map_[g] = std::pair<std::string, BodyType>(link->getName(), LINK);
00563     }
00564   }
00565   revertAttachedBodiesLinkPadding();
00566   
00567   
00568   collision_space::EnvironmentModel::revertAlteredLinkPadding();
00569 } 
00570 
00571 bool collision_space::EnvironmentModelODE::ODECollide2::empty(void) const
00572 {
00573   return geoms_x.empty();
00574 }
00575 
00576 void collision_space::EnvironmentModelODE::ODECollide2::registerSpace(dSpaceID space)
00577 {
00578   int n = dSpaceGetNumGeoms(space);
00579   for (int i = 0 ; i < n ; ++i)
00580     registerGeom(dSpaceGetGeom(space, i));
00581 }
00582 
00583 void collision_space::EnvironmentModelODE::ODECollide2::unregisterGeom(dGeomID geom)
00584 {
00585   setup();
00586     
00587   Geom g;
00588   g.id = geom;
00589   dGeomGetAABB(geom, g.aabb);
00590     
00591   Geom *found = NULL;
00592     
00593   std::vector<Geom*>::iterator posStart1 = std::lower_bound(geoms_x.begin(), geoms_x.end(), &g, SortByXTest());
00594   std::vector<Geom*>::iterator posEnd1   = std::upper_bound(posStart1, geoms_x.end(), &g, SortByXTest());
00595   while (posStart1 < posEnd1)
00596   {
00597     if ((*posStart1)->id == geom)
00598     {
00599       found = *posStart1;
00600       geoms_x.erase(posStart1);
00601       break;
00602     }
00603     ++posStart1;
00604   }
00605 
00606   std::vector<Geom*>::iterator posStart2 = std::lower_bound(geoms_y.begin(), geoms_y.end(), &g, SortByYTest());
00607   std::vector<Geom*>::iterator posEnd2   = std::upper_bound(posStart2, geoms_y.end(), &g, SortByYTest());
00608   while (posStart2 < posEnd2)
00609   {
00610     if ((*posStart2)->id == geom)
00611     {
00612       assert(found == *posStart2);
00613       geoms_y.erase(posStart2);
00614       break;
00615     }
00616     ++posStart2;
00617   }
00618     
00619   std::vector<Geom*>::iterator posStart3 = std::lower_bound(geoms_z.begin(), geoms_z.end(), &g, SortByZTest());
00620   std::vector<Geom*>::iterator posEnd3   = std::upper_bound(posStart3, geoms_z.end(), &g, SortByZTest());
00621   while (posStart3 < posEnd3)
00622   {
00623     if ((*posStart3)->id == geom)
00624     {
00625       assert(found == *posStart3);
00626       geoms_z.erase(posStart3);
00627       break;
00628     }
00629     ++posStart3;
00630   }
00631     
00632   assert(found);
00633   delete found;
00634 }
00635 
00636 void collision_space::EnvironmentModelODE::ODECollide2::registerGeom(dGeomID geom)
00637 {
00638   Geom *g = new Geom();
00639   g->id = geom;
00640   dGeomGetAABB(geom, g->aabb);
00641   geoms_x.push_back(g);
00642   geoms_y.push_back(g);
00643   geoms_z.push_back(g);
00644   setup_ = false;
00645 }
00646         
00647 void collision_space::EnvironmentModelODE::ODECollide2::clear(void)
00648 {
00649   for (unsigned int i = 0 ; i < geoms_x.size() ; ++i)
00650     delete geoms_x[i];
00651   geoms_x.clear();
00652   geoms_y.clear();
00653   geoms_z.clear();
00654   setup_ = false;
00655 }
00656 
00657 void collision_space::EnvironmentModelODE::ODECollide2::setup(void)
00658 {
00659   if (!setup_)
00660   {
00661     std::sort(geoms_x.begin(), geoms_x.end(), SortByXLow());
00662     std::sort(geoms_y.begin(), geoms_y.end(), SortByYLow());
00663     std::sort(geoms_z.begin(), geoms_z.end(), SortByZLow());
00664     setup_ = true;
00665   }         
00666 }
00667 
00668 void collision_space::EnvironmentModelODE::ODECollide2::getGeoms(std::vector<dGeomID> &geoms) const
00669 {
00670   geoms.resize(geoms_x.size());
00671   for (unsigned int i = 0 ; i < geoms.size() ; ++i)
00672     geoms[i] = geoms_x[i]->id;
00673 }
00674 
00675 void collision_space::EnvironmentModelODE::ODECollide2::checkColl(std::vector<Geom*>::const_iterator posStart, std::vector<Geom*>::const_iterator posEnd,
00676                                                                   Geom *g, void *data, dNearCallback *nearCallback) const
00677 {
00678   
00679 
00680 
00681     
00682   while (posStart < posEnd)
00683   {
00684     
00685     if (!((*posStart)->aabb[2] > g->aabb[3] ||
00686           (*posStart)->aabb[3] < g->aabb[2] ||
00687           (*posStart)->aabb[4] > g->aabb[5] ||
00688           (*posStart)->aabb[5] < g->aabb[4]))
00689       dSpaceCollide2(g->id, (*posStart)->id, data, nearCallback);
00690     posStart++;
00691   }
00692 }
00693 
00694 void collision_space::EnvironmentModelODE::ODECollide2::collide(dGeomID geom, void *data, dNearCallback *nearCallback) const
00695 {
00696   static const int CUTOFF = 100;
00697 
00698   assert(setup_);
00699 
00700   Geom g;
00701   g.id = geom;
00702   dGeomGetAABB(geom, g.aabb);
00703     
00704   std::vector<Geom*>::const_iterator posStart1 = std::lower_bound(geoms_x.begin(), geoms_x.end(), &g, SortByXTest());
00705   if (posStart1 != geoms_x.end())
00706   {
00707     std::vector<Geom*>::const_iterator posEnd1 = std::upper_bound(posStart1, geoms_x.end(), &g, SortByXTest());
00708     int                                d1      = posEnd1 - posStart1;
00709         
00710     
00711 
00712 
00713 
00714     if (d1 > CUTOFF)
00715     {
00716       std::vector<Geom*>::const_iterator posStart2 = std::lower_bound(geoms_y.begin(), geoms_y.end(), &g, SortByYTest());
00717       if (posStart2 != geoms_y.end())
00718       {
00719         std::vector<Geom*>::const_iterator posEnd2 = std::upper_bound(posStart2, geoms_y.end(), &g, SortByYTest());
00720         int                                d2      = posEnd2 - posStart2;
00721                 
00722         if (d2 > CUTOFF)
00723         {
00724           std::vector<Geom*>::const_iterator posStart3 = std::lower_bound(geoms_z.begin(), geoms_z.end(), &g, SortByZTest());
00725           if (posStart3 != geoms_z.end())
00726           {
00727             std::vector<Geom*>::const_iterator posEnd3 = std::upper_bound(posStart3, geoms_z.end(), &g, SortByZTest());
00728             int                                d3      = posEnd3 - posStart3;
00729             if (d3 > CUTOFF)
00730             {
00731               if (d3 <= d2 && d3 <= d1)
00732                 checkColl(posStart3, posEnd3, &g, data, nearCallback);
00733               else
00734                 if (d2 <= d3 && d2 <= d1)
00735                   checkColl(posStart2, posEnd2, &g, data, nearCallback);
00736                 else
00737                   checkColl(posStart1, posEnd1, &g, data, nearCallback);
00738             }
00739             else
00740               checkColl(posStart3, posEnd3, &g, data, nearCallback);   
00741           }
00742         }
00743         else
00744           checkColl(posStart2, posEnd2, &g, data, nearCallback);   
00745       }
00746     }
00747     else 
00748       checkColl(posStart1, posEnd1, &g, data, nearCallback);
00749   }
00750 }
00751 
00752 namespace collision_space
00753 {
00754 
00755 void nearCallbackFn(void *data, dGeomID o1, dGeomID o2)
00756 {
00757   EnvironmentModelODE::CollisionData *cdata = reinterpret_cast<EnvironmentModelODE::CollisionData*>(data);
00758   
00759   if (cdata->done) {
00760     return;
00761   }
00762   
00763   
00764   bool check_in_allowed_collision_matrix = true;
00765   
00766   std::string object_name;
00767 
00768   std::map<dGeomID, std::pair<std::string, EnvironmentModelODE::BodyType> >::const_iterator it1 = cdata->geom_lookup_map->find(o1);
00769   std::map<dGeomID, std::pair<std::string, EnvironmentModelODE::BodyType> >::const_iterator it2 = cdata->geom_lookup_map->find(o2);
00770   
00771   if(it1 != cdata->geom_lookup_map->end()) {
00772     cdata->body_name_1 = it1->second.first;
00773     cdata->body_type_1 = it1->second.second;
00774   } else {
00775     for(std::map<std::string, dSpaceID>::const_iterator it = cdata->dspace_lookup_map->begin();
00776         it != cdata->dspace_lookup_map->end();
00777         it++) {
00778       if(dSpaceQuery(it->second, o1)) {
00779         object_name = it->first;
00780         break;
00781       }
00782     }
00783     if(object_name == "") {
00784       ROS_WARN_STREAM("Object does not have entry in dspace map");
00785     }
00786     cdata->body_name_1 = object_name;
00787     cdata->body_type_1 = EnvironmentModelODE::OBJECT;
00788     check_in_allowed_collision_matrix = false;
00789   }
00790 
00791   if(it2 != cdata->geom_lookup_map->end()) {
00792     cdata->body_name_2 = it2->second.first;
00793     cdata->body_type_2 = it2->second.second;
00794   } else {
00795     for(std::map<std::string, dSpaceID>::const_iterator it = cdata->dspace_lookup_map->begin();
00796         it != cdata->dspace_lookup_map->end();
00797         it++) {
00798       if(dSpaceQuery(it->second, o2)) {
00799         object_name = it->first;
00800         break;
00801       }
00802     }
00803     if(object_name == "") {
00804       ROS_WARN_STREAM("Object does not have entry in dspace map");
00805     }
00806     cdata->body_name_2 = object_name;
00807     cdata->body_type_2 = EnvironmentModelODE::OBJECT;
00808     check_in_allowed_collision_matrix = false;
00809   }
00810 
00811   
00812   if (cdata->allowed_collision_matrix && check_in_allowed_collision_matrix) {
00813     bool allowed;
00814     if(!cdata->allowed_collision_matrix->getAllowedCollision(cdata->body_name_1, cdata->body_name_2, allowed)) {
00815       ROS_WARN_STREAM("No entry in allowed collision matrix for " << cdata->body_name_1 << " and " << cdata->body_name_2);
00816       return;
00817     }
00818     if(allowed) {
00819       ROS_DEBUG_STREAM("Will not test for collision between " << cdata->body_name_1 << " and " << cdata->body_name_2);
00820       return;
00821     } else {
00822       ROS_DEBUG_STREAM("Will test for collision between " << cdata->body_name_1 << " and " << cdata->body_name_2);
00823     }
00824   }
00825 
00826   
00827   int num_contacts = 1;
00828   if(cdata->contacts) {
00829     num_contacts = std::min(MAX_ODE_CONTACTS, (int) cdata->max_contacts_pair);
00830   } 
00831   if(cdata->allowed) {
00832     num_contacts = std::max(num_contacts, TEST_FOR_ALLOWED_NUM);
00833   }
00834   num_contacts = std::max(num_contacts, 1);
00835   
00836   ROS_DEBUG_STREAM("Testing " << cdata->body_name_1
00837                   << " and " << cdata->body_name_2 << " contact size " << num_contacts);
00838 
00839   dContactGeom contactGeoms[num_contacts];
00840   int numc = dCollide(o1, o2, num_contacts,
00841                       &(contactGeoms[0]), sizeof(dContactGeom));
00842   
00843   
00844   if(!numc) 
00845     return;
00846 
00847   if(!cdata->contacts && !cdata->allowed) {
00848     
00849     ROS_DEBUG_STREAM_NAMED(CONTACT_ONLY_NAME, "Detected collision between " << cdata->body_name_1 << " and " << cdata->body_name_2);
00850     cdata->collides = true;      
00851     cdata->done = true;
00852   } else {
00853     unsigned int num_not_allowed = 0;
00854     if(numc != num_contacts) {
00855       ROS_INFO_STREAM("Asked for " << num_contacts << " but only got " << numc);
00856     }
00857     for (int i = 0 ; i < numc ; ++i) {
00858 
00859       ROS_DEBUG_STREAM("Contact at " << contactGeoms[i].pos[0] << " " 
00860                        << contactGeoms[i].pos[1] << " " << contactGeoms[i].pos[2]);    
00861       const dReal *pos1 = dGeomGetPosition(o1);
00862       dQuaternion quat1, quat2;
00863       dGeomGetQuaternion(o1, quat1);
00864       const dReal *pos2 = dGeomGetPosition(o2);
00865       dGeomGetQuaternion(o2, quat2);
00866 
00867       ROS_DEBUG_STREAM("Body pos 1 " << pos1[0] << " " << pos1[1] << " " << pos1[2]);
00868       ROS_DEBUG_STREAM("Body quat 1 " << quat1[1] << " " << quat1[2] << " " << quat1[3] << " " << quat1[0]);
00869       ROS_DEBUG_STREAM("Body pos 2 " << pos2[0] << " " << pos2[1] << " " << pos2[2]);
00870       ROS_DEBUG_STREAM("Body quat 2 " << quat2[1] << " " << quat2[2] << " " << quat2[3] << " " << quat2[0]);
00871 
00872       tf::Vector3 pos(contactGeoms[i].pos[0], contactGeoms[i].pos[1], contactGeoms[i].pos[2]);
00873       
00874       
00875       
00876       bool allowed = false;
00877       if(cdata->allowed) { 
00878         EnvironmentModel::AllowedContactMap::const_iterator it1 = cdata->allowed->find(cdata->body_name_1);
00879         if(it1 != cdata->allowed->end()) {
00880           std::map<std::string, std::vector<EnvironmentModel::AllowedContact> >::const_iterator it2 = it1->second.find(cdata->body_name_2);
00881           if(it2 != it1->second.end()) {
00882             ROS_DEBUG_STREAM("Testing allowed contact for " << cdata->body_name_1 << " and " << cdata->body_name_2 << " num " << i);
00883             ROS_DEBUG_STREAM("Contact at " << contactGeoms[i].pos[0] << " " 
00884                             << contactGeoms[i].pos[1] << " " << contactGeoms[i].pos[2]);      
00885             
00886             const std::vector<EnvironmentModel::AllowedContact>& av = it2->second;
00887             for(unsigned int j = 0; j < av.size(); j++) {
00888               if(av[j].bound->containsPoint(pos)) {
00889                 if(av[j].depth >= fabs(contactGeoms[i].depth)) {
00890                   allowed = true;
00891                   ROS_DEBUG_STREAM("Contact allowed by allowed collision region");
00892                   break;
00893                 } else {
00894                   ROS_DEBUG_STREAM("Depth check failing " << av[j].depth << " detected " << contactGeoms[i].depth);
00895                 }
00896               }
00897             }
00898           }
00899         }
00900       }
00901       if(!allowed) {
00902 
00903         cdata->collides = true;
00904         num_not_allowed++;
00905 
00906         ROS_DEBUG_STREAM_NAMED(CONTACT_ONLY_NAME, "Detected collision between " << cdata->body_name_1 << " and " << cdata->body_name_2);
00907 
00908         if(cdata->contacts != NULL) {
00909           if(num_not_allowed <= cdata->max_contacts_pair) {
00910             collision_space::EnvironmentModelODE::Contact add;
00911             
00912             add.pos = pos;
00913             
00914             add.normal.setX(contactGeoms[i].normal[0]);
00915             add.normal.setY(contactGeoms[i].normal[1]);
00916             add.normal.setZ(contactGeoms[i].normal[2]);
00917             
00918             add.depth = contactGeoms[i].depth;
00919             
00920             add.body_name_1 = cdata->body_name_1;
00921             add.body_name_2 = cdata->body_name_2;
00922             add.body_type_1 = cdata->body_type_1;
00923             add.body_type_2 = cdata->body_type_2;
00924             
00925             cdata->contacts->push_back(add);
00926             if(cdata->contacts->size() >= cdata->max_contacts_total) {
00927               cdata->done = true;
00928             }
00929           }
00930         } else {
00931           cdata->done = true;    
00932         }
00933       }
00934     }
00935   }
00936 }
00937 }
00938 
00939 bool collision_space::EnvironmentModelODE::getCollisionContacts(std::vector<Contact> &contacts, unsigned int max_total, unsigned int max_per_pair) const
00940 {
00941   contacts.clear();
00942   CollisionData cdata;
00943   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
00944   cdata.geom_lookup_map = &geom_lookup_map_;
00945   cdata.dspace_lookup_map = &dspace_lookup_map_;
00946   cdata.contacts = &contacts;
00947   cdata.max_contacts_total = max_total;
00948   cdata.max_contacts_pair = max_per_pair;
00949   if (!allowed_contacts_.empty())
00950     cdata.allowed = &allowed_contact_map_;
00951   contacts.clear();
00952   checkThreadInit();
00953   testCollision(&cdata);
00954   return cdata.collides;
00955 }
00956 
00957 bool collision_space::EnvironmentModelODE::getAllCollisionContacts(std::vector<Contact> &contacts, unsigned int num_contacts_per_pair) const
00958 {
00959   contacts.clear();
00960   CollisionData cdata;
00961   cdata.geom_lookup_map = &geom_lookup_map_;
00962   cdata.dspace_lookup_map = &dspace_lookup_map_;
00963   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
00964   cdata.contacts = &contacts;
00965   cdata.max_contacts_total = UINT_MAX;
00966   cdata.max_contacts_pair = num_contacts_per_pair;
00967   if (!allowed_contacts_.empty())
00968     cdata.allowed = &allowed_contact_map_;
00969   contacts.clear();
00970   checkThreadInit();
00971   testCollision(&cdata);
00972   return cdata.collides;
00973 }
00974 
00975 bool collision_space::EnvironmentModelODE::isCollision(void) const
00976 {
00977   CollisionData cdata;
00978   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
00979   cdata.geom_lookup_map = &geom_lookup_map_;
00980   cdata.dspace_lookup_map = &dspace_lookup_map_;
00981   if (!allowed_contacts_.empty()) {
00982     cdata.allowed = &allowed_contact_map_;
00983     ROS_DEBUG_STREAM("Got contacts size " << cdata.allowed->size());
00984   } else {
00985     ROS_DEBUG_STREAM("No allowed contacts");
00986   }
00987   checkThreadInit();
00988   testCollision(&cdata);
00989   return cdata.collides;
00990 }
00991 
00992 bool collision_space::EnvironmentModelODE::isSelfCollision(void) const
00993 {
00994   CollisionData cdata; 
00995   cdata.geom_lookup_map = &geom_lookup_map_;
00996   cdata.dspace_lookup_map = &dspace_lookup_map_;
00997   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
00998   if (!allowed_contacts_.empty())
00999     cdata.allowed = &allowed_contact_map_;
01000   checkThreadInit();
01001   testSelfCollision(&cdata);
01002   return cdata.collides;
01003 }
01004 
01005 bool collision_space::EnvironmentModelODE::isEnvironmentCollision(void) const
01006 {
01007   CollisionData cdata; 
01008   cdata.geom_lookup_map = &geom_lookup_map_;
01009   cdata.dspace_lookup_map = &dspace_lookup_map_;
01010   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
01011   if (!allowed_contacts_.empty())
01012     cdata.allowed = &allowed_contact_map_;
01013   checkThreadInit();
01014   testEnvironmentCollision(&cdata);
01015   return cdata.collides;
01016 }
01017 
01018 bool collision_space::EnvironmentModelODE::isObjectRobotCollision(const std::string& object_name) const {
01019   std::map<std::string, CollisionNamespace *>::const_iterator it =
01020     coll_namespaces_.find(object_name);
01021   if (it == coll_namespaces_.end()) {
01022     ROS_WARN("Attempt to check collision for %s and robot, but no such object exists", object_name.c_str());
01023     return false;
01024   }
01025   CollisionData cdata; 
01026   cdata.geom_lookup_map = &geom_lookup_map_;
01027   cdata.dspace_lookup_map = &dspace_lookup_map_;
01028   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
01029   if (!allowed_contacts_.empty())
01030     cdata.allowed = &allowed_contact_map_;
01031   checkThreadInit();
01032   testObjectCollision(it->second, &cdata);
01033   return cdata.collides;
01034 }
01035 
01036 bool collision_space::EnvironmentModelODE::isObjectObjectCollision(const std::string& object1_name, 
01037                                                                    const std::string& object2_name) const
01038 {
01039   CollisionData cdata; 
01040   cdata.geom_lookup_map = &geom_lookup_map_;
01041   cdata.dspace_lookup_map = &dspace_lookup_map_;
01042   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
01043   if (!allowed_contacts_.empty())
01044     cdata.allowed = &allowed_contact_map_;
01045   checkThreadInit();
01046   testObjectObjectCollision(&cdata, object1_name, object2_name);
01047   return cdata.collides;
01048 }
01049 
01050 bool collision_space::EnvironmentModelODE::isObjectInEnvironmentCollision(const std::string& object_name) const
01051 {
01052   CollisionData cdata; 
01053   cdata.geom_lookup_map = &geom_lookup_map_;
01054   cdata.dspace_lookup_map = &dspace_lookup_map_;
01055   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
01056   if (!allowed_contacts_.empty())
01057     cdata.allowed = &allowed_contact_map_;
01058   checkThreadInit();
01059   testObjectEnvironmentCollision(&cdata, object_name);
01060   return cdata.collides;
01061 }
01062 
01063 bool collision_space::EnvironmentModelODE::getAllObjectEnvironmentCollisionContacts(const std::string& object_name, 
01064                                                                                     std::vector<Contact> &contacts,
01065                                                                                     unsigned int num_contacts_per_pair) const {
01066   contacts.clear();
01067   CollisionData cdata;
01068   cdata.geom_lookup_map = &geom_lookup_map_;
01069   cdata.dspace_lookup_map = &dspace_lookup_map_;
01070   cdata.allowed_collision_matrix = &getCurrentAllowedCollisionMatrix();
01071   cdata.contacts = &contacts;
01072   cdata.max_contacts_total = UINT_MAX;
01073   cdata.max_contacts_pair = num_contacts_per_pair;
01074   if (!allowed_contacts_.empty())
01075     cdata.allowed = &allowed_contact_map_;
01076   checkThreadInit();
01077   testObjectEnvironmentCollision(&cdata, object_name);
01078   return cdata.collides;
01079 }
01080 
01081 void collision_space::EnvironmentModelODE::testObjectEnvironmentCollision(CollisionData *cdata, const std::string& object_name) const {
01082   
01083   for (std::map<std::string, CollisionNamespace*>::const_iterator it = coll_namespaces_.begin() ; it != coll_namespaces_.end() && !cdata->done ; ++it) {
01084     if (it->first != object_name) 
01085     {
01086       testObjectObjectCollision(cdata, object_name, it->first);
01087     }
01088   }
01089 }
01090 
01091 void collision_space::EnvironmentModelODE::testObjectObjectCollision(CollisionData *cdata, 
01092                                                                      const std::string& object1_name, 
01093                                                                      const std::string& object2_name) const
01094 {
01095   
01096   std::map<std::string, CollisionNamespace*>::const_iterator it1 = coll_namespaces_.find(object1_name);
01097   if (it1 == coll_namespaces_.end())
01098   {
01099     ROS_WARN_STREAM("Failed to find object " << object1_name << " during collision check.");
01100     return;
01101   }
01102   std::map<std::string, CollisionNamespace*>::const_iterator it2 = coll_namespaces_.find(object2_name);
01103   if (it2 == coll_namespaces_.end())
01104   {
01105     ROS_WARN_STREAM("Failed to find object " << object2_name << " during collision check.");
01106     return;
01107   }
01108 
01109   
01110   bool allowed = false;
01111   if(cdata->allowed_collision_matrix) {
01112     if(!cdata->allowed_collision_matrix->getAllowedCollision(object1_name, object2_name, allowed)) {
01113       ROS_WARN_STREAM("No entry in cdata allowed collision matrix for " << object1_name << " and " << object2_name);
01114     } 
01115   }
01116 
01117   if (!allowed)
01118   {
01119     ROS_DEBUG_STREAM("Checking collision between " << object1_name << " and " << object2_name << ".");
01120     dSpaceCollide2((dxGeom *)it1->second->space, (dxGeom *)it2->second->space, cdata, nearCallbackFn);
01121   }
01122   else
01123   {
01124     ROS_DEBUG_STREAM("Not checking collision between " << object1_name << " and " << object2_name << " since collision is allowed between the two.");
01125     return;
01126   }
01127  
01128 }
01129 
01130 void collision_space::EnvironmentModelODE::testObjectCollision(CollisionNamespace *cn, CollisionData *cdata) const
01131 { 
01132   if (cn->collide2.empty()) {
01133     ROS_WARN_STREAM("Problem - collide2 required for body collision for " << cn->name);
01134     return;
01135   }
01136   
01137   cn->collide2.setup();
01138   for (int i = model_geom_.link_geom.size() - 1 ; i >= 0 && !cdata->done; --i) {
01139     LinkGeom *lg = model_geom_.link_geom[i];
01140     
01141     bool allowed = false;
01142     if(cdata->allowed_collision_matrix) {
01143       if(!cdata->allowed_collision_matrix->getAllowedCollision(cn->name, lg->link->getName(), allowed)) {
01144         ROS_WARN_STREAM("No entry in cdata allowed collision matrix for " << cn->name << " and " << lg->link->getName());
01145         return;
01146       } 
01147     }
01148     
01149     
01150     if(!allowed) {
01151       ROS_DEBUG_STREAM("Will test for collision between object " << cn->name << " and link " << lg->link->getName());
01152       for(unsigned int j = 0; j < lg->padded_geom.size(); j++) {
01153         
01154         unsigned int current_contacts_size = 0;
01155         if(cdata->contacts) {
01156           current_contacts_size = cdata->contacts->size();
01157         }
01158         cn->collide2.collide(lg->padded_geom[j], cdata, nearCallbackFn);
01159         if(cdata->contacts && cdata->contacts->size() > current_contacts_size) {
01160           
01161           for(unsigned int k = current_contacts_size; k < cdata->contacts->size(); k++) {
01162             if(cdata->contacts->at(k).body_type_1 == OBJECT) {
01163               cdata->contacts->at(k).body_name_1 = cn->name;
01164             } else if(cdata->contacts->at(k).body_type_2 == OBJECT) {
01165               cdata->contacts->at(k).body_name_2 = cn->name;
01166             } else {
01167               ROS_WARN_STREAM("New contacts really should have an object as one of the bodys");
01168             }
01169           }
01170         }
01171         if(cdata->done) {
01172           return;
01173         }
01174       }
01175     } else {
01176       ROS_DEBUG_STREAM("Will not test for allowed collision between object " << cn->name << " and link " << lg->link->getName());
01177     }
01178     
01179     for(unsigned int j = 0; j < lg->att_bodies.size(); j++) {
01180       std::string att_name = lg->att_bodies[j]->att->getName();
01181       allowed = false;
01182       if(cdata->allowed_collision_matrix) {
01183         if(!cdata->allowed_collision_matrix->getAllowedCollision(cn->name, att_name, allowed)) {
01184           ROS_WARN_STREAM("No entry in current allowed collision matrix for " << cn->name << " and " << att_name);
01185           return;
01186         }
01187       }
01188       if(!allowed) {
01189         ROS_DEBUG_STREAM("Will test for collision between object " << cn->name << " and attached object " << att_name);
01190         for(unsigned int k = 0; k < lg->att_bodies[j]->padded_geom.size(); k++) {
01191           
01192           unsigned int current_contacts_size = 0;
01193           if(cdata->contacts) {
01194             current_contacts_size = cdata->contacts->size();
01195           }
01196           cn->collide2.collide(lg->att_bodies[j]->padded_geom[k], cdata, nearCallbackFn);
01197           if(cdata->contacts && cdata->contacts->size() > current_contacts_size) {
01198             
01199             for(unsigned int l = current_contacts_size; l < cdata->contacts->size(); l++) {
01200               if(cdata->contacts->at(l).body_type_1 == OBJECT) {
01201                 cdata->contacts->at(l).body_name_1 = cn->name;
01202               } else if(cdata->contacts->at(l).body_type_2 == OBJECT) {
01203                 cdata->contacts->at(l).body_name_2 = cn->name;
01204               } else {
01205                 ROS_WARN_STREAM("New contacts really should have an object as one of the bodys");
01206               }
01207             }
01208           }
01209           if(cdata->done) {
01210             return;
01211           }
01212         }
01213       } else {
01214         ROS_DEBUG_STREAM("Will not test for allowed collision between object " << cn->name << " and attached object " << att_name);
01215       } 
01216     }
01217   }
01218 }
01219 
01220 void collision_space::EnvironmentModelODE::testCollision(CollisionData *cdata) const
01221 {
01222   testSelfCollision(cdata);
01223   testEnvironmentCollision(cdata);    
01224 }
01225 
01226 void collision_space::EnvironmentModelODE::testSelfCollision(CollisionData *cdata) const
01227 {
01228   dSpaceCollide(model_geom_.self_space, cdata, nearCallbackFn);
01229 }
01230 
01231 void collision_space::EnvironmentModelODE::testEnvironmentCollision(CollisionData *cdata) const
01232 {
01233   
01234   for (std::map<std::string, CollisionNamespace*>::const_iterator it = coll_namespaces_.begin() ; it != coll_namespaces_.end() && !cdata->done ; ++it) {
01235     testObjectCollision(it->second, cdata);
01236   }
01237 }
01238 
01239 bool collision_space::EnvironmentModelODE::hasObject(const std::string& ns) const
01240 {
01241   if(coll_namespaces_.find(ns) != coll_namespaces_.end()) {
01242     return true;
01243   }
01244   return false;
01245 }
01246 
01247 void collision_space::EnvironmentModelODE::addObjects(const std::string &ns, const std::vector<shapes::Shape*> &shapes, const std::vector<tf::Transform> &poses)
01248 {
01249   assert(shapes.size() == poses.size());
01250   std::map<std::string, CollisionNamespace*>::iterator it = coll_namespaces_.find(ns);
01251   CollisionNamespace* cn = NULL;    
01252   if (it == coll_namespaces_.end())
01253   {
01254     cn = new CollisionNamespace(ns);
01255     dspace_lookup_map_[ns] = cn->space;
01256     coll_namespaces_[ns] = cn;
01257     default_collision_matrix_.addEntry(ns, false);
01258   }
01259   else {
01260      cn = it->second;
01261   }
01262 
01263   
01264   objects_->addObjectNamespace(ns);
01265 
01266   unsigned int n = shapes.size();
01267   for (unsigned int i = 0 ; i < n ; ++i)
01268   {
01269     dGeomID g = createODEGeom(cn->space, cn->storage, shapes[i], 1.0, 0.0);
01270     assert(g);
01271     dGeomSetData(g, reinterpret_cast<void*>(shapes[i]));
01272     updateGeom(g, poses[i]);
01273     cn->collide2.registerGeom(g);
01274     objects_->addObject(ns, shapes[i], poses[i]);
01275   }
01276   cn->collide2.setup();
01277 }
01278 
01279 void collision_space::EnvironmentModelODE::addObject(const std::string &ns, shapes::Shape *shape, const tf::Transform &pose)
01280 {
01281   std::map<std::string, CollisionNamespace*>::iterator it = coll_namespaces_.find(ns);
01282   CollisionNamespace* cn = NULL;    
01283   if (it == coll_namespaces_.end())
01284   {
01285     cn = new CollisionNamespace(ns);
01286     dspace_lookup_map_[ns] = cn->space;
01287     coll_namespaces_[ns] = cn;
01288     default_collision_matrix_.addEntry(ns, false);
01289   }
01290   else
01291     cn = it->second;
01292 
01293   dGeomID g = createODEGeom(cn->space, cn->storage, shape, 1.0, 0.0);
01294   assert(g);
01295   dGeomSetData(g, reinterpret_cast<void*>(shape));
01296 
01297   updateGeom(g, pose);
01298   cn->geoms.push_back(g);
01299   objects_->addObject(ns, shape, pose);
01300 }
01301 
01302 void collision_space::EnvironmentModelODE::addObject(const std::string &ns, shapes::StaticShape* shape)
01303 {   
01304   std::map<std::string, CollisionNamespace*>::iterator it = coll_namespaces_.find(ns);
01305   CollisionNamespace* cn = NULL;    
01306   if (it == coll_namespaces_.end())
01307   {
01308     cn = new CollisionNamespace(ns);
01309     dspace_lookup_map_[ns] = cn->space;
01310     coll_namespaces_[ns] = cn;
01311     default_collision_matrix_.addEntry(ns, false);
01312   }
01313   else
01314     cn = it->second;
01315 
01316   dGeomID g = createODEGeom(cn->space, cn->storage, shape);
01317   assert(g);
01318   dGeomSetData(g, reinterpret_cast<void*>(shape));
01319   cn->geoms.push_back(g);
01320   objects_->addObject(ns, shape);
01321 }
01322 
01323 void collision_space::EnvironmentModelODE::clearObjects(void)
01324 {
01325   for (std::map<std::string, CollisionNamespace*>::iterator it = coll_namespaces_.begin() ; it != coll_namespaces_.end() ; ++it) {
01326     default_collision_matrix_.removeEntry(it->first);
01327     delete it->second;
01328   }
01329   dspace_lookup_map_.clear();
01330   coll_namespaces_.clear();
01331   objects_->clearObjects();
01332 }
01333 
01334 void collision_space::EnvironmentModelODE::clearObjects(const std::string &ns)
01335 {
01336   std::map<std::string, CollisionNamespace*>::iterator it = coll_namespaces_.find(ns);
01337   if (it != coll_namespaces_.end()) {
01338     default_collision_matrix_.removeEntry(ns);
01339     delete it->second;
01340     coll_namespaces_.erase(ns);
01341     dspace_lookup_map_.erase(ns);
01342   }
01343   objects_->clearObjects(ns);
01344 }
01345 
01346 dGeomID collision_space::EnvironmentModelODE::copyGeom(dSpaceID space, ODEStorage &storage, dGeomID geom, ODEStorage &sourceStorage) const
01347 {
01348   int c = dGeomGetClass(geom);
01349   dGeomID ng = NULL;
01350   bool location = true;
01351   switch (c)
01352   {
01353   case dSphereClass:
01354     ng = dCreateSphere(space, dGeomSphereGetRadius(geom));
01355     break;
01356   case dBoxClass:
01357     {
01358       dVector3 r;
01359       dGeomBoxGetLengths(geom, r);
01360       ng = dCreateBox(space, r[0], r[1], r[2]);
01361     }
01362     break;
01363   case dCylinderClass:
01364     {
01365       dReal r, l;
01366       dGeomCylinderGetParams(geom, &r, &l);
01367       ng = dCreateCylinder(space, r, l);
01368     }
01369     break;
01370   case dPlaneClass:
01371     {
01372       dVector4 p;
01373       dGeomPlaneGetParams(geom, p);
01374       ng = dCreatePlane(space, p[0], p[1], p[2], p[3]);
01375       location = false;
01376     }
01377     break;
01378   case dTriMeshClass:
01379     {
01380       dTriMeshDataID tdata = dGeomTriMeshGetData(geom);
01381       dTriMeshDataID cdata = dGeomTriMeshDataCreate();
01382       for(std::map<dGeomID, ODEStorage::Element>::const_iterator it = sourceStorage.meshes.begin();
01383           it != sourceStorage.meshes.end();
01384           it++) {
01385         if (it->second.data == tdata)
01386         {
01387           ODEStorage::Element& e = storage.meshes[geom];
01388           e.n_vertices = it->second.n_vertices;
01389           e.n_indices = it->second.n_indices;
01390           e.indices = new dTriIndex[e.n_indices];
01391           for (int j = 0 ; j < e.n_indices ; ++j)
01392             e.indices[j] = it->second.indices[j];
01393           e.vertices = new double[e.n_vertices];
01394           for (int j = 0 ; j < e.n_vertices ; ++j)
01395             e.vertices[j] = e.vertices[j];
01396           dGeomTriMeshDataBuildDouble(cdata, e.vertices, sizeof(double) * 3, e.n_vertices, e.indices, e.n_indices, sizeof(dTriIndex) * 3);
01397           e.data = cdata;
01398           break;
01399         }
01400         ng = dCreateTriMesh(space, cdata, NULL, NULL, NULL);
01401       }
01402     }
01403     break;
01404   default:
01405     assert(0); 
01406     break;
01407   }
01408     
01409   if (ng && location)
01410   {
01411     const dReal *pos = dGeomGetPosition(geom);
01412     dGeomSetPosition(ng, pos[0], pos[1], pos[2]);
01413     dQuaternion q;
01414     dGeomGetQuaternion(geom, q);
01415     dGeomSetQuaternion(ng, q);
01416   }
01417     
01418   return ng;
01419 }
01420 
01421 collision_space::EnvironmentModel* collision_space::EnvironmentModelODE::clone(void) const
01422 {
01423   EnvironmentModelODE *env = new EnvironmentModelODE();
01424   env->default_collision_matrix_ = default_collision_matrix_;
01425   env->default_link_padding_map_ = default_link_padding_map_;
01426   env->verbose_ = verbose_;
01427   env->robot_scale_ = robot_scale_;
01428   env->default_robot_padding_ = default_robot_padding_;
01429   env->robot_model_ = new planning_models::KinematicModel(*robot_model_);
01430   env->createODERobotModel();
01431 
01432   for (std::map<std::string, CollisionNamespace*>::const_iterator it = coll_namespaces_.begin() ; it != coll_namespaces_.end() ; ++it) {
01433     
01434     std::map<void*, int> shapePtrs;
01435     const EnvironmentObjects::NamespaceObjects &ns = objects_->getObjects(it->first);
01436     unsigned int n = ns.static_shape.size();
01437     for (unsigned int i = 0 ; i < n ; ++i)
01438       shapePtrs[ns.static_shape[i]] = -1 - i;
01439     n = ns.shape.size();
01440     for (unsigned int i = 0 ; i < n ; ++i)
01441       shapePtrs[ns.shape[i]] = i;
01442     
01443     
01444     CollisionNamespace *cn = new CollisionNamespace(it->first);
01445     env->coll_namespaces_[it->first] = cn;
01446     env->dspace_lookup_map_[cn->name] = cn->space;
01447     n = it->second->geoms.size();
01448     cn->geoms.reserve(n);
01449     for (unsigned int i = 0 ; i < n ; ++i)
01450     {
01451       dGeomID newGeom = copyGeom(cn->space, cn->storage, it->second->geoms[i], it->second->storage);
01452       int idx = shapePtrs[dGeomGetData(it->second->geoms[i])];
01453       if (idx < 0) 
01454       {
01455         shapes::StaticShape *newShape = shapes::cloneShape(ns.static_shape[-idx - 1]);
01456         dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01457         env->objects_->addObject(it->first, newShape);
01458       }
01459       else 
01460       {
01461         shapes::Shape *newShape = shapes::cloneShape(ns.shape[idx]);
01462         dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01463         env->objects_->addObject(it->first, newShape, ns.shape_pose[idx]);
01464       }
01465       cn->geoms.push_back(newGeom);
01466     }
01467     std::vector<dGeomID> geoms;
01468     it->second->collide2.getGeoms(geoms);
01469     n = geoms.size();
01470     for (unsigned int i = 0 ; i < n ; ++i)
01471     {
01472       dGeomID newGeom = copyGeom(cn->space, cn->storage, geoms[i], it->second->storage);
01473       int idx = shapePtrs[dGeomGetData(geoms[i])];
01474       if (idx < 0) 
01475       {
01476         shapes::StaticShape *newShape = shapes::cloneShape(ns.static_shape[-idx - 1]);
01477         dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01478         env->objects_->addObject(it->first, newShape);
01479       }
01480       else 
01481       {
01482         shapes::Shape *newShape = shapes::cloneShape(ns.shape[idx]);
01483         dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01484         env->objects_->addObject(it->first, newShape, ns.shape_pose[idx]);
01485       }
01486       cn->collide2.registerGeom(newGeom);
01487     }
01488   }
01489     
01490   return env;    
01491 }