38 #include <gtest/gtest.h> 40 #include "fcl/config.h" 55 #include <sparsehash/sparse_hash_map> 56 #include <sparsehash/dense_hash_map> 75 template<
typename U,
typename V>
76 struct GoogleSparseHashTable :
public google::sparse_hash_map<U, V, std::tr1::hash<size_t>, std::equal_to<size_t> > {};
78 template<
typename U,
typename V>
79 struct GoogleDenseHashTable :
public google::dense_hash_map<U, V, std::tr1::hash<size_t>, std::equal_to<size_t> >
81 GoogleDenseHashTable() : google::dense_hash_map<U, V,
std::tr1::hash<size_t>,
std::equal_to<size_t> >()
83 this->set_empty_key(
nullptr);
90 GTEST_TEST(FCL_BROADPHASE, test_broad_phase_dont_duplicate_check)
93 broad_phase_duplicate_check_test<double>(2000, 1000);
95 broad_phase_duplicate_check_test<double>(2000, 100);
100 GTEST_TEST(FCL_BROADPHASE, test_core_bf_broad_phase_update_collision_binary)
103 broad_phase_update_collision_test<double>(2000, 100, 1000, 1,
false);
104 broad_phase_update_collision_test<double>(2000, 1000, 1000, 1,
false);
106 broad_phase_update_collision_test<double>(2000, 10, 100, 1,
false);
107 broad_phase_update_collision_test<double>(2000, 100, 100, 1,
false);
112 GTEST_TEST(FCL_BROADPHASE, test_core_bf_broad_phase_update_collision)
115 broad_phase_update_collision_test<double>(2000, 100, 1000, 10,
false);
116 broad_phase_update_collision_test<double>(2000, 1000, 1000, 10,
false);
118 broad_phase_update_collision_test<double>(2000, 10, 100, 10,
false);
119 broad_phase_update_collision_test<double>(2000, 100, 100, 10,
false);
124 GTEST_TEST(FCL_BROADPHASE, test_core_bf_broad_phase_update_collision_exhaustive)
127 broad_phase_update_collision_test<double>(2000, 100, 1000, 1,
true);
128 broad_phase_update_collision_test<double>(2000, 1000, 1000, 1,
true);
130 broad_phase_update_collision_test<double>(2000, 10, 100, 1,
true);
131 broad_phase_update_collision_test<double>(2000, 100, 100, 1,
true);
136 GTEST_TEST(FCL_BROADPHASE, test_core_mesh_bf_broad_phase_update_collision_mesh_binary)
139 broad_phase_update_collision_test<double>(2000, 100, 1000, 1,
false,
true);
140 broad_phase_update_collision_test<double>(2000, 1000, 1000, 1,
false,
true);
142 broad_phase_update_collision_test<double>(2000, 2, 4, 1,
false,
true);
143 broad_phase_update_collision_test<double>(2000, 4, 4, 1,
false,
true);
148 GTEST_TEST(FCL_BROADPHASE, test_core_mesh_bf_broad_phase_update_collision_mesh)
151 broad_phase_update_collision_test<double>(2000, 100, 1000, 10,
false,
true);
152 broad_phase_update_collision_test<double>(2000, 1000, 1000, 10,
false,
true);
154 broad_phase_update_collision_test<double>(200, 2, 4, 10,
false,
true);
155 broad_phase_update_collision_test<double>(200, 4, 4, 10,
false,
true);
160 GTEST_TEST(FCL_BROADPHASE, test_core_mesh_bf_broad_phase_update_collision_mesh_exhaustive)
163 broad_phase_update_collision_test<double>(2000, 100, 1000, 1,
true,
true);
164 broad_phase_update_collision_test<double>(2000, 1000, 1000, 1,
true,
true);
166 broad_phase_update_collision_test<double>(2000, 2, 4, 1,
true,
true);
167 broad_phase_update_collision_test<double>(2000, 4, 4, 1,
true,
true);
172 template <
typename S>
179 auto search = checkedPairs.find(std::make_pair(o1, o2));
181 if (search != checkedPairs.end())
184 checkedPairs.emplace(o1, o2);
191 template <
typename S>
197 EXPECT_TRUE(cdata->checkUniquenessAndAddPair(o1, o2));
203 template <
typename S>
206 std::vector<test::TStruct> ts;
207 std::vector<test::Timer> timers;
209 std::vector<CollisionObject<S>*> env;
212 std::vector<BroadPhaseCollisionManager<S>*> managers;
219 S cell_size =
std::min(
std::min((upper_limit[0] - lower_limit[0]) / 20, (upper_limit[1] - lower_limit[1]) / 20), (upper_limit[2] - lower_limit[2])/20);
231 managers.push_back(m);
237 managers.push_back(m);
240 ts.resize(managers.size());
241 timers.resize(managers.size());
243 for(
size_t i = 0; i < managers.size(); ++i)
246 managers[i]->registerObjects(env);
248 ts[i].push_back(timers[i].getElapsedTime());
251 for(
size_t i = 0; i < managers.size(); ++i)
254 managers[i]->setup();
256 ts[i].push_back(timers[i].getElapsedTime());
261 S delta_trans_max = 0.01 * env_scale;
262 for(
size_t i = 0; i < env.size(); ++i)
264 S rand_angle_x = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_angle_max;
265 S rand_trans_x = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_trans_max;
266 S rand_angle_y = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_angle_max;
267 S rand_trans_y = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_trans_max;
268 S rand_angle_z = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_angle_max;
269 S rand_trans_z = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_trans_max;
275 Vector3<S> dT(rand_trans_x, rand_trans_y, rand_trans_z);
279 env[i]->setTransform(dR * R, dR * T + dT);
280 env[i]->computeAABB();
283 for(
size_t i = 0; i < managers.size(); ++i)
286 managers[i]->update();
288 ts[i].push_back(timers[i].getElapsedTime());
291 std::vector<CollisionDataForUniquenessChecking<S>> self_data(managers.size());
293 for(
size_t i = 0; i < managers.size(); ++i)
298 ts[i].push_back(timers[i].getElapsedTime());
307 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
310 std::cout <<
"collision timing summary" << std::endl;
311 std::cout << env_size <<
" objs" << std::endl;
312 std::cout <<
"register time" << std::endl;
313 for(
size_t i = 0; i < ts.size(); ++i)
314 std::cout << std::setw(w) << ts[i].records[0] <<
" ";
315 std::cout << std::endl;
317 std::cout <<
"setup time" << std::endl;
318 for(
size_t i = 0; i < ts.size(); ++i)
319 std::cout << std::setw(w) << ts[i].records[1] <<
" ";
320 std::cout << std::endl;
322 std::cout <<
"update time" << std::endl;
323 for(
size_t i = 0; i < ts.size(); ++i)
324 std::cout << std::setw(w) << ts[i].records[2] <<
" ";
325 std::cout << std::endl;
327 std::cout <<
"self collision time" << std::endl;
328 for(
size_t i = 0; i < ts.size(); ++i)
329 std::cout << std::setw(w) << ts[i].records[3] <<
" ";
330 std::cout << std::endl;
332 std::cout <<
"collision time" << std::endl;
333 for(
size_t i = 0; i < ts.size(); ++i)
336 for(
size_t j = 4; j < ts[i].records.size(); ++j)
337 tmp += ts[i].records[j];
338 std::cout << std::setw(w) << tmp <<
" ";
340 std::cout << std::endl;
342 std::cout <<
"overall time" << std::endl;
343 for(
size_t i = 0; i < ts.size(); ++i)
344 std::cout << std::setw(w) << ts[i].overall_time <<
" ";
345 std::cout << std::endl;
346 std::cout << std::endl;
349 template <
typename S>
352 std::vector<test::TStruct> ts;
353 std::vector<test::Timer> timers;
355 std::vector<CollisionObject<S>*> env;
361 std::vector<CollisionObject<S>*> query;
367 std::vector<BroadPhaseCollisionManager<S>*> managers;
378 S cell_size =
std::min(
std::min((upper_limit[0] - lower_limit[0]) / 20, (upper_limit[1] - lower_limit[1]) / 20), (upper_limit[2] - lower_limit[2])/20);
391 managers.push_back(m);
397 managers.push_back(m);
400 ts.resize(managers.size());
401 timers.resize(managers.size());
403 for(
size_t i = 0; i < managers.size(); ++i)
406 managers[i]->registerObjects(env);
408 ts[i].push_back(timers[i].getElapsedTime());
411 for(
size_t i = 0; i < managers.size(); ++i)
414 managers[i]->setup();
416 ts[i].push_back(timers[i].getElapsedTime());
421 S delta_trans_max = 0.01 * env_scale;
422 for(
size_t i = 0; i < env.size(); ++i)
424 S rand_angle_x = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_angle_max;
425 S rand_trans_x = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_trans_max;
426 S rand_angle_y = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_angle_max;
427 S rand_trans_y = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_trans_max;
428 S rand_angle_z = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_angle_max;
429 S rand_trans_z = 2 * (rand() / (S)RAND_MAX - 0.5) * delta_trans_max;
435 Vector3<S> dT(rand_trans_x, rand_trans_y, rand_trans_z);
439 env[i]->setTransform(dR * R, dR * T + dT);
440 env[i]->computeAABB();
443 for(
size_t i = 0; i < managers.size(); ++i)
446 managers[i]->update();
448 ts[i].push_back(timers[i].getElapsedTime());
451 std::vector<DefaultCollisionData<S>> self_data(managers.size());
452 for(
size_t i = 0; i < managers.size(); ++i)
454 if(exhaustive) self_data[i].request.num_max_contacts = 100000;
458 for(
size_t i = 0; i < managers.size(); ++i)
463 ts[i].push_back(timers[i].getElapsedTime());
467 for(
size_t i = 0; i < managers.size(); ++i)
468 std::cout << self_data[i].result.numContacts() <<
" ";
469 std::cout << std::endl;
473 for(
size_t i = 1; i < managers.size(); ++i)
474 EXPECT_TRUE(self_data[i].result.numContacts() == self_data[0].result.numContacts());
478 std::vector<bool> self_res(managers.size());
479 for(
size_t i = 0; i < self_res.size(); ++i)
480 self_res[i] = (self_data[i].result.numContacts() > 0);
482 for(
size_t i = 1; i < self_res.size(); ++i)
485 for(
size_t i = 1; i < managers.size(); ++i)
486 EXPECT_TRUE(self_data[i].result.numContacts() == self_data[0].result.numContacts());
490 for(
size_t i = 0; i < query.size(); ++i)
492 std::vector<DefaultCollisionData<S>> query_data(managers.size());
493 for(
size_t j = 0; j < query_data.size(); ++j)
495 if(exhaustive) query_data[j].request.num_max_contacts = 100000;
499 for(
size_t j = 0; j < query_data.size(); ++j)
504 ts[j].push_back(timers[j].getElapsedTime());
514 for(
size_t j = 1; j < managers.size(); ++j)
515 EXPECT_TRUE(query_data[j].result.numContacts() == query_data[0].result.numContacts());
519 std::vector<bool> query_res(managers.size());
520 for(
size_t j = 0; j < query_res.size(); ++j)
521 query_res[j] = (query_data[j].result.numContacts() > 0);
522 for(
size_t j = 1; j < query_res.size(); ++j)
525 for(
size_t j = 1; j < managers.size(); ++j)
526 EXPECT_TRUE(query_data[j].result.numContacts() == query_data[0].result.numContacts());
531 for(
size_t i = 0; i < env.size(); ++i)
533 for(
size_t i = 0; i < query.size(); ++i)
536 for(
size_t i = 0; i < managers.size(); ++i)
540 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
543 std::cout <<
"collision timing summary" << std::endl;
544 std::cout << env_size <<
" objs, " << query_size <<
" queries" << std::endl;
545 std::cout <<
"register time" << std::endl;
546 for(
size_t i = 0; i < ts.size(); ++i)
547 std::cout << std::setw(w) << ts[i].records[0] <<
" ";
548 std::cout << std::endl;
550 std::cout <<
"setup time" << std::endl;
551 for(
size_t i = 0; i < ts.size(); ++i)
552 std::cout << std::setw(w) << ts[i].records[1] <<
" ";
553 std::cout << std::endl;
555 std::cout <<
"update time" << std::endl;
556 for(
size_t i = 0; i < ts.size(); ++i)
557 std::cout << std::setw(w) << ts[i].records[2] <<
" ";
558 std::cout << std::endl;
560 std::cout <<
"self collision time" << std::endl;
561 for(
size_t i = 0; i < ts.size(); ++i)
562 std::cout << std::setw(w) << ts[i].records[3] <<
" ";
563 std::cout << std::endl;
565 std::cout <<
"collision time" << std::endl;
566 for(
size_t i = 0; i < ts.size(); ++i)
569 for(
size_t j = 4; j < ts[i].records.size(); ++j)
570 tmp += ts[i].records[j];
571 std::cout << std::setw(w) << tmp <<
" ";
573 std::cout << std::endl;
576 std::cout <<
"overall time" << std::endl;
577 for(
size_t i = 0; i < ts.size(); ++i)
578 std::cout << std::setw(w) << ts[i].overall_time <<
" ";
579 std::cout << std::endl;
580 std::cout << std::endl;
584 int main(
int argc,
char* argv[])
586 ::testing::InitGoogleTest(&argc, argv);
587 return RUN_ALL_TESTS();
void generateEnvironmentsMesh(std::vector< CollisionObject< S > *> &env, S env_scale, std::size_t n)
Generate environment with 3 * n objects, but all in meshes.
std::set< std::pair< CollisionObject< S > *, CollisionObject< S > * > > checkedPairs
Functor to help unregister one object.
void broad_phase_update_collision_test(S env_scale, std::size_t env_size, std::size_t query_size, std::size_t num_max_contacts=1, bool exhaustive=false, bool use_mesh=false)
test for broad phase update
bool checkUniquenessAndAddPair(CollisionObject< S > *o1, CollisionObject< S > *o2)
GTEST_TEST(FCL_BROADPHASE, test_broad_phase_dont_duplicate_check)
static void computeBound(std::vector< CollisionObject< S > *> &objs, Vector3< S > &l, Vector3< S > &u)
compute the bound for the environent
bool collisionFunctionForUniquenessChecking(CollisionObject< S > *o1, CollisionObject< S > *o2, void *cdata_)
spatial hashing collision mananger
Eigen::Matrix< S, 3, 3 > Matrix3
Eigen::Matrix< S, 3, 1 > Vector3
Eigen::AngleAxis< S > AngleAxis
A hash table implemented using unordered_map.
int main(int argc, char *argv[])
void generateEnvironments(std::vector< CollisionObject< S > *> &env, S env_scale, std::size_t n)
Generate environment with 3 * n objects: n boxes, n spheres and n cylinders.
Simple SAP collision manager.
static constexpr S pi()
The mathematical constant pi.
Spatial hash function: hash an AABB to a set of integer values.
the object for collision or distance computation, contains the geometry and the transform information...
Brute force N-body collision manager.
bool DefaultCollisionFunction(CollisionObject< S > *o1, CollisionObject< S > *o2, void *data)
Provides a simple callback for the collision query in the BroadPhaseCollisionManager. It assumes the data parameter is non-null and points to an instance of DefaultCollisionData. It simply invokes the collide() method on the culled pair of geometries and stores the results in the data's CollisionResult instance.
void broad_phase_duplicate_check_test(S env_scale, std::size_t env_size, bool verbose=false)
make sure if broadphase algorithms doesn't check twice for the same collision object pair ...
CollisionObject< S > * obj
object
#define EXPECT_TRUE(args)