diff --git a/src/collision_node.cpp b/src/collision_node.cpp index d7a5071fbe8a6557ca6adff1d1106ae5e1629f12..c69457030e0ea3d387bcb42cfea06a2ba9822c72 100644 --- a/src/collision_node.cpp +++ b/src/collision_node.cpp @@ -46,7 +46,8 @@ namespace fcl void collide(CollisionTraversalNodeBase* node, const CollisionRequest& request, CollisionResult& result, - BVHFrontList* front_list) + BVHFrontList* front_list, + bool recursive) { if(front_list && front_list->size() > 0) { @@ -55,7 +56,10 @@ void collide(CollisionTraversalNodeBase* node, else { FCL_REAL sqrDistLowerBound=0; - collisionRecurse(node, 0, 0, front_list, sqrDistLowerBound); + if (recursive) + collisionRecurse(node, 0, 0, front_list, sqrDistLowerBound); + else + collisionNonRecurse(node, front_list, sqrDistLowerBound); result.distance_lower_bound = sqrt (sqrDistLowerBound); } } diff --git a/src/collision_node.h b/src/collision_node.h index 23fd309de6da0d0281da458463727c00e40d367b..2f17fec589163edb1a7e65451d322a511113909e 100644 --- a/src/collision_node.h +++ b/src/collision_node.h @@ -62,7 +62,8 @@ namespace fcl void collide(CollisionTraversalNodeBase* node, const CollisionRequest& request, CollisionResult& result, - BVHFrontList* front_list = NULL); + BVHFrontList* front_list = NULL, + bool recursive = true); /// @brief distance computation on distance traversal node; can use front list to accelerate void distance(DistanceTraversalNodeBase* node, BVHFrontList* front_list = NULL, int qsize = 2); diff --git a/test/test_fcl_collision-bench.py b/test/test_fcl_collision-bench.py index 8bd9836e35dcd2993efff7517c29ff5edc3fa9ab..41a46cf4210354a9efeaeb1836a4eff3ee144845 100644 --- a/test/test_fcl_collision-bench.py +++ b/test/test_fcl_collision-bench.py @@ -26,9 +26,10 @@ while values[0][0:3] == values[Ntransforms][0:3]: Ntransforms += 1 splitMethods = ['avg', 'med', 'cen'] +type = ["o", "or", "r", ] BVs = list (set ([ v[0] for v in request1[::Ntransforms] ])) xvals = [ BVs.index(v[0]) + len(BVs)*v[2] + 3*len(BVs)*v[1] for v in request1[::Ntransforms] ] -cases = [ v[0] + ("*" if v[1] == 1 else "") + " " + splitMethods[v[2]] for v in request1[::Ntransforms] ] +cases = [ v[0] + " " + type[v[1]] + " " + splitMethods[v[2]] for v in request1[::Ntransforms] ] idx_reorder = sorted (list(range(len(xvals))), key=lambda i: xvals[i]) def reorder (l): return [ l[i] for i in idx_reorder ] @@ -36,10 +37,12 @@ def reorder (l): return [ l[i] for i in idx_reorder ] xvals_s = reorder (xvals) cases_s = reorder (cases) +onlyLB = True # Time plt.figure(0) for i in range(Ntransforms): - plt.plot(xvals_s, reorder([ v[5] for v in request1[i::Ntransforms] ]) , '-.o', label=str(i)) + if not onlyLB: + plt.plot(xvals_s, reorder([ v[5] for v in request1[i::Ntransforms] ]) , '-.o', label=str(i)) plt.plot(xvals_s, reorder([ v[5] for v in request2[i::Ntransforms] ]) , ':+', label=str(i)+"+lb") plt.legend() @@ -47,6 +50,19 @@ plt.xticks(ticks=xvals_s, labels=cases_s, rotation=90) plt.ylabel('Time (us)') plt.yscale('log') +# Time +plt.figure(2) +for k in range (0, len(request1), Ntransforms): + if not onlyLB: + plt.plot([ xvals[int(k/Ntransforms)], ], sum([ v[5] for v in request1[k:k+Ntransforms] ])/Ntransforms) + plt.plot([ xvals[int(k/Ntransforms)], ], sum([ v[5] for v in request2[k:k+Ntransforms] ])/Ntransforms) + +plt.plot(xvals_s, reorder ([ sum([ v[5] for v in request2[k:k+Ntransforms] ])/Ntransforms for k in range (0, len(request1), Ntransforms) ])) + +plt.xticks(ticks=xvals_s, labels=cases_s, rotation=90) +plt.ylabel('Time (us)') +plt.yscale('log') + # Distance plt.figure(1) for i in range(Ntransforms): diff --git a/test/test_fcl_collision.cpp b/test/test_fcl_collision.cpp index eb09945343f49809851d221e95624bc8cc687c7a..d0dd6c6f9efe9dcf96a97051c98716733d1fbab3 100644 --- a/test/test_fcl_collision.cpp +++ b/test/test_fcl_collision.cpp @@ -244,12 +244,19 @@ struct base_traits }; }; -template<typename BV, int _Options> +enum { + Oriented = true, + NonOriented = false, + Recursive = true, + NonRecursive = false +}; + +template<typename BV, bool Oriented, bool recursive> struct traits : base_traits {}; -template<size_t N> -struct traits<KDOP<N>, 0> : base_traits +template<size_t N, bool recursive> +struct traits<KDOP<N>, Oriented, recursive> : base_traits { enum { IS_IMPLEMENTED = false }; @@ -318,21 +325,20 @@ struct mesh_mesh_run_test clock_type::time_point start, end; const Transform3f tf2; const std::size_t N = transforms.size(); - std::size_t s = N, e; - std::vector<CollisionResult> results (2 * N); - if (traits<BV, 0>::IS_IMPLEMENTED) + + contacts.resize (3*N); + + if (traits<BV, Oriented, Recursive>::IS_IMPLEMENTED) { BOOST_TEST_MESSAGE (getindent() << "BV: " << str<BV>() << " oriented"); ++indent; - s = 0; - e = N; - start = clock_type::now(); for(std::size_t i = 0; i < transforms.size(); ++i) { + start = clock_type::now(); const Transform3f& tf1 = transforms[i]; - CollisionResult& local_result (results[i]); + CollisionResult local_result; MeshCollisionTraversalNode<BV, 0> node (request); node.enable_statistics = enable_statistics; @@ -358,22 +364,27 @@ struct mesh_mesh_run_test BENCHMARK(local_result.distance_lower_bound); BENCHMARK((end - start).count()); BENCHMARK_NEXT(); + + if(local_result.numContacts() > 0) + { + local_result.getContacts(contacts[i]); + std::sort(contacts[i].begin(), contacts[i].end()); + } } --indent; } - if (traits<BV, RelativeTransformationIsIdentity>::IS_IMPLEMENTED) + if (traits<BV, NonOriented, Recursive>::IS_IMPLEMENTED) { BOOST_TEST_MESSAGE (getindent() << "BV: " << str<BV>()); ++indent; - e = 2*N; for(std::size_t i = 0; i < transforms.size(); ++i) { start = clock_type::now(); const Transform3f tf1 = transforms[i]; - CollisionResult& local_result (results[i + N]); + CollisionResult local_result; MeshCollisionTraversalNode<BV, RelativeTransformationIsIdentity> node (request); node.enable_statistics = enable_statistics; @@ -393,7 +404,7 @@ struct mesh_mesh_run_test end = clock_type::now(); BENCHMARK(str<BV>()); - BENCHMARK("0"); + BENCHMARK(2); BENCHMARK(splitMethod); if (enable_statistics) { BOOST_TEST_MESSAGE (getindent() << "statistics: " << node.num_bv_tests << " " << node.num_leaf_tests); @@ -405,20 +416,59 @@ struct mesh_mesh_run_test BENCHMARK(local_result.distance_lower_bound); BENCHMARK((end - start).count()); BENCHMARK_NEXT(); + + if(local_result.numContacts() > 0) + { + local_result.getContacts(contacts[i+N]); + std::sort(contacts[i+N].begin(), contacts[i+N].end()); + } } --indent; } - contacts.resize (2*N); - for(std::size_t i = s; i < e; ++i) + if (traits<BV, Oriented, NonRecursive>::IS_IMPLEMENTED) { - const CollisionResult& local_result (results[i]); + BOOST_TEST_MESSAGE (getindent() << "BV: " << str<BV>() << " oriented non-recursive"); + ++indent; - if(local_result.numContacts() > 0) + for(std::size_t i = 0; i < transforms.size(); ++i) { - local_result.getContacts(contacts[i]); - std::sort(contacts[i].begin(), contacts[i].end()); + start = clock_type::now(); + const Transform3f tf1 = transforms[i]; + + CollisionResult local_result; + MeshCollisionTraversalNode<BV, 0> node (request); + node.enable_statistics = enable_statistics; + + bool success = initialize (node, + *model1, tf1, *model2, tf2, + local_result); + BOOST_REQUIRE (success); + + collide(&node, request, local_result, NULL, false); + + end = clock_type::now(); + BENCHMARK(str<BV>()); + BENCHMARK(0); + BENCHMARK(splitMethod); + if (enable_statistics) { + BOOST_TEST_MESSAGE (getindent() << "statistics: " << node.num_bv_tests << " " << node.num_leaf_tests); + BOOST_TEST_MESSAGE (getindent() << "nb contacts: " << local_result.numContacts()); + BENCHMARK(node.num_bv_tests); + BENCHMARK(node.num_leaf_tests); + } + BENCHMARK(local_result.numContacts()); + BENCHMARK(local_result.distance_lower_bound); + BENCHMARK((end - start).count()); + BENCHMARK_NEXT(); + + if(local_result.numContacts() > 0) + { + local_result.getContacts(contacts[i+2*N]); + std::sort(contacts[i+2*N].begin(), contacts[i+2*N].end()); + } } + --indent; } } @@ -428,10 +478,10 @@ struct mesh_mesh_run_test if (benchmark) return; const std::size_t N = transforms.size(); - BOOST_REQUIRE_EQUAL(contacts.size(), 2*N); + BOOST_REQUIRE_EQUAL(contacts.size(), 3*N); BOOST_REQUIRE_EQUAL(contacts.size(), contacts_ref.size()); - if (traits<BV, 0>::IS_IMPLEMENTED) { + if (traits<BV, Oriented, Recursive>::IS_IMPLEMENTED) { for(std::size_t i = 0; i < N; ++i) { BOOST_CHECK_EQUAL(contacts_ref[i].size(), contacts[i].size()); for(std::size_t j = 0; j < contacts[i].size(); ++j) { @@ -440,7 +490,7 @@ struct mesh_mesh_run_test } } } - if (traits<BV, RelativeTransformationIsIdentity>::IS_IMPLEMENTED) { + if (traits<BV, NonOriented, Recursive>::IS_IMPLEMENTED) { for(std::size_t i = N; i < 2*N; ++i) { BOOST_CHECK_EQUAL(contacts_ref[i].size(), contacts[i].size()); for(std::size_t j = 0; j < contacts[i].size(); ++j) { @@ -449,6 +499,15 @@ struct mesh_mesh_run_test } } } + if (traits<BV, Oriented, NonRecursive>::IS_IMPLEMENTED) { + for(std::size_t i = 2*N; i < 3*N; ++i) { + BOOST_CHECK_EQUAL(contacts_ref[i].size(), contacts[i].size()); + for(std::size_t j = 0; j < contacts[i].size(); ++j) { + BOOST_CHECK_EQUAL(contacts_ref[i][j].b1, contacts[i][j].b1); + BOOST_CHECK_EQUAL(contacts_ref[i][j].b2, contacts[i][j].b2); + } + } + } } template<typename BV>