Collision Checker
container_fcl_inl.h
Go to the documentation of this file.
1 #ifndef CPP_COLLISION_INCLUDE_COLLISION_GRID_FCL_H_
2 #define CPP_COLLISION_INCLUDE_COLLISION_GRID_FCL_H_
3 
5 
6 #include <fcl/broadphase/broadphase_SSaP.h>
7 #include <fcl/broadphase/broadphase_SaP.h>
8 #include <fcl/broadphase/broadphase_collision_manager.h>
9 #include <fcl/broadphase/broadphase_dynamic_AABB_tree.h>
10 #include <fcl/broadphase/broadphase_interval_tree.h>
11 #include <fcl/broadphase/broadphase_spatialhash.h>
12 #include <stdint.h>
13 #include <boost/align/aligned_allocator.hpp>
14 #include "collision/shape_group.h"
16 
17 #include <fcl/narrowphase/collision_object.h>
18 
24 
28 
29 namespace collision {
30 namespace detail {
31 namespace accelerators {
33  public:
35  : candidates_(&candidates){
36 
37  };
39 };
40 
41 template <typename S>
44  void* cdata_) {
45  auto* cdata = static_cast<ContainerCollisionRequestDataFCL*>(cdata_);
46  if (o1->getUserData()) {
47  cdata->candidates_->push_back(*((int*)o1->getUserData()));
48  } else if (o2->getUserData()) {
49  cdata->candidates_->push_back(*((int*)o2->getUserData()));
50  }
51  return false;
52 };
53 
60 };
61 
62 typedef Eigen::Matrix<uint64_t, Eigen::Dynamic, 1> VectorXi64;
63 
64 class ContainerFCL {
65  public:
66  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
67 
69  const ContainerSettings& sett) {
70  constructHelper();
71 
72  for (auto obj : objects_in) {
73  addObject(obj);
74  }
75  double min_x = std::numeric_limits<double>::max();
76  double max_x = std::numeric_limits<double>::min();
77  double min_y = std::numeric_limits<double>::max();
78  double max_y = std::numeric_limits<double>::min();
79  for (auto obj : objects_in) {
80  AABB aabb = getAABB(obj);
81 
82  min_x = std::min(min_x, aabb.x_min);
83  min_y = std::min(min_y, aabb.y_min);
84  max_x = std::max(max_x, aabb.x_max);
85  max_y = std::max(max_y, aabb.y_max);
86  }
87 
88  double gridlen = max_x - min_x;
89  double cell_size = gridlen / sett.num_cells;
90 
91  switch (sett.fcl_broadphase_type) {
93  broadphase_manager_ = new fcl::DynamicAABBTreeCollisionManager<double>;
94  break;
95  case FCL_BT_SPATIALHASH:
96 
97  broadphase_manager_ = new fcl::SpatialHashingCollisionManager<double>(
98  cell_size, fcl::Vector3<double>(min_x, min_y, -FCL_HEIGHT),
99  fcl::Vector3<double>(max_x, max_y, FCL_HEIGHT),
100  sett.fcl_num_buckets);
101  break;
102  case FCL_BT_INTERVALTREE:
103 
104  broadphase_manager_ = new fcl::IntervalTreeCollisionManager<double>;
105 
106  break;
107  case FCL_BT_SAP:
108 
109  broadphase_manager_ = new fcl::SaPCollisionManager<double>;
110 
111  break;
112  case FCL_BT_SSAP:
113 
114  broadphase_manager_ = new fcl::SSaPCollisionManager<double>;
115 
116  break;
117  default:
118  throw std::invalid_argument("Invalid FCL broadphase manager ID");
119  }
120  finalizeCreation();
121  }
122 
123  ContainerFCL(const ShapeGroup* sg_ptr, const ContainerSettings& sett) {
124  constructHelper();
125  for (auto obj : sg_ptr->unpack()) {
126  addObject(obj.get());
127  }
128 
129  auto sg_aabb = sg_ptr->getAABB();
130  double min_x = sg_aabb->min()(0);
131  double min_y = sg_aabb->min()(1);
132  double max_x = sg_aabb->max()(0);
133  double max_y = sg_aabb->max()(1);
134 
135  double gridlen = max_x - min_x;
136  double cell_size = gridlen / sett.num_cells;
137 
138  switch (sett.fcl_broadphase_type) {
139  case FCL_BT_DYNAMIC_TREE:
140  broadphase_manager_ = new fcl::DynamicAABBTreeCollisionManager<double>;
141  break;
142  case FCL_BT_SPATIALHASH:
143 
144  broadphase_manager_ = new fcl::SpatialHashingCollisionManager<double>(
145  cell_size, fcl::Vector3<double>(min_x, min_y, -FCL_HEIGHT),
146  fcl::Vector3<double>(max_x, max_y, FCL_HEIGHT),
147  sett.fcl_num_buckets);
148  break;
149  case FCL_BT_INTERVALTREE:
150 
151  broadphase_manager_ = new fcl::IntervalTreeCollisionManager<double>;
152 
153  break;
154  case FCL_BT_SAP:
155 
156  broadphase_manager_ = new fcl::SaPCollisionManager<double>;
157 
158  break;
159  case FCL_BT_SSAP:
160 
161  broadphase_manager_ = new fcl::SSaPCollisionManager<double>;
162 
163  break;
164  default:
165  throw std::invalid_argument("Invalid FCL broadphase manager ID");
166  }
167 
168  finalizeCreation();
169  }
170 
171  virtual ~ContainerFCL() {
172  if (broadphase_manager_) delete broadphase_manager_;
173  }
174 
175  int addObject(const CollisionObject* obj) {
177  AABB aabb = getAABB(obj);
178 
179  registerObjectId(obj);
180  aabbs_.push_back(aabb);
181  ObjectProxy proxy = CreateProxy(obj, aabbs_.back());
182  objects_.push_back(proxy);
183  return 0;
184  }
185  return -1;
186  }
187 
189  const ContainerCollisionRequest& req) {
190  bool res = false;
192  AABB aabb = getAABB(obj);
193 
194  ObjectProxy proxy = CreateProxy(obj, aabb);
196  aligned_vector<int> collision_candidates;
197 
198  {
200 
201  numchecks_ += objects_.size();
202  getCandidates(proxy, collision_candidates);
203  }
204  if (req.enable_verification) {
205  aligned_vector<int> collision_candidates2;
206  {
207  for (int i = 0; i < objects_optimized_id_.size(); i++) {
208  // ground truth collisions between AABBs not including border
209  // collisions
210  if (AABB_SAT2D(getAABB(object_by_id_[objects_optimized_id_[i]]))
211  .collides_eps(AABB_SAT2D(aabb), -1e-11)) {
212  collision_candidates2.push_back(objects_optimized_id_[i]);
213  }
214  }
215  }
216 
217  std::sort(collision_candidates2.begin(), collision_candidates2.end());
218  std::set<int> collision_candidates_set;
219  for (auto el : collision_candidates) {
220  collision_candidates_set.insert(el);
221  }
222  std::sort(collision_candidates.begin(), collision_candidates.end());
223  int found_count = std::unique(collision_candidates.begin(),
224  collision_candidates.end()) -
225  collision_candidates.begin();
226  int real_count = std::unique(collision_candidates2.begin(),
227  collision_candidates2.end()) -
228  collision_candidates2.begin();
229 
230  volatile int missed = real_count - found_count;
231 
232  bool bMissed = false;
233 
234  for (auto el : collision_candidates2) {
235  if (collision_candidates_set.find(el) ==
236  collision_candidates_set.end()) {
237  bMissed = true;
238  break;
239  }
240  }
241 
242  if (missed > 0 || bMissed) {
243  std::cout << "broadphase verification: miss\n";
244  throw std::exception();
245  return -1;
246  }
247  }
248  {
250  collision_checked_id_.fill(0);
251  int numcands_local = 0;
252  if (obj->getCollisionObjectType() == OBJ_TYPE_OBB_BOX && all_obbs_) {
253  const RectangleOBB* obb1 = static_cast<const RectangleOBB*>(obj);
254  std::vector<OBB_SAT2D, Eigen::aligned_allocator<OBB_SAT2D>>
255  obb1_fast_container;
256  obb1_fast_container.emplace_back(obb1->center(), obb1->r_x() * 2,
257  obb1->r_y() * 2, obb1->local_x_axis(),
258  obb1->local_y_axis());
259 
260  for (auto el : collision_candidates) {
261  if ((el < 0) || (el >= fast_obbs_.size())) {
262  std::cout << "internal error";
263  throw std::exception();
264  }
265  if (!collision_checked_id_(el)) {
266  numcands_local += 1;
267  collision_checked_id_(el) = 1;
268  if (fast_obbs_[el].overlaps(*(obb1_fast_container.begin())))
269 
270  {
271  numcands_ += numcands_local;
272  return 1;
273  }
274  }
275  }
276  } else {
277  for (auto el : collision_candidates) {
278  if (!collision_checked_id_(el)) {
279  numcands_local += 1;
280  collision_checked_id_(el) = 1;
281 
282  if (object_by_id_[el]->collide(*obj)) {
283  numcands_ += numcands_local;
284  return 1;
285  }
286  }
287  }
288  }
289  numcands_ += numcands_local;
290  }
291  return 0;
292  }
293 
294  int numcands() const { return numcands_; }
295 
296  int numchecks() const { return numchecks_; }
297 
298  private:
299  inline int finalizeCreation(void) {
300  int total_objects = 0;
301  total_objects += objects_.size();
302 
303  objects_optimized_id_.clear();
304  object_by_id_.clear();
305  object_by_id_.resize(object_ids_.size());
306  collision_checked_id_ = Eigen::VectorXi::Zero(object_ids_.size());
307 
308  masks_optimized_ = VectorXi64::Zero(total_objects);
309  res_mask_optimized_ = Eigen::VectorXi::Zero(total_objects);
310 
311  all_obbs_ = true;
312  for (auto el : objects_) {
313  if (all_obbs_ &&
314  el.obj_ptr->getCollisionObjectType() != OBJ_TYPE_OBB_BOX) {
315  all_obbs_ = false;
316  }
317 
318  objects_optimized_id_.push_back(getObjectId(el.obj_ptr));
319  object_by_id_[objects_optimized_id_.back()] = el.obj_ptr;
320  masks_optimized_[objects_optimized_id_.size() - 1] = el.mask;
321  auto curAABB = &aabbs_[objects_optimized_id_.back()];
323  (curAABB->x_max - curAABB->x_min) / 2,
324  (curAABB->y_max - curAABB->y_min) / 2,
325  Eigen::Vector2d((curAABB->x_max + curAABB->x_min) / 2,
326  (curAABB->y_max + curAABB->y_min) / 2)));
327  fcl_object_geometries_.emplace_back(rect->createFCLCollisionGeometry());
328  fcl_objects_.emplace_back(
329  fcl_object_geometries_.back(),
331  rect->center()));
332  }
333  for (auto id : objects_optimized_id_) {
334  fcl_objects_[id].setUserData(&objects_optimized_id_[id]);
335  broadphase_manager_->registerObject(&fcl_objects_[id]);
336  }
337 
338  broadphase_manager_->setup();
339  return 0;
340  }
341 
342  inline int getCandidates(ObjectProxy& proxy,
343  aligned_vector<int>& candidates) {
344  AABB curAABB = getAABB(proxy.obj_ptr);
346  (curAABB.x_max - curAABB.x_min) / 2,
347  (curAABB.y_max - curAABB.y_min) / 2,
348  Eigen::Vector2d((curAABB.x_max + curAABB.x_min) / 2,
349  (curAABB.y_max + curAABB.y_min) / 2));
350  auto cur_geom = std::shared_ptr<fcl::CollisionGeometry<FCL_PRECISION>>(
353  cur_geom,
355  rect.center()));
356  cur_obj.setUserData(0);
357  ContainerCollisionRequestDataFCL reqData(candidates);
358  broadphase_manager_->collide(
359  &cur_obj, &reqData, ContainerFunctionWindowQueryFCL<FCL_PRECISION>);
360  return 0;
361  }
362 
363  inline int getObjectId(const collision::CollisionObject* obj) {
364  auto search = object_ids_.find(obj);
365  if (search != object_ids_.end()) {
366  return search->second;
367  } else
368  throw std::exception();
369  }
370 
371  inline uint64_t get_mask(const AABB& obj) { return 0; }
372 
373  inline ObjectProxy CreateProxy(const CollisionObject* obj,
374  const collision::AABB& aabb) {
375  uint64_t mask = get_mask(aabb);
376  return ObjectProxy{mask, const_cast<CollisionObject*>(obj)};
377  // return ObjectProxy{mask,const_cast<CollisionObject*>(obj), aabb};
378  }
379 
380  int registerObjectId(const CollisionObject* obj) {
381  object_ids_.insert(std::make_pair(obj, (int)object_ids_.size()));
383  const collision::RectangleOBB* obb_in =
384  static_cast<const collision::RectangleOBB*>(obj);
385 
386  fast_obbs_.emplace_back(obb_in->center(), obb_in->r_x() * 2,
387  obb_in->r_y() * 2, obb_in->local_x_axis(),
388  obb_in->local_y_axis());
389  }
390  return 0;
391  }
392 
393  inline AABB getAABB(const CollisionObject* obj) {
395  AABB a = (static_cast<const RectangleOBB*>(obj))->getAABB_fast();
396  return a;
397  } else {
398  auto aabb_fcl = obj->getAABB();
399  return AABB(*aabb_fcl);
400  }
401  }
402 
403  fcl::BroadPhaseCollisionManagerd* broadphase_manager_;
404 
405  std::vector<AABB> aabbs_;
406  std::vector<ObjectProxy> objects_;
407 
408  std::vector<std::shared_ptr<fcl::CollisionGeometry<FCL_PRECISION>>>
409  fcl_object_geometries_;
410  std::vector<fcl::CollisionObject<FCL_PRECISION>> fcl_objects_;
411 
412  VectorXi64 masks_optimized_;
413  Eigen::VectorXi res_mask_optimized_;
414  aligned_vector<int> objects_optimized_id_;
415  aligned_vector<CollisionObject*> object_by_id_;
416  std::vector<OBB_SAT2D, Eigen::aligned_allocator<OBB_SAT2D>> fast_obbs_;
417  Eigen::VectorXi collision_checked_id_;
418 
419  std::map<const CollisionObject*, int> object_ids_;
420 
421  bool all_obbs_;
422 
423  int numchecks_;
424  int numcands_;
425 
426  void constructHelper(void) {
427  numchecks_ = 0;
428  numcands_ = 0;
429  broadphase_manager_ = 0;
430  }
431 };
432 } // namespace accelerators
433 } // namespace detail
434 } // namespace collision
435 
436 #endif /* CPP_COLLISION_INCLUDE_COLLISION_GRID_FCL_H_ */
Eigen::Vector2d local_y_axis() const
Oriented rectangle.
Definition: rectangle_obb.h:19
#define TIMER_START(x)
Definition: application.h:47
std::vector< T, boost::alignment::aligned_allocator< T, 16 > > aligned_vector
Definition: declarations.h:9
double y_min
Definition: aabb.h:11
#define TIMER_grid_narrowphase
Definition: application.h:35
virtual CollisionObjectClass getCollisionObjectClass() const
std::vector< ShapeConstPtr > unpack() const
Returns Vector of all shapes contained inside the ShapeGroup.
Definition: shape_group.cc:187
std::shared_ptr< const RectangleAABB > RectangleAABBConstPtr
Eigen::Matrix< uint64_t, Eigen::Dynamic, 1 > VectorXi64
std::shared_ptr< const collision::RectangleAABB > getAABB() const
Definition: shape_group.cc:21
bool collides_eps(const AABB_SAT2D &other, double eps)
Definition: aabb_sat2d.h:36
ShapeGroup can contain simple shapes.
Definition: shape_group.h:33
static fcl::Transform3< FCL_PRECISION > fcl_get_3d_translation(const Eigen::Vector2d &pos)
Definition: fcl_transform.h:21
#define TIMER_grid_hashing
Definition: application.h:37
AABB getAABB(const CollisionObject *obj)
fcl::CollisionGeometry< FCL_PRECISION > * createFCLCollisionGeometry(void) const override
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ContainerFCL(aligned_vector< collision::CollisionObject *> objects_in, const ContainerSettings &sett)
virtual CollisionObjectType getCollisionObjectType() const
Axis-aligned rectangle.
#define TIMER_STOP(x)
Definition: application.h:48
double x_max
Definition: aabb.h:10
int addObject(const CollisionObject *obj)
double x_min
Definition: aabb.h:9
virtual std::shared_ptr< const collision::RectangleAABB > getAABB() const =0
bool ContainerFunctionWindowQueryFCL(fcl::CollisionObject< S > *o1, fcl::CollisionObject< S > *o2, void *cdata_)
int checkCollision(const CollisionObject *obj, const ContainerCollisionRequest &req)
Base class for CollisionObjects and some of their groups.
Eigen::Vector2d local_x_axis() const
#define FCL_HEIGHT
Definition: fcl_decl.h:10
bool overlaps(const Triangle_SAT2D &tri, const OBB_SAT2D &obb)
Definition: sat2d_checks.cc:56
#define TIMER_grid_candidates
Definition: application.h:34
Eigen::Vector2d center() const
Get geometric center of shape.
Definition: shape.cc:16
ContainerFCL(const ShapeGroup *sg_ptr, const ContainerSettings &sett)
double y_max
Definition: aabb.h:12
#define STACK_TIMER
Definition: application.h:11