diff --git a/trunk/fcl/include/fcl/octomap_extension.h b/trunk/fcl/include/fcl/octomap_extension.h index fa52446a1f1ddcea237be2f6b15bff28198482c1..9ab327e639895cae01088e010ef44544e03d20e8 100644 --- a/trunk/fcl/include/fcl/octomap_extension.h +++ b/trunk/fcl/include/fcl/octomap_extension.h @@ -71,6 +71,8 @@ typedef bool (*CollisionCostOctomapCallBackExt)(CollisionObject* o1, CollisionOb void collide(DynamicAABBTreeCollisionManager* manager, octomap::OcTree* octree, void* cdata, CollisionCallBack callback); +void distance(DynamicAABBTreeCollisionManager* manager, octomap::OcTree* octree, void* cdata, DistanceCallBack callback); + FCL_REAL collideCost(DynamicAABBTreeCollisionManager* manager, octomap::OcTree* octree, void* cdata, CollisionCostOctomapCallBack callback); FCL_REAL collideCost(DynamicAABBTreeCollisionManager* manager, octomap::OcTree* octree, void* cdata, CollisionCostOctomapCallBackExt callback, std::vector<AABB>& nodes); diff --git a/trunk/fcl/src/broad_phase_collision.cpp b/trunk/fcl/src/broad_phase_collision.cpp index 5e8fbb8a32d542a688f5e0abb78c74249c2a378f..fbacd9745107aabfe75c9fea31cb874852e82bdd 100644 --- a/trunk/fcl/src/broad_phase_collision.cpp +++ b/trunk/fcl/src/broad_phase_collision.cpp @@ -81,6 +81,9 @@ bool defaultDistanceFunction(CollisionObject* o1, CollisionObject* o2, void* cda if(cdata->min_distance > d) cdata->min_distance = d; dist = cdata->min_distance; + + if(dist <= 0) return true; // in collision or in touch + return cdata->done; } diff --git a/trunk/fcl/src/octomap_extension.cpp b/trunk/fcl/src/octomap_extension.cpp index 81b9cfc3e49aee8b311733f1f5328899ea82b346..9ee15c6aa0e1918e1e85fe4bfacd631ae0e2a492 100644 --- a/trunk/fcl/src/octomap_extension.cpp +++ b/trunk/fcl/src/octomap_extension.cpp @@ -40,6 +40,42 @@ namespace fcl { +static inline void computeChildBV(const AABB& root_bv, unsigned int i, AABB& child_bv) +{ + if(i&1) + { + child_bv.min_[0] = (root_bv.min_[0] + root_bv.max_[0]) * 0.5; + child_bv.max_[0] = root_bv.max_[0]; + } + else + { + child_bv.min_[0] = root_bv.min_[0]; + child_bv.max_[0] = (root_bv.min_[0] + root_bv.max_[0]) * 0.5; + } + + if(i&2) + { + child_bv.min_[1] = (root_bv.min_[1] + root_bv.max_[1]) * 0.5; + child_bv.max_[1] = root_bv.max_[1]; + } + else + { + child_bv.min_[1] = root_bv.min_[1]; + child_bv.max_[1] = (root_bv.min_[1] + root_bv.max_[1]) * 0.5; + } + + if(i&4) + { + child_bv.min_[2] = (root_bv.min_[2] + root_bv.max_[2]) * 0.5; + child_bv.max_[2] = root_bv.max_[2]; + } + else + { + child_bv.min_[2] = root_bv.min_[2]; + child_bv.max_[2] = (root_bv.min_[2] + root_bv.max_[2]) * 0.5; + } +} + class ExtendedBox : public Box { public: @@ -91,38 +127,7 @@ bool collisionRecurse(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, { octomap::OcTreeNode* child = root2->getChild(i); AABB child_bv; - if(i&1) - { - child_bv.min_[0] = (root2_bv.min_[0] + root2_bv.max_[0]) * 0.5; - child_bv.max_[0] = root2_bv.max_[0]; - } - else - { - child_bv.min_[0] = root2_bv.min_[0]; - child_bv.max_[0] = (root2_bv.min_[0] + root2_bv.max_[0]) * 0.5; - } - - if(i&2) - { - child_bv.min_[1] = (root2_bv.min_[1] + root2_bv.max_[1]) * 0.5; - child_bv.max_[1] = root2_bv.max_[1]; - } - else - { - child_bv.min_[1] = root2_bv.min_[1]; - child_bv.max_[1] = (root2_bv.min_[1] + root2_bv.max_[1]) * 0.5; - } - - if(i&4) - { - child_bv.min_[2] = (root2_bv.min_[2] + root2_bv.max_[2]) * 0.5; - child_bv.max_[2] = root2_bv.max_[2]; - } - else - { - child_bv.min_[2] = root2_bv.min_[2]; - child_bv.max_[2] = (root2_bv.min_[2] + root2_bv.max_[2]) * 0.5; - } + computeChildBV(root2_bv, i, child_bv); if(collisionRecurse(root1, tree2, child, child_bv, cdata, callback)) return true; @@ -133,6 +138,7 @@ bool collisionRecurse(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, return false; } + void collide(DynamicAABBTreeCollisionManager* manager, octomap::OcTree* octree, void* cdata, CollisionCallBack callback) { DynamicAABBTreeCollisionManager::DynamicAABBNode* root1 = manager->getTree().getRoot(); @@ -145,6 +151,79 @@ void collide(DynamicAABBTreeCollisionManager* manager, octomap::OcTree* octree, } +bool distanceRecurse(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, + octomap::OcTree* tree2, octomap::OcTreeNode* root2, const AABB& root2_bv, + void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) +{ + if(root1->isLeaf() && !root2->hasChildren()) + { + if(tree2->isNodeOccupied(root2)) + { + Box* box = new Box(root2_bv.max_[0] - root2_bv.min_[0], + root2_bv.max_[1] - root2_bv.min_[1], + root2_bv.max_[2] - root2_bv.min_[2]); + CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), SimpleTransform(root2_bv.center())); + return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata, min_dist); + } + else return false; + } + + if(!tree2->isNodeOccupied(root2)) return false; + + if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) + { + FCL_REAL d1 = root2_bv.distance(root1->childs[0]->bv); + FCL_REAL d2 = root2_bv.distance(root1->childs[1]->bv); + + if(d2 < d1) + { + if(d2 < min_dist) + { + if(distanceRecurse(root1->childs[1], tree2, root2, root2_bv, cdata, callback, min_dist)) + return true; + } + + if(d1 < min_dist) + { + if(distanceRecurse(root1->childs[0], tree2, root2, root2_bv, cdata, callback, min_dist)) + return true; + } + } + else + { + if(d1 < min_dist) + { + if(distanceRecurse(root1->childs[0], tree2, root2, root2_bv, cdata, callback, min_dist)) + return true; + } + + if(d2 < min_dist) + { + if(distanceRecurse(root1->childs[1], tree2, root2, root2_bv, cdata, callback, min_dist)) + return true; + } + } + } + else + { + for(unsigned int i = 0; i < 8; ++i) + { + if(root2->childExists(i)) + { + octomap::OcTreeNode* child = root2->getChild(i); + AABB child_bv; + computeChildBV(root2_bv, i, child_bv); + + if(distanceRecurse(root1, tree2, child, child_bv, cdata, callback, min_dist)) + return true; + } + } + } + + return false; +} + + bool collisionCostRecurse(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, octomap::OcTree* tree2, octomap::OcTreeNode* root2, const AABB& root2_bv, void* cdata, CollisionCostOctomapCallBack callback, FCL_REAL& cost) @@ -184,38 +263,7 @@ bool collisionCostRecurse(DynamicAABBTreeCollisionManager::DynamicAABBNode* root { octomap::OcTreeNode* child = root2->getChild(i); AABB child_bv; - if(i&1) - { - child_bv.min_[0] = (root2_bv.min_[0] + root2_bv.max_[0]) * 0.5; - child_bv.max_[0] = root2_bv.max_[0]; - } - else - { - child_bv.min_[0] = root2_bv.min_[0]; - child_bv.max_[0] = (root2_bv.min_[0] + root2_bv.max_[0]) * 0.5; - } - - if(i&2) - { - child_bv.min_[1] = (root2_bv.min_[1] + root2_bv.max_[1]) * 0.5; - child_bv.max_[1] = root2_bv.max_[1]; - } - else - { - child_bv.min_[1] = root2_bv.min_[1]; - child_bv.max_[1] = (root2_bv.min_[1] + root2_bv.max_[1]) * 0.5; - } - - if(i&4) - { - child_bv.min_[2] = (root2_bv.min_[2] + root2_bv.max_[2]) * 0.5; - child_bv.max_[2] = root2_bv.max_[2]; - } - else - { - child_bv.min_[2] = root2_bv.min_[2]; - child_bv.max_[2] = (root2_bv.min_[2] + root2_bv.max_[2]) * 0.5; - } + computeChildBV(root2_bv, i, child_bv); if(collisionCostRecurse(root1, tree2, child, child_bv, cdata, callback, cost)) return true; @@ -265,38 +313,7 @@ bool collisionCostExtRecurse(DynamicAABBTreeCollisionManager::DynamicAABBNode* r { octomap::OcTreeNode* child = root2->getChild(i); AABB child_bv; - if(i&1) - { - child_bv.min_[0] = (root2_bv.min_[0] + root2_bv.max_[0]) * 0.5; - child_bv.max_[0] = root2_bv.max_[0]; - } - else - { - child_bv.min_[0] = root2_bv.min_[0]; - child_bv.max_[0] = (root2_bv.min_[0] + root2_bv.max_[0]) * 0.5; - } - - if(i&2) - { - child_bv.min_[1] = (root2_bv.min_[1] + root2_bv.max_[1]) * 0.5; - child_bv.max_[1] = root2_bv.max_[1]; - } - else - { - child_bv.min_[1] = root2_bv.min_[1]; - child_bv.max_[1] = (root2_bv.min_[1] + root2_bv.max_[1]) * 0.5; - } - - if(i&4) - { - child_bv.min_[2] = (root2_bv.min_[2] + root2_bv.max_[2]) * 0.5; - child_bv.max_[2] = root2_bv.max_[2]; - } - else - { - child_bv.min_[2] = root2_bv.min_[2]; - child_bv.max_[2] = (root2_bv.min_[2] + root2_bv.max_[2]) * 0.5; - } + computeChildBV(root2_bv, i, child_bv); if(collisionCostExtRecurse(root1, tree2, child, child_bv, cdata, callback, cost, nodes)) return true;