result_set.h
Go to the documentation of this file.
1 /***********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
5  * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
6  *
7  * THE BSD LICENSE
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *************************************************************************/
30 
31 #ifndef RTABMAP_FLANN_RESULTSET_H
32 #define RTABMAP_FLANN_RESULTSET_H
33 
34 #include <algorithm>
35 #include <cstring>
36 #include <iostream>
37 #include <limits>
38 #include <set>
39 #include <vector>
40 
41 namespace rtflann
42 {
43 
44 /* This record represents a branch point when finding neighbors in
45  the tree. It contains a record of the minimum distance to the query
46  point, as well as the node at which the search resumes.
47  */
48 
49 template <typename T, typename DistanceType>
51 {
52  T node; /* Tree node at which search resumes */
53  DistanceType mindist; /* Minimum distance to query for all nodes below. */
54 
56  BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
57 
58  bool operator<(const BranchStruct<T, DistanceType>& rhs) const
59  {
60  return mindist<rhs.mindist;
61  }
62 };
63 
64 
65 template <typename DistanceType>
67 {
68  DistanceIndex(DistanceType dist, size_t index) :
69  dist_(dist), index_(index)
70  {
71  }
72  bool operator<(const DistanceIndex& dist_index) const
73  {
74  return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_);
75  }
76  DistanceType dist_;
77  size_t index_;
78 };
79 
80 
81 template <typename DistanceType>
82 class ResultSet
83 {
84 public:
85  virtual ~ResultSet() {}
86 
87  virtual bool full() const = 0;
88 
89  virtual void addPoint(DistanceType dist, size_t index) = 0;
90 
91  virtual DistanceType worstDist() const = 0;
92 
93 };
94 
100 template <typename DistanceType>
101 class KNNSimpleResultSet : public ResultSet<DistanceType>
102 {
103 public:
105 
106  KNNSimpleResultSet(size_t capacity_) :
107  capacity_(capacity_)
108  {
109  // reserving capacity to prevent memory re-allocations
110  dist_index_.resize(capacity_, DistIndex(std::numeric_limits<DistanceType>::max(),-1));
111  clear();
112  }
113 
115  {
116  }
117 
121  void clear()
122  {
123  worst_distance_ = std::numeric_limits<DistanceType>::max();
124  dist_index_[capacity_-1].dist_ = worst_distance_;
125  count_ = 0;
126  }
127 
132  size_t size() const
133  {
134  return count_;
135  }
136 
141  bool full() const
142  {
143  return count_==capacity_;
144  }
145 
151  void addPoint(DistanceType dist, size_t index)
152  {
153  if (dist>=worst_distance_) return;
154 
155  if (count_ < capacity_) ++count_;
156  size_t i;
157  for (i=count_-1; i>0; --i) {
158 #ifdef FLANN_FIRST_MATCH
159  if ( (dist_index_[i-1].dist_>dist) || ((dist==dist_index_[i-1].dist_)&&(dist_index_[i-1].index_>index)) )
160 #else
161  if (dist_index_[i-1].dist_>dist)
162 #endif
163  {
164  dist_index_[i] = dist_index_[i-1];
165  }
166  else break;
167  }
168  dist_index_[i].dist_ = dist;
169  dist_index_[i].index_ = index;
170  worst_distance_ = dist_index_[capacity_-1].dist_;
171  }
172 
180  void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true)
181  {
182  size_t n = std::min(count_, num_elements);
183  for (size_t i=0; i<n; ++i) {
184  *indices++ = dist_index_[i].index_;
185  *dists++ = dist_index_[i].dist_;
186  }
187  }
188 
189  DistanceType worstDist() const
190  {
191  return worst_distance_;
192  }
193 
194 private:
195  size_t capacity_;
196  size_t count_;
197  DistanceType worst_distance_;
198  std::vector<DistIndex> dist_index_;
199 };
200 
204 template <typename DistanceType>
205 class KNNResultSet : public ResultSet<DistanceType>
206 {
207 public:
209 
210  KNNResultSet(int capacity) : capacity_(capacity)
211  {
212  // reserving capacity to prevent memory re-allocations
213  dist_index_.resize(capacity_, DistIndex(std::numeric_limits<DistanceType>::max(),-1));
214  clear();
215  }
216 
218  {
219 
220  }
221 
225  void clear()
226  {
227  worst_distance_ = std::numeric_limits<DistanceType>::max();
228  dist_index_[capacity_-1].dist_ = worst_distance_;
229  count_ = 0;
230  }
231 
232  size_t size() const
233  {
234  return count_;
235  }
236 
237  bool full() const
238  {
239  return count_ == capacity_;
240  }
241 
242 
243  void addPoint(DistanceType dist, size_t index)
244  {
245  if (dist >= worst_distance_) return;
246  size_t i;
247  for (i = count_; i > 0; --i) {
248 #ifdef FLANN_FIRST_MATCH
249  if ( (dist_index_[i-1].dist_<=dist) && ((dist!=dist_index_[i-1].dist_)||(dist_index_[i-1].index_<=index)) )
250 #else
251  if (dist_index_[i-1].dist_<=dist)
252 #endif
253  {
254  // Check for duplicate indices
255  for (size_t j = i - 1; dist_index_[j].dist_ == dist && j--;) {
256  if (dist_index_[j].index_ == index) {
257  return;
258  }
259  }
260  break;
261  }
262  }
263  if (count_ < capacity_) ++count_;
264  for (size_t j = count_-1; j > i; --j) {
265  dist_index_[j] = dist_index_[j-1];
266  }
267  dist_index_[i].dist_ = dist;
268  dist_index_[i].index_ = index;
269  worst_distance_ = dist_index_[capacity_-1].dist_;
270  }
271 
279  void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true)
280  {
281  size_t n = std::min(count_, num_elements);
282  for (size_t i=0; i<n; ++i) {
283  *indices++ = dist_index_[i].index_;
284  *dists++ = dist_index_[i].dist_;
285  }
286  }
287 
288  DistanceType worstDist() const
289  {
290  return worst_distance_;
291  }
292 
293 private:
294  size_t capacity_;
295  size_t count_;
296  DistanceType worst_distance_;
297  std::vector<DistIndex> dist_index_;
298 
299 };
300 
301 
302 
303 template <typename DistanceType>
304 class KNNResultSet2 : public ResultSet<DistanceType>
305 {
306 public:
308 
309  KNNResultSet2(size_t capacity_) :
310  capacity_(capacity_)
311  {
312  // reserving capacity to prevent memory re-allocations
313  dist_index_.reserve(capacity_);
314  clear();
315  }
316 
318  {
319  }
320 
324  void clear()
325  {
326  dist_index_.clear();
328  is_full_ = false;
329  }
330 
335  size_t size() const
336  {
337  return dist_index_.size();
338  }
339 
344  bool full() const
345  {
346  return is_full_;
347  }
348 
355  void addPoint(DistanceType dist, size_t index)
356  {
357  if (dist>=worst_dist_) return;
358 
359  if (dist_index_.size()==capacity_) {
360  // if result set if filled to capacity, remove farthest element
361  std::pop_heap(dist_index_.begin(), dist_index_.end());
362  dist_index_.pop_back();
363  }
364 
365  // add new element
366  dist_index_.push_back(DistIndex(dist,index));
367  if (is_full_) { // when is_full_==true, we have a heap
368  std::push_heap(dist_index_.begin(), dist_index_.end());
369  }
370 
371  if (dist_index_.size()==capacity_) {
372  if (!is_full_) {
373  std::make_heap(dist_index_.begin(), dist_index_.end());
374  is_full_ = true;
375  }
376  // we replaced the farthest element, update worst distance
377  worst_dist_ = dist_index_[0].dist_;
378  }
379  }
380 
388  void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true)
389  {
390  if (sorted) {
391  // std::sort_heap(dist_index_.begin(), dist_index_.end());
392  // sort seems faster here, even though dist_index_ is a heap
393  std::sort(dist_index_.begin(), dist_index_.end());
394  }
395  else {
396  if (num_elements<size()) {
397  std::nth_element(dist_index_.begin(), dist_index_.begin()+num_elements, dist_index_.end());
398  }
399  }
400 
401  size_t n = std::min(dist_index_.size(), num_elements);
402  for (size_t i=0; i<n; ++i) {
403  *indices++ = dist_index_[i].index_;
404  *dists++ = dist_index_[i].dist_;
405  }
406  }
407 
408  DistanceType worstDist() const
409  {
410  return worst_dist_;
411  }
412 
413 private:
414  size_t capacity_;
415  DistanceType worst_dist_;
416  std::vector<DistIndex> dist_index_;
417  bool is_full_;
418 };
419 
420 
425 template <typename DistanceType>
426 class RadiusResultSet : public ResultSet<DistanceType>
427 {
428 public:
430 
431  RadiusResultSet(DistanceType radius_) :
432  radius_(radius_)
433  {
434  // reserving some memory to limit number of re-allocations
435  dist_index_.reserve(1024);
436  clear();
437  }
438 
440  {
441  }
442 
446  void clear()
447  {
448  dist_index_.clear();
449  }
450 
455  size_t size() const
456  {
457  return dist_index_.size();
458  }
459 
464  bool full() const
465  {
466  return true;
467  }
468 
475  void addPoint(DistanceType dist, size_t index)
476  {
477  if (dist<radius_) {
478  // add new element
479  dist_index_.push_back(DistIndex(dist,index));
480  }
481  }
482 
490  void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true)
491  {
492  if (sorted) {
493  // std::sort_heap(dist_index_.begin(), dist_index_.end());
494  // sort seems faster here, even though dist_index_ is a heap
495  std::sort(dist_index_.begin(), dist_index_.end());
496  }
497  else {
498  if (num_elements<size()) {
499  std::nth_element(dist_index_.begin(), dist_index_.begin()+num_elements, dist_index_.end());
500  }
501  }
502 
503  size_t n = std::min(dist_index_.size(), num_elements);
504  for (size_t i=0; i<n; ++i) {
505  *indices++ = dist_index_[i].index_;
506  *dists++ = dist_index_[i].dist_;
507  }
508  }
509 
510  DistanceType worstDist() const
511  {
512  return radius_;
513  }
514 
515 private:
516  DistanceType radius_;
517  std::vector<DistIndex> dist_index_;
518 };
519 
520 
521 
526 template <typename DistanceType>
527 class KNNRadiusResultSet : public ResultSet<DistanceType>
528 {
529 public:
531 
532  KNNRadiusResultSet(DistanceType radius_, size_t capacity_) :
533  radius_(radius_), capacity_(capacity_)
534  {
535  // reserving capacity to prevent memory re-allocations
536  dist_index_.reserve(capacity_);
537  clear();
538  }
539 
541  {
542  }
543 
547  void clear()
548  {
549  dist_index_.clear();
550  worst_dist_ = radius_;
551  is_heap_ = false;
552  }
553 
558  size_t size() const
559  {
560  return dist_index_.size();
561  }
562 
567  bool full() const
568  {
569  return true;
570  }
571 
578  void addPoint(DistanceType dist, size_t index)
579  {
580  if (dist>=worst_dist_) return;
581 
582  if (dist_index_.size()==capacity_) {
583  // if result set is filled to capacity, remove farthest element
584  std::pop_heap(dist_index_.begin(), dist_index_.end());
585  dist_index_.pop_back();
586  }
587 
588  // add new element
589  dist_index_.push_back(DistIndex(dist,index));
590  if (is_heap_) {
591  std::push_heap(dist_index_.begin(), dist_index_.end());
592  }
593 
594  if (dist_index_.size()==capacity_) {
595  // when got to full capacity, make it a heap
596  if (!is_heap_) {
597  std::make_heap(dist_index_.begin(), dist_index_.end());
598  is_heap_ = true;
599  }
600  // we replaced the farthest element, update worst distance
601  worst_dist_ = dist_index_[0].dist_;
602  }
603  }
604 
612  void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true)
613  {
614  if (sorted) {
615  // std::sort_heap(dist_index_.begin(), dist_index_.end());
616  // sort seems faster here, even though dist_index_ is a heap
617  std::sort(dist_index_.begin(), dist_index_.end());
618  }
619  else {
620  if (num_elements<size()) {
621  std::nth_element(dist_index_.begin(), dist_index_.begin()+num_elements, dist_index_.end());
622  }
623  }
624 
625  size_t n = std::min(dist_index_.size(), num_elements);
626  for (size_t i=0; i<n; ++i) {
627  *indices++ = dist_index_[i].index_;
628  *dists++ = dist_index_[i].dist_;
629  }
630  }
631 
632  DistanceType worstDist() const
633  {
634  return worst_dist_;
635  }
636 
637 private:
638  bool is_heap_;
639  DistanceType radius_;
640  size_t capacity_;
641  DistanceType worst_dist_;
642  std::vector<DistIndex> dist_index_;
643 };
644 
645 
647 
651 template <typename DistanceType>
652 class CountRadiusResultSet : public ResultSet<DistanceType>
653 {
654  DistanceType radius;
655  size_t count;
656 
657 public:
658  CountRadiusResultSet(DistanceType radius_ ) :
659  radius(radius_)
660  {
661  clear();
662  }
663 
665  {
666  }
667 
668  void clear()
669  {
670  count = 0;
671  }
672 
673  size_t size() const
674  {
675  return count;
676  }
677 
678  bool full() const
679  {
680  return true;
681  }
682 
683  void addPoint(DistanceType dist, size_t index)
684  {
685  if (dist<radius) {
686  count++;
687  }
688  }
689 
690  DistanceType worstDist() const
691  {
692  return radius;
693  }
694 
695 };
696 
697 
698 
700 
703 template<typename DistanceType>
704 class UniqueResultSet : public ResultSet<DistanceType>
705 {
706 public:
707  struct DistIndex
708  {
709  DistIndex(DistanceType dist, unsigned int index) :
710  dist_(dist), index_(index)
711  {
712  }
713  bool operator<(const DistIndex dist_index) const
714  {
715  return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_);
716  }
717  DistanceType dist_;
718  unsigned int index_;
719  };
720 
723  worst_distance_(std::numeric_limits<DistanceType>::max())
724  {
725  }
726 
730  inline bool full() const
731  {
732  return is_full_;
733  }
734 
740  void copy(size_t* indices, DistanceType* dist, int n_neighbors, bool sorted = true)
741  {
742  if (n_neighbors<0) n_neighbors = dist_indices_.size();
743  int i = 0;
744  typedef typename std::set<DistIndex>::const_iterator Iterator;
745  for (Iterator dist_index = dist_indices_.begin(), dist_index_end =
746  dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) {
747  *indices = dist_index->index_;
748  *dist = dist_index->dist_;
749  }
750  }
751 
755  size_t size() const
756  {
757  return dist_indices_.size();
758  }
759 
764  inline DistanceType worstDist() const
765  {
766  return worst_distance_;
767  }
768 protected:
770  bool is_full_;
771 
773  DistanceType worst_distance_;
774 
776  std::set<DistIndex> dist_indices_;
777 };
778 
780 
784 template<typename DistanceType>
785 class KNNUniqueResultSet : public UniqueResultSet<DistanceType>
786 {
787 public:
791  KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity)
792  {
793  this->is_full_ = false;
794  this->clear();
795  }
796 
801  inline void addPoint(DistanceType dist, size_t index)
802  {
803  // Don't do anything if we are worse than the worst
804  if (dist >= worst_distance_) return;
805  dist_indices_.insert(DistIndex(dist, index));
806 
807  if (is_full_) {
808  if (dist_indices_.size() > capacity_) {
809  dist_indices_.erase(*dist_indices_.rbegin());
810  worst_distance_ = dist_indices_.rbegin()->dist_;
811  }
812  }
813  else if (dist_indices_.size() == capacity_) {
814  is_full_ = true;
815  worst_distance_ = dist_indices_.rbegin()->dist_;
816  }
817  }
818 
821  void clear()
822  {
823  dist_indices_.clear();
824  worst_distance_ = std::numeric_limits<DistanceType>::max();
825  is_full_ = false;
826  }
827 
828 protected:
833 
835  unsigned int capacity_;
836 };
837 
839 
843 template<typename DistanceType>
844 class RadiusUniqueResultSet : public UniqueResultSet<DistanceType>
845 {
846 public:
850  RadiusUniqueResultSet(DistanceType radius) :
851  radius_(radius)
852  {
853  is_full_ = true;
854  }
855 
860  void addPoint(DistanceType dist, size_t index)
861  {
862  if (dist < radius_) dist_indices_.insert(DistIndex(dist, index));
863  }
864 
867  inline void clear()
868  {
869  dist_indices_.clear();
870  }
871 
872 
876  inline bool full() const
877  {
878  return true;
879  }
880 
885  inline DistanceType worstDist() const
886  {
887  return radius_;
888  }
889 private:
893 
895  DistanceType radius_;
896 };
897 
899 
902 template<typename DistanceType>
903 class KNNRadiusUniqueResultSet : public KNNUniqueResultSet<DistanceType>
904 {
905 public:
909  KNNRadiusUniqueResultSet(DistanceType radius, size_t capacity) : KNNUniqueResultSet<DistanceType>(capacity)
910  {
911  this->radius_ = radius;
912  this->clear();
913  }
914 
917  void clear()
918  {
919  dist_indices_.clear();
920  worst_distance_ = radius_;
921  is_full_ = true;
922  }
923 private:
927 
929  DistanceType radius_;
930 };
931 }
932 
933 #endif //FLANN_RESULTSET_H
934 
DistanceIndex< DistanceType > DistIndex
Definition: result_set.h:530
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:243
DistIndex(DistanceType dist, unsigned int index)
Definition: result_set.h:709
void copy(size_t *indices, DistanceType *dist, int n_neighbors, bool sorted=true)
Definition: result_set.h:740
KNNUniqueResultSet(unsigned int capacity)
Definition: result_set.h:791
RadiusUniqueResultSet(DistanceType radius)
Definition: result_set.h:850
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
Definition: result_set.h:388
DistanceType worst_dist_
Definition: result_set.h:415
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
Definition: result_set.h:612
DistanceType worstDist() const
Definition: result_set.h:632
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
DistanceType worst_distance_
Definition: result_set.h:296
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:151
std::set< DistIndex > dist_indices_
Definition: result_set.h:776
DistanceIndex< DistanceType > DistIndex
Definition: result_set.h:429
Definition: lz4.c:365
DistanceType worst_distance_
Definition: result_set.h:773
bool operator<(const DistIndex dist_index) const
Definition: result_set.h:713
DistanceType worstDist() const
Definition: result_set.h:690
KNNRadiusUniqueResultSet(DistanceType radius, size_t capacity)
Definition: result_set.h:909
T
size_t size() const
Definition: result_set.h:455
KNNSimpleResultSet(size_t capacity_)
Definition: result_set.h:106
DistanceIndex< DistanceType > DistIndex
Definition: result_set.h:208
RadiusResultSet(DistanceType radius_)
Definition: result_set.h:431
DistanceType worstDist() const
Definition: result_set.h:764
CountRadiusResultSet(DistanceType radius_)
Definition: result_set.h:658
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:860
std::vector< DistIndex > dist_index_
Definition: result_set.h:642
BranchStruct(const T &aNode, DistanceType dist)
Definition: result_set.h:56
size_t size() const
Definition: result_set.h:232
virtual ~ResultSet()
Definition: result_set.h:85
DistanceType worstDist() const
Definition: result_set.h:408
std::vector< DistIndex > dist_index_
Definition: result_set.h:297
KNNResultSet(int capacity)
Definition: result_set.h:210
bool full() const
Definition: result_set.h:237
DistanceIndex< DistanceType > DistIndex
Definition: result_set.h:307
std::vector< DistIndex > dist_index_
Definition: result_set.h:416
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:801
DistanceType dist_
Definition: result_set.h:76
KNNResultSet2(size_t capacity_)
Definition: result_set.h:309
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:578
DistanceType worstDist() const
Definition: result_set.h:510
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:683
DistanceIndex< DistanceType > DistIndex
Definition: result_set.h:104
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
Definition: result_set.h:490
UniqueResultSet< DistanceType >::DistIndex DistIndex
Definition: result_set.h:829
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
Definition: result_set.h:279
std::vector< DistIndex > dist_index_
Definition: result_set.h:517
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
UniqueResultSet< DistanceType >::DistIndex DistIndex
Definition: result_set.h:890
size_t size() const
Definition: result_set.h:335
dist
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:475
KNNRadiusResultSet(DistanceType radius_, size_t capacity_)
Definition: result_set.h:532
DistanceType worstDist() const
Definition: result_set.h:288
size_t size() const
Definition: result_set.h:755
void addPoint(DistanceType dist, size_t index)
Definition: result_set.h:355
DistanceType worstDist() const
Definition: result_set.h:189
DistanceType worstDist() const
Definition: result_set.h:885
bool operator<(const DistanceIndex &dist_index) const
Definition: result_set.h:72
void copy(size_t *indices, DistanceType *dists, size_t num_elements, bool sorted=true)
Definition: result_set.h:180
DistanceType mindist
Definition: result_set.h:53
std::vector< DistIndex > dist_index_
Definition: result_set.h:198
DistanceIndex(DistanceType dist, size_t index)
Definition: result_set.h:68
DistanceType worst_distance_
Definition: result_set.h:197


rtabmap
Author(s): Mathieu Labbe
autogenerated on Mon Jan 23 2023 03:37:29