Gazebo Math

API Reference

8.1.0
VolumetricGridLookupField.hh
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 Open Source Robotics Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18#ifndef GZ_MATH_VOLUMETRIC_GRID_LOOKUP_FIELD_HH_
19#define GZ_MATH_VOLUMETRIC_GRID_LOOKUP_FIELD_HH_
20
21#include <optional>
22#include <utility>
23#include <vector>
24
25#include <gz/math/Vector3.hh>
26#include <gz/math/detail/InterpolationPoint.hh>
27
28#include <gz/math/detail/AxisIndex.hh>
29
30namespace gz::math
31{
32 // Inline bracket to help doxygen filtering.
33 inline namespace GZ_MATH_VERSION_NAMESPACE {
34 template<typename T, typename I = std::size_t>
40 {
42 private: AxisIndex<T> z_indices_by_depth;
43
44 private: AxisIndex<T> x_indices_by_lat;
45
46 private: AxisIndex<T> y_indices_by_lon;
47
48 private: std::vector<
50
55 {
56 // NOTE: This part of the code assumes an exact grid of points.
57 // The grid may be distorted or the stride between different points
58 // may not be the same, but fundamentally the data is structured still
59 // forms a grid-like structure. It keeps track of the axis indices for
60 // each point in the grid.
61 for(auto pt : _cloud)
62 {
63 x_indices_by_lat.AddIndexIfNotFound(pt.X());
64 y_indices_by_lon.AddIndexIfNotFound(pt.Y());
65 z_indices_by_depth.AddIndexIfNotFound(pt.Z());
66 }
67
68 int num_x = x_indices_by_lat.GetNumUniqueIndices();
69 int num_y = y_indices_by_lon.GetNumUniqueIndices();
70 int num_z = z_indices_by_depth.GetNumUniqueIndices();
71
72 index_table.resize(num_z);
73 for(int i = 0; i < num_z; ++i)
74 {
75 index_table[i].resize(num_y);
76 for(int j = 0; j < num_y; ++j)
77 {
78 index_table[i][j].resize(num_x);
79 }
80 }
81
82 for(std::size_t i = 0; i < _cloud.size(); ++i)
83 {
84 const auto &pt = _cloud[i];
85 const std::size_t x_index =
86 x_indices_by_lat.GetIndex(pt.X()).value();
87 const std::size_t y_index =
88 y_indices_by_lon.GetIndex(pt.Y()).value();
89 const std::size_t z_index =
90 z_indices_by_depth.GetIndex(pt.Z()).value();
91 index_table[z_index][y_index][x_index] = i;
92 }
93 }
94
110 const Vector3<T> &_pt,
111 const double _xTol = 1e-6,
112 const double _yTol = 1e-6,
113 const double _zTol = 1e-6) const
114 {
116
117 auto x_indices = x_indices_by_lat.GetInterpolators(_pt.X(), _xTol);
118 auto y_indices = y_indices_by_lon.GetInterpolators(_pt.Y(), _yTol);
119 auto z_indices = z_indices_by_depth.GetInterpolators(_pt.Z(), _zTol);
120
121 for(const auto &x_index : x_indices)
122 {
123 for(const auto &y_index : y_indices)
124 {
125 for(const auto &z_index : z_indices)
126 {
127 auto index =
128 index_table[z_index.index][y_index.index][x_index.index];
129 interpolators.push_back(
132 x_index.position,
133 y_index.position,
134 z_index.position
135 ),
136 std::optional{index}
137 });
138 }
139 }
140 }
141
142 return interpolators;
143 }
144
151 {
152 assert(_indices.size() == _cloud.size());
153 // NOTE: This part of the code assumes an exact grid of points.
154 // The grid may be distorted or the stride between different points
155 // may not be the same, but fundamentally the data is structured in
156 // a grid-like structure. It keeps track of the axis indices for
157 // each point in the grid.
158 for(auto pt : _cloud)
159 {
160 x_indices_by_lat.AddIndexIfNotFound(pt.X());
161 y_indices_by_lon.AddIndexIfNotFound(pt.Y());
162 z_indices_by_depth.AddIndexIfNotFound(pt.Z());
163 }
164
165 int num_x = x_indices_by_lat.GetNumUniqueIndices();
166 int num_y = y_indices_by_lon.GetNumUniqueIndices();
167 int num_z = z_indices_by_depth.GetNumUniqueIndices();
168
169 index_table.resize(num_z);
170 for(int i = 0; i < num_z; ++i)
171 {
172 index_table[i].resize(num_y);
173 for(int j = 0; j < num_y; ++j)
174 {
175 index_table[i][j].resize(num_x);
176 }
177 }
178
179 for(std::size_t i = 0; i < _cloud.size(); ++i)
180 {
181 const auto &pt = _cloud[i];
182 const std::size_t x_index =
183 x_indices_by_lat.GetIndex(pt.X()).value();
184 const std::size_t y_index =
185 y_indices_by_lon.GetIndex(pt.Y()).value();
186 const std::size_t z_index =
187 z_indices_by_depth.GetIndex(pt.Z()).value();
188 index_table[z_index][y_index][x_index] = _indices[i];
189 }
190 }
191
199 public: template<typename V>
201 const Vector3<T> &_pt,
202 const std::vector<V> &_values,
203 const V &_default = V(0)) const
204 {
205 auto interpolators = GetInterpolators(_pt);
206 return EstimateValueUsingTrilinear(
208 _pt,
209 _values,
210 _default);
211 }
212
224 public: template<typename V>
227 const Vector3<T> &_pt,
228 const std::vector<V> &_values,
229 const V &_default = V(0)) const
230 {
231 if (_interpolators.size() == 0)
232 {
233 return std::nullopt;
234 }
235 else if (_interpolators.size() == 1)
236 {
237 if (!_interpolators[0].index.has_value())
238 {
239 return _default;
240 }
241 return _values[_interpolators[0].index.value()];
242 }
243 else if (_interpolators.size() == 2)
244 {
247 }
248 else if (_interpolators.size() == 4)
249 {
250 return BiLinearInterpolate(
252 }
253 else if (_interpolators.size() == 8)
254 {
256 }
257 else
258 {
259 // should never get here
260 return std::nullopt;
261 }
262 }
263
267 {
270 x_indices_by_lat.MinKey(),
271 y_indices_by_lon.MinKey(),
272 z_indices_by_depth.MinKey()
273 },
275 x_indices_by_lat.MaxKey(),
276 y_indices_by_lon.MaxKey(),
277 z_indices_by_depth.MaxKey()
278 });
279 }
280
281 };
282 } // namespace GZ_MATH_VERSION_NAMESPACE
283} // namespace gz::math
284#endif // GZ_MATH_VOLUMETRIC_GRID_LOOKUP_FIELD_HH_