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 <boost/thread.hpp>
00041 #include <cassert>
00042 #include <cstdio>
00043 #include <cmath>
00044 #include <algorithm>
00045 #include <map>
00046
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 static const unsigned int MAX_ODE_CONTACTS = 128;
00054
00055 collision_space::EnvironmentModelODE::EnvironmentModelODE(void) : EnvironmentModel()
00056 {
00057 ODEInitCountLock.lock();
00058 if (ODEInitCount == 0)
00059 {
00060 ROS_DEBUG("Initializing ODE");
00061 dInitODE2(0);
00062 }
00063 ODEInitCount++;
00064 ODEInitCountLock.unlock();
00065
00066 checkThreadInit();
00067
00068 m_modelGeom.space = dSweepAndPruneSpaceCreate(0, dSAP_AXES_XZY);
00069 }
00070
00071 collision_space::EnvironmentModelODE::~EnvironmentModelODE(void)
00072 {
00073 freeMemory();
00074 ODEInitCountLock.lock();
00075 ODEInitCount--;
00076 if (ODEInitCount == 0)
00077 {
00078 ROS_DEBUG("Closing ODE");
00079 dCloseODE();
00080 }
00081 ODEInitCountLock.unlock();
00082 }
00083
00084 void collision_space::EnvironmentModelODE::checkThreadInit(void) const
00085 {
00086 boost::thread::id id = boost::this_thread::get_id();
00087 ODEThreadMapLock.lock();
00088 if (ODEThreadMap.find(id) == ODEThreadMap.end())
00089 {
00090 ODEThreadMap[id] = 1;
00091 ROS_DEBUG("Initializing new thread (%d total)", (int)ODEThreadMap.size());
00092 dAllocateODEDataForThread(dAllocateMaskAll);
00093 }
00094 ODEThreadMapLock.unlock();
00095 }
00096
00097 void collision_space::EnvironmentModelODE::freeMemory(void)
00098 {
00099 for (unsigned int j = 0 ; j < m_modelGeom.linkGeom.size() ; ++j)
00100 delete m_modelGeom.linkGeom[j];
00101 if (m_modelGeom.space)
00102 dSpaceDestroy(m_modelGeom.space);
00103 for (std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.begin() ; it != m_collNs.end() ; ++it)
00104 delete it->second;
00105 }
00106
00107 void collision_space::EnvironmentModelODE::setRobotModel(const boost::shared_ptr<const planning_models::KinematicModel> &model,
00108 const std::vector<std::string> &links,
00109 const std::map<std::string, double>& link_padding_map,
00110 double default_padding,
00111 double scale)
00112 {
00113 collision_space::EnvironmentModel::setRobotModel(model, links, link_padding_map, default_padding, scale);
00114 link_padding_map_ = link_padding_map;
00115 createODERobotModel();
00116 }
00117
00118 const std::vector<const planning_models::KinematicModel::AttachedBodyModel*> collision_space::EnvironmentModelODE::getAttachedBodies(void) const
00119 {
00120 std::vector<const planning_models::KinematicModel::AttachedBodyModel*> ret_vec;
00121
00122 const unsigned int n = m_modelGeom.linkGeom.size();
00123 for (unsigned int i = 0 ; i < n ; ++i)
00124 {
00125 kGeom *kg = m_modelGeom.linkGeom[i];
00126
00127
00128 const unsigned int nab = kg->link->getAttachedBodyModels().size();
00129 for (unsigned int k = 0 ; k < nab ; ++k)
00130 {
00131 ret_vec.push_back(kg->link->getAttachedBodyModels()[k]);
00132 }
00133 }
00134 return ret_vec;
00135 }
00136
00137 const std::vector<const planning_models::KinematicModel::AttachedBodyModel*> collision_space::EnvironmentModelODE::getAttachedBodies(std::string link_name) const
00138 {
00139 std::vector<const planning_models::KinematicModel::AttachedBodyModel*> ret_vec;
00140
00141 if(m_collisionLinkIndex.find(link_name) == m_collisionLinkIndex.end()) {
00142 return ret_vec;
00143 }
00144
00145 unsigned int ind = m_collisionLinkIndex.find(link_name)->second;
00146
00147 kGeom *kg = m_modelGeom.linkGeom[ind];
00148
00149
00150 const unsigned int nab = kg->link->getAttachedBodyModels().size();
00151 for (unsigned int k = 0 ; k < nab ; ++k)
00152 {
00153 ret_vec.push_back(kg->link->getAttachedBodyModels()[k]);
00154 }
00155 return ret_vec;
00156 }
00157
00158 void collision_space::EnvironmentModelODE::createODERobotModel()
00159 {
00160 for (unsigned int i = 0 ; i < m_collisionLinks.size() ; ++i)
00161 {
00162
00163
00164
00165 const planning_models::KinematicModel::LinkModel *link = m_robotModel->getLinkModel(m_collisionLinks[i]);
00166 if (!link || !link->getLinkShape())
00167 continue;
00168
00169 kGeom *kg = new kGeom();
00170 kg->link = link;
00171 kg->enabled = true;
00172 kg->index = i;
00173 double padd = m_robotPadd;
00174 if(link_padding_map_.find(link->getName()) != link_padding_map_.end()) {
00175 padd = link_padding_map_.find(link->getName())->second;
00176 }
00177 ROS_DEBUG_STREAM("Link " << link->getName() << " padding " << padd);
00178 dGeomID g = createODEGeom(m_modelGeom.space, m_modelGeom.storage, link->getLinkShape(), m_robotScale, padd);
00179 assert(g);
00180 dGeomSetData(g, reinterpret_cast<void*>(kg));
00181 kg->geom.push_back(g);
00182 const std::vector<planning_models::KinematicModel::AttachedBodyModel*>& attached_bodies = link->getAttachedBodyModels();
00183 for (unsigned int j = 0 ; j < attached_bodies.size() ; ++j)
00184 {
00185 for(unsigned int k = 0; k < attached_bodies[j]->getShapes().size(); k++) {
00186 padd = m_robotPadd;
00187 if(link_padding_map_.find(attached_bodies[j]->getName()) != link_padding_map_.end()) {
00188 padd = link_padding_map_.find(attached_bodies[j]->getName())->second;
00189 } else if (link_padding_map_.find("attached") != link_padding_map_.end()) {
00190 padd = link_padding_map_.find("attached")->second;
00191 }
00192 dGeomID ga = createODEGeom(m_modelGeom.space, m_modelGeom.storage, attached_bodies[j]->getShapes()[k], m_robotScale, padd);
00193 assert(ga);
00194 dGeomSetData(ga, reinterpret_cast<void*>(kg));
00195 kg->geom.push_back(ga);
00196 kg->geomAttachedBodyMap[ga] = j+1;
00197 }
00198 }
00199 m_modelGeom.linkGeom.push_back(kg);
00200 }
00201 updateAllowedTouch();
00202 }
00203
00204 dGeomID collision_space::EnvironmentModelODE::createODEGeom(dSpaceID space, ODEStorage &storage, const shapes::StaticShape *shape)
00205 {
00206 dGeomID g = NULL;
00207 switch (shape->type)
00208 {
00209 case shapes::PLANE:
00210 {
00211 const shapes::Plane *p = static_cast<const shapes::Plane*>(shape);
00212 g = dCreatePlane(space, p->a, p->b, p->c, p->d);
00213 }
00214 break;
00215 default:
00216 break;
00217 }
00218 return g;
00219 }
00220
00221 dGeomID collision_space::EnvironmentModelODE::createODEGeom(dSpaceID space, ODEStorage &storage, const shapes::Shape *shape, double scale, double padding)
00222 {
00223 dGeomID g = NULL;
00224 switch (shape->type)
00225 {
00226 case shapes::SPHERE:
00227 {
00228 g = dCreateSphere(space, static_cast<const shapes::Sphere*>(shape)->radius * scale + padding);
00229 }
00230 break;
00231 case shapes::BOX:
00232 {
00233 const double *size = static_cast<const shapes::Box*>(shape)->size;
00234 g = dCreateBox(space, size[0] * scale + padding * 2.0, size[1] * scale + padding * 2.0, size[2] * scale + padding * 2.0);
00235 }
00236 break;
00237 case shapes::CYLINDER:
00238 {
00239 g = dCreateCylinder(space, static_cast<const shapes::Cylinder*>(shape)->radius * scale + padding,
00240 static_cast<const shapes::Cylinder*>(shape)->length * scale + padding * 2.0);
00241 }
00242 break;
00243 case shapes::MESH:
00244 {
00245 const shapes::Mesh *mesh = static_cast<const shapes::Mesh*>(shape);
00246 if (mesh->vertexCount > 0 && mesh->triangleCount > 0)
00247 {
00248
00249 int icount = mesh->triangleCount * 3;
00250 dTriIndex *indices = new dTriIndex[icount];
00251 for (int i = 0 ; i < icount ; ++i)
00252 indices[i] = mesh->triangles[i];
00253
00254
00255 double *vertices = new double[mesh->vertexCount* 3];
00256 double sx = 0.0, sy = 0.0, sz = 0.0;
00257 for (unsigned int i = 0 ; i < mesh->vertexCount ; ++i)
00258 {
00259 unsigned int i3 = i * 3;
00260 vertices[i3] = mesh->vertices[i3];
00261 vertices[i3 + 1] = mesh->vertices[i3 + 1];
00262 vertices[i3 + 2] = mesh->vertices[i3 + 2];
00263 sx += vertices[i3];
00264 sy += vertices[i3 + 1];
00265 sz += vertices[i3 + 2];
00266 }
00267
00268 sx /= (double)mesh->vertexCount;
00269 sy /= (double)mesh->vertexCount;
00270 sz /= (double)mesh->vertexCount;
00271
00272
00273 for (unsigned int i = 0 ; i < mesh->vertexCount ; ++i)
00274 {
00275 unsigned int i3 = i * 3;
00276
00277
00278 double dx = vertices[i3] - sx;
00279 double dy = vertices[i3 + 1] - sy;
00280 double dz = vertices[i3 + 2] - sz;
00281
00282
00283
00284
00285 double ndx = ((dx > 0) ? dx+padding : dx-padding);
00286 double ndy = ((dy > 0) ? dy+padding : dy-padding);
00287 double ndz = ((dz > 0) ? dz+padding : dz-padding);
00288
00289
00290
00291 vertices[i3] = sx + ndx;
00292 vertices[i3 + 1] = sy + ndy;
00293 vertices[i3 + 2] = sz + ndz;
00294 }
00295
00296 dTriMeshDataID data = dGeomTriMeshDataCreate();
00297 dGeomTriMeshDataBuildDouble(data, vertices, sizeof(double) * 3, mesh->vertexCount, indices, icount, sizeof(dTriIndex) * 3);
00298 g = dCreateTriMesh(space, data, NULL, NULL, NULL);
00299 unsigned int p = storage.mesh.size();
00300 storage.mesh.resize(p + 1);
00301 storage.mesh[p].vertices = vertices;
00302 storage.mesh[p].indices = indices;
00303 storage.mesh[p].data = data;
00304 storage.mesh[p].nVertices = mesh->vertexCount;
00305 storage.mesh[p].nIndices = icount;
00306 }
00307 }
00308
00309 default:
00310 break;
00311 }
00312 return g;
00313 }
00314
00315 void collision_space::EnvironmentModelODE::updateGeom(dGeomID geom, const btTransform &pose) const
00316 {
00317 btVector3 pos = pose.getOrigin();
00318 dGeomSetPosition(geom, pos.getX(), pos.getY(), pos.getZ());
00319 btQuaternion quat = pose.getRotation();
00320 dQuaternion q;
00321 q[0] = quat.getW(); q[1] = quat.getX(); q[2] = quat.getY(); q[3] = quat.getZ();
00322 dGeomSetQuaternion(geom, q);
00323 }
00324
00325 void collision_space::EnvironmentModelODE::updateAttachedBodies()
00326 {
00327 updateAttachedBodies(link_padding_map_);
00328 }
00329
00330 void collision_space::EnvironmentModelODE::updateAttachedBodies(const std::map<std::string, double>& link_padding_map)
00331 {
00332 for (unsigned int i = 0 ; i < m_modelGeom.linkGeom.size() ; ++i) {
00333 kGeom *kg = m_modelGeom.linkGeom[i];
00334
00335 kg->geomAttachedBodyMap.clear();
00336
00337 for (unsigned int j = 1 ; j < kg->geom.size() ; ++j)
00338 dGeomDestroy(kg->geom[j]);
00339 kg->geom.resize(1);
00340
00341
00342 const std::vector<planning_models::KinematicModel::AttachedBodyModel*>& attached_bodies = kg->link->getAttachedBodyModels();
00343 for (unsigned int j = 0 ; j < attached_bodies.size(); ++j) {
00344 ROS_DEBUG_STREAM("Updating attached body " << attached_bodies[j]->getName());
00345 for(unsigned int k = 0; k < attached_bodies[j]->getShapes().size(); k++) {
00346 double padd = m_robotPadd;
00347 if(link_padding_map.find(attached_bodies[j]->getName()) != link_padding_map.end()) {
00348 padd = link_padding_map.find(attached_bodies[j]->getName())->second;
00349 } else if (link_padding_map.find("attached") != link_padding_map.end()) {
00350 padd = link_padding_map.find("attached")->second;
00351 }
00352 ROS_DEBUG_STREAM("Setting padding for attached body " << attached_bodies[j]->getName() << " to " << padd);
00353 dGeomID ga = createODEGeom(m_modelGeom.space, m_modelGeom.storage, attached_bodies[j]->getShapes()[k], m_robotScale, padd);
00354 assert(ga);
00355 dGeomSetData(ga, reinterpret_cast<void*>(kg));
00356 kg->geom.push_back(ga);
00357 kg->geomAttachedBodyMap[ga] = j+1;
00358 }
00359 }
00360 }
00361 updateAllowedTouch();
00362 }
00363
00364 void collision_space::EnvironmentModelODE::updateRobotModel(const planning_models::KinematicState* state)
00365 {
00366 const unsigned int n = m_modelGeom.linkGeom.size();
00367
00368 for (unsigned int i = 0 ; i < n ; ++i) {
00369 const planning_models::KinematicState::LinkState* link_state = state->getLinkState(m_modelGeom.linkGeom[i]->link->getName());
00370 if(link_state == NULL) {
00371 ROS_WARN_STREAM("No link state for link " << m_modelGeom.linkGeom[i]->link->getName());
00372 continue;
00373 }
00374 updateGeom(m_modelGeom.linkGeom[i]->geom[0], link_state->getGlobalCollisionBodyTransform());
00375 const std::vector<planning_models::KinematicState::AttachedBodyState*>& attached_bodies = link_state->getAttachedBodyStateVector();
00376 for (unsigned int j = 0 ; j < attached_bodies.size(); ++j) {
00377 for(unsigned int k = 0; k < attached_bodies[j]->getGlobalCollisionBodyTransforms().size(); k++) {
00378 updateGeom(m_modelGeom.linkGeom[i]->geom[k + 1], attached_bodies[j]->getGlobalCollisionBodyTransforms()[k]);
00379 }
00380 }
00381 }
00382 }
00383
00384 void collision_space::EnvironmentModelODE::setRobotLinkPadding(const std::map<std::string, double>& new_link_padding) {
00385
00386 for(unsigned int i = 0; i < m_modelGeom.linkGeom.size(); i++) {
00387
00388 kGeom *kg = m_modelGeom.linkGeom[i];
00389
00390 if(new_link_padding.find(kg->link->getName()) != new_link_padding.end()) {
00391 if(link_padding_map_.find(kg->link->getName()) == link_padding_map_.end()) {
00392 ROS_WARN_STREAM("No existing padding for object " << kg->link->getName());
00393 continue;
00394 }
00395 double new_padding = new_link_padding.find(kg->link->getName())->second;
00396 if(link_padding_map_[kg->link->getName()] == new_padding) {
00397
00398 continue;
00399 }
00400 const planning_models::KinematicModel::LinkModel *link = m_robotModel->getLinkModel(m_collisionLinks[i]);
00401 if (!link || !link->getLinkShape()) {
00402 ROS_WARN_STREAM("Can't get kinematic model for link " << link->getName() << " to make new padding");
00403 continue;
00404 }
00405 ROS_DEBUG_STREAM("Setting padding for link " << kg->link->getName() << " from " << link_padding_map_[kg->link->getName()]
00406 << " to " << new_padding);
00407
00408 for (unsigned int j = 0 ; j < kg->geom.size() ; ++j) {
00409 dGeomDestroy(kg->geom[j]);
00410 }
00411 kg->geom.clear();
00412 dGeomID g = createODEGeom(m_modelGeom.space, m_modelGeom.storage, link->getLinkShape(), m_robotScale, new_padding);
00413 assert(g);
00414 dGeomSetData(g, reinterpret_cast<void*>(kg));
00415 kg->geom.push_back(g);
00416 }
00417 }
00418
00419 updateAttachedBodies(new_link_padding);
00420
00421
00422 collision_space::EnvironmentModel::setRobotLinkPadding(new_link_padding);
00423 }
00424
00425 void collision_space::EnvironmentModelODE::revertRobotLinkPadding() {
00426 for(unsigned int i = 0; i < m_modelGeom.linkGeom.size(); i++) {
00427
00428 kGeom *kg = m_modelGeom.linkGeom[i];
00429
00430 if(altered_link_padding_.find(kg->link->getName()) != altered_link_padding_.end()) {
00431 if(link_padding_map_.find(kg->link->getName()) == link_padding_map_.end()) {
00432 ROS_WARN_STREAM("No initial padding for object " << kg->link->getName());
00433 continue;
00434 }
00435 double old_padding = link_padding_map_[kg->link->getName()];
00436 if(altered_link_padding_[kg->link->getName()] == old_padding) {
00437
00438 continue;
00439 }
00440 const planning_models::KinematicModel::LinkModel *link = m_robotModel->getLinkModel(m_collisionLinks[i]);
00441 if (!link || !link->getLinkShape()) {
00442 ROS_WARN_STREAM("Can't get kinematic model for link " << link->getName() << " to revert to old padding");
00443 continue;
00444 }
00445
00446 for (unsigned int j = 0 ; j < kg->geom.size() ; ++j) {
00447 dGeomDestroy(kg->geom[j]);
00448 }
00449 ROS_DEBUG_STREAM("Reverting padding for link " << kg->link->getName() << " from " << altered_link_padding_[kg->link->getName()]
00450 << " to " << old_padding);
00451 kg->geom.clear();
00452 dGeomID g = createODEGeom(m_modelGeom.space, m_modelGeom.storage, link->getLinkShape(), m_robotScale, old_padding);
00453 assert(g);
00454 dGeomSetData(g, reinterpret_cast<void*>(kg));
00455 kg->geom.push_back(g);
00456 }
00457 }
00458
00459 updateAttachedBodies();
00460
00461
00462 collision_space::EnvironmentModel::revertRobotLinkPadding();
00463 }
00464
00465 bool collision_space::EnvironmentModelODE::ODECollide2::empty(void) const
00466 {
00467 return m_geomsX.empty();
00468 }
00469
00470 void collision_space::EnvironmentModelODE::ODECollide2::registerSpace(dSpaceID space)
00471 {
00472 int n = dSpaceGetNumGeoms(space);
00473 for (int i = 0 ; i < n ; ++i)
00474 registerGeom(dSpaceGetGeom(space, i));
00475 }
00476
00477 void collision_space::EnvironmentModelODE::ODECollide2::unregisterGeom(dGeomID geom)
00478 {
00479 setup();
00480
00481 Geom g;
00482 g.id = geom;
00483 dGeomGetAABB(geom, g.aabb);
00484
00485 Geom *found = NULL;
00486
00487 std::vector<Geom*>::iterator posStart1 = std::lower_bound(m_geomsX.begin(), m_geomsX.end(), &g, SortByXTest());
00488 std::vector<Geom*>::iterator posEnd1 = std::upper_bound(posStart1, m_geomsX.end(), &g, SortByXTest());
00489 while (posStart1 < posEnd1)
00490 {
00491 if ((*posStart1)->id == geom)
00492 {
00493 found = *posStart1;
00494 m_geomsX.erase(posStart1);
00495 break;
00496 }
00497 ++posStart1;
00498 }
00499
00500 std::vector<Geom*>::iterator posStart2 = std::lower_bound(m_geomsY.begin(), m_geomsY.end(), &g, SortByYTest());
00501 std::vector<Geom*>::iterator posEnd2 = std::upper_bound(posStart2, m_geomsY.end(), &g, SortByYTest());
00502 while (posStart2 < posEnd2)
00503 {
00504 if ((*posStart2)->id == geom)
00505 {
00506 assert(found == *posStart2);
00507 m_geomsY.erase(posStart2);
00508 break;
00509 }
00510 ++posStart2;
00511 }
00512
00513 std::vector<Geom*>::iterator posStart3 = std::lower_bound(m_geomsZ.begin(), m_geomsZ.end(), &g, SortByZTest());
00514 std::vector<Geom*>::iterator posEnd3 = std::upper_bound(posStart3, m_geomsZ.end(), &g, SortByZTest());
00515 while (posStart3 < posEnd3)
00516 {
00517 if ((*posStart3)->id == geom)
00518 {
00519 assert(found == *posStart3);
00520 m_geomsZ.erase(posStart3);
00521 break;
00522 }
00523 ++posStart3;
00524 }
00525
00526 assert(found);
00527 delete found;
00528 }
00529
00530 void collision_space::EnvironmentModelODE::ODECollide2::registerGeom(dGeomID geom)
00531 {
00532 Geom *g = new Geom();
00533 g->id = geom;
00534 dGeomGetAABB(geom, g->aabb);
00535 m_geomsX.push_back(g);
00536 m_geomsY.push_back(g);
00537 m_geomsZ.push_back(g);
00538 m_setup = false;
00539 }
00540
00541 void collision_space::EnvironmentModelODE::ODECollide2::clear(void)
00542 {
00543 for (unsigned int i = 0 ; i < m_geomsX.size() ; ++i)
00544 delete m_geomsX[i];
00545 m_geomsX.clear();
00546 m_geomsY.clear();
00547 m_geomsZ.clear();
00548 m_setup = false;
00549 }
00550
00551 void collision_space::EnvironmentModelODE::ODECollide2::setup(void)
00552 {
00553 if (!m_setup)
00554 {
00555 std::sort(m_geomsX.begin(), m_geomsX.end(), SortByXLow());
00556 std::sort(m_geomsY.begin(), m_geomsY.end(), SortByYLow());
00557 std::sort(m_geomsZ.begin(), m_geomsZ.end(), SortByZLow());
00558 m_setup = true;
00559 }
00560 }
00561
00562 void collision_space::EnvironmentModelODE::ODECollide2::getGeoms(std::vector<dGeomID> &geoms) const
00563 {
00564 geoms.resize(m_geomsX.size());
00565 for (unsigned int i = 0 ; i < geoms.size() ; ++i)
00566 geoms[i] = m_geomsX[i]->id;
00567 }
00568
00569 void collision_space::EnvironmentModelODE::ODECollide2::checkColl(std::vector<Geom*>::const_iterator posStart, std::vector<Geom*>::const_iterator posEnd,
00570 Geom *g, void *data, dNearCallback *nearCallback) const
00571 {
00572
00573
00574
00575
00576 while (posStart < posEnd)
00577 {
00578
00579 if (!((*posStart)->aabb[2] > g->aabb[3] ||
00580 (*posStart)->aabb[3] < g->aabb[2] ||
00581 (*posStart)->aabb[4] > g->aabb[5] ||
00582 (*posStart)->aabb[5] < g->aabb[4]))
00583 dSpaceCollide2(g->id, (*posStart)->id, data, nearCallback);
00584 posStart++;
00585 }
00586 }
00587
00588 void collision_space::EnvironmentModelODE::ODECollide2::collide(dGeomID geom, void *data, dNearCallback *nearCallback) const
00589 {
00590 static const int CUTOFF = 100;
00591
00592 assert(m_setup);
00593
00594 Geom g;
00595 g.id = geom;
00596 dGeomGetAABB(geom, g.aabb);
00597
00598 std::vector<Geom*>::const_iterator posStart1 = std::lower_bound(m_geomsX.begin(), m_geomsX.end(), &g, SortByXTest());
00599 if (posStart1 != m_geomsX.end())
00600 {
00601 std::vector<Geom*>::const_iterator posEnd1 = std::upper_bound(posStart1, m_geomsX.end(), &g, SortByXTest());
00602 int d1 = posEnd1 - posStart1;
00603
00604
00605
00606
00607
00608 if (d1 > CUTOFF)
00609 {
00610 std::vector<Geom*>::const_iterator posStart2 = std::lower_bound(m_geomsY.begin(), m_geomsY.end(), &g, SortByYTest());
00611 if (posStart2 != m_geomsY.end())
00612 {
00613 std::vector<Geom*>::const_iterator posEnd2 = std::upper_bound(posStart2, m_geomsY.end(), &g, SortByYTest());
00614 int d2 = posEnd2 - posStart2;
00615
00616 if (d2 > CUTOFF)
00617 {
00618 std::vector<Geom*>::const_iterator posStart3 = std::lower_bound(m_geomsZ.begin(), m_geomsZ.end(), &g, SortByZTest());
00619 if (posStart3 != m_geomsZ.end())
00620 {
00621 std::vector<Geom*>::const_iterator posEnd3 = std::upper_bound(posStart3, m_geomsZ.end(), &g, SortByZTest());
00622 int d3 = posEnd3 - posStart3;
00623 if (d3 > CUTOFF)
00624 {
00625 if (d3 <= d2 && d3 <= d1)
00626 checkColl(posStart3, posEnd3, &g, data, nearCallback);
00627 else
00628 if (d2 <= d3 && d2 <= d1)
00629 checkColl(posStart2, posEnd2, &g, data, nearCallback);
00630 else
00631 checkColl(posStart1, posEnd1, &g, data, nearCallback);
00632 }
00633 else
00634 checkColl(posStart3, posEnd3, &g, data, nearCallback);
00635 }
00636 }
00637 else
00638 checkColl(posStart2, posEnd2, &g, data, nearCallback);
00639 }
00640 }
00641 else
00642 checkColl(posStart1, posEnd1, &g, data, nearCallback);
00643 }
00644 }
00645
00646 namespace collision_space
00647 {
00648
00649 void nearCallbackFn(void *data, dGeomID o1, dGeomID o2)
00650 {
00651 EnvironmentModelODE::CollisionData *cdata = reinterpret_cast<EnvironmentModelODE::CollisionData*>(data);
00652
00653 if (cdata->done)
00654 return;
00655
00656 std::string attached_body;
00657 unsigned int link1_attached_index = 0;
00658 unsigned int link2_attached_index = 0;
00659
00660 if (cdata->selfCollisionTest) {
00661 dSpaceID s1 = dGeomGetSpace(o1);
00662 dSpaceID s2 = dGeomGetSpace(o2);
00663 if (s1 == s2 && s1 == cdata->selfSpace) {
00664 EnvironmentModelODE::kGeom* kg1 = reinterpret_cast<EnvironmentModelODE::kGeom*>(dGeomGetData(o1));
00665 EnvironmentModelODE::kGeom* kg2 = reinterpret_cast<EnvironmentModelODE::kGeom*>(dGeomGetData(o2));
00666 if (kg1 && kg2) {
00667
00668 if (kg1->geom[0] == o1 && kg2->geom[0] == o2) {
00669 if(kg2->allowedTouch[0][kg1->index] != kg1->allowedTouch[0][kg2->index]) {
00670 ROS_WARN_STREAM("Non-symmetric touch entries for " << kg2->link->getName() << " and " << kg1->link->getName());
00671 }
00672 if(kg2->allowedTouch[0][kg1->index] || kg1->allowedTouch[0][kg2->index]) {
00673 ROS_DEBUG_STREAM("Collision but allowed touch between " << kg2->link->getName() << " and " << kg1->link->getName());
00674 return;
00675 } else {
00676 ROS_DEBUG_STREAM("Collision and no allowed touch between " << kg2->link->getName() << " and " << kg1->link->getName());
00677 }
00678 } else {
00679
00680
00681 int p1 = -1, p2 = -1;
00682 for (unsigned int i = 0 ; i < kg1->geom.size() ; ++i) {
00683 if (kg1->geom[i] == o1) {
00684 p1 = i;
00685 break;
00686 }
00687 }
00688 for (unsigned int i = 0 ; i < kg2->geom.size() ; ++i) {
00689 if (kg2->geom[i] == o2) {
00690 p2 = i;
00691 break;
00692 }
00693 }
00694 assert(p1 >= 0 && p2 >= 0);
00695
00696 if(p1 > 0 && p2 > 0) {
00697
00698 if(kg1->geom[0] == kg2->geom[0]) {
00699 return;
00700 }
00701
00702 }
00703 if (p1 == 0) {
00704 if(kg2->geomAttachedBodyMap.find(o2) == kg2->geomAttachedBodyMap.end()) {
00705 ROS_WARN("No attached body for geom");
00706 return;
00707 } else {
00708 unsigned int bodyNum = kg2->geomAttachedBodyMap[o2];
00709 if (kg2->allowedTouch[bodyNum][kg1->index]) {
00710 ROS_DEBUG_STREAM("Collision but allowed touch between attached body of " << kg2->link->getName() << " and " << kg1->link->getName());
00711 ROS_DEBUG_STREAM("Attached body id is " << kg2->link->getAttachedBodyModels()[bodyNum-1]->getName());
00712 attached_body = kg2->link->getAttachedBodyModels()[bodyNum-1]->getName();
00713 return;
00714 } else {
00715 ROS_DEBUG_STREAM("Collision and no allowed touch between attached body of " << kg2->link->getName() << " and " << kg1->link->getName());
00716 ROS_DEBUG_STREAM("Attached body id is " << kg2->link->getAttachedBodyModels()[bodyNum-1]->getName());
00717 link2_attached_index = bodyNum;
00718 }
00719 }
00720 } else {
00721 ROS_DEBUG("P1 is not zero");
00722 }
00723 if (p2 == 0) {
00724 if(kg1->geomAttachedBodyMap.find(o1) == kg1->geomAttachedBodyMap.end()) {
00725 ROS_WARN("No attached body for geom");
00726 return;
00727 } else {
00728 unsigned int bodyNum = kg1->geomAttachedBodyMap[o1];
00729 if (kg1->allowedTouch[bodyNum][kg2->index]) {
00730 ROS_DEBUG_STREAM("Collision but allowed touch between attached body of " << kg1->link->getName() << " and " << kg2->link->getName());
00731 ROS_DEBUG_STREAM("Attached body id is " << kg1->link->getAttachedBodyModels()[bodyNum-1]->getName());
00732 return;
00733 } else {
00734 ROS_DEBUG_STREAM("Collision and no allowed touch between attached body of " << kg1->link->getName() << " and " << kg2->link->getName());
00735 ROS_DEBUG_STREAM("Attached body id is " << kg1->link->getAttachedBodyModels()[bodyNum-1]->getName());
00736 link1_attached_index = bodyNum;
00737 }
00738 }
00739 } else {
00740 ROS_DEBUG("P2 is not zero");
00741 }
00742 }
00743 }
00744
00745 cdata->link1 = kg1->link;
00746 cdata->link2 = kg2->link;
00747 }
00748 } else {
00749 ROS_DEBUG("No self collision test");
00750 }
00751
00752 unsigned int num_contacts = 1;
00753 if(cdata->contacts) {
00754 num_contacts = std::min(MAX_ODE_CONTACTS, cdata->max_contacts);
00755 }
00756 num_contacts = std::max(num_contacts, (unsigned int)1);
00757
00758 dContactGeom contactGeoms[num_contacts];
00759 int numc = dCollide (o1, o2, num_contacts,
00760 &(contactGeoms[0]), sizeof(dContactGeom));
00761
00762 if(!cdata->contacts) {
00763 if (numc)
00764 {
00765 cdata->collides = true;
00766 cdata->done = true;
00767 }
00768 } else if (numc) {
00769 for (int i = 0 ; i < numc ; ++i)
00770 {
00771 if(cdata->max_contacts > 0 && cdata->contacts->size() >= cdata->max_contacts) {
00772 break;
00773 }
00774 ROS_DEBUG_STREAM("Contact at " << contactGeoms[i].pos[0] << " "
00775 << contactGeoms[i].pos[1] << " " << contactGeoms[i].pos[2]);
00776
00777 btVector3 pos(contactGeoms[i].pos[0], contactGeoms[i].pos[1], contactGeoms[i].pos[2]);
00778
00779 if (cdata->allowed)
00780 {
00781 dSpaceID s1 = dGeomGetSpace(o1);
00782 dSpaceID s2 = dGeomGetSpace(o2);
00783
00784 bool b1 = s1 == cdata->selfSpace;
00785 bool b2 = s2 == cdata->selfSpace;
00786
00787 if (b1 != b2)
00788 {
00789 std::string link_name;
00790 if (b1)
00791 {
00792 EnvironmentModelODE::kGeom* kg1 = reinterpret_cast<EnvironmentModelODE::kGeom*>(dGeomGetData(o1));
00793 link_name = kg1->link->getName();
00794 }
00795 else
00796 {
00797 EnvironmentModelODE::kGeom* kg2 = reinterpret_cast<EnvironmentModelODE::kGeom*>(dGeomGetData(o2));
00798 link_name = kg2->link->getName();
00799 }
00800
00801 bool allow = false;
00802 for (unsigned int j = 0 ; !allow && j < cdata->allowed->size() ; ++j)
00803 {
00804 if (cdata->allowed->at(j).bound->containsPoint(pos) && cdata->allowed->at(j).depth > fabs(contactGeoms[i].depth))
00805 {
00806 for (unsigned int k = 0 ; k < cdata->allowed->at(j).links.size() ; ++k) {
00807 if (cdata->allowed->at(j).links[k] == link_name)
00808 {
00809 allow = true;
00810 break;
00811 }
00812 }
00813 }
00814 }
00815
00816 if (allow)
00817 continue;
00818 }
00819 }
00820
00821 cdata->collides = true;
00822
00823 collision_space::EnvironmentModelODE::Contact add;
00824
00825 add.pos = pos;
00826
00827 add.normal.setX(contactGeoms[i].normal[0]);
00828 add.normal.setY(contactGeoms[i].normal[1]);
00829 add.normal.setZ(contactGeoms[i].normal[2]);
00830
00831 add.depth = contactGeoms[i].depth;
00832
00833 add.link1 = cdata->link1;
00834 add.link1_attached_body_index = link1_attached_index;
00835 add.link2 = cdata->link2;
00836 add.link2_attached_body_index = link2_attached_index;
00837
00838 cdata->contacts->push_back(add);
00839 }
00840 if (cdata->max_contacts > 0 && cdata->contacts->size() >= cdata->max_contacts)
00841 cdata->done = true;
00842 }
00843 }
00844 }
00845
00846 bool collision_space::EnvironmentModelODE::getCollisionContacts(const std::vector<AllowedContact> &allowedContacts, std::vector<Contact> &contacts, unsigned int max_count)
00847 {
00848 contacts.clear();
00849 CollisionData cdata;
00850 if(use_set_collision_matrix_) {
00851 cdata.selfCollisionTest = &set_collision_matrix_;
00852 } else {
00853 cdata.selfCollisionTest = &m_selfCollisionTest;
00854 }
00855 cdata.contacts = &contacts;
00856 cdata.max_contacts = max_count;
00857 if (!allowedContacts.empty())
00858 cdata.allowed = &allowedContacts;
00859 cdata.selfSpace = m_modelGeom.space;
00860 contacts.clear();
00861 checkThreadInit();
00862 testCollision(&cdata);
00863 return cdata.collides;
00864 }
00865
00866 bool collision_space::EnvironmentModelODE::isCollision(void)
00867 {
00868 CollisionData cdata;
00869 cdata.selfSpace = m_modelGeom.space;
00870 checkThreadInit();
00871 testCollision(&cdata);
00872 return cdata.collides;
00873 }
00874
00875 bool collision_space::EnvironmentModelODE::isSelfCollision(void)
00876 {
00877 CollisionData cdata;
00878 cdata.selfSpace = m_modelGeom.space;
00879 checkThreadInit();
00880 testSelfCollision(&cdata);
00881 return cdata.collides;
00882 }
00883
00884 void collision_space::EnvironmentModelODE::testSelfCollision(CollisionData *cdata)
00885 {
00886 if(use_set_collision_matrix_) {
00887 cdata->selfCollisionTest = &set_collision_matrix_;
00888 } else {
00889 cdata->selfCollisionTest = &m_selfCollisionTest;
00890 }
00891 dSpaceCollide(m_modelGeom.space, cdata, nearCallbackFn);
00892 }
00893
00894 void collision_space::EnvironmentModelODE::testBodyCollision(CollisionNamespace *cn, CollisionData *cdata)
00895 {
00896 if (cn->collide2.empty())
00897 {
00898
00899 for (int i = m_modelGeom.linkGeom.size() - 1 ; i >= 0 && !cdata->done ; --i)
00900 {
00901 kGeom *kg = m_modelGeom.linkGeom[i];
00902
00903
00904 if (!kg->enabled)
00905 continue;
00906 const unsigned int ng = kg->geom.size();
00907 cdata->link1 = kg->link;
00908
00909 for (unsigned int ig = 0 ; ig < ng && !cdata->done ; ++ig)
00910 {
00911 if(use_set_collision_matrix_) {
00912 std::string kg1name = cn->name;
00913 std::string kg2name;
00914 if(ig == 0) {
00915
00916 kg2name = cdata->link1->getName();
00917 } else {
00918
00919 if(kg->geomAttachedBodyMap.find(kg->geom[ig]) == kg->geomAttachedBodyMap.end()) {
00920 ROS_WARN_STREAM("Attached body geom for link " << cdata->link1->getName() << " num " << ig << " not found in geomMap");
00921 kg2name = cdata->link1->getName();
00922 } else {
00923 kg2name = kg->link->getAttachedBodyModels()[kg->geomAttachedBodyMap[kg->geom[ig]]-1]->getName();
00924 }
00925 }
00926 if(set_collision_ind_.find(kg1name) == set_collision_ind_.end()) {
00927 ROS_ERROR_STREAM("1Problem in collision_space. Using set collision but can't find link name for link one " << kg1name);
00928 return;
00929 }
00930 if(set_collision_ind_.find(kg2name) == set_collision_ind_.end()) {
00931 ROS_ERROR_STREAM("1Problem in collision_space. Using set collision but can't find link or attached body name " << kg2name);
00932 return;
00933 }
00934
00935 unsigned int kg1ind = set_collision_ind_[kg1name];
00936 unsigned int kg2ind = set_collision_ind_[kg2name];
00937
00938 if(set_collision_matrix_[kg1ind][kg2ind]) {
00939
00940 continue;
00941 } else {
00942
00943 }
00944 }
00945
00946
00947 dGeomID g1 = m_modelGeom.linkGeom[i]->geom[ig];
00948 dReal aabb1[6];
00949 dGeomGetAABB(g1, aabb1);
00950
00951 for (int j = cn->geoms.size() - 1 ; j >= 0 ; --j)
00952 {
00953 dGeomID g2 = cn->geoms[j];
00954 dReal aabb2[6];
00955 dGeomGetAABB(g2, aabb2);
00956
00957 bool currentCollides = cdata->collides;
00958 cdata->collides = false;
00959
00960 unsigned int current_contacts_size = 0;
00961 if(cdata->contacts) {
00962 current_contacts_size = cdata->contacts->size();
00963 }
00964
00965 if (!(aabb1[2] > aabb2[3] ||
00966 aabb1[3] < aabb2[2] ||
00967 aabb1[4] > aabb2[5] ||
00968 aabb1[5] < aabb2[4]))
00969 dSpaceCollide2(g1, g2, cdata, nearCallbackFn);
00970
00971 if (cdata->collides) {
00972 kGeom *kg = m_modelGeom.linkGeom[i];
00973 if(m_verbose) {
00974 ROS_INFO("Collision between body in namespace %s and link %s",
00975 cn->name.c_str(), m_modelGeom.linkGeom[i]->link->getName().c_str());
00976 if(ig > 0) {
00977 ROS_INFO_STREAM("Collision is really between namespace " << cn->name.c_str() << " and attached body "
00978 << kg->link->getAttachedBodyModels()[kg->geomAttachedBodyMap[kg->geom[ig]]-1]->getName());
00979 }
00980 }
00981 if(cdata->contacts) {
00982 if(cdata->contacts->size() <= current_contacts_size) {
00983 ROS_WARN("Supposedly new contacts but none in vector");
00984 } else {
00985 for(unsigned int j = current_contacts_size; j < cdata->contacts->size(); j++) {
00986 if(!cdata->contacts->at(j).object_name.empty()) {
00987 ROS_WARN("Object name really should be empty");
00988 } else if(cdata->contacts->at(j).link2 == NULL) {
00989 cdata->contacts->at(j).object_name = cn->name;
00990 }
00991 if(ig > 0) {
00992 cdata->contacts->at(j).link1_attached_body_index = kg->geomAttachedBodyMap[kg->geom[ig]];
00993 }
00994 }
00995 }
00996 }
00997 } else {
00998
00999 cdata->collides = currentCollides;
01000 }
01001 }
01002 }
01003 }
01004 }
01005 else
01006 {
01007 cn->collide2.setup();
01008 for (int i = m_modelGeom.linkGeom.size() - 1 ; i >= 0 && !cdata->done ; --i) {
01009 if (m_modelGeom.linkGeom[i]->enabled)
01010 {
01011 kGeom *kg = m_modelGeom.linkGeom[i];
01012 const unsigned int ng = m_modelGeom.linkGeom[i]->geom.size();
01013 cdata->link1 = m_modelGeom.linkGeom[i]->link;
01014 for (unsigned int ig = 0 ; ig < ng && !cdata->done ; ++ig)
01015 {
01016
01017 if(use_set_collision_matrix_) {
01018 std::string kg1name = cn->name;
01019 std::string kg2name;
01020 if(ig == 0) {
01021
01022 kg2name = cdata->link1->getName();
01023 } else {
01024
01025 if(kg->geomAttachedBodyMap.find(kg->geom[ig]) == kg->geomAttachedBodyMap.end()) {
01026 ROS_WARN_STREAM("Attached body geom for link " << cdata->link1->getName() << " num " << ig << " not found in geomMap");
01027 kg2name = cdata->link1->getName();
01028 } else {
01029 kg2name = kg->link->getAttachedBodyModels()[kg->geomAttachedBodyMap[kg->geom[ig]]-1]->getName();
01030 }
01031 }
01032 if(set_collision_ind_.find(kg1name) == set_collision_ind_.end()) {
01033 ROS_ERROR_STREAM("2Problem in collision_space. Using set collision but can't find link name " << kg1name);
01034 return;
01035 }
01036 if(set_collision_ind_.find(kg2name) == set_collision_ind_.end()) {
01037 ROS_ERROR_STREAM("2Problem in collision_space. Using set collision but can't find link or attached body name " << kg2name);
01038 return;
01039 }
01040
01041 unsigned int kg1ind = set_collision_ind_[kg1name];
01042 unsigned int kg2ind = set_collision_ind_[kg2name];
01043
01044 if(set_collision_matrix_[kg1ind][kg2ind]) {
01045
01046 continue;
01047 } else {
01048
01049 }
01050 }
01051 bool currentCollides = cdata->collides;
01052 cdata->collides = false;
01053
01054
01055 unsigned int current_contacts_size = 0;
01056 if(cdata->contacts) {
01057 current_contacts_size = cdata->contacts->size();
01058 }
01059
01060 cn->collide2.collide(m_modelGeom.linkGeom[i]->geom[ig], cdata, nearCallbackFn);
01061
01062 if (cdata->collides) {
01063 kGeom *kg = m_modelGeom.linkGeom[i];
01064 if(m_verbose) {
01065 ROS_INFO("Collision between body in namespace %s and link %s",
01066 cn->name.c_str(), m_modelGeom.linkGeom[i]->link->getName().c_str());
01067 if(ig > 0) {
01068 ROS_INFO_STREAM("Collision is really between namespace " << cn->name.c_str() << " and attached body "
01069 << kg->link->getAttachedBodyModels()[kg->geomAttachedBodyMap[kg->geom[ig]]-1]->getName());
01070 }
01071 }
01072 if(cdata->contacts) {
01073 if(cdata->contacts->size() <= current_contacts_size) {
01074 ROS_WARN("Supposedly new contacts but none in vector");
01075 } else {
01076 for(unsigned int j = current_contacts_size; j < cdata->contacts->size(); j++) {
01077 if(!cdata->contacts->at(j).object_name.empty()) {
01078 ROS_WARN("Object name really should be empty");
01079 } else if(cdata->contacts->at(j).link2 == NULL) {
01080 cdata->contacts->at(j).object_name = cn->name;
01081 }
01082 if(ig > 0) {
01083 cdata->contacts->at(j).link1_attached_body_index = kg->geomAttachedBodyMap[kg->geom[ig]];
01084 }
01085 }
01086 }
01087 }
01088 } else {
01089
01090 cdata->collides = currentCollides;
01091 }
01092 }
01093 }
01094 }
01095 }
01096 }
01097
01098 void collision_space::EnvironmentModelODE::testCollision(CollisionData *cdata)
01099 {
01100
01101 if (m_selfCollision)
01102 testSelfCollision(cdata);
01103
01104 if (!cdata->done)
01105 {
01106 cdata->link2 = NULL;
01107
01108 for (std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.begin() ; it != m_collNs.end() && !cdata->done ; ++it) {
01109 testBodyCollision(it->second, cdata);
01110 }
01111 cdata->done = true;
01112 }
01113 }
01114
01115 void collision_space::EnvironmentModelODE::addObjects(const std::string &ns, const std::vector<shapes::Shape*> &shapes, const std::vector<btTransform> &poses)
01116 {
01117 assert(shapes.size() == poses.size());
01118 std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.find(ns);
01119 CollisionNamespace* cn = NULL;
01120 if (it == m_collNs.end())
01121 {
01122 cn = new CollisionNamespace(ns);
01123 m_collNs[ns] = cn;
01124 }
01125 else {
01126 cn = it->second;
01127 }
01128
01129
01130 m_objects->addObjectNamespace(ns);
01131
01132 unsigned int n = shapes.size();
01133 for (unsigned int i = 0 ; i < n ; ++i)
01134 {
01135 dGeomID g = createODEGeom(cn->space, cn->storage, shapes[i], 1.0, 0.0);
01136 assert(g);
01137 dGeomSetData(g, reinterpret_cast<void*>(shapes[i]));
01138 updateGeom(g, poses[i]);
01139 cn->collide2.registerGeom(g);
01140 m_objects->addObject(ns, shapes[i], poses[i]);
01141 }
01142 cn->collide2.setup();
01143 }
01144
01145 void collision_space::EnvironmentModelODE::addObject(const std::string &ns, shapes::Shape *shape, const btTransform &pose)
01146 {
01147 std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.find(ns);
01148 CollisionNamespace* cn = NULL;
01149 if (it == m_collNs.end())
01150 {
01151 cn = new CollisionNamespace(ns);
01152 m_collNs[ns] = cn;
01153 }
01154 else
01155 cn = it->second;
01156
01157 dGeomID g = createODEGeom(cn->space, cn->storage, shape, 1.0, 0.0);
01158 assert(g);
01159 dGeomSetData(g, reinterpret_cast<void*>(shape));
01160
01161 updateGeom(g, pose);
01162 cn->geoms.push_back(g);
01163 m_objects->addObject(ns, shape, pose);
01164 }
01165
01166 void collision_space::EnvironmentModelODE::addObject(const std::string &ns, shapes::StaticShape* shape)
01167 {
01168 std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.find(ns);
01169 CollisionNamespace* cn = NULL;
01170 if (it == m_collNs.end())
01171 {
01172 cn = new CollisionNamespace(ns);
01173 m_collNs[ns] = cn;
01174 }
01175 else
01176 cn = it->second;
01177
01178 dGeomID g = createODEGeom(cn->space, cn->storage, shape);
01179 assert(g);
01180 dGeomSetData(g, reinterpret_cast<void*>(shape));
01181 cn->geoms.push_back(g);
01182 m_objects->addObject(ns, shape);
01183 }
01184
01185 void collision_space::EnvironmentModelODE::clearObjects(void)
01186 {
01187 for (std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.begin() ; it != m_collNs.end() ; ++it)
01188 delete it->second;
01189 m_collNs.clear();
01190 m_objects->clearObjects();
01191 }
01192
01193 void collision_space::EnvironmentModelODE::clearObjects(const std::string &ns)
01194 {
01195 std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.find(ns);
01196 if (it != m_collNs.end()) {
01197 delete it->second;
01198 m_collNs.erase(ns);
01199 }
01200 m_objects->clearObjects(ns);
01201 }
01202
01203 void collision_space::EnvironmentModelODE::updateAllowedTouch()
01204 {
01205 if(use_set_collision_matrix_) {
01206 ROS_WARN("Shouldn't update allowed touch in use collision matrix mode");
01207 return;
01208 }
01209
01210 const unsigned int n = m_modelGeom.linkGeom.size();
01211 for (unsigned int i = 0 ; i < n ; ++i)
01212 {
01213 kGeom *kg = m_modelGeom.linkGeom[i];
01214 kg->allowedTouch.resize(kg->geom.size());
01215
01216 if (kg->geom.empty())
01217 continue;
01218
01219 kg->allowedTouch[0].resize(n);
01220
01221
01222 for (unsigned int j = 0 ; j < n ; ++j)
01223
01224
01225 kg->allowedTouch[0][j] = m_selfCollisionTest[kg->index][j];
01226
01227 const unsigned int nab = kg->link->getAttachedBodyModels().size();
01228 for (unsigned int k = 0 ; k < nab ; ++k)
01229 {
01230 kg->allowedTouch[k + 1].clear();
01231 kg->allowedTouch[k + 1].resize(n, false);
01232
01233
01234
01235 for (unsigned int j = 0 ; j < kg->link->getAttachedBodyModels()[k]->getTouchLinks().size() ; ++j)
01236 {
01237 const std::string &tlink = kg->link->getAttachedBodyModels()[k]->getTouchLinks()[j];
01238 std::map<std::string, unsigned int>::const_iterator it = m_collisionLinkIndex.find(tlink);
01239 if (it != m_collisionLinkIndex.end())
01240 kg->allowedTouch[k + 1][it->second] = true;
01241 else
01242 ROS_WARN("Unknown link %s specified for touch link", tlink.c_str());
01243 }
01244 }
01245 }
01246 }
01247
01248 void collision_space::EnvironmentModelODE::getDefaultAllowedCollisionMatrix(std::vector<std::vector<bool> > &curAllowed,
01249 std::map<std::string, unsigned int> &vecIndices) const{
01250
01251
01252
01253 curAllowed.clear();
01254 vecIndices.clear();
01255
01256 vecIndices = m_collisionLinkIndex;
01257
01258 unsigned int num_links = m_modelGeom.linkGeom.size();
01259
01260 unsigned int num_attached = 0;
01261
01262 for (unsigned int i = 0 ; i < num_links ; ++i)
01263 {
01264 kGeom *kg = m_modelGeom.linkGeom[i];
01265 num_attached += kg->link->getAttachedBodyModels().size();
01266 }
01267
01268 std::vector<std::string> ns = m_objects->getNamespaces();
01269 unsigned int num_objects = ns.size();
01270
01271
01272 unsigned int total_num = num_links+num_attached+num_objects;
01273
01274
01275 std::vector<bool> all_false(total_num, false);
01276 curAllowed.resize(total_num, all_false);
01277
01278
01279 for(unsigned int i = 0; i < num_links; i++) {
01280 kGeom *kg = m_modelGeom.linkGeom[i];
01281 for(unsigned int j = 0; j < num_links; j++) {
01282 curAllowed[i][j] = kg->allowedTouch[0][j];
01283 }
01284 }
01285
01286 unsigned int cur_index_counter = num_links;
01287 for (unsigned int i = 0 ; i < ns.size() ; ++i)
01288 {
01289 vecIndices[ns[i]] = cur_index_counter++;
01290 }
01291
01292
01293 for(unsigned int i = 0; i < num_links; i++) {
01294 kGeom *kg = m_modelGeom.linkGeom[i];
01295 for (unsigned int j = 0 ; j < kg->link->getAttachedBodyModels().size(); ++j) {
01296 vecIndices[kg->link->getAttachedBodyModels()[j]->getName()] = cur_index_counter;
01297
01298 for(unsigned int k = 0; k < kg->link->getAttachedBodyModels()[j]->getTouchLinks().size(); k++) {
01299 std::string lname = kg->link->getAttachedBodyModels()[j]->getTouchLinks()[k];
01300 std::map<std::string, unsigned int>::const_iterator it = vecIndices.find(lname);
01301 if (it != vecIndices.end()) {
01302 curAllowed[vecIndices[lname]][cur_index_counter] = true;
01303 curAllowed[cur_index_counter][vecIndices[lname]] = true;
01304 }
01305 }
01306 cur_index_counter++;
01307 }
01308 }
01309 }
01310
01311 void collision_space::EnvironmentModelODE::setAllowedCollisionMatrix(const std::vector<std::vector<bool> > &matrix,
01312 const std::map<std::string, unsigned int > &ind) {
01313
01314 EnvironmentModel::setAllowedCollisionMatrix(matrix, ind);
01315
01316
01317 const unsigned int n = m_modelGeom.linkGeom.size();
01318 for (unsigned int i = 0 ; i < n ; ++i)
01319 {
01320 kGeom *kg = m_modelGeom.linkGeom[i];
01321 kg->allowedTouch.resize(kg->geom.size());
01322 kg->allowedTouch[0].resize(n);
01323
01324 if(ind.find(kg->link->getName()) == ind.end()) {
01325 ROS_WARN_STREAM("Can't find link name " << kg->link->getName() << " in collision matrix ind.");
01326 continue;
01327 }
01328
01329 unsigned int cur_mat_ind = ind.find(kg->link->getName())->second;
01330 if(kg->index != cur_mat_ind) {
01331 ROS_ERROR_STREAM("Index for link " << kg->link->getName() << " has changed. Gonna be trouble in collision test.");
01332 }
01333
01334
01335 for (unsigned int j = 0 ; j < n ; ++j) {
01336 kg->allowedTouch[0][j] = matrix[cur_mat_ind][j];
01337 }
01338
01339 const unsigned int nab = kg->link->getAttachedBodyModels().size();
01340 for (unsigned int j = 0 ; j < nab ; ++j)
01341 {
01342 kg->allowedTouch[j + 1].clear();
01343 kg->allowedTouch[j + 1].resize(n, false);
01344 std::string aname = kg->link->getAttachedBodyModels()[j]->getName();
01345 if(ind.find(aname) == ind.end()) {
01346 ROS_WARN_STREAM("Attached body id " << aname << " does not seem to have an entry in the matrix");
01347 continue;
01348 }
01349 unsigned int a_ind = ind.find(aname)->second;
01350 for(unsigned int k = 0; k < n; k++) {
01351 kg->allowedTouch[j + 1][k] = matrix[a_ind][k];
01352 }
01353
01354 }
01355 }
01356 }
01357
01358 void collision_space::EnvironmentModelODE::revertAllowedCollisionMatrix() {
01359 EnvironmentModel::revertAllowedCollisionMatrix();
01360 updateAllowedTouch();
01361 }
01362
01363 void collision_space::EnvironmentModelODE::addSelfCollisionGroup(const std::vector<std::string> &group1,
01364 const std::vector<std::string> &group2)
01365 {
01366 EnvironmentModel::addSelfCollisionGroup(group1,group2);
01367 updateAllowedTouch();
01368 }
01369
01370 void collision_space::EnvironmentModelODE::removeSelfCollisionGroup(const std::vector<std::string> &group1,
01371 const std::vector<std::string> &group2)
01372 {
01373 EnvironmentModel::removeSelfCollisionGroup(group1,group2);
01374 updateAllowedTouch();
01375 }
01376
01377 void collision_space::EnvironmentModelODE::removeCollidingObjects(const shapes::StaticShape *shape)
01378 {
01379 checkThreadInit();
01380 dSpaceID space = dSimpleSpaceCreate(0);
01381 ODEStorage storage;
01382 dGeomID g = createODEGeom(space, storage, shape);
01383 removeCollidingObjects(g);
01384 dSpaceDestroy(space);
01385 }
01386
01387 void collision_space::EnvironmentModelODE::removeCollidingObjects(const shapes::Shape *shape, const btTransform &pose)
01388 {
01389 checkThreadInit();
01390 dSpaceID space = dSimpleSpaceCreate(0);
01391 ODEStorage storage;
01392 dGeomID g = createODEGeom(space, storage, shape, 1.0, 0.0);
01393 updateGeom(g, pose);
01394 removeCollidingObjects(g);
01395 dSpaceDestroy(space);
01396 }
01397
01398 void collision_space::EnvironmentModelODE::removeCollidingObjects(dGeomID geom)
01399 {
01400 CollisionData cdata;
01401 for (std::map<std::string, CollisionNamespace*>::iterator it = m_collNs.begin() ; it != m_collNs.end() ; ++it)
01402 {
01403 std::map<void*, bool> remove;
01404
01405
01406 unsigned int n = it->second->geoms.size();
01407 std::vector<dGeomID> replaceGeoms;
01408 replaceGeoms.reserve(n);
01409 for (unsigned int j = 0 ; j < n ; ++j)
01410 {
01411 cdata.done = cdata.collides = false;
01412 dSpaceCollide2(geom, it->second->geoms[j], &cdata, nearCallbackFn);
01413 if (cdata.collides)
01414 {
01415 remove[dGeomGetData(it->second->geoms[j])] = true;
01416 dGeomDestroy(it->second->geoms[j]);
01417 }
01418 else
01419 {
01420 replaceGeoms.push_back(it->second->geoms[j]);
01421 remove[dGeomGetData(it->second->geoms[j])] = false;
01422 }
01423 }
01424 it->second->geoms = replaceGeoms;
01425
01426
01427 std::vector<dGeomID> geoms;
01428 it->second->collide2.getGeoms(geoms);
01429 n = geoms.size();
01430 for (unsigned int j = 0 ; j < n ; ++j)
01431 {
01432 cdata.done = cdata.collides = false;
01433 dSpaceCollide2(geom, geoms[j], &cdata, nearCallbackFn);
01434 if (cdata.collides)
01435 {
01436 remove[dGeomGetData(geoms[j])] = true;
01437 it->second->collide2.unregisterGeom(geoms[j]);
01438 dGeomDestroy(geoms[j]);
01439 }
01440 else
01441 remove[dGeomGetData(geoms[j])] = false;
01442 }
01443
01444 EnvironmentObjects::NamespaceObjects &no = m_objects->getObjects(it->first);
01445
01446 std::vector<shapes::Shape*> replaceShapes;
01447 std::vector<btTransform> replaceShapePoses;
01448 n = no.shape.size();
01449 replaceShapes.reserve(n);
01450 replaceShapePoses.reserve(n);
01451 for (unsigned int i = 0 ; i < n ; ++i)
01452 if (remove[reinterpret_cast<void*>(no.shape[i])])
01453 delete no.shape[i];
01454 else
01455 {
01456 replaceShapes.push_back(no.shape[i]);
01457 replaceShapePoses.push_back(no.shapePose[i]);
01458 }
01459 no.shape = replaceShapes;
01460 no.shapePose = replaceShapePoses;
01461
01462 std::vector<shapes::StaticShape*> replaceStaticShapes;
01463 n = no.staticShape.size();
01464 replaceStaticShapes.resize(n);
01465 for (unsigned int i = 0 ; i < n ; ++i)
01466 if (remove[reinterpret_cast<void*>(no.staticShape[i])])
01467 delete no.staticShape[i];
01468 else
01469 replaceStaticShapes.push_back(no.staticShape[i]);
01470 no.staticShape = replaceStaticShapes;
01471 }
01472 }
01473
01474 int collision_space::EnvironmentModelODE::setCollisionCheck(const std::string &link, bool state)
01475 {
01476 int result = -1;
01477 for (unsigned int j = 0 ; j < m_modelGeom.linkGeom.size() ; ++j)
01478 {
01479 if (m_modelGeom.linkGeom[j]->link->getName() == link)
01480 {
01481 result = m_modelGeom.linkGeom[j]->enabled ? 1 : 0;
01482 m_modelGeom.linkGeom[j]->enabled = state;
01483 break;
01484 }
01485 }
01486
01487 return result;
01488 }
01489
01490 void collision_space::EnvironmentModelODE::setCollisionCheckLinks(const std::vector<std::string> &links, bool state)
01491 {
01492 if(links.empty())
01493 return;
01494
01495 for (unsigned int i = 0 ; i < m_modelGeom.linkGeom.size() ; ++i)
01496 {
01497 for (unsigned int j=0; j < links.size(); j++)
01498 {
01499 if (m_modelGeom.linkGeom[i]->link->getName() == links[j])
01500 {
01501 m_modelGeom.linkGeom[i]->enabled = state;
01502 break;
01503 }
01504 }
01505 }
01506 }
01507
01508 void collision_space::EnvironmentModelODE::setCollisionCheckOnlyLinks(const std::vector<std::string> &links, bool state)
01509 {
01510 if(links.empty())
01511 return;
01512
01513 for (unsigned int i = 0 ; i < m_modelGeom.linkGeom.size() ; ++i)
01514 {
01515 int result = -1;
01516 for (unsigned int j=0; j < links.size(); j++)
01517 {
01518 if (m_modelGeom.linkGeom[i]->link->getName() == links[j])
01519 {
01520 m_modelGeom.linkGeom[i]->enabled = state;
01521 result = j;
01522 break;
01523 }
01524 }
01525 if(result < 0)
01526 m_modelGeom.linkGeom[i]->enabled = !state;
01527 }
01528 }
01529
01530 void collision_space::EnvironmentModelODE::setCollisionCheckAll(bool state)
01531 {
01532 for (unsigned int j = 0 ; j < m_modelGeom.linkGeom.size() ; ++j)
01533 {
01534 m_modelGeom.linkGeom[j]->enabled = state;
01535 }
01536 }
01537
01538 dGeomID collision_space::EnvironmentModelODE::copyGeom(dSpaceID space, ODEStorage &storage, dGeomID geom, ODEStorage &sourceStorage) const
01539 {
01540 int c = dGeomGetClass(geom);
01541 dGeomID ng = NULL;
01542 bool location = true;
01543 switch (c)
01544 {
01545 case dSphereClass:
01546 ng = dCreateSphere(space, dGeomSphereGetRadius(geom));
01547 break;
01548 case dBoxClass:
01549 {
01550 dVector3 r;
01551 dGeomBoxGetLengths(geom, r);
01552 ng = dCreateBox(space, r[0], r[1], r[2]);
01553 }
01554 break;
01555 case dCylinderClass:
01556 {
01557 dReal r, l;
01558 dGeomCylinderGetParams(geom, &r, &l);
01559 ng = dCreateCylinder(space, r, l);
01560 }
01561 break;
01562 case dPlaneClass:
01563 {
01564 dVector4 p;
01565 dGeomPlaneGetParams(geom, p);
01566 ng = dCreatePlane(space, p[0], p[1], p[2], p[3]);
01567 location = false;
01568 }
01569 break;
01570 case dTriMeshClass:
01571 {
01572 dTriMeshDataID tdata = dGeomTriMeshGetData(geom);
01573 dTriMeshDataID cdata = dGeomTriMeshDataCreate();
01574 for (unsigned int i = 0 ; i < sourceStorage.mesh.size() ; ++i)
01575 if (sourceStorage.mesh[i].data == tdata)
01576 {
01577 unsigned int p = storage.mesh.size();
01578 storage.mesh.resize(p + 1);
01579 storage.mesh[p].nVertices = sourceStorage.mesh[i].nVertices;
01580 storage.mesh[p].nIndices = sourceStorage.mesh[i].nIndices;
01581 storage.mesh[p].indices = new dTriIndex[storage.mesh[p].nIndices];
01582 for (int j = 0 ; j < storage.mesh[p].nIndices ; ++j)
01583 storage.mesh[p].indices[j] = sourceStorage.mesh[i].indices[j];
01584 storage.mesh[p].vertices = new double[storage.mesh[p].nVertices];
01585 for (int j = 0 ; j < storage.mesh[p].nVertices ; ++j)
01586 storage.mesh[p].vertices[j] = sourceStorage.mesh[i].vertices[j];
01587 dGeomTriMeshDataBuildDouble(cdata, storage.mesh[p].vertices, sizeof(double) * 3, storage.mesh[p].nVertices, storage.mesh[p].indices, storage.mesh[p].nIndices, sizeof(dTriIndex) * 3);
01588 storage.mesh[p].data = cdata;
01589 break;
01590 }
01591 ng = dCreateTriMesh(space, cdata, NULL, NULL, NULL);
01592 }
01593 break;
01594 default:
01595 assert(0);
01596 break;
01597 }
01598
01599 if (ng && location)
01600 {
01601 const dReal *pos = dGeomGetPosition(geom);
01602 dGeomSetPosition(ng, pos[0], pos[1], pos[2]);
01603 dQuaternion q;
01604 dGeomGetQuaternion(geom, q);
01605 dGeomSetQuaternion(ng, q);
01606 }
01607
01608 return ng;
01609 }
01610
01611 collision_space::EnvironmentModel* collision_space::EnvironmentModelODE::clone(void) const
01612 {
01613 EnvironmentModelODE *env = new EnvironmentModelODE();
01614 env->m_collisionLinks = m_collisionLinks;
01615 env->m_collisionLinkIndex = m_collisionLinkIndex;
01616 env->m_selfCollisionTest = m_selfCollisionTest;
01617 env->m_selfCollision = m_selfCollision;
01618 env->m_verbose = m_verbose;
01619 env->m_robotScale = m_robotScale;
01620 env->m_robotPadd = m_robotPadd;
01621 env->m_robotModel = boost::shared_ptr<planning_models::KinematicModel>(new planning_models::KinematicModel(*m_robotModel));
01622 env->createODERobotModel();
01623 for (unsigned int j = 0 ; j < m_modelGeom.linkGeom.size() ; ++j)
01624 env->m_modelGeom.linkGeom[j]->enabled = m_modelGeom.linkGeom[j]->enabled;
01625
01626 for (std::map<std::string, CollisionNamespace*>::const_iterator it = m_collNs.begin() ; it != m_collNs.end() ; ++it)
01627 {
01628
01629 std::map<void*, int> shapePtrs;
01630 const EnvironmentObjects::NamespaceObjects &ns = m_objects->getObjects(it->first);
01631 unsigned int n = ns.staticShape.size();
01632 for (unsigned int i = 0 ; i < n ; ++i)
01633 shapePtrs[ns.staticShape[i]] = -1 - i;
01634 n = ns.shape.size();
01635 for (unsigned int i = 0 ; i < n ; ++i)
01636 shapePtrs[ns.shape[i]] = i;
01637
01638
01639 CollisionNamespace *cn = new CollisionNamespace(it->first);
01640 env->m_collNs[it->first] = cn;
01641 n = it->second->geoms.size();
01642 cn->geoms.reserve(n);
01643 for (unsigned int i = 0 ; i < n ; ++i)
01644 {
01645 dGeomID newGeom = copyGeom(cn->space, cn->storage, it->second->geoms[i], it->second->storage);
01646 int idx = shapePtrs[dGeomGetData(it->second->geoms[i])];
01647 if (idx < 0)
01648 {
01649 shapes::StaticShape *newShape = shapes::cloneShape(ns.staticShape[-idx - 1]);
01650 dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01651 env->m_objects->addObject(it->first, newShape);
01652 }
01653 else
01654 {
01655 shapes::Shape *newShape = shapes::cloneShape(ns.shape[idx]);
01656 dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01657 env->m_objects->addObject(it->first, newShape, ns.shapePose[idx]);
01658 }
01659 cn->geoms.push_back(newGeom);
01660 }
01661 std::vector<dGeomID> geoms;
01662 it->second->collide2.getGeoms(geoms);
01663 n = geoms.size();
01664 for (unsigned int i = 0 ; i < n ; ++i)
01665 {
01666 dGeomID newGeom = copyGeom(cn->space, cn->storage, geoms[i], it->second->storage);
01667 int idx = shapePtrs[dGeomGetData(geoms[i])];
01668 if (idx < 0)
01669 {
01670 shapes::StaticShape *newShape = shapes::cloneShape(ns.staticShape[-idx - 1]);
01671 dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01672 env->m_objects->addObject(it->first, newShape);
01673 }
01674 else
01675 {
01676 shapes::Shape *newShape = shapes::cloneShape(ns.shape[idx]);
01677 dGeomSetData(newGeom, reinterpret_cast<void*>(newShape));
01678 env->m_objects->addObject(it->first, newShape, ns.shapePose[idx]);
01679 }
01680 cn->collide2.registerGeom(newGeom);
01681 }
01682 }
01683
01684 return env;
01685 }