kdtree_map.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, The Regents of the University of California (Regents).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following
14  * disclaimer in the documentation and/or other materials provided
15  * with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Please contact the author(s) of this library if you have any questions.
34  * Authors: David Fridovich-Keil ( dfk@eecs.berkeley.edu )
35  */
36 
38 //
39 // Defines KdtreeMap class, which is a wrapper around the FLANN library's
40 // fast kdtree index. KdtreeMaps allow for rapid nearest neighbor searches by
41 // Eigen vector (fixed size) keys and return nearest neighbors as key-value
42 // pairs.
43 //
45 
46 #ifndef FASTRACK_UTILS_KDTREE_MAP_H
47 #define FASTRACK_UTILS_KDTREE_MAP_H
48 
49 #include <fastrack/utils/types.h>
51 
52 #include <flann/flann.h>
53 #include <ros/ros.h>
54 
55 namespace fastrack {
56 
57 template <int K, typename V>
58 class KdtreeMap : private Uncopyable {
59  public:
60  typedef Eigen::Matrix<double, K, 1> VectorKd;
61 
63  explicit KdtreeMap() {}
64 
65  // Insert a new pair into the kdtree.
66  bool Insert(const std::pair<VectorKd, V>& entry);
67  bool Insert(const VectorKd& key, const V& value) {
68  return Insert({key, value});
69  }
70 
71  // Insert a bunch of entries.
72  template <typename Container>
73  bool Insert(const Container& pairs) {
74  for (const std::pair<VectorKd, V>& entry : pairs)
75  if (!Insert(entry)) return false;
76 
77  return true;
78  }
79 
80  // Nearest neighbor search.
81  std::vector<std::pair<VectorKd, V>> KnnSearch(const VectorKd& query,
82  size_t k) const;
83 
84  // Radius search.
85  std::vector<std::pair<VectorKd, V>> RadiusSearch(const VectorKd& query,
86  double r) const;
87 
88  // Accessor.
89  const std::vector<std::pair<VectorKd, V>>& Registry() const {
90  return registry_;
91  }
92  size_t Size() const { return registry_.size(); }
93 
94  private:
95  // A Flann kdtree. Searches in this index return indices, which are then
96  // mapped to key-value pairs.
97  std::unique_ptr<flann::KDTreeIndex<flann::L2<double>>> index_;
98  std::vector<std::pair<VectorKd, V>> registry_;
99 };
100 
101 // ------------------------------ IMPLEMENTATION -----------------------------
102 
103 // Insert a new pair into the kdtree.
104 template <int K, typename V>
105 bool KdtreeMap<K, V>::Insert(const std::pair<VectorKd, V>& entry) {
106  // Append to registry.
107  registry_.push_back(entry);
108 
109  // Create a FLANN-specific matrix for the key.
110  flann::Matrix<double> flann_point(registry_.back().first.data(), 1, K);
111 
112  // If this is the first point in the index, create the index and exit.
113  if (index_ == nullptr) {
114  constexpr int kNumTrees = 1;
115  index_.reset(new flann::KDTreeIndex<flann::L2<double>>(
116  flann_point, flann::KDTreeIndexParams(kNumTrees)));
117  index_->buildIndex();
118  } else {
119  // If the index is already created, add the data point to the index.
120  // Rebuild every time the index doubles in size to occasionally rebalance
121  // the kdtree.
122  constexpr float kRebuildThreshold = 2.0;
123  index_->addPoints(flann_point, kRebuildThreshold);
124  }
125 
126  return true;
127 }
128 
129 // Nearest neighbor search.
130 template <int K, typename V>
131 std::vector<std::pair<typename KdtreeMap<K, V>::VectorKd, V>>
132 KdtreeMap<K, V>::KnnSearch(const VectorKd& query, size_t k) const {
133  std::vector<std::pair<VectorKd, V>> neighbors;
134 
135  if (index_ == nullptr) {
136  ROS_WARN_THROTTLE(1.0, "KdtreeMap: Cannot search empty index.");
137  return neighbors;
138  }
139 
140  // Convert the input point to the FLANN format.
141  flann::Matrix<double> flann_query(new double[K], 1, K);
142  for (size_t ii = 0; ii < K; ii++) flann_query[0][ii] = query(ii);
143 
144  // Search the kd tree for the nearest neighbor to the query.
145  std::vector<std::vector<int>> query_match_indices;
146  std::vector<std::vector<double>> query_squared_distances;
147 
148  const int num_neighbors_found = index_->knnSearch(
149  flann_query, query_match_indices, query_squared_distances,
150  static_cast<int>(k), flann::SearchParams(FLANN_CHECKS_UNLIMITED));
151 
152  // Assign output.
153  for (size_t ii = 0; ii < num_neighbors_found; ii++)
154  neighbors.push_back(registry_[query_match_indices[0][ii]]);
155 
156  // Free flann_query memory.
157  delete[] flann_query.ptr();
158 
159  return neighbors;
160 }
161 
162 // Radius search.
163 template <int K, typename V>
164 std::vector<std::pair<typename KdtreeMap<K, V>::VectorKd, V>>
165 KdtreeMap<K, V>::RadiusSearch(const VectorKd& query, double r) const {
166  std::vector<std::pair<VectorKd, V>> neighbors;
167 
168  if (index_ == nullptr) {
169  ROS_WARN("KdtreeMap: cannot search empty index.");
170  return neighbors;
171  }
172 
173  // Convert the input point to the FLANN format.
174  flann::Matrix<double> flann_query(new double[K], 1, K);
175  for (size_t ii = 0; ii < K; ii++) flann_query[0][ii] = query(ii);
176 
177  // Search the kd tree for the nearest neighbor to the query.
178  std::vector<std::vector<int>> query_match_indices;
179  std::vector<std::vector<double>> query_squared_distances;
180 
181  // FLANN checks Euclidean distance squared, so we pass in r * r.
182  constexpr double kExactSearch = 0.0;
183  constexpr bool kDoNotSort = false;
184  const int num_neighbors_found = index_->radiusSearch(
185  flann_query, query_match_indices, query_squared_distances, r * r,
186  flann::SearchParams(FLANN_CHECKS_UNLIMITED, kExactSearch, kDoNotSort));
187 
188  // Assign output.
189  for (size_t ii = 0; ii < num_neighbors_found; ii++)
190  neighbors.push_back(registry_[query_match_indices[0][ii]]);
191 
192  // Free flann_query memory.
193  delete[] flann_query.ptr();
194 
195  return neighbors;
196 }
197 
198 } // namespace fastrack
199 
200 #endif
std::vector< std::pair< VectorKd, V > > KnnSearch(const VectorKd &query, size_t k) const
Definition: kdtree_map.h:132
size_t Size() const
Definition: kdtree_map.h:92
const std::vector< std::pair< VectorKd, V > > & Registry() const
Definition: kdtree_map.h:89
bool Insert(const Container &pairs)
Definition: kdtree_map.h:73
Eigen::Matrix< double, K, 1 > VectorKd
Definition: kdtree_map.h:60
std::vector< std::pair< VectorKd, V > > registry_
Definition: kdtree_map.h:98
Definition: box.h:53
std::unique_ptr< flann::KDTreeIndex< flann::L2< double > > > index_
Definition: kdtree_map.h:97
std::vector< std::pair< VectorKd, V > > RadiusSearch(const VectorKd &query, double r) const
Definition: kdtree_map.h:165
bool Insert(const std::pair< VectorKd, V > &entry)
Definition: kdtree_map.h:105
bool Insert(const VectorKd &key, const V &value)
Definition: kdtree_map.h:67


fastrack
Author(s): David Fridovich-Keil
autogenerated on Mon Aug 3 2020 21:28:37