gtsam_points
Loading...
Searching...
No Matches
incremental_voxelmap_impl.hpp
1// SPDX-FileCopyrightText: Copyright 2024 Kenji Koide
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include <gtsam_points/ann/incremental_voxelmap.hpp>
6
7#include <gtsam_points/ann/knn_result.hpp>
8#include <gtsam_points/util/fast_floor.hpp>
9
10namespace gtsam_points {
11
12template <typename VoxelContents>
14: inv_leaf_size(1.0 / leaf_size),
15 lru_horizon(10),
16 lru_clear_cycle(10),
17 lru_counter(0),
18 offsets(neighbor_offsets(7)) {}
19
20template <typename VoxelContents>
22
23template <typename VoxelContents>
25 lru_counter = 0;
26 flat_voxels.clear();
27 voxels.clear();
28}
29
30template <typename VoxelContents>
32 // Insert points to the voxelmap
33 for (size_t i = 0; i < points.size(); i++) {
34 const Eigen::Vector3i coord = fast_floor(points.points[i] * inv_leaf_size).template head<3>();
35
36 auto found = voxels.find(coord);
37 if (found == voxels.end()) {
38 auto voxel = std::make_shared<std::pair<VoxelInfo, VoxelContents>>(VoxelInfo(coord, lru_counter), VoxelContents());
39
40 found = voxels.emplace_hint(found, coord, flat_voxels.size());
41 flat_voxels.emplace_back(voxel);
42 }
43
44 auto& [info, voxel] = *flat_voxels[found->second];
45 info.lru = lru_counter;
46 voxel.add(voxel_setting, points, i);
47 }
48
49 if ((++lru_counter) % lru_clear_cycle == 0) {
50 // Remove least recently used voxels
51 auto remove_counter =
52 std::remove_if(flat_voxels.begin(), flat_voxels.end(), [&](const std::shared_ptr<std::pair<VoxelInfo, VoxelContents>>& voxel) {
53 return voxel->first.lru + lru_horizon < lru_counter;
54 });
55 flat_voxels.erase(remove_counter, flat_voxels.end());
56
57 // Rehash
58 voxels.clear();
59 for (size_t i = 0; i < flat_voxels.size(); i++) {
60 voxels[flat_voxels[i]->first.coord] = i;
61 }
62 }
64 // Finalize voxel means and covs
65 for (auto& voxel : flat_voxels) {
66 voxel->second.finalize();
67 }
69
70template <typename VoxelContents>
71size_t IncrementalVoxelMap<VoxelContents>::knn_search(const double* pt, size_t k, size_t* k_indices, double* k_sq_dists, double max_sq_dist) const {
72 const Eigen::Vector4d query = (Eigen::Vector4d() << pt[0], pt[1], pt[2], 1.0).finished();
73 const Eigen::Vector3i center = fast_floor(query * inv_leaf_size).template head<3>();
74
75 size_t voxel_index = 0;
76 const auto index_transform = [&](const size_t point_index) { return calc_index(voxel_index, point_index); };
77
78 KnnResult<-1, decltype(index_transform)> result(k_indices, k_sq_dists, k, index_transform, max_sq_dist);
79 for (const auto& offset : offsets) {
80 const Eigen::Vector3i coord = center + offset;
81 const auto found = voxels.find(coord);
82 if (found == voxels.end()) {
83 continue;
84 }
85
86 voxel_index = found->second;
87 const auto& voxel = flat_voxels[voxel_index]->second;
88 voxel.knn_search(query, result);
89 }
90
91 return result.num_found();
92}
93
94template <typename VoxelContents>
95std::vector<Eigen::Vector3i> IncrementalVoxelMap<VoxelContents>::neighbor_offsets(const int neighbor_voxel_mode) const {
96 switch (neighbor_voxel_mode) {
97 case 1:
98 return std::vector<Eigen::Vector3i>{Eigen::Vector3i(0, 0, 0)};
99 case 7:
100 return std::vector<Eigen::Vector3i>{
101 Eigen::Vector3i(0, 0, 0),
102 Eigen::Vector3i(1, 0, 0),
103 Eigen::Vector3i(-1, 0, 0),
104 Eigen::Vector3i(0, 1, 0),
105 Eigen::Vector3i(0, -1, 0),
106 Eigen::Vector3i(0, 0, 1),
107 Eigen::Vector3i(0, 0, -1)};
108 case 19: {
109 std::vector<Eigen::Vector3i> offsets;
110 for (int i = -1; i <= 1; i++) {
111 for (int j = -1; j <= 1; j++) {
112 for (int k = -1; k <= 1; k++) {
113 if (std::abs(i) == 1 && std::abs(j) == 1 && std::abs(k) == 1) {
114 continue;
115 }
116
117 offsets.push_back(Eigen::Vector3i(i, j, k));
118 }
119 }
120 }
121 return offsets;
122 }
123 case 27: {
124 std::vector<Eigen::Vector3i> offsets;
125 for (int i = -1; i <= 1; i++) {
126 for (int j = -1; j <= 1; j++) {
127 for (int k = -1; k <= 1; k++) {
128 offsets.push_back(Eigen::Vector3i(i, j, k));
129 }
130 }
131 }
132 return offsets;
133 }
134
135 default:
136 std::cerr << "error: invalid neighbor voxel mode " << neighbor_voxel_mode << std::endl;
137 std::cerr << " : neighbor voxel mode must be 1, 7, 19, or 27" << std::endl;
138 return std::vector<Eigen::Vector3i>();
139 }
140}
141
142template <typename VoxelContents>
143bool IncrementalVoxelMap<VoxelContents>::has_points() const {
144 return flat_voxels.empty() ? false : frame::has_points(flat_voxels.front()->second);
145}
146
147template <typename VoxelContents>
148bool IncrementalVoxelMap<VoxelContents>::has_normals() const {
149 return flat_voxels.empty() ? false : frame::has_normals(flat_voxels.front()->second);
150}
151
152template <typename VoxelContents>
153bool IncrementalVoxelMap<VoxelContents>::has_covs() const {
154 return flat_voxels.empty() ? false : frame::has_covs(flat_voxels.front()->second);
155}
156
157template <typename VoxelContents>
158bool IncrementalVoxelMap<VoxelContents>::has_intensities() const {
159 return flat_voxels.empty() ? false : frame::has_intensities(flat_voxels.front()->second);
160}
161
162template <typename VoxelContents>
163std::vector<Eigen::Vector4d> IncrementalVoxelMap<VoxelContents>::voxel_points() const {
164 std::vector<Eigen::Vector4d> points;
165 points.reserve(flat_voxels.size() * 10);
166 visit_points([&](const auto& voxel, const int i) { points.emplace_back(frame::point(voxel, i)); });
167 return points;
168}
169
170template <typename VoxelContents>
171std::vector<Eigen::Vector4d> IncrementalVoxelMap<VoxelContents>::voxel_normals() const {
172 std::vector<Eigen::Vector4d> normals;
173 normals.reserve(flat_voxels.size() * 10);
174 visit_points([&](const auto& voxel, const int i) { normals.emplace_back(frame::normal(voxel, i)); });
175 return normals;
176}
177
178template <typename VoxelContents>
179std::vector<Eigen::Matrix4d> IncrementalVoxelMap<VoxelContents>::voxel_covs() const {
180 std::vector<Eigen::Matrix4d> covs;
181 covs.reserve(flat_voxels.size() * 10);
182 visit_points([&](const auto& voxel, const int i) { covs.emplace_back(frame::cov(voxel, i)); });
183 return covs;
184}
185
186template <typename VoxelContents>
187std::vector<double> IncrementalVoxelMap<VoxelContents>::voxel_intensities() const {
188 std::vector<double> intensities;
189 intensities.reserve(flat_voxels.size() * 10);
190 visit_points([&](const auto& voxel, const int i) { intensities.emplace_back(frame::intensity(voxel, i)); });
191 return intensities;
192}
193
194template <typename VoxelContents>
195PointCloudCPU::Ptr IncrementalVoxelMap<VoxelContents>::voxel_data() const {
196 auto frame = std::make_shared<PointCloudCPU>();
197 frame->points_storage.reserve(flat_voxels.size() * 10);
198 if (has_normals()) {
199 frame->normals_storage.reserve(flat_voxels.size() * 10);
200 }
201 if (has_covs()) {
202 frame->covs_storage.reserve(flat_voxels.size() * 10);
203 }
204 if (has_intensities()) {
205 frame->intensities_storage.reserve(flat_voxels.size() * 10);
206 }
207
208 visit_points([&](const auto& voxel, const int i) {
209 frame->points_storage.emplace_back(frame::point(voxel, i));
210 if (frame::has_normals(voxel)) {
211 frame->normals_storage.emplace_back(frame::normal(voxel, i));
212 }
213 if (frame::has_covs(voxel)) {
214 frame->covs_storage.emplace_back(frame::cov(voxel, i));
215 }
216 if (frame::has_intensities(voxel)) {
217 frame->intensities_storage.emplace_back(frame::intensity(voxel, i));
218 }
219 });
220
221 frame->num_points = frame->points_storage.size();
222 frame->points = frame->points_storage.data();
223 frame->normals = frame->normals_storage.empty() ? nullptr : frame->normals_storage.data();
224 frame->covs = frame->covs_storage.empty() ? nullptr : frame->covs_storage.data();
225 frame->intensities = frame->intensities_storage.empty() ? nullptr : frame->intensities_storage.data();
226
227 return frame;
228}
229
230} // namespace gtsam_points
Incremental voxelmap. This class supports incremental point cloud insertion and LRU-based voxel delet...
Definition incremental_voxelmap.hpp:35
virtual void clear()
Clear the voxelmap.
Definition incremental_voxelmap_impl.hpp:24
virtual void insert(const PointCloud &points)
Insert points to the voxelmap.
Definition incremental_voxelmap_impl.hpp:31
IncrementalVoxelMap(double leaf_size)
Constructor.
Definition incremental_voxelmap_impl.hpp:13
virtual size_t knn_search(const double *pt, size_t k, size_t *k_indices, double *k_sq_dists, double max_sq_dist=std::numeric_limits< double >::max()) const override
Find k nearest neighbors.
Definition incremental_voxelmap_impl.hpp:71
K-nearest neighbor search result container.
Definition knn_result.hpp:36
Standard point cloud class that holds only pointers to point attributes.
Definition point_cloud.hpp:19
size_t size() const
Number of points.
Definition point_cloud.hpp:43
Eigen::Vector4d * points
Point coordinates (x, y, z, 1)
Definition point_cloud.hpp:106
Voxel meta information.
Definition incremental_voxelmap.hpp:13