Collision Checker
broadphase_test.cc
Go to the documentation of this file.
2 #if ENABLE_COLLISION_TESTS
6 
8 
10 
12 
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 
23 
24 namespace collision {
25 namespace test {
26 // tests collision checker broadphase algorithms
27 // all narrowphase checks are assumed to be done with FCL solver
28 
29 bool CollisionCheckerTest::test_collide(CollisionObjectConstPtr co,
30  const CollisionChecker *cc) {
31  // int col_time;
32  bool res_collision_checker = cc->collide(co, 0, false);
33 
34  std::vector<collision::CollisionObjectConstPtr> obstacles =
35  cc->getObstacles();
36 
37  bool res_bruteforce = false;
38 
39  for (auto &obstacle : obstacles) {
40  if (obstacle->collide(*(co.get()), CollisionRequest(COL_FCL))) {
41  res_bruteforce = true;
42  break;
43  }
44  }
45  if (res_collision_checker != res_bruteforce) {
46  return false;
47  } else {
48  return true;
49  }
50 }
51 
52 bool CollisionCheckerTest::test_collide_obstacle(CollisionObjectConstPtr co,
53  const CollisionChecker *cc) {
55  new collision::RectangleAABB(0, 0, Eigen::Vector2d(0, 0)));
56 
57  CollisionObjectConstPtr obst_cc = rect1;
58  bool res_cc = cc->collide(co, obst_cc, false, false, false);
59 
60  CollisionObjectConstPtr obst_primit = rect1;
61  bool res_primitive = false;
62  for (auto &c : cc->collision_objects_) {
63  if (c->collide(*co, CollisionRequest(COL_FCL))) {
64  obst_primit = c;
65  res_primitive = true;
66  break;
67  }
68  }
69 
70  if (res_cc != res_primitive) {
71  return false;
72  } else {
73  return true;
74  }
75 }
76 
77 bool ShapeGroupTest::cmp(const std::pair<int, int> &pair1,
78  const std::pair<int, int> &pair2) {
79  if (pair1.first != pair2.first) {
80  return pair1.first < pair2.first;
81  }
82  return pair1.second > pair2.second;
83  return false;
84 }
85 
86 bool CollisionCheckerTest::cmp(const CollisionObjectConstPtr &a,
87  const CollisionObjectConstPtr &b) {
88  return (a.get() < b.get());
89 }
90 
91 bool CollisionCheckerTest::test_narrowphase(CollisionObjectConstPtr co,
92  const CollisionChecker *cc,
93  std::vector<int> *failure_export)
94 
95 {
96  if (!co.get()) return false;
97  // const FCLCollisionObject* co_fcl = get_fcl_object_ptr(co.get());
98  // if (!co_fcl) return false;
99 
100  std::vector<collision::CollisionObjectConstPtr> children = cc->getObstacles();
101  int counter = 0;
102  bool res = true;
103  for (auto &el : children) {
104  bool res_fcl = el->collide(*(co.get()), CollisionRequest(COL_FCL));
105  // bool res_prim = el->collide(*(co.get()),
106  // CollisionRequest(COL_PRIMITIVE));
107  bool res_def = el->collide(*(co.get()), CollisionRequest(COL_DEFAULT));
108  // bool res_local = (res_fcl==res_prim && res_prim==res_def &&
109  // res_def==res_fcl) ;
110  bool res_local = (res_def == res_fcl);
111  res = res_local && res;
112  if (!res_local) {
113  if (failure_export) failure_export->push_back(counter);
114  }
115 
116  counter++;
117  }
118  return res;
119 }
120 
121 bool CollisionCheckerTest::test_collide_obstacles(
122  CollisionObjectConstPtr co, const CollisionChecker *cc,
123  std::vector<CollisionObjectConstPtr> &missed_obstacles,
124  std::vector<CollisionObjectConstPtr> &missed_obstacles_primit) {
125 #if ENABLE_SERIALIZER_TESTS
126  if (serialize_broadphase_failure_test(cc, co.get())) {
127  std::cout << "serialization CC_OBJ failed";
128  }
129 #endif
130  std::vector<int> failure_export;
131 #if ENABLE_COLLISION_TESTS_NARROWPHASE
132  if (!test_narrowphase(co, cc, &failure_export)) {
133  std::vector<int> failure_export2;
134  test_narrowphase(co, cc, &failure_export2);
135  test::serialize_narrowphase_failure(co, cc, failure_export);
136  }
137 #endif
138 label1:
139  std::vector<CollisionObjectConstPtr> obstacles_cc;
140  // fcl_cc.collideHelper(co,0,&obstacles, -1, false, false);
141  bool res_cc = cc->collide(co, obstacles_cc, false, false, false);
142  /*if (obstacles_cc.size()) // simulates a broadphase failure
143  {
144  for (auto iter= obstacles_cc.begin(); iter<obstacles_cc.end(); iter++)
145  {
146  if ((*iter)->getCollisionObjectClass() ==
147  collision::OBJ_CLASS_SHAPE)
148  {
149  obstacles_cc.erase(iter);
150  break;
151  }
152  }
153 
154  }
155  */
156  std::vector<CollisionObjectConstPtr> obstacles_primit;
157  bool res_primitive = false;
158  for (auto &c : cc->collision_objects_) {
159  if (c->collide(*co, CollisionRequest(COL_FCL))) {
160  obstacles_primit.push_back(c);
161  res_primitive = true;
162  }
163  }
164 
165  std::unordered_map<const CollisionObject *, bool> obstacles_cc_map;
166  for (auto &c : obstacles_cc) {
167  obstacles_cc_map.emplace(c.get(), true);
168  }
169 
170  std::unordered_map<const CollisionObject *, bool> obstacles_primit_map;
171  for (auto &c : obstacles_primit) {
172  obstacles_primit_map.emplace(c.get(), true);
173  }
174 
175  if ((res_cc == false) && (res_primitive == false)) {
176  if ((obstacles_cc.size() == 0) && (obstacles_primit.size() == 0)) {
177  return true;
178  }
179  } else {
180  for (auto &c : obstacles_primit) {
181  if (obstacles_cc_map.find(c.get()) == obstacles_cc_map.end()) {
182  missed_obstacles.push_back(c);
183  }
184  }
185  for (auto &c : obstacles_cc) {
186  if (obstacles_primit_map.find(c.get()) == obstacles_primit_map.end()) {
187  missed_obstacles_primit.push_back(c);
188  }
189  }
190 
191  if (res_cc == res_primitive) {
192  if ((obstacles_cc.size() == obstacles_primit.size())) {
193  std::sort(obstacles_cc.begin(), obstacles_cc.end(), cmp);
194  std::sort(obstacles_primit.begin(), obstacles_primit.end(), cmp);
195 
196  if (obstacles_cc == obstacles_primit) {
197  return true;
198  } else
199  return false;
200 
201  } else {
202  std::sort(obstacles_cc.begin(), obstacles_cc.end(), cmp);
203  std::sort(obstacles_primit.begin(), obstacles_primit.end(), cmp);
204  }
205  }
206  }
207 
208  return false;
209 }
210 
211 // tests ShapeGroup broadphase algorithms
212 // all narowphase checks are supposed to be done with FCL solver
213 
214 bool ShapeGroupTest::test_collide(CollisionObjectConstPtr co,
215  const ShapeGroup *sg) {
216  bool res_sg = false;
217  const FCLCollisionObjectGroup *sg_fcl = get_fcl_object_group_ptr(sg);
218  const FCLCollisionObject *co_fcl = get_fcl_object_ptr(co.get());
219  if (!sg_fcl || !co_fcl) return false;
220 
222  *sg_fcl, *co_fcl, false);
223 
224  std::vector<collision::ShapeConstPtr> obstacles = sg->shapes_;
225 
226  bool res_bruteforce = false;
227 
228  for (auto &obstacle : obstacles) {
229  if (obstacle->collide(*(co.get()), CollisionRequest(COL_FCL))) {
230  res_bruteforce = true;
231  break;
232  }
233  }
234  if (res_bruteforce != res_sg) {
235  int cont = 1;
236  }
237  return res_bruteforce == res_sg;
238 }
239 bool ShapeGroupTest::test_collide(const ShapeGroup *sg1,
240  const ShapeGroup *sg2) {
241  bool res_sg = false;
242  const FCLCollisionObjectGroup *sg1_fcl = get_fcl_object_group_ptr(sg1);
243  const FCLCollisionObjectGroup *sg2_fcl = get_fcl_object_group_ptr(sg2);
244  if (!sg1_fcl || !sg2_fcl) return false;
245 
247  *sg1_fcl, *sg2_fcl, false);
248 
249  std::vector<collision::ShapeConstPtr> obstacles1 = sg1->unpack();
250  std::vector<collision::ShapeConstPtr> obstacles2 = sg2->unpack();
251 
252  bool res_bruteforce = false;
253 
254  std::vector<std::pair<int, int>> overlap_res = sg1->overlap(*sg2);
255  bool res2 = false;
256  for (auto &res1 : overlap_res) {
257  if (obstacles1[res1.first]->collide(*obstacles2[res1.second])) {
258  res2 = true;
259  }
260  }
261  for (auto obstacle1 : obstacles1) {
262  for (auto obstacle2 : obstacles2) {
263  if (obstacle1->collide(*obstacle2, CollisionRequest(COL_FCL))) {
264  res_bruteforce = true;
265  break;
266  }
267  }
268  }
269  return res_bruteforce == res_sg;
270 }
271 
272 bool ShapeGroupTest::test_narrowphase(
273  const ShapeGroup *sg1, const ShapeGroup *sg2,
274  std::vector<std::pair<int, int>> *failure_pair_export)
275 
276 {
277  std::vector<collision::ShapeConstPtr> obstacles1 = sg1->shapes_;
278  int counter1 = 0;
279  std::vector<int> failure_export;
280  bool res = true;
281  for (auto &obstacle : obstacles1) {
282  failure_export.clear();
283  res = test_narrowphase(obstacle, sg2, &failure_export) && res;
284  for (auto el : failure_export) {
285  if (failure_pair_export) failure_pair_export->emplace_back(counter1, el);
286  }
287  counter1++;
288  }
289  return res;
290 }
291 
292 bool ShapeGroupTest::test_narrowphase(CollisionObjectConstPtr co,
293  const ShapeGroup *sg,
294  std::vector<int> *failure_export)
295 
296 {
297  const FCLCollisionObject *co_fcl = get_fcl_object_ptr(co.get());
298  if (!co_fcl) return false;
299 
300  std::vector<collision::ShapeConstPtr> shapes = sg->shapes_;
301  int counter = 0;
302  bool res = true;
303  for (auto &shape : shapes) {
304  if (shape->type() == TYPE_POLYGON) {
305  collision::ShapeGroup triangles_sg;
306  const collision::Polygon *shape_polyg =
307  static_cast<const collision::Polygon *>(shape.get());
308  std::vector<TriangleConstPtr> triangles = shape_polyg->getTriangleMesh();
309  for (auto &tri : triangles) {
310  triangles_sg.addToGroup(tri);
311  }
312  bool res_local = ShapeGroupTest::test_narrowphase(co, &triangles_sg, 0);
313  res = res_local && res;
314  if (!res_local) {
315  if (failure_export) failure_export->push_back(counter);
316  }
317 
318  } else {
319  // bool res_local = shape->collide(*(co.get()), CollisionRequest(COL_FCL))
320  // == shape->collide(*(co.get()), CollisionRequest(COL_PRIMITIVE));
321  bool res_local =
322  shape->collide(*(co.get()), CollisionRequest(COL_FCL)) ==
323  shape->collide(*(co.get()), CollisionRequest(COL_DEFAULT));
324  res = res_local && res;
325  if (!res_local) {
326  if (failure_export) failure_export->push_back(counter);
327  }
328  }
329  counter++;
330  }
331  return res;
332 }
333 
335  const CollisionChecker *cc) {
336  bool res = test_collide(co, cc);
337  if (!res) {
338  log_broadphase_failure(co, cc);
339  }
340  return res;
341 }
342 
344  CollisionObjectConstPtr co, const CollisionChecker *cc) {
345  bool res = test_collide_obstacle(co, cc);
346  if (!res) {
347  log_broadphase_failure(co, cc);
348  }
349  return res;
350 }
351 
353  CollisionObjectConstPtr co, const CollisionChecker *cc) {
354  if (0 && serialize_broadphase_failure_test(cc, co.get())) {
355  std::cout << "serialization CC obj failed";
356  }
357  std::vector<CollisionObjectConstPtr> missed_obstacles;
358  std::vector<CollisionObjectConstPtr> missed_obstacles_primit;
359  bool res =
360  test_collide_obstacles(co, cc, missed_obstacles, missed_obstacles_primit);
361  if (!res) {
362  // log_broadphase_failure(co, cc);
363  CollisionChecker cc2;
364  for (auto &obst : missed_obstacles) {
365  // bool naive_collide = obst->collide(*co,
366  // CollisionRequest(COL_PRIMITIVE));
367  bool naive_collide = obst->collide(*co, CollisionRequest(COL_DEFAULT));
368  bool non_naive_collide = obst->collide(*co, CollisionRequest(COL_FCL));
369  cc2.addCollisionObject(obst);
370  }
371  for (auto &obst : missed_obstacles_primit) {
372  // bool naive_collide = obst->collide(*co,
373  // CollisionRequest(COL_PRIMITIVE));
374  bool naive_collide = obst->collide(*co, CollisionRequest(COL_DEFAULT));
375  bool non_naive_collide = obst->collide(*co, CollisionRequest(COL_FCL));
376  std::cout << "narrowphase internal failure";
377  }
378  bool tolerance_result = test_tolerance_check(co, &cc2);
379  std::vector<CollisionObjectConstPtr> new_obstacles;
380  if (tolerance_result) {
381  test_tolerance_check(co, &cc2);
382  cc->collide(co, new_obstacles, false, false, false);
383  cc->collide(co);
384  log_broadphase_failure(co, cc);
385  }
386  for (auto &obst : missed_obstacles) {
387  for (auto &obst2 : new_obstacles) {
388  if (obst == obst2) {
389  std::cout << "found";
390  }
391  }
392  }
393  }
394  return res;
395 }
396 
397 int ToleranceCheck(CollisionObjectConstPtr obj1, CollisionObjectConstPtr obj2,
398  bool &tolerance_result, double &distance,
399  bool narrowphase = false) {
400  DistanceRequest req;
401  DistanceResult res;
402  req.dist_request_type = DistanceRequestType::DRT_TOLERANCE_NEG;
403 #if TOLERANCE_BBONLY
404  req.dist_node_type = DistanceNodeType::DNT_AABB;
405 #else
406  req.dist_node_type = DistanceNodeType::DNT_NARROWPHASE;
407 #endif
408  if (narrowphase) {
409  req.dist_node_type = DistanceNodeType::DNT_NARROWPHASE;
410  }
411  if (collision::distance(*obj1, *obj2, res, req) >= 0) {
412  tolerance_result = res.getTolerancePassed();
413  return 0;
414  } else {
415  tolerance_result = false;
416  return -1;
417  }
418 }
419 
421  const ShapeGroup *sg1, const ShapeGroup *sg2,
422  std::vector<std::pair<int, int>> *missed_col_naive_out) {
423  std::vector<std::pair<int, int>> res = sg1->overlap(*sg2);
424  std::vector<collision::ShapeConstPtr> obstacles1 = sg1->unpack();
425  std::vector<collision::ShapeConstPtr> obstacles2 = sg2->unpack();
426 
427  std::vector<std::pair<int, int>> overlap_res = sg1->overlap(*sg2);
428  std::vector<std::pair<int, int>> overlap_res2;
429  bool res2 = false;
430  for (int cc1 = 0; cc1 < obstacles1.size(); cc1++) {
431  for (int cc2 = 0; cc2 < obstacles2.size(); cc2++) {
432  if (obstacles1[cc1]->collide(*obstacles2[cc2],
433  CollisionRequest(COL_FCL))) {
434  overlap_res2.emplace_back(cc1, cc2);
435  }
436  }
437  }
438  /*
439  if (overlap_res.size()) // simulates a broadphase failure
440  {
441  for (auto iter= overlap_res.begin(); iter<overlap_res.end(); iter++)
442  {
443 
444  overlap_res.erase(iter);
445  break;
446  }
447 
448  }
449  */
450 
451  // test function returning ordered list of pairs
452 
453  std::sort(overlap_res.begin(), overlap_res.end(), cmp);
454  std::sort(overlap_res2.begin(), overlap_res2.end(), cmp);
455  std::vector<std::pair<int, int>> missed_col;
456 
457  bool local_failure1 = !(overlap_res == overlap_res2);
458  if (local_failure1) {
459  local_failure1 = false;
460  std::map<std::pair<int, int>, bool> overlap_res_hash;
461  for (auto res1 : overlap_res) {
462  overlap_res_hash.emplace(res1, true);
463  }
464  for (auto res2 : overlap_res2) {
465  if (overlap_res_hash.find(res2) == overlap_res_hash.end()) {
466  missed_col.push_back(res2);
467  }
468  }
469  for (auto miss : missed_col) {
470  bool tolerance_result = false;
471  double distance;
472  int tol_res =
473  ToleranceCheck(obstacles1[miss.first], obstacles2[miss.second],
474  tolerance_result, distance);
475 
476  if (!tolerance_result) {
477  local_failure1 = true;
478  break;
479  }
480  }
481  }
482 
483  if (overlap_res.size() + missed_col.size() >
484  overlap_res2.size()) // if returned extra pairs
485  {
486  std::map<std::pair<int, int>, bool> overlap_res2_hash;
487  for (auto res2 : overlap_res2) {
488  overlap_res2_hash.emplace(res2, true);
489  }
490  std::vector<std::pair<int, int>> missed_col_naive;
491  for (auto res : overlap_res) {
492  if (overlap_res2_hash.find(res) == overlap_res2_hash.end()) {
493  missed_col_naive.push_back(res);
494  }
495  }
496 
497  for (auto miss : missed_col_naive) {
498  bool tolerance_result = false;
499  bool tolerance_result2 = false;
500  double distance;
501  int tol_res =
502  ToleranceCheck(obstacles1[miss.first], obstacles2[miss.second],
503  tolerance_result, distance);
504  if (!tolerance_result) {
505  local_failure1 = true;
506  break;
507  }
508  }
509 
510  if (missed_col_naive_out) {
511  *missed_col_naive_out = missed_col_naive;
512  }
513  // local_failure1 = true;
514  }
515  // test that after hashmapping no new collisions are listed
516 
517  if (local_failure1) return false;
518 
519  std::map<std::pair<int, int>, bool> overlap_res_hash;
520  for (auto res2 : overlap_res) {
521  overlap_res_hash.emplace(res2, true);
522  }
523 
524  std::vector<std::set<int>> overlap_map_result = sg1->overlapMap(*sg2);
525  bool true_failure = true;
526  bool local_failure2 = false;
527  for (int cc1 = 0; cc1 < overlap_map_result.size(); cc1++) {
528  std::set<int> iter1 = overlap_map_result[cc1];
529  for (auto cc2 : iter1) {
530  if (overlap_res_hash.find(std::pair<int, int>(cc1, cc2)) ==
531  overlap_res_hash.end()) {
532  local_failure2 = true;
533  break;
534  }
535  }
536  if (local_failure2) break;
537  }
538  if (local_failure2) return false;
539 
540  // test that no collisions are missed after hashmapping
541  bool local_failure3 = false;
542  for (auto res1 : overlap_res) {
543  if (overlap_map_result[res1.first].find(res1.second) ==
544  overlap_map_result[res1.first].end()) {
545  // overlap pair not found in the overlap_map result
546  local_failure3 = true;
547  break;
548  }
549  }
550  if (local_failure3) return false;
551  true_failure = local_failure1 || local_failure2 || local_failure3;
552 
553  return !true_failure;
554 }
555 
557  const ShapeGroup *sg) {
558  bool res = test_collide(co, sg);
559 #if ENABLE_SERIALIZER_TESTS
560  if (serialize_broadphase_failure_test(sg, co.get())) {
561  std::cout << "serializer OBJ OBJ failed";
562  }
563 #endif
564  if (!res) {
565  bool local_failure1 = false;
566  for (auto el : sg->unpack()) {
567  bool tolerance_result = false;
568  double distance;
569  int tol_res = ToleranceCheck(el, co, tolerance_result, distance);
570  if (!tolerance_result) {
571  local_failure1 = true;
572  break;
573  }
574  }
575  if (local_failure1) {
576  res = test_collide(co, sg);
577 
578  log_broadphase_failure(co, sg);
579  }
580  }
581  return res;
582 }
583 bool ShapeGroupTest::run_test_collide(const ShapeGroup *sg1,
584  const ShapeGroup *sg2) {
585  bool res = test_collide(sg1, sg2);
586  // bool res2=true;
587  bool res2 = test_overlap_map(sg1, sg2);
588  test::BroadphaseFailureObjObj bf;
589  bf.obj1 = sg1->shared_from_this();
590  bf.obj2 = sg2->shared_from_this();
591 #if ENABLE_SERIALIZER_TESTS
592  if (serialize_broadphase_failure_test(sg1, sg2)) {
593  std::cout << "serializer OBJ OBJ failed";
594  }
595 #endif
596  // if(1)
597  if (!res || !res2)
598  // if (!res || !res2)
599  {
600  res = test_collide(sg1, sg2);
601  res2 = test_overlap_map(sg1, sg2);
602  log_broadphase_failure(sg1, sg2);
603  }
604  return res && res2;
605 }
606 
607 bool ShapeGroupTest::run_test_narrowphase(const ShapeGroup *sg1,
608  const ShapeGroup *sg2) {
609  std::vector<std::pair<int, int>> failure_pair_export;
610  bool res = test_narrowphase(sg1, sg2, &failure_pair_export);
611  if (!res) {
612  log_narrowphase_failure(sg1, sg2, failure_pair_export);
613  }
614  return res;
615 }
616 
618  const ShapeGroup *sg) {
619  std::vector<int> failure_export;
620  bool res = test_narrowphase(co, sg, &failure_export);
621  if (!res) {
622  log_narrowphase_failure(co, sg, failure_export);
623  }
624  return res;
625 }
628  int res = 0;
629  // if ((obj1->getCollisionObjectClass() == collision::OBJ_CLASS_SHAPE) &&
630  // (obj2->getCollisionObjectClass() == collision::OBJ_CLASS_SHAPE))
631  //{
632  // return
633  // serialize_narrowphase_failure_helper(std::static_pointer_cast<const
634  // Shape>(obj1), std::static_pointer_cast<const Shape>(obj2));
635  //}
636  int type1 = obj1->getCollisionObjectType();
637  int type2 = obj2->getCollisionObjectType();
638  if (type1 > type2) {
639  std::swap(type1, type2);
640  }
641  std::string descriptor = "narrowphase_failure_obj_obj";
642  descriptor += std::to_string(type1) + std::string("_") +
643  std::to_string(type2) + std::string(".dump");
644  std::string filename =
645  get_free_file(descriptor, 100, NARROWPHASE_DUMP_DIRECTORY);
646  if (filename != std::string("")) {
647  test::BroadphaseFailureObjObj failure_export;
648  failure_export.obj1 = obj1;
649  failure_export.obj2 = obj2;
650  std::ofstream ofs(filename, std::ofstream::out);
651  if (serialize::serialize(failure_export, ofs)) {
652  res = -1;
653  }
654  ofs.close();
655  }
656  return res;
657 }
658 
660  ShapeConstPtr obj2) {
661  int res = 0;
662 
663  int type1 = obj1->type();
664  int type2 = obj2->type();
665 
666  if (type1 > type2) {
667  std::swap(type1, type2);
668  }
669  std::string descriptor = "narrowphase_failure_";
670  descriptor += std::to_string(type1) + std::string("_") +
671  std::to_string(type2) + std::string(".dump");
672  std::string filename =
673  get_free_file(descriptor, 100, NARROWPHASE_DUMP_DIRECTORY);
674  if (filename != std::string("")) {
675  test::BroadphaseFailureObjObj failure_export;
676  failure_export.obj1 = obj1;
677  failure_export.obj2 = obj2;
678  std::ofstream ofs(filename, std::ofstream::out);
679  if (serialize::serialize(failure_export, ofs)) {
680  res = -1;
681  }
682  ofs.close();
683  }
684 
685  bool tolerance_result;
686  double distance;
687  int tol_res = ToleranceCheck(obj1, obj2, tolerance_result, distance, true);
688  if (!tolerance_result) {
689  std::string descriptor = "narrowphase_failure_tolerance_checked";
690  descriptor += std::to_string(type1) + std::string("_") +
691  std::to_string(type2) + std::string(".dump");
692  std::string filename =
693  get_free_file(descriptor, 100, NARROWPHASE_DUMP_DIRECTORY);
694  if (filename != std::string("")) {
695  test::BroadphaseFailureObjObj failure_export;
696  failure_export.obj1 = obj1;
697  failure_export.obj2 = obj2;
698  std::ofstream ofs(filename, std::ofstream::out);
699  if (serialize::serialize(failure_export, ofs)) {
700  res = -1;
701  }
702  ofs.close();
703  }
704  }
705 
706  return res;
707 }
708 
710  const ShapeGroup *sg1, const ShapeGroup *sg2,
711  const std::vector<std::pair<int, int>> &failure_pair_export) {
712  int res = 0;
713  std::vector<collision::ShapeConstPtr> obstacles1 = sg1->unpack();
714  std::vector<collision::ShapeConstPtr> obstacles2 = sg2->unpack();
715  for (auto el : failure_pair_export) {
716  ShapeConstPtr obj1 = obstacles1[el.first];
717  ShapeConstPtr obj2 = obstacles2[el.second];
718  if (serialize_narrowphase_failure_helper(obj1, obj2)) {
719  res = -1;
720  }
721  }
722  return res;
723 }
724 int serialize_narrowphase_failure(ShapeConstPtr co, const ShapeGroup *sg,
725  const std::vector<int> &failure_export) {
726  int res = 0;
727  std::vector<collision::ShapeConstPtr> obstacles1 = sg->unpack();
728  for (auto el : failure_export) {
729  ShapeConstPtr obj1 = obstacles1[el];
730  if (serialize_narrowphase_failure_helper(co, obj1)) {
731  res = -1;
732  }
733  }
734  return res;
735 }
736 
738  const CollisionChecker *cc,
739  const std::vector<int> &failure_export) {
740  int res = 0;
741  std::vector<collision::CollisionObjectConstPtr> obstacles1 =
742  cc->getObstacles();
743  for (auto el : failure_export) {
744  if (serialize_narrowphase_failure_helper_obj(co, obstacles1[el])) {
745  res = -1;
746  }
747  }
748  return res;
749 }
750 
752  const ShapeGroup *sg1, const ShapeGroup *sg2,
753  const std::vector<std::pair<int, int>> &failure_pair_export) {
754  serialize_narrowphase_failure(sg1, sg2, failure_pair_export);
755  std::ostringstream outstrstream;
756  outstrstream << "[Narrowphase failure]" << std::endl;
757  // sg1->toString(outstrstream);
758  // sg2->toString(outstrstream);
759  outstrstream << "[/Narrowphase failure]" << std::endl;
760  TestFailureLoggerNarrowphase logger;
761  logger.log_failure(outstrstream.str());
762  return 0;
763 }
764 
765 int log_narrowphase_failure(CollisionObjectConstPtr co, const ShapeGroup *sg,
766  const std::vector<int> &failure_export) {
767  if (co->getCollisionObjectClass() ==
769  serialize_narrowphase_failure(std::static_pointer_cast<const Shape>(co), sg,
770  failure_export);
771  std::ostringstream outstrstream;
772  outstrstream << "[Narrowphase failure]" << std::endl;
773  // co->toString(outstrstream);
774  // cc->toString(outstrstream);
775  outstrstream << "[/Narrowphase failure]" << std::endl;
776  TestFailureLoggerNarrowphase logger;
777  logger.log_failure(outstrstream.str());
778  return 0;
779  }
780  return 0;
781 }
783  std::ostringstream outstrstream;
784  outstrstream << "[Parentmap failure]" << std::endl;
785  co->toString(outstrstream);
786  outstrstream << "[/Parentmap failure]" << std::endl;
787  TestFailureLoggerParentMap logger;
788  logger.log_failure(outstrstream.str());
789  return 0;
790 }
791 
792 int dirExists(const char *path) {
793  struct stat info;
794 
795  if (stat(path, &info) != 0)
796  return 0;
797  else if (info.st_mode & S_IFDIR)
798  return 1;
799  else
800  return 0;
801 }
802 
803 std::string get_free_file(std::string prefix, int max_files,
804  std::string directory) {
805  std::string full_name_test = directory;
806  if (!dirExists(full_name_test.c_str())) {
807  return std::string("");
808  }
809  for (int cc1 = 0; cc1 < max_files; cc1++) {
810  full_name_test = directory + std::string("/") + prefix + std::string("_") +
811  std::to_string(cc1) + std::string(".dump");
812  std::ifstream f(full_name_test.c_str());
813  if (!f.good()) {
814  return full_name_test;
815  }
816  }
817  return std::string("");
818 }
819 int serialize_broadphase_failure_test(const CollisionObject *obj1,
820  const CollisionObject *obj2) {
821  test::BroadphaseFailureObjObj bf;
822  bf.obj1 = obj1->shared_from_this();
823  bf.obj2 = obj2->shared_from_this();
824  std::stringstream strstr1;
825  std::stringstream strstr2;
826  std::string str1;
827  std::string str2;
828  serialize::serialize(bf, strstr1);
829  str1 = strstr1.str();
830  BroadphaseFailureObjObj bf_load;
831  serialize::deserialize(bf_load, strstr1);
832  if (bf_load.obj1.get() && bf_load.obj2.get()) {
833  serialize::serialize(bf_load, strstr2);
834  str2 = strstr2.str();
835  bool passed = str1 == str2;
836  if (passed) {
837  return 0;
838  } else
839  return 1;
840  } else {
841  return -1;
842  }
843 }
844 int serialize_broadphase_failure_test(const CollisionChecker *cc,
845  const CollisionObject *obj) {
846  test::BroadphaseFailureCCObj bf;
847  bf.cc =
848  std::static_pointer_cast<const CollisionChecker>(cc->shared_from_this());
849  bf.obj = obj->shared_from_this();
850  std::stringstream strstr1;
851  std::stringstream strstr2;
852  std::string str1;
853  std::string str2;
854  serialize::serialize(bf, strstr1);
855  str1 = strstr1.str();
856  BroadphaseFailureCCObj bf_load;
857  serialize::deserialize(bf_load, strstr1);
858  if (bf_load.cc.get() && bf_load.obj.get()) {
859  serialize::serialize(bf_load, strstr2);
860  str2 = strstr2.str();
861  bool passed = str1 == str2;
862  if (passed) {
863  return 0;
864  } else
865  return 1;
866  } else {
867  return -1;
868  }
869 }
870 
871 int serialize_broadphase_failure(const CollisionChecker *cc,
872  const CollisionObject *obj) {
873  test::BroadphaseFailureCCObj bf;
874  bf.cc =
875  std::static_pointer_cast<const CollisionChecker>(cc->shared_from_this());
876  bf.obj = obj->shared_from_this();
877  std::string filename = get_free_file("broadphase_failure_cc_obj", 10000,
878  BROADPHASE_DUMP_DIRECTORY);
879  if (filename == "") return -1;
880  std::ofstream ofs(filename, std::ofstream::out);
881  serialize::serialize(bf, ofs);
882  ofs.close();
883  return 0;
884 }
885 int serialize_broadphase_failure(const CollisionObject *obj1,
886  const CollisionObject *obj2) {
887  test::BroadphaseFailureObjObj bf;
888  bf.obj1 = obj1->shared_from_this();
889  bf.obj2 = obj2->shared_from_this();
890  std::string filename = get_free_file("broadphase_failure_obj_obj", 10000,
891  BROADPHASE_DUMP_DIRECTORY);
892  if (filename == "") return -1;
893  std::ofstream ofs(filename, std::ofstream::out);
894  serialize::serialize(bf, ofs);
895  ofs.close();
896  return 0;
897 }
898 
899 int log_broadphase_failure(const ShapeGroup *sg1, const ShapeGroup *sg2) {
900  serialize_broadphase_failure(sg1, sg2);
901  std::ostringstream outstrstream;
902  outstrstream << "[Broadphase failure]" << std::endl;
903  sg1->toString(outstrstream);
904  sg2->toString(outstrstream);
905  outstrstream << "[/Broadphase failure]" << std::endl;
906  TestFailureLoggerBroadphase logger;
907  logger.log_failure(outstrstream.str());
908  return 0;
909 }
911  const CollisionChecker *cc) {
912  bool result = true;
913  double distance = std::numeric_limits<FCL_PRECISION>::max();
914  bool true_Failure = false;
915 
916  for (auto &obj : cc->getObstacles()) {
917  if (obj->getCollisionObjectClass() == OBJ_CLASS_TVOBSTACLE ||
918  co->getCollisionObjectClass() == OBJ_CLASS_TVOBSTACLE) {
919  bool tvgroup_tolerance_passed = true;
920  int time_start_idx = 0, time_end_idx = 0;
921  const TimeVariantCollisionObject *obj_tv = 0;
922  const TimeVariantCollisionObject *co_tv = 0;
923  if (co->getCollisionObjectClass() == OBJ_CLASS_TVOBSTACLE) {
924  co_tv = static_cast<const TimeVariantCollisionObject *>(co.get());
925  }
926  if (obj->getCollisionObjectClass() == OBJ_CLASS_TVOBSTACLE) {
927  obj_tv = static_cast<const TimeVariantCollisionObject *>(obj.get());
928  }
929  if (obj_tv && co_tv) {
930  time_start_idx =
931  std::min(obj_tv->time_start_idx(), co_tv->time_start_idx());
932  time_end_idx = std::max(obj_tv->time_end_idx(), co_tv->time_end_idx());
933  } else {
934  if (obj_tv) {
935  time_start_idx = obj_tv->time_start_idx();
936  time_end_idx = obj_tv->time_end_idx();
937  } else if (co_tv) {
938  time_start_idx = co_tv->time_start_idx();
939  time_end_idx = co_tv->time_end_idx();
940  } else
941  throw;
942  }
943  for (int time_idx = time_start_idx; time_idx < time_end_idx; time_idx++) {
944  CollisionObjectConstPtr obj1(nullptr);
945  if (obj_tv) {
946  obj1 = obj_tv->getObstacleAtTime(time_idx);
947  } else
948  obj1 = obj;
949  CollisionObjectConstPtr obj2(nullptr);
950  if (co_tv)
951  obj2 = co_tv->getObstacleAtTime(time_idx);
952  else
953  obj2 = co;
954  if (!obj1.get() || !obj2.get()) {
955  continue;
956  }
957 
958  bool tol_res = false;
959  double dist = 0;
960  ToleranceCheck(obj1, obj2, tol_res, dist);
961  if (!tol_res) {
962  tvgroup_tolerance_passed = false;
963  break;
964  }
965  }
966  if (tvgroup_tolerance_passed) {
967  result = true;
968  } else {
969  result = false;
970  }
971  } else {
972  bool tol_res = false;
973  double dist = 0;
974  ToleranceCheck(obj, co, tol_res, dist);
975  if (!tol_res) {
976  result = false;
977  }
978  }
979  if (!result) {
980  true_Failure = true;
981  break;
982  }
983  }
984  return true_Failure;
985 }
987  const CollisionChecker *cc) {
988  serialize_broadphase_failure(cc, co.get());
989  std::ostringstream outstrstream;
990  outstrstream << "[Broadphase failure]" << std::endl;
991  co->toString(outstrstream);
992  cc->toString(outstrstream);
993  TestFailureLoggerBroadphase logger;
994 
995  logger.log_failure(outstrstream.str());
996  return 0;
997 }
998 int log_broadphase_failure(CollisionObjectConstPtr co, const ShapeGroup *sg) {
999  std::string outstr;
1000  std::ostringstream outstrstream;
1001  outstrstream << "[Broadphase failure]" << std::endl;
1002  co->toString(outstrstream);
1003  sg->toString(outstrstream);
1004  outstrstream << "[/Broadphase failure]" << std::endl;
1005  TestFailureLoggerBroadphase logger;
1006  logger.log_failure(outstrstream.str());
1007  return 0;
1008 }
1009 
1010 } // namespace test
1011 } // namespace collision
1012 #endif
std::shared_ptr< const Shape > ShapeConstPtr
std::vector< TriangleConstPtr > getTriangleMesh() const
Definition: polygon.cc:149
int serialize_narrowphase_failure_helper_obj(CollisionObjectConstPtr obj1, CollisionObjectConstPtr obj2)
int log_narrowphase_failure(const ShapeGroup *sg1, const ShapeGroup *sg2, const std::vector< std::pair< int, int >> &failure_pair_export)
std::shared_ptr< const RectangleAABB > RectangleAABBConstPtr
int serialize_broadphase_failure_test(const CollisionChecker *cc, const CollisionObject *obj)
ShapeGroup can contain simple shapes.
Definition: shape_group.h:33
std::size_t distance(const CollisionObject &obj1, const CollisionObject &obj2, DistanceResult &res, const DistanceRequest &req)
std::string get_free_file(std::string prefix, int max_files, std::string directory)
std::shared_ptr< const CollisionObject > CollisionObjectConstPtr
const FCLCollisionObject * get_fcl_object_ptr(const CollisionObject *obj)
Definition: fcl_helpers.h:40
int serialize_narrowphase_failure(ShapeConstPtr co, const ShapeGroup *sg, const std::vector< int > &failure_export)
bool run_test_collide(CollisionObjectConstPtr co, const ShapeGroup *sg)
int serialize_narrowphase_failure_helper(ShapeConstPtr obj1, ShapeConstPtr obj2)
bool run_test_collide(CollisionObjectConstPtr co, const collision::CollisionChecker *cc)
bool run_test_collide_obstacle(CollisionObjectConstPtr co, const collision::CollisionChecker *cc)
int deserialize(test::BroadphaseFailureCCObj &bf_object, std::istream &input_stream, const char *format=SERIALIZER_DEFAULT_FORMAT)
bool test_tolerance_check(CollisionObjectConstPtr co, const CollisionChecker *cc)
bool test_overlap_map(const ShapeGroup *sg1, const ShapeGroup *sg2, std::vector< std::pair< int, int >> *missed_col_naive_out=0)
bool fcl_generic_collisionDetection(const FCLCollisionObject &obj_first, const FCLCollisionObject &obj_second)
Axis-aligned rectangle.
int log_broadphase_failure(CollisionObjectConstPtr co, const ShapeGroup *sg)
int serialize(const test::BroadphaseFailureCCObj &bf_object, std::ostream &output_stream, const char *format=SERIALIZER_DEFAULT_FORMAT)
bool run_test_collide_obstacles(CollisionObjectConstPtr co, const collision::CollisionChecker *cc)
void addToGroup(ShapeConstPtr shape)
Adds a simple shape to the ShapeGroup.
Definition: shape_group.cc:176
int log_parentmap_failure(CollisionObjectConstPtr co)
bool run_test_narrowphase(CollisionObjectConstPtr co, const ShapeGroup *sg)
Polygon contains Triangles and Vertices.
Definition: polygon.h:29
const FCLCollisionObjectGroup * get_fcl_object_group_ptr(const CollisionObject *obj)
Definition: fcl_helpers.h:27