diff --git a/include/fcl/collision_data.h b/include/fcl/collision_data.h index e299e26ede247732092ac9992c3fe62d6b747d83..eee6acf4ebe89fcbd44f0127d249a98816801a9a 100644 --- a/include/fcl/collision_data.h +++ b/include/fcl/collision_data.h @@ -182,6 +182,9 @@ struct CollisionRequest /// @brief whether the contact information (normal, penetration depth and contact position) will return bool enable_contact; + /// Whether a lower bound on distance is returned when objects are disjoint + bool enable_distance_lower_bound; + /// @brief The maximum number of cost sources will return size_t num_max_cost_sources; @@ -202,6 +205,7 @@ struct CollisionRequest CollisionRequest(size_t num_max_contacts_ = 1, bool enable_contact_ = false, + bool enable_distance_lower_bound = false, size_t num_max_cost_sources_ = 1, bool enable_cost_ = false, bool use_approximate_cost_ = true, @@ -232,6 +236,10 @@ private: public: Vec3f cached_gjk_guess; + /// Lower bound on distance between objects if they are disjoint + /// \note computed only on request. + FCL_REAL distance_lower_bound; + public: CollisionResult() { diff --git a/include/fcl/math/matrix_3f.h b/include/fcl/math/matrix_3f.h index 9ecbeee5fbb2b63414a616e9a4a116b8f141c6d8..9bfec2b37d81e430dfc5c705ffbfb0628e3cf7c0 100644 --- a/include/fcl/math/matrix_3f.h +++ b/include/fcl/math/matrix_3f.h @@ -274,41 +274,49 @@ public: return res.timesTranspose(*this); } + // (1 0 0)^T (*this)^T v inline U transposeDotX(const Vec3fX<S>& v) const { return data.transposeDot(0, v.data); } + // (0 1 0)^T (*this)^T v inline U transposeDotY(const Vec3fX<S>& v) const { return data.transposeDot(1, v.data); } + // (0 0 1)^T (*this)^T v inline U transposeDotZ(const Vec3fX<S>& v) const { return data.transposeDot(2, v.data); } + // (\delta_{i3})^T (*this)^T v inline U transposeDot(size_t i, const Vec3fX<S>& v) const { return data.transposeDot(i, v.data); } + // (1 0 0)^T (*this) v inline U dotX(const Vec3fX<S>& v) const { return data.dot(0, v.data); } + // (0 1 0)^T (*this) v inline U dotY(const Vec3fX<S>& v) const { return data.dot(1, v.data); } + // (0 0 1)^T (*this) v inline U dotZ(const Vec3fX<S>& v) const { return data.dot(2, v.data); } + // (\delta_{i3})^T (*this) v inline U dot(size_t i, const Vec3fX<S>& v) const { return data.dot(i, v.data); diff --git a/src/BV/OBB.cpp b/src/BV/OBB.cpp index 60f9de15705c87d264b306e2249c4e30f3ad07e0..f54fe602b076d6654a988f9c59a994b834177881 100644 --- a/src/BV/OBB.cpp +++ b/src/BV/OBB.cpp @@ -298,6 +298,205 @@ bool obbDisjoint(const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f& } +// B, T orientation and position of 2nd OBB in frame of 1st OBB, +// a extent of 1st OBB, +// b extent of 2nd OBB. +bool obbDisjointAndLowerBoundDistance (const Matrix3f& B, const Vec3f& T, + const Vec3f& a, const Vec3f& b, + FCL_REAL& squaredLowerBoundDistance) +{ + FCL_REAL t, s; + const FCL_REAL reps = 1e-6; + FCL_REAL diff; + + Matrix3f Bf = abs(B); + Bf += reps; + squaredLowerBoundDistance = 0; + + // if any of these tests are one-sided, then the polyhedra are disjoint + + // A1 x A2 = A0 + t = ((T[0] < 0.0) ? -T[0] : T[0]); + + diff = t - (a[0] + Bf.dotX(b)); + if (diff > 0) { + squaredLowerBoundDistance += diff*diff; + } + + // A2 x A0 = A1 + t = ((T[1] < 0.0) ? -T[1] : T[1]); + + diff = t - (a[1] + Bf.dotY(b)); + if (diff > 0) { + squaredLowerBoundDistance += diff*diff; + } + + // A0 x A1 = A2 + t =((T[2] < 0.0) ? -T[2] : T[2]); + + diff = t - (a[2] + Bf.dotZ(b)); + if (diff > 0) { + squaredLowerBoundDistance += diff*diff; + } + + if (squaredLowerBoundDistance > 0) + return true; + + // B1 x B2 = B0 + s = B.transposeDotX(T); + t = ((s < 0.0) ? -s : s); + + diff = t - (b[0] + Bf.transposeDotX(a)); + if (diff > 0) { + squaredLowerBoundDistance += diff*diff; + } + + // B2 x B0 = B1 + s = B.transposeDotY(T); + t = ((s < 0.0) ? -s : s); + + diff = t - (b[1] + Bf.transposeDotY(a)); + if (diff > 0) { + squaredLowerBoundDistance += diff*diff; + } + + // B0 x B1 = B2 + s = B.transposeDotZ(T); + t = ((s < 0.0) ? -s : s); + + diff = t - (b[2] + Bf.transposeDotZ(a)); + if (diff > 0) { + squaredLowerBoundDistance += diff*diff; + } + + if (squaredLowerBoundDistance > 0) + return true; + + // A0 x B0 + s = T[2] * B(1, 0) - T[1] * B(2, 0); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[1] * Bf(2, 0) + a[2] * Bf(1, 0) + + b[1] * Bf(0, 2) + b[2] * Bf(0, 1)); + // We need to divide by the norm || A0 x B0 || + // As ||A0|| = ||B0|| = 1, + // 2 2 + // || A0 x B0 || + (A0 | B0) = 1 + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (0,0) * Bf (0,0); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A0 x B1 + s = T[2] * B(1, 1) - T[1] * B(2, 1); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[1] * Bf(2, 1) + a[2] * Bf(1, 1) + + b[0] * Bf(0, 2) + b[2] * Bf(0, 0)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (0,1) * Bf (0,1); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A0 x B2 + s = T[2] * B(1, 2) - T[1] * B(2, 2); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[1] * Bf(2, 2) + a[2] * Bf(1, 2) + + b[0] * Bf(0, 1) + b[1] * Bf(0, 0)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (0,2) * Bf (0,2); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A1 x B0 + s = T[0] * B(2, 0) - T[2] * B(0, 0); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[0] * Bf(2, 0) + a[2] * Bf(0, 0) + + b[1] * Bf(1, 2) + b[2] * Bf(1, 1)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (1,0) * Bf (1,0); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A1 x B1 + s = T[0] * B(2, 1) - T[2] * B(0, 1); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[0] * Bf(2, 1) + a[2] * Bf(0, 1) + + b[0] * Bf(1, 2) + b[2] * Bf(1, 0)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (1,1) * Bf (1,1); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A1 x B2 + s = T[0] * B(2, 2) - T[2] * B(0, 2); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[0] * Bf(2, 2) + a[2] * Bf(0, 2) + + b[0] * Bf(1, 1) + b[1] * Bf(1, 0)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (1,2) * Bf (1,2); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A2 x B0 + s = T[1] * B(0, 0) - T[0] * B(1, 0); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[0] * Bf(1, 0) + a[1] * Bf(0, 0) + + b[1] * Bf(2, 2) + b[2] * Bf(2, 1)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (2,0) * Bf (2,0); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A2 x B1 + s = T[1] * B(0, 1) - T[0] * B(1, 1); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[0] * Bf(1, 1) + a[1] * Bf(0, 1) + + b[0] * Bf(2, 2) + b[2] * Bf(2, 0)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (2,1) * Bf (2,1); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + // A2 x B2 + s = T[1] * B(0, 2) - T[0] * B(1, 2); + t = ((s < 0.0) ? -s : s); + + diff = t - (a[0] * Bf(1, 2) + a[1] * Bf(0, 2) + + b[0] * Bf(2, 1) + b[1] * Bf(2, 0)); + if (diff > 0) { + FCL_REAL sinus2 = 1 - Bf (2,2) * Bf (2,2); + assert (sinus2 > 0); + squaredLowerBoundDistance = diff * diff / sinus2; + return true; + } + + return false; + +} + bool OBB::overlap(const OBB& other) const diff --git a/src/BV/OBB.h b/src/BV/OBB.h new file mode 100644 index 0000000000000000000000000000000000000000..c00b7793468c9f6a9bd644f2a0a19777474c7171 --- /dev/null +++ b/src/BV/OBB.h @@ -0,0 +1,50 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2014, CNRS + * Author: Florent Lamiraux + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of CNRS nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FCL_SRC_OBB_H +# define FCL_SRC_OBB_H + +namespace fcl +{ + + bool obbDisjointAndLowerBoundDistance (const Matrix3f& B, const Vec3f& T, + const Vec3f& a, const Vec3f& b, + FCL_REAL& squaredLowerBoundDistance); + + bool obbDisjoint(const Matrix3f& B, const Vec3f& T, const Vec3f& a, + const Vec3f& b); +} // namespace fcl + +#endif // FCL_SRC_OBB_H diff --git a/src/BV/RSS.cpp b/src/BV/RSS.cpp index 118bf11f66a145f3087b0ed06c7c53e11e34de5e..fc49ea3bdf552e5cc106792dd8aea62ef6443d38 100644 --- a/src/BV/RSS.cpp +++ b/src/BV/RSS.cpp @@ -852,10 +852,14 @@ bool RSS::overlap(const RSS& other) const bool overlap(const Matrix3f& R0, const Vec3f& T0, const RSS& b1, const RSS& b2) { + // ROb2 = R0 . b2 + // where b2 = [ b2.axis [0] | b2.axis [1] | b2.axis [2] ] Matrix3f R0b2(R0.dotX(b2.axis[0]), R0.dotX(b2.axis[1]), R0.dotX(b2.axis[2]), R0.dotY(b2.axis[0]), R0.dotY(b2.axis[1]), R0.dotY(b2.axis[2]), R0.dotZ(b2.axis[0]), R0.dotZ(b2.axis[1]), R0.dotZ(b2.axis[2])); + // (1 0 0)^T R0b2^T axis [0] = (1 0 0)^T b2^T R0^T axis [0] + // R = b2^T RO^T b1 Matrix3f R(R0b2.transposeDotX(b1.axis[0]), R0b2.transposeDotY(b1.axis[0]), R0b2.transposeDotZ(b1.axis[0]), R0b2.transposeDotX(b1.axis[1]), R0b2.transposeDotY(b1.axis[1]), R0b2.transposeDotZ(b1.axis[1]), R0b2.transposeDotX(b1.axis[2]), R0b2.transposeDotY(b1.axis[2]), R0b2.transposeDotZ(b1.axis[2])); diff --git a/src/collision.cpp b/src/collision.cpp index b3569e4dc92d4705cb9bca9733badd3a591a4473..5979fe8d92c60adb55b37f3fcd76effbefe1816e 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -74,7 +74,7 @@ std::size_t collide(const CollisionGeometry* o1, const Transform3f& tf1, nsolver = new NarrowPhaseSolver(); const CollisionFunctionMatrix<NarrowPhaseSolver>& looktable = getCollisionFunctionLookTable<NarrowPhaseSolver>(); - + result.distance_lower_bound = -1; std::size_t res; if(request.num_max_contacts == 0) { diff --git a/src/collision_func_matrix.cpp b/src/collision_func_matrix.cpp index 32ce18e7bbea2872e39a340fa84b012798ad91c1..40ca30366359f71f5e34c4fb32bc8d97623f5ed3 100644 --- a/src/collision_func_matrix.cpp +++ b/src/collision_func_matrix.cpp @@ -41,7 +41,7 @@ #include "fcl/traversal/traversal_node_setup.h" #include "fcl/collision_node.h" #include "fcl/narrowphase/narrowphase.h" - +#include "distance_func_matrix.h" namespace fcl { @@ -200,6 +200,25 @@ std::size_t ShapeShapeCollide(const CollisionGeometry* o1, const Transform3f& tf { if(request.isSatisfied(result)) return result.numContacts(); + if (request.enable_distance_lower_bound) { + DistanceResult distanceResult; + DistanceRequest distanceRequest (request.enable_contact); + FCL_REAL distance = ShapeShapeDistance <T_SH1, T_SH2, NarrowPhaseSolver> + (o1, tf1, o2, tf2, nsolver, distanceRequest, distanceResult); + + if (distance <= 0) { + Contact contact (o1, o2, distanceResult.b1, distanceResult.b2); + const Vec3f& p1 = distanceResult.nearest_points [0]; + const Vec3f& p2 = distanceResult.nearest_points [1]; + contact.pos = .5*(p1+p2); + contact.normal = (p2-p1)/(p2-p1).length (); + result.addContact (contact); + return 1; + } + result.distance_lower_bound = distance; + return 0; + } + ShapeCollisionTraversalNode<T_SH1, T_SH2, NarrowPhaseSolver> node; const T_SH1* obj1 = static_cast<const T_SH1*>(o1); const T_SH2* obj2 = static_cast<const T_SH2*>(o2); diff --git a/src/distance_capsule_capsule.cpp b/src/distance_capsule_capsule.cpp index 112a1ff6cef93ebae20a8507c15d61a55b5adea1..7b88f61aafdb1f7419aa96e808ffe494da27dba4 100644 --- a/src/distance_capsule_capsule.cpp +++ b/src/distance_capsule_capsule.cpp @@ -346,16 +346,15 @@ namespace fcl { (o1, tf1, o2, tf2, unused, distanceRequest, distanceResult); if (distance <= 0) { - if (request.enable_contact) { - Contact contact (o1, o2, distanceResult.b1, distanceResult.b2); - const Vec3f& p1 = distanceResult.nearest_points [0]; - const Vec3f& p2 = distanceResult.nearest_points [1]; - contact.pos = .5*(p1+p2); - contact.normal = (p2-p1)/(p2-p1).length (); - result.addContact (contact); - } + Contact contact (o1, o2, distanceResult.b1, distanceResult.b2); + const Vec3f& p1 = distanceResult.nearest_points [0]; + const Vec3f& p2 = distanceResult.nearest_points [1]; + contact.pos = .5*(p1+p2); + contact.normal = (p2-p1)/(p2-p1).length (); + result.addContact (contact); return 1; } + result.distance_lower_bound = distance; return 0; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 77d81bf2810a68cdabac38355c167632fd02c8fe..66005fcb477c61ade405d7313fd213cd5d64d11b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,6 +27,8 @@ add_fcl_test(test_fcl_box_box_distance test_fcl_box_box_distance.cpp) add_fcl_test(test_fcl_simple test_fcl_simple.cpp) add_fcl_test(test_fcl_capsule_box_1 test_fcl_capsule_box_1.cpp) add_fcl_test(test_fcl_capsule_box_2 test_fcl_capsule_box_2.cpp) +add_fcl_test(test_fcl_obb test_fcl_obb.cpp) + #add_fcl_test(test_fcl_global_penetration test_fcl_global_penetration.cpp libsvm/svm.cpp test_fcl_utility.cpp) add_fcl_test(test_fcl_bvh_models test_fcl_bvh_models.cpp test_fcl_utility.cpp) diff --git a/test/test_fcl_obb.cpp b/test/test_fcl_obb.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42d173e8feb8c749a71a0971ea0ca56987f04b2c --- /dev/null +++ b/test/test_fcl_obb.cpp @@ -0,0 +1,194 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2014, CNRS + * Author: Florent Lamiraux + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of CNRS nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define BOOST_TEST_MODULE "FCL_DISTANCE_OBB" +#define CHECK_CLOSE_TO_0(x, eps) BOOST_CHECK_CLOSE ((x + 1.0), (1.0), (eps)) + +#include <boost/test/included/unit_test.hpp> +#include <fcl/narrowphase/narrowphase.h> + +#include "../src/BV/OBB.h" +#include "../src/distance_func_matrix.h" + +using fcl::FCL_REAL; + +struct Sample +{ + fcl::Matrix3f R; + fcl::Vec3f T; + fcl::Vec3f extent1; + fcl::Vec3f extent2; +}; + +struct Result +{ + bool overlap; + FCL_REAL distance; +}; + +BOOST_AUTO_TEST_CASE(obb_overlap) +{ + static const size_t nbSamples = 10000; + Sample sample [nbSamples]; + FCL_REAL range = 2; + FCL_REAL sumDistance = 0, sumDistanceLowerBound = 0; + for (std::size_t i=0; i<nbSamples; ++i) { + // sample unit quaternion + FCL_REAL u1 = (FCL_REAL) rand() / RAND_MAX; + FCL_REAL u2 = (FCL_REAL) rand() / RAND_MAX; + FCL_REAL u3 = (FCL_REAL) rand() / RAND_MAX; + + FCL_REAL q1 = sqrt (1-u1)*sin(2*M_PI*u2); + FCL_REAL q2 = sqrt (1-u1)*cos(2*M_PI*u2); + FCL_REAL q3 = sqrt (u1) * sin(2*M_PI*u3); + FCL_REAL q4 = sqrt (u1) * cos(2*M_PI*u3); + fcl::Quaternion3f (q1, q2, q3, q4).toRotation (sample [i].R); + + // sample translation + sample [i].T = fcl::Vec3f ((FCL_REAL) range * rand() / RAND_MAX, + (FCL_REAL) range * rand() / RAND_MAX, + (FCL_REAL) range * rand() / RAND_MAX); + + // sample extents + sample [i].extent1 = fcl::Vec3f ((FCL_REAL) rand() / RAND_MAX, + (FCL_REAL) rand() / RAND_MAX, + (FCL_REAL) rand() / RAND_MAX); + + sample [i].extent2 = fcl::Vec3f ((FCL_REAL) rand() / RAND_MAX, + (FCL_REAL) rand() / RAND_MAX, + (FCL_REAL) rand() / RAND_MAX); + } + + // Compute result for each function + Result resultDistance [nbSamples]; + Result resultDisjoint [nbSamples]; + Result resultDisjointAndLowerBound [nbSamples]; + + fcl::Transform3f tf1; + fcl::Transform3f tf2; + fcl::Box box1 (0, 0, 0); + fcl::Box box2 (0, 0, 0); + fcl::DistanceRequest request (false, 0, 0, fcl::GST_INDEP); + fcl::DistanceResult result; + FCL_REAL distance; + FCL_REAL squaredDistance; + timeval t0, t1; + fcl::GJKSolver_indep gjkSolver; + + // ShapeShapeDistance + gettimeofday (&t0, NULL); + for (std::size_t i=0; i<nbSamples; ++i) { + box1.side = 2*sample [i].extent1; + box2.side = 2*sample [i].extent2; + tf2.setTransform (sample [i].R, sample [i].T); + resultDistance [i].distance = + fcl::ShapeShapeDistance<fcl::Box, fcl::Box, fcl::GJKSolver_indep> + (&box1, tf1, &box2, tf2, &gjkSolver, request, result); + resultDistance [i].overlap = (resultDistance [i].distance < 0); + if (resultDistance [i].distance < 0) { + resultDistance [i].distance = 0; + } + result.clear (); + } + gettimeofday (&t1, NULL); + double t = (t1.tv_sec - t0.tv_sec) + 1e-6*(t1.tv_usec - t0.tv_usec + 0.); + std::cout << "Time for " << nbSamples + << " calls to ShapeShapeDistance (in seconds): " + << t << std::endl; + + // obbDisjointAndLowerBoundDistance + gettimeofday (&t0, NULL); + for (std::size_t i=0; i<nbSamples; ++i) { + resultDisjointAndLowerBound [i].overlap = + !obbDisjointAndLowerBoundDistance (sample [i].R, sample [i].T, + sample [i].extent1, + sample [i].extent2, + squaredDistance); + resultDisjointAndLowerBound [i].distance = sqrt (squaredDistance); + } + gettimeofday (&t1, NULL); + t = (t1.tv_sec - t0.tv_sec) + 1e-6*(t1.tv_usec - t0.tv_usec + 0.); + std::cout << "Time for " << nbSamples + << " calls to obbDisjointAndLowerBoundDistance" + << " (in seconds): " + << t << std::endl; + + gettimeofday (&t0, NULL); + for (std::size_t i=0; i<nbSamples; ++i) { + resultDisjoint [i].overlap = + !obbDisjoint (sample [i].R, sample [i].T, + sample [i].extent1, + sample [i].extent2); + resultDisjoint [i].distance = 0; + } + gettimeofday (&t1, NULL); + t = (t1.tv_sec - t0.tv_sec) + 1e-6*(t1.tv_usec - t0.tv_usec + 0.); + std::cout << "Time for " << nbSamples << " calls to obbDisjoint" + << " (in seconds): " + << t << std::endl; + + // Test correctness of results + bool res1, res2, res3; + for (std::size_t i=0; i<nbSamples; ++i) { + res1 = resultDisjoint [i].overlap; + res2 = resultDisjointAndLowerBound [i].overlap; + res3 = resultDistance [i].overlap; + sumDistanceLowerBound += resultDisjointAndLowerBound [i].distance; + sumDistance += resultDistance [i].distance; + +#if 0 + std::cout << "ShapeShapeDistance: overlap: " + << resultDistance [i].overlap + << ", distance: " << resultDistance [i].distance << std::endl; + std::cout << "disjoint: overlap: " + << resultDisjoint [i].overlap + << ", distance: " << resultDisjoint [i].distance << std::endl; + std::cout << "disjointAndLowerBound: overlap: " + << resultDisjointAndLowerBound [i].overlap + << ", distance: " << resultDisjointAndLowerBound [i].distance + << std::endl << std::endl; +#endif + BOOST_CHECK (res1 == res2); + BOOST_CHECK (res1 == res3); + BOOST_CHECK ((!res1 && resultDisjointAndLowerBound [i].distance > 0) || + (res1 && resultDisjointAndLowerBound [i].distance == 0)); + BOOST_CHECK (resultDisjointAndLowerBound [i].distance <= + resultDistance [i].distance); + } + std::cout << "Sum distances ShapeShapeDistance: " + << sumDistance << std::endl; + std::cout << "Sum distances obbDisjointAndLowerBoundDistance: " + << sumDistanceLowerBound << std::endl; +}