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
00038 #define BOOST_TEST_MODULE "FCL_BROADPHASE"
00039 #include <boost/test/unit_test.hpp>
00040
00041 #include "fcl/broadphase/broadphase.h"
00042 #include "fcl/shape/geometric_shape_to_BVH_model.h"
00043 #include "fcl/math/transform.h"
00044 #include "test_fcl_utility.h"
00045
00046 #if USE_GOOGLEHASH
00047 #include <sparsehash/sparse_hash_map>
00048 #include <sparsehash/dense_hash_map>
00049 #include <hash_map>
00050 #endif
00051
00052 #include <boost/math/constants/constants.hpp>
00053 #include <iostream>
00054 #include <iomanip>
00055
00056 using namespace fcl;
00057
00058 struct TStruct
00059 {
00060 std::vector<double> records;
00061 double overall_time;
00062
00063 TStruct() { overall_time = 0; }
00064
00065 void push_back(double t)
00066 {
00067 records.push_back(t);
00068 overall_time += t;
00069 }
00070 };
00071
00073 void generateEnvironments(std::vector<CollisionObject*>& env, double env_scale, std::size_t n);
00074
00076 void generateSelfDistanceEnvironments(std::vector<CollisionObject*>& env, double env_scale, std::size_t n);
00077
00079 void generateEnvironmentsMesh(std::vector<CollisionObject*>& env, double env_scale, std::size_t n);
00080
00082 void generateSelfDistanceEnvironmentsMesh(std::vector<CollisionObject*>& env, double env_scale, std::size_t n);
00083
00085 void broad_phase_collision_test(double 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);
00086
00088 void broad_phase_distance_test(double env_scale, std::size_t env_size, std::size_t query_size, bool use_mesh = false);
00089
00091 void broad_phase_self_distance_test(double env_scale, std::size_t env_size, bool use_mesh = false);
00092
00094 void broad_phase_update_collision_test(double 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);
00095
00096 FCL_REAL DELTA = 0.01;
00097
00098
00099 #if USE_GOOGLEHASH
00100 template<typename U, typename V>
00101 struct GoogleSparseHashTable : public google::sparse_hash_map<U, V, std::tr1::hash<size_t>, std::equal_to<size_t> > {};
00102
00103 template<typename U, typename V>
00104 struct GoogleDenseHashTable : public google::dense_hash_map<U, V, std::tr1::hash<size_t>, std::equal_to<size_t> >
00105 {
00106 GoogleDenseHashTable() : google::dense_hash_map<U, V, std::tr1::hash<size_t>, std::equal_to<size_t> >()
00107 {
00108 this->set_empty_key(NULL);
00109 }
00110 };
00111 #endif
00112
00114 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_update_collision_binary)
00115 {
00116 broad_phase_update_collision_test(2000, 100, 1000, 1, false);
00117 broad_phase_update_collision_test(2000, 1000, 1000, 1, false);
00118 }
00119
00121 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_update_collision)
00122 {
00123 broad_phase_update_collision_test(2000, 100, 1000, 10, false);
00124 broad_phase_update_collision_test(2000, 1000, 1000, 10, false);
00125 }
00126
00128 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_update_collision_exhaustive)
00129 {
00130 broad_phase_update_collision_test(2000, 100, 1000, 1, true);
00131 broad_phase_update_collision_test(2000, 1000, 1000, 1, true);
00132 }
00133
00135 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_distance)
00136 {
00137 broad_phase_distance_test(200, 100, 100);
00138 broad_phase_distance_test(200, 1000, 100);
00139 broad_phase_distance_test(2000, 100, 100);
00140 broad_phase_distance_test(2000, 1000, 100);
00141 }
00142
00144 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_self_distance)
00145 {
00146 broad_phase_self_distance_test(200, 512);
00147 broad_phase_self_distance_test(200, 1000);
00148 broad_phase_self_distance_test(200, 5000);
00149 }
00150
00152 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_collision_binary)
00153 {
00154 broad_phase_collision_test(2000, 100, 1000, 1, false);
00155 broad_phase_collision_test(2000, 1000, 1000, 1, false);
00156 broad_phase_collision_test(2000, 100, 1000, 1, true);
00157 broad_phase_collision_test(2000, 1000, 1000, 1, true);
00158 }
00159
00161 BOOST_AUTO_TEST_CASE(test_core_bf_broad_phase_collision)
00162 {
00163 broad_phase_collision_test(2000, 100, 1000, 10, false);
00164 broad_phase_collision_test(2000, 1000, 1000, 10, false);
00165 }
00166
00168 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_update_collision_mesh_binary)
00169 {
00170 broad_phase_update_collision_test(2000, 100, 1000, false, true);
00171 broad_phase_update_collision_test(2000, 1000, 1000, false, true);
00172 }
00173
00175 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_update_collision_mesh)
00176 {
00177 broad_phase_update_collision_test(2000, 100, 1000, 10, false, true);
00178 broad_phase_update_collision_test(2000, 1000, 1000, 10, false, true);
00179 }
00180
00182 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_update_collision_mesh_exhaustive)
00183 {
00184 broad_phase_update_collision_test(2000, 100, 1000, 1, true, true);
00185 broad_phase_update_collision_test(2000, 1000, 1000, 1, true, true);
00186 }
00187
00189 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_distance_mesh)
00190 {
00191 broad_phase_distance_test(200, 100, 100, true);
00192 broad_phase_distance_test(200, 1000, 100, true);
00193 broad_phase_distance_test(2000, 100, 100, true);
00194 broad_phase_distance_test(2000, 1000, 100, true);
00195 }
00196
00198 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_self_distance_mesh)
00199 {
00200 broad_phase_self_distance_test(200, 512, true);
00201 broad_phase_self_distance_test(200, 1000, true);
00202 broad_phase_self_distance_test(200, 5000, true);
00203 }
00204
00206 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_collision_mesh_binary)
00207 {
00208 broad_phase_collision_test(2000, 100, 1000, 1, false, true);
00209 broad_phase_collision_test(2000, 1000, 1000, 1, false, true);
00210 }
00211
00213 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_collision_mesh)
00214 {
00215 broad_phase_collision_test(2000, 100, 1000, 10, false, true);
00216 broad_phase_collision_test(2000, 1000, 1000, 10, false, true);
00217 }
00218
00220 BOOST_AUTO_TEST_CASE(test_core_mesh_bf_broad_phase_collision_mesh_exhaustive)
00221 {
00222 broad_phase_collision_test(2000, 100, 1000, 1, true, true);
00223 broad_phase_collision_test(2000, 1000, 1000, 1, true, true);
00224 }
00225
00226 void generateEnvironments(std::vector<CollisionObject*>& env, double env_scale, std::size_t n)
00227 {
00228 FCL_REAL extents[] = {-env_scale, env_scale, -env_scale, env_scale, -env_scale, env_scale};
00229 std::vector<Transform3f> transforms;
00230
00231 generateRandomTransforms(extents, transforms, n);
00232 for(std::size_t i = 0; i < n; ++i)
00233 {
00234 Box* box = new Box(5, 10, 20);
00235 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(box), transforms[i]));
00236 }
00237
00238 generateRandomTransforms(extents, transforms, n);
00239 for(std::size_t i = 0; i < n; ++i)
00240 {
00241 Sphere* sphere = new Sphere(30);
00242 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(sphere), transforms[i]));
00243 }
00244
00245 generateRandomTransforms(extents, transforms, n);
00246 for(std::size_t i = 0; i < n; ++i)
00247 {
00248 Cylinder* cylinder = new Cylinder(10, 40);
00249 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(cylinder), transforms[i]));
00250 }
00251 }
00252
00253 void generateEnvironmentsMesh(std::vector<CollisionObject*>& env, double env_scale, std::size_t n)
00254 {
00255 FCL_REAL extents[] = {-env_scale, env_scale, -env_scale, env_scale, -env_scale, env_scale};
00256 std::vector<Transform3f> transforms;
00257
00258 generateRandomTransforms(extents, transforms, n);
00259 Box box(5, 10, 20);
00260 for(std::size_t i = 0; i < n; ++i)
00261 {
00262 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00263 generateBVHModel(*model, box, Transform3f());
00264 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model), transforms[i]));
00265 }
00266
00267 generateRandomTransforms(extents, transforms, n);
00268 Sphere sphere(30);
00269 for(std::size_t i = 0; i < n; ++i)
00270 {
00271 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00272 generateBVHModel(*model, sphere, Transform3f(), 16, 16);
00273 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model), transforms[i]));
00274 }
00275
00276 generateRandomTransforms(extents, transforms, n);
00277 Cylinder cylinder(10, 40);
00278 for(std::size_t i = 0; i < n; ++i)
00279 {
00280 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00281 generateBVHModel(*model, cylinder, Transform3f(), 16, 16);
00282 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model), transforms[i]));
00283 }
00284 }
00285
00286 void generateSelfDistanceEnvironments(std::vector<CollisionObject*>& env, double env_scale, std::size_t n)
00287 {
00288 int n_edge = std::floor(std::pow(n, 1/3.0));
00289
00290 FCL_REAL step_size = env_scale * 2 / n_edge;
00291 FCL_REAL delta_size = step_size * 0.05;
00292 FCL_REAL single_size = step_size - 2 * delta_size;
00293
00294 std::size_t i = 0;
00295 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00296 {
00297 int x = i % (n_edge * n_edge);
00298 int y = (i - n_edge * n_edge * x) % n_edge;
00299 int z = i - n_edge * n_edge * x - n_edge * y;
00300
00301 Box* box = new Box(single_size, single_size, single_size);
00302 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(box),
00303 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00304 y * step_size + delta_size + 0.5 * single_size - env_scale,
00305 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00306 }
00307
00308 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00309 {
00310 int x = i % (n_edge * n_edge);
00311 int y = (i - n_edge * n_edge * x) % n_edge;
00312 int z = i - n_edge * n_edge * x - n_edge * y;
00313
00314 Sphere* sphere = new Sphere(single_size / 2);
00315 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(sphere),
00316 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00317 y * step_size + delta_size + 0.5 * single_size - env_scale,
00318 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00319 }
00320
00321 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00322 {
00323 int x = i % (n_edge * n_edge);
00324 int y = (i - n_edge * n_edge * x) % n_edge;
00325 int z = i - n_edge * n_edge * x - n_edge * y;
00326
00327 Cylinder* cylinder = new Cylinder(single_size / 2, single_size);
00328 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(cylinder),
00329 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00330 y * step_size + delta_size + 0.5 * single_size - env_scale,
00331 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00332 }
00333
00334 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00335 {
00336 int x = i % (n_edge * n_edge);
00337 int y = (i - n_edge * n_edge * x) % n_edge;
00338 int z = i - n_edge * n_edge * x - n_edge * y;
00339
00340 Cone* cone = new Cone(single_size / 2, single_size);
00341 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(cone),
00342 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00343 y * step_size + delta_size + 0.5 * single_size - env_scale,
00344 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00345 }
00346 }
00347
00348 void generateSelfDistanceEnvironmentsMesh(std::vector<CollisionObject*>& env, double env_scale, std::size_t n)
00349 {
00350 int n_edge = std::floor(std::pow(n, 1/3.0));
00351
00352 FCL_REAL step_size = env_scale * 2 / n_edge;
00353 FCL_REAL delta_size = step_size * 0.05;
00354 FCL_REAL single_size = step_size - 2 * delta_size;
00355
00356 std::size_t i = 0;
00357 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00358 {
00359 int x = i % (n_edge * n_edge);
00360 int y = (i - n_edge * n_edge * x) % n_edge;
00361 int z = i - n_edge * n_edge * x - n_edge * y;
00362
00363 Box box(single_size, single_size, single_size);
00364 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00365 generateBVHModel(*model, box, Transform3f());
00366 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model),
00367 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00368 y * step_size + delta_size + 0.5 * single_size - env_scale,
00369 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00370 }
00371
00372 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00373 {
00374 int x = i % (n_edge * n_edge);
00375 int y = (i - n_edge * n_edge * x) % n_edge;
00376 int z = i - n_edge * n_edge * x - n_edge * y;
00377
00378 Sphere sphere(single_size / 2);
00379 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00380 generateBVHModel(*model, sphere, Transform3f(), 16, 16);
00381 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model),
00382 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00383 y * step_size + delta_size + 0.5 * single_size - env_scale,
00384 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00385 }
00386
00387 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00388 {
00389 int x = i % (n_edge * n_edge);
00390 int y = (i - n_edge * n_edge * x) % n_edge;
00391 int z = i - n_edge * n_edge * x - n_edge * y;
00392
00393 Cylinder cylinder(single_size / 2, single_size);
00394 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00395 generateBVHModel(*model, cylinder, Transform3f(), 16, 16);
00396 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model),
00397 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00398 y * step_size + delta_size + 0.5 * single_size - env_scale,
00399 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00400 }
00401
00402 for(; i < n_edge * n_edge * n_edge / 4; ++i)
00403 {
00404 int x = i % (n_edge * n_edge);
00405 int y = (i - n_edge * n_edge * x) % n_edge;
00406 int z = i - n_edge * n_edge * x - n_edge * y;
00407
00408 Cone cone(single_size / 2, single_size);
00409 BVHModel<OBBRSS>* model = new BVHModel<OBBRSS>();
00410 generateBVHModel(*model, cone, Transform3f(), 16, 16);
00411 env.push_back(new CollisionObject(boost::shared_ptr<CollisionGeometry>(model),
00412 Transform3f(Vec3f(x * step_size + delta_size + 0.5 * single_size - env_scale,
00413 y * step_size + delta_size + 0.5 * single_size - env_scale,
00414 z * step_size + delta_size + 0.5 * single_size - env_scale))));
00415 }
00416 }
00417
00418
00419 void broad_phase_collision_test(double env_scale, std::size_t env_size, std::size_t query_size, std::size_t num_max_contacts, bool exhaustive, bool use_mesh)
00420 {
00421 std::vector<TStruct> ts;
00422 std::vector<Timer> timers;
00423
00424 std::vector<CollisionObject*> env;
00425 if(use_mesh)
00426 generateEnvironmentsMesh(env, env_scale, env_size);
00427 else
00428 generateEnvironments(env, env_scale, env_size);
00429
00430 std::vector<CollisionObject*> query;
00431 if(use_mesh)
00432 generateEnvironmentsMesh(query, env_scale, query_size);
00433 else
00434 generateEnvironments(query, env_scale, query_size);
00435
00436 std::vector<BroadPhaseCollisionManager*> managers;
00437
00438 managers.push_back(new NaiveCollisionManager());
00439 managers.push_back(new SSaPCollisionManager());
00440 managers.push_back(new SaPCollisionManager());
00441 managers.push_back(new IntervalTreeCollisionManager());
00442
00443 Vec3f lower_limit, upper_limit;
00444 SpatialHashingCollisionManager<>::computeBound(env, lower_limit, upper_limit);
00445
00446 FCL_REAL ncell_per_axis = 20;
00447 FCL_REAL cell_size = std::min(std::min((upper_limit[0] - lower_limit[0]) / ncell_per_axis, (upper_limit[1] - lower_limit[1]) / ncell_per_axis), (upper_limit[2] - lower_limit[2]) / ncell_per_axis);
00448
00449 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash> >(cell_size, lower_limit, upper_limit));
00450 #if USE_GOOGLEHASH
00451 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleSparseHashTable> >(cell_size, lower_limit, upper_limit));
00452 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleDenseHashTable> >(cell_size, lower_limit, upper_limit));
00453 #endif
00454 managers.push_back(new DynamicAABBTreeCollisionManager());
00455
00456 managers.push_back(new DynamicAABBTreeCollisionManager_Array());
00457
00458 {
00459 DynamicAABBTreeCollisionManager* m = new DynamicAABBTreeCollisionManager();
00460 m->tree_init_level = 2;
00461 managers.push_back(m);
00462 }
00463
00464 {
00465 DynamicAABBTreeCollisionManager_Array* m = new DynamicAABBTreeCollisionManager_Array();
00466 m->tree_init_level = 2;
00467 managers.push_back(m);
00468 }
00469
00470 ts.resize(managers.size());
00471 timers.resize(managers.size());
00472
00473 for(size_t i = 0; i < managers.size(); ++i)
00474 {
00475 timers[i].start();
00476 managers[i]->registerObjects(env);
00477 timers[i].stop();
00478 ts[i].push_back(timers[i].getElapsedTime());
00479 }
00480
00481 for(size_t i = 0; i < managers.size(); ++i)
00482 {
00483 timers[i].start();
00484 managers[i]->setup();
00485 timers[i].stop();
00486 ts[i].push_back(timers[i].getElapsedTime());
00487 }
00488
00489 std::vector<CollisionData> self_data(managers.size());
00490 for(size_t i = 0; i < managers.size(); ++i)
00491 {
00492 if(exhaustive) self_data[i].request.num_max_contacts = 100000;
00493 else self_data[i].request.num_max_contacts = num_max_contacts;
00494 }
00495
00496 for(size_t i = 0; i < managers.size(); ++i)
00497 {
00498 timers[i].start();
00499 managers[i]->collide(&self_data[i], defaultCollisionFunction);
00500 timers[i].stop();
00501 ts[i].push_back(timers[i].getElapsedTime());
00502 }
00503
00504 for(size_t i = 0; i < managers.size(); ++i)
00505 std::cout << self_data[i].result.numContacts() << " ";
00506 std::cout << std::endl;
00507
00508 if(exhaustive)
00509 {
00510 for(size_t i = 1; i < managers.size(); ++i)
00511 BOOST_CHECK(self_data[i].result.numContacts() == self_data[0].result.numContacts());
00512 }
00513 else
00514 {
00515 std::vector<bool> self_res(managers.size());
00516 for(size_t i = 0; i < self_res.size(); ++i)
00517 self_res[i] = (self_data[i].result.numContacts() > 0);
00518
00519 for(size_t i = 1; i < self_res.size(); ++i)
00520 BOOST_CHECK(self_res[0] == self_res[i]);
00521
00522 for(size_t i = 1; i < managers.size(); ++i)
00523 BOOST_CHECK(self_data[i].result.numContacts() == self_data[0].result.numContacts());
00524 }
00525
00526
00527 for(size_t i = 0; i < query.size(); ++i)
00528 {
00529 std::vector<CollisionData> query_data(managers.size());
00530 for(size_t j = 0; j < query_data.size(); ++j)
00531 {
00532 if(exhaustive) query_data[j].request.num_max_contacts = 100000;
00533 else query_data[j].request.num_max_contacts = num_max_contacts;
00534 }
00535
00536 for(size_t j = 0; j < query_data.size(); ++j)
00537 {
00538 timers[j].start();
00539 managers[j]->collide(query[i], &query_data[j], defaultCollisionFunction);
00540 timers[j].stop();
00541 ts[j].push_back(timers[j].getElapsedTime());
00542 }
00543
00544
00545
00546
00547
00548
00549 if(exhaustive)
00550 {
00551 for(size_t j = 1; j < managers.size(); ++j)
00552 BOOST_CHECK(query_data[j].result.numContacts() == query_data[0].result.numContacts());
00553 }
00554 else
00555 {
00556 std::vector<bool> query_res(managers.size());
00557 for(size_t j = 0; j < query_res.size(); ++j)
00558 query_res[j] = (query_data[j].result.numContacts() > 0);
00559 for(size_t j = 1; j < query_res.size(); ++j)
00560 BOOST_CHECK(query_res[0] == query_res[j]);
00561
00562 for(size_t j = 1; j < managers.size(); ++j)
00563 BOOST_CHECK(query_data[j].result.numContacts() == query_data[0].result.numContacts());
00564 }
00565 }
00566
00567 for(size_t i = 0; i < env.size(); ++i)
00568 delete env[i];
00569 for(size_t i = 0; i < query.size(); ++i)
00570 delete query[i];
00571
00572 for(size_t i = 0; i < managers.size(); ++i)
00573 delete managers[i];
00574
00575 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
00576 size_t w = 7;
00577
00578 std::cout << "collision timing summary" << std::endl;
00579 std::cout << env_size << " objs, " << query_size << " queries" << std::endl;
00580 std::cout << "register time" << std::endl;
00581 for(size_t i = 0; i < ts.size(); ++i)
00582 std::cout << std::setw(w) << ts[i].records[0] << " ";
00583 std::cout << std::endl;
00584
00585 std::cout << "setup time" << std::endl;
00586 for(size_t i = 0; i < ts.size(); ++i)
00587 std::cout << std::setw(w) << ts[i].records[1] << " ";
00588 std::cout << std::endl;
00589
00590 std::cout << "self collision time" << std::endl;
00591 for(size_t i = 0; i < ts.size(); ++i)
00592 std::cout << std::setw(w) << ts[i].records[2] << " ";
00593 std::cout << std::endl;
00594
00595 std::cout << "collision time" << std::endl;
00596 for(size_t i = 0; i < ts.size(); ++i)
00597 {
00598 FCL_REAL tmp = 0;
00599 for(size_t j = 3; j < ts[i].records.size(); ++j)
00600 tmp += ts[i].records[j];
00601 std::cout << std::setw(w) << tmp << " ";
00602 }
00603 std::cout << std::endl;
00604
00605
00606 std::cout << "overall time" << std::endl;
00607 for(size_t i = 0; i < ts.size(); ++i)
00608 std::cout << std::setw(w) << ts[i].overall_time << " ";
00609 std::cout << std::endl;
00610 std::cout << std::endl;
00611
00612 }
00613
00614 void broad_phase_self_distance_test(double env_scale, std::size_t env_size, bool use_mesh)
00615 {
00616 std::vector<TStruct> ts;
00617 std::vector<Timer> timers;
00618
00619 std::vector<CollisionObject*> env;
00620 if(use_mesh)
00621 generateSelfDistanceEnvironmentsMesh(env, env_scale, env_size);
00622 else
00623 generateSelfDistanceEnvironments(env, env_scale, env_size);
00624
00625 std::vector<BroadPhaseCollisionManager*> managers;
00626
00627 managers.push_back(new NaiveCollisionManager());
00628 managers.push_back(new SSaPCollisionManager());
00629 managers.push_back(new SaPCollisionManager());
00630 managers.push_back(new IntervalTreeCollisionManager());
00631
00632 Vec3f lower_limit, upper_limit;
00633 SpatialHashingCollisionManager<>::computeBound(env, lower_limit, upper_limit);
00634 FCL_REAL cell_size = std::min(std::min((upper_limit[0] - lower_limit[0]) / 5, (upper_limit[1] - lower_limit[1]) / 5), (upper_limit[2] - lower_limit[2]) / 5);
00635
00636 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash> >(cell_size, lower_limit, upper_limit));
00637 #if USE_GOOGLEHASH
00638 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleSparseHashTable> >(cell_size, lower_limit, upper_limit));
00639 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleDenseHashTable> >(cell_size, lower_limit, upper_limit));
00640 #endif
00641 managers.push_back(new DynamicAABBTreeCollisionManager());
00642 managers.push_back(new DynamicAABBTreeCollisionManager_Array());
00643
00644 {
00645 DynamicAABBTreeCollisionManager* m = new DynamicAABBTreeCollisionManager();
00646 m->tree_init_level = 2;
00647 managers.push_back(m);
00648 }
00649
00650 {
00651 DynamicAABBTreeCollisionManager_Array* m = new DynamicAABBTreeCollisionManager_Array();
00652 m->tree_init_level = 2;
00653 managers.push_back(m);
00654 }
00655
00656 ts.resize(managers.size());
00657 timers.resize(managers.size());
00658
00659 for(size_t i = 0; i < managers.size(); ++i)
00660 {
00661 timers[i].start();
00662 managers[i]->registerObjects(env);
00663 timers[i].stop();
00664 ts[i].push_back(timers[i].getElapsedTime());
00665 }
00666
00667 for(size_t i = 0; i < managers.size(); ++i)
00668 {
00669 timers[i].start();
00670 managers[i]->setup();
00671 timers[i].stop();
00672 ts[i].push_back(timers[i].getElapsedTime());
00673 }
00674
00675
00676 std::vector<DistanceData> self_data(managers.size());
00677
00678 for(size_t i = 0; i < self_data.size(); ++i)
00679 {
00680 timers[i].start();
00681 managers[i]->distance(&self_data[i], defaultDistanceFunction);
00682 timers[i].stop();
00683 ts[i].push_back(timers[i].getElapsedTime());
00684
00685 }
00686
00687
00688 for(size_t i = 1; i < managers.size(); ++i)
00689 BOOST_CHECK(fabs(self_data[0].result.min_distance - self_data[i].result.min_distance) < DELTA ||
00690 fabs(self_data[0].result.min_distance - self_data[i].result.min_distance) / fabs(self_data[0].result.min_distance) < DELTA);
00691
00692 for(size_t i = 0; i < env.size(); ++i)
00693 delete env[i];
00694
00695 for(size_t i = 0; i < managers.size(); ++i)
00696 delete managers[i];
00697
00698 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
00699 size_t w = 7;
00700
00701 std::cout << "self distance timing summary" << std::endl;
00702 std::cout << env.size() << " objs" << std::endl;
00703 std::cout << "register time" << std::endl;
00704 for(size_t i = 0; i < ts.size(); ++i)
00705 std::cout << std::setw(w) << ts[i].records[0] << " ";
00706 std::cout << std::endl;
00707
00708 std::cout << "setup time" << std::endl;
00709 for(size_t i = 0; i < ts.size(); ++i)
00710 std::cout << std::setw(w) << ts[i].records[1] << " ";
00711 std::cout << std::endl;
00712
00713 std::cout << "self distance time" << std::endl;
00714 for(size_t i = 0; i < ts.size(); ++i)
00715 std::cout << std::setw(w) << ts[i].records[2] << " ";
00716 std::cout << std::endl;
00717
00718 std::cout << "overall time" << std::endl;
00719 for(size_t i = 0; i < ts.size(); ++i)
00720 std::cout << std::setw(w) << ts[i].overall_time << " ";
00721 std::cout << std::endl;
00722 std::cout << std::endl;
00723 }
00724
00725
00726 void broad_phase_distance_test(double env_scale, std::size_t env_size, std::size_t query_size, bool use_mesh)
00727 {
00728 std::vector<TStruct> ts;
00729 std::vector<Timer> timers;
00730
00731 std::vector<CollisionObject*> env;
00732 if(use_mesh)
00733 generateEnvironmentsMesh(env, env_scale, env_size);
00734 else
00735 generateEnvironments(env, env_scale, env_size);
00736
00737 std::vector<CollisionObject*> query;
00738
00739 BroadPhaseCollisionManager* manager = new NaiveCollisionManager();
00740 for(std::size_t i = 0; i < env.size(); ++i)
00741 manager->registerObject(env[i]);
00742 manager->setup();
00743
00744 while(1)
00745 {
00746 std::vector<CollisionObject*> candidates;
00747 if(use_mesh)
00748 generateEnvironmentsMesh(candidates, env_scale, query_size);
00749 else
00750 generateEnvironments(candidates, env_scale, query_size);
00751
00752 for(std::size_t i = 0; i < candidates.size(); ++i)
00753 {
00754 CollisionData query_data;
00755 manager->collide(candidates[i], &query_data, defaultCollisionFunction);
00756 if(query_data.result.numContacts() == 0)
00757 query.push_back(candidates[i]);
00758 else
00759 delete candidates[i];
00760 if(query.size() == query_size) break;
00761 }
00762
00763 if(query.size() == query_size) break;
00764 }
00765
00766 delete manager;
00767
00768 std::vector<BroadPhaseCollisionManager*> managers;
00769
00770 managers.push_back(new NaiveCollisionManager());
00771 managers.push_back(new SSaPCollisionManager());
00772 managers.push_back(new SaPCollisionManager());
00773 managers.push_back(new IntervalTreeCollisionManager());
00774
00775 Vec3f lower_limit, upper_limit;
00776 SpatialHashingCollisionManager<>::computeBound(env, lower_limit, upper_limit);
00777 FCL_REAL 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);
00778
00779 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash> >(cell_size, lower_limit, upper_limit));
00780 #if USE_GOOGLEHASH
00781 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleSparseHashTable> >(cell_size, lower_limit, upper_limit));
00782 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleDenseHashTable> >(cell_size, lower_limit, upper_limit));
00783 #endif
00784 managers.push_back(new DynamicAABBTreeCollisionManager());
00785 managers.push_back(new DynamicAABBTreeCollisionManager_Array());
00786
00787 {
00788 DynamicAABBTreeCollisionManager* m = new DynamicAABBTreeCollisionManager();
00789 m->tree_init_level = 2;
00790 managers.push_back(m);
00791 }
00792
00793 {
00794 DynamicAABBTreeCollisionManager_Array* m = new DynamicAABBTreeCollisionManager_Array();
00795 m->tree_init_level = 2;
00796 managers.push_back(m);
00797 }
00798
00799 ts.resize(managers.size());
00800 timers.resize(managers.size());
00801
00802 for(size_t i = 0; i < managers.size(); ++i)
00803 {
00804 timers[i].start();
00805 managers[i]->registerObjects(env);
00806 timers[i].stop();
00807 ts[i].push_back(timers[i].getElapsedTime());
00808 }
00809
00810 for(size_t i = 0; i < managers.size(); ++i)
00811 {
00812 timers[i].start();
00813 managers[i]->setup();
00814 timers[i].stop();
00815 ts[i].push_back(timers[i].getElapsedTime());
00816 }
00817
00818
00819 for(size_t i = 0; i < query.size(); ++i)
00820 {
00821 std::vector<DistanceData> query_data(managers.size());
00822 for(size_t j = 0; j < managers.size(); ++j)
00823 {
00824 timers[j].start();
00825 managers[j]->distance(query[i], &query_data[j], defaultDistanceFunction);
00826 timers[j].stop();
00827 ts[j].push_back(timers[j].getElapsedTime());
00828
00829 }
00830
00831
00832 for(size_t j = 1; j < managers.size(); ++j)
00833 BOOST_CHECK(fabs(query_data[0].result.min_distance - query_data[j].result.min_distance) < DELTA ||
00834 fabs(query_data[0].result.min_distance - query_data[j].result.min_distance) / fabs(query_data[0].result.min_distance) < DELTA);
00835 }
00836
00837
00838 for(std::size_t i = 0; i < env.size(); ++i)
00839 delete env[i];
00840 for(std::size_t i = 0; i < query.size(); ++i)
00841 delete query[i];
00842
00843 for(size_t i = 0; i < managers.size(); ++i)
00844 delete managers[i];
00845
00846
00847 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
00848 size_t w = 7;
00849
00850 std::cout << "distance timing summary" << std::endl;
00851 std::cout << env_size << " objs, " << query_size << " queries" << std::endl;
00852 std::cout << "register time" << std::endl;
00853 for(size_t i = 0; i < ts.size(); ++i)
00854 std::cout << std::setw(w) << ts[i].records[0] << " ";
00855 std::cout << std::endl;
00856
00857 std::cout << "setup time" << std::endl;
00858 for(size_t i = 0; i < ts.size(); ++i)
00859 std::cout << std::setw(w) << ts[i].records[1] << " ";
00860 std::cout << std::endl;
00861
00862 std::cout << "distance time" << std::endl;
00863 for(size_t i = 0; i < ts.size(); ++i)
00864 {
00865 FCL_REAL tmp = 0;
00866 for(size_t j = 2; j < ts[i].records.size(); ++j)
00867 tmp += ts[i].records[j];
00868 std::cout << std::setw(w) << tmp << " ";
00869 }
00870 std::cout << std::endl;
00871
00872 std::cout << "overall time" << std::endl;
00873 for(size_t i = 0; i < ts.size(); ++i)
00874 std::cout << std::setw(w) << ts[i].overall_time << " ";
00875 std::cout << std::endl;
00876 std::cout << std::endl;
00877 }
00878
00879
00880 void broad_phase_update_collision_test(double env_scale, std::size_t env_size, std::size_t query_size, std::size_t num_max_contacts, bool exhaustive, bool use_mesh)
00881 {
00882 std::vector<TStruct> ts;
00883 std::vector<Timer> timers;
00884
00885 std::vector<CollisionObject*> env;
00886 if(use_mesh)
00887 generateEnvironmentsMesh(env, env_scale, env_size);
00888 else
00889 generateEnvironments(env, env_scale, env_size);
00890
00891 std::vector<CollisionObject*> query;
00892 if(use_mesh)
00893 generateEnvironmentsMesh(query, env_scale, query_size);
00894 else
00895 generateEnvironments(query, env_scale, query_size);
00896
00897 std::vector<BroadPhaseCollisionManager*> managers;
00898
00899 managers.push_back(new NaiveCollisionManager());
00900 managers.push_back(new SSaPCollisionManager());
00901
00902
00903 managers.push_back(new SaPCollisionManager());
00904 managers.push_back(new IntervalTreeCollisionManager());
00905
00906 Vec3f lower_limit, upper_limit;
00907 SpatialHashingCollisionManager<>::computeBound(env, lower_limit, upper_limit);
00908 FCL_REAL 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);
00909
00910 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash> >(cell_size, lower_limit, upper_limit));
00911 #if USE_GOOGLEHASH
00912 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleSparseHashTable> >(cell_size, lower_limit, upper_limit));
00913 managers.push_back(new SpatialHashingCollisionManager<SparseHashTable<AABB, CollisionObject*, SpatialHash, GoogleDenseHashTable> >(cell_size, lower_limit, upper_limit));
00914 #endif
00915 managers.push_back(new DynamicAABBTreeCollisionManager());
00916 managers.push_back(new DynamicAABBTreeCollisionManager_Array());
00917
00918 {
00919 DynamicAABBTreeCollisionManager* m = new DynamicAABBTreeCollisionManager();
00920 m->tree_init_level = 2;
00921 managers.push_back(m);
00922 }
00923
00924 {
00925 DynamicAABBTreeCollisionManager_Array* m = new DynamicAABBTreeCollisionManager_Array();
00926 m->tree_init_level = 2;
00927 managers.push_back(m);
00928 }
00929
00930 ts.resize(managers.size());
00931 timers.resize(managers.size());
00932
00933 for(size_t i = 0; i < managers.size(); ++i)
00934 {
00935 timers[i].start();
00936 managers[i]->registerObjects(env);
00937 timers[i].stop();
00938 ts[i].push_back(timers[i].getElapsedTime());
00939 }
00940
00941 for(size_t i = 0; i < managers.size(); ++i)
00942 {
00943 timers[i].start();
00944 managers[i]->setup();
00945 timers[i].stop();
00946 ts[i].push_back(timers[i].getElapsedTime());
00947 }
00948
00949
00950 FCL_REAL delta_angle_max = 10 / 360.0 * 2 * boost::math::constants::pi<FCL_REAL>();
00951 FCL_REAL delta_trans_max = 0.01 * env_scale;
00952 for(size_t i = 0; i < env.size(); ++i)
00953 {
00954 FCL_REAL rand_angle_x = 2 * (rand() / (FCL_REAL)RAND_MAX - 0.5) * delta_angle_max;
00955 FCL_REAL rand_trans_x = 2 * (rand() / (FCL_REAL)RAND_MAX - 0.5) * delta_trans_max;
00956 FCL_REAL rand_angle_y = 2 * (rand() / (FCL_REAL)RAND_MAX - 0.5) * delta_angle_max;
00957 FCL_REAL rand_trans_y = 2 * (rand() / (FCL_REAL)RAND_MAX - 0.5) * delta_trans_max;
00958 FCL_REAL rand_angle_z = 2 * (rand() / (FCL_REAL)RAND_MAX - 0.5) * delta_angle_max;
00959 FCL_REAL rand_trans_z = 2 * (rand() / (FCL_REAL)RAND_MAX - 0.5) * delta_trans_max;
00960
00961 Quaternion3f q1, q2, q3;
00962 q1.fromAxisAngle(Vec3f(1, 0, 0), rand_angle_x);
00963 q2.fromAxisAngle(Vec3f(0, 1, 0), rand_angle_y);
00964 q3.fromAxisAngle(Vec3f(0, 0, 1), rand_angle_z);
00965 Quaternion3f q = q1 * q2 * q3;
00966 Matrix3f dR;
00967 q.toRotation(dR);
00968 Vec3f dT(rand_trans_x, rand_trans_y, rand_trans_z);
00969
00970 Matrix3f R = env[i]->getRotation();
00971 Vec3f T = env[i]->getTranslation();
00972 env[i]->setTransform(dR * R, dR * T + dT);
00973 env[i]->computeAABB();
00974 }
00975
00976 for(size_t i = 0; i < managers.size(); ++i)
00977 {
00978 timers[i].start();
00979 managers[i]->update();
00980 timers[i].stop();
00981 ts[i].push_back(timers[i].getElapsedTime());
00982 }
00983
00984 std::vector<CollisionData> self_data(managers.size());
00985 for(size_t i = 0; i < managers.size(); ++i)
00986 {
00987 if(exhaustive) self_data[i].request.num_max_contacts = 100000;
00988 else self_data[i].request.num_max_contacts = num_max_contacts;
00989 }
00990
00991 for(size_t i = 0; i < managers.size(); ++i)
00992 {
00993 timers[i].start();
00994 managers[i]->collide(&self_data[i], defaultCollisionFunction);
00995 timers[i].stop();
00996 ts[i].push_back(timers[i].getElapsedTime());
00997 }
00998
00999
01000 for(size_t i = 0; i < managers.size(); ++i)
01001 std::cout << self_data[i].result.numContacts() << " ";
01002 std::cout << std::endl;
01003
01004 if(exhaustive)
01005 {
01006 for(size_t i = 1; i < managers.size(); ++i)
01007 BOOST_CHECK(self_data[i].result.numContacts() == self_data[0].result.numContacts());
01008 }
01009 else
01010 {
01011 std::vector<bool> self_res(managers.size());
01012 for(size_t i = 0; i < self_res.size(); ++i)
01013 self_res[i] = (self_data[i].result.numContacts() > 0);
01014
01015 for(size_t i = 1; i < self_res.size(); ++i)
01016 BOOST_CHECK(self_res[0] == self_res[i]);
01017
01018 for(size_t i = 1; i < managers.size(); ++i)
01019 BOOST_CHECK(self_data[i].result.numContacts() == self_data[0].result.numContacts());
01020 }
01021
01022
01023 for(size_t i = 0; i < query.size(); ++i)
01024 {
01025 std::vector<CollisionData> query_data(managers.size());
01026 for(size_t j = 0; j < query_data.size(); ++j)
01027 {
01028 if(exhaustive) query_data[j].request.num_max_contacts = 100000;
01029 else query_data[j].request.num_max_contacts = num_max_contacts;
01030 }
01031
01032 for(size_t j = 0; j < query_data.size(); ++j)
01033 {
01034 timers[j].start();
01035 managers[j]->collide(query[i], &query_data[j], defaultCollisionFunction);
01036 timers[j].stop();
01037 ts[j].push_back(timers[j].getElapsedTime());
01038 }
01039
01040
01041
01042
01043
01044
01045 if(exhaustive)
01046 {
01047 for(size_t j = 1; j < managers.size(); ++j)
01048 BOOST_CHECK(query_data[j].result.numContacts() == query_data[0].result.numContacts());
01049 }
01050 else
01051 {
01052 std::vector<bool> query_res(managers.size());
01053 for(size_t j = 0; j < query_res.size(); ++j)
01054 query_res[j] = (query_data[j].result.numContacts() > 0);
01055 for(size_t j = 1; j < query_res.size(); ++j)
01056 BOOST_CHECK(query_res[0] == query_res[j]);
01057
01058 for(size_t j = 1; j < managers.size(); ++j)
01059 BOOST_CHECK(query_data[j].result.numContacts() == query_data[0].result.numContacts());
01060 }
01061 }
01062
01063
01064 for(size_t i = 0; i < env.size(); ++i)
01065 delete env[i];
01066 for(size_t i = 0; i < query.size(); ++i)
01067 delete query[i];
01068
01069 for(size_t i = 0; i < managers.size(); ++i)
01070 delete managers[i];
01071
01072
01073 std::cout.setf(std::ios_base::left, std::ios_base::adjustfield);
01074 size_t w = 7;
01075
01076 std::cout << "collision timing summary" << std::endl;
01077 std::cout << env_size << " objs, " << query_size << " queries" << std::endl;
01078 std::cout << "register time" << std::endl;
01079 for(size_t i = 0; i < ts.size(); ++i)
01080 std::cout << std::setw(w) << ts[i].records[0] << " ";
01081 std::cout << std::endl;
01082
01083 std::cout << "setup time" << std::endl;
01084 for(size_t i = 0; i < ts.size(); ++i)
01085 std::cout << std::setw(w) << ts[i].records[1] << " ";
01086 std::cout << std::endl;
01087
01088 std::cout << "update time" << std::endl;
01089 for(size_t i = 0; i < ts.size(); ++i)
01090 std::cout << std::setw(w) << ts[i].records[2] << " ";
01091 std::cout << std::endl;
01092
01093 std::cout << "self collision time" << std::endl;
01094 for(size_t i = 0; i < ts.size(); ++i)
01095 std::cout << std::setw(w) << ts[i].records[3] << " ";
01096 std::cout << std::endl;
01097
01098 std::cout << "collision time" << std::endl;
01099 for(size_t i = 0; i < ts.size(); ++i)
01100 {
01101 FCL_REAL tmp = 0;
01102 for(size_t j = 4; j < ts[i].records.size(); ++j)
01103 tmp += ts[i].records[j];
01104 std::cout << std::setw(w) << tmp << " ";
01105 }
01106 std::cout << std::endl;
01107
01108
01109 std::cout << "overall time" << std::endl;
01110 for(size_t i = 0; i < ts.size(); ++i)
01111 std::cout << std::setw(w) << ts[i].overall_time << " ";
01112 std::cout << std::endl;
01113 std::cout << std::endl;
01114 }
01115
01116
01117