Autoware.Auto
spatial_hash_config.hpp
Go to the documentation of this file.
1 // Copyright 2019 the Autoware Foundation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Co-developed by Tier IV, Inc. and Apex.AI, Inc.
19 
20 #ifndef GEOMETRY__SPATIAL_HASH_CONFIG_HPP_
21 #define GEOMETRY__SPATIAL_HASH_CONFIG_HPP_
22 
23 #include <common/types.hpp>
25 #include <geometry/common_2d.hpp>
26 
27 #include <algorithm>
28 #include <cmath>
29 #include <limits>
30 #include <stdexcept>
31 #include <utility>
32 
34 
38 
39 namespace autoware
40 {
41 namespace common
42 {
43 namespace geometry
44 {
46 namespace spatial_hash
47 {
49 using Index = std::size_t;
51 namespace details
52 {
59 struct GEOMETRY_PUBLIC Index3
60 {
64 }; // struct Index3
65 
66 using BinRange = std::pair<Index3, Index3>;
67 } // namespace details
68 
71 template<typename Derived>
72 class GEOMETRY_PUBLIC Config : public autoware::common::helper_functions::crtp<Derived>
73 {
74 public:
85  const float32_t min_x,
86  const float32_t max_x,
87  const float32_t min_y,
88  const float32_t max_y,
89  const float32_t min_z,
90  const float32_t max_z,
91  const float32_t radius,
92  const Index capacity)
93  : m_min_x{min_x},
94  m_min_y{min_y},
95  m_min_z{min_z},
96  m_max_x{max_x},
97  m_max_y{max_y},
98  m_max_z{max_z},
99  m_side_length{radius},
100  m_side_length2{radius * radius},
101  m_side_length_inv{1.0F / radius},
102  m_capacity{capacity},
103  m_max_x_idx{check_basis_direction(min_x, max_x)},
104  m_max_y_idx{check_basis_direction(min_y, max_y)},
105  m_max_z_idx{check_basis_direction(min_z, max_z)},
106  m_y_stride{m_max_x_idx + 1U},
107  m_z_stride{m_y_stride * (m_max_y_idx + 1U)}
108  {
109  if (radius <= 0.0F) {
110  throw std::domain_error("Error constructing SpatialHash: must have positive side length");
111  }
112 
113  if ((m_max_y_idx + m_y_stride) > std::numeric_limits<Index>::max() / 2U) {
114  // TODO(c.ho) properly check for multiplication overflow
115  throw std::domain_error("SpatialHash::Config: voxel index may overflow!");
116  }
117  // small fudging to prevent weird boundary effects
118  // (e.g (x=xmax, y) rolls index over to (x=0, y+1)
119  constexpr auto FEPS = std::numeric_limits<float32_t>::epsilon();
120  //lint -e{1938} read only access is fine NOLINT
121  m_max_x -= FEPS;
122  m_max_y -= FEPS;
123  m_max_z -= FEPS;
124  if ((m_z_stride + m_max_z_idx) > std::numeric_limits<Index>::max() / 2U) {
125  // TODO(c.ho) properly check for multiplication overflow
126  throw std::domain_error("SpatialHash::Config: voxel index may overflow!");
127  }
128  // I don't know if this is even possible given other checks
129  if (std::numeric_limits<Index>::max() == m_max_z_idx) {
130  throw std::domain_error("SpatialHash::Config: max z index exceeds reasonable value");
131  }
132  }
133 
139  {
140  // Compute distance in units of voxels
141  constexpr Index iradius = 1;
142  // Dumb ternary because potentially unsigned Index type
143  const Index xmin = (ref.x > iradius) ? (ref.x - iradius) : 0U;
144  const Index ymin = (ref.y > iradius) ? (ref.y - iradius) : 0U;
145  const Index zmin = (ref.z > iradius) ? (ref.z - iradius) : 0U;
146  // In 2D mode, m_max_z should be 0, same with ref.z
147  const Index xmax = std::min(ref.x + iradius, m_max_x_idx);
148  const Index ymax = std::min(ref.y + iradius, m_max_y_idx);
149  const Index zmax = std::min(ref.z + iradius, m_max_z_idx);
150  // return bottom-left portion of cube and top-right portion of cube
151  return {{xmin, ymin, zmin}, {xmax, ymax, zmax}};
152  }
157  bool8_t next_bin(const details::BinRange & range, details::Index3 & idx) const
158  {
159  // TODO(c.ho) is there any way to make this neater without triple nested if?
160  bool8_t ret = true;
161  ++idx.x;
162  if (idx.x > range.second.x) {
163  idx.x = range.first.x;
164  ++idx.y;
165  if (idx.y > range.second.y) {
166  idx.y = range.first.y;
167  ++idx.z;
168  if (idx.z > range.second.z) {
169  ret = false;
170  }
171  }
172  }
173  return ret;
174  }
178  {
179  return m_capacity;
180  }
181 
184  {
185  return m_side_length2;
186  }
187 
189  // "Polymorphic" API
195  Index bin(const float32_t x, const float32_t y, const float32_t z) const
196  {
197  return this->impl().bin_(x, y, z);
198  }
205  bool8_t is_candidate_bin(const details::Index3 & ref, const details::Index3 & query) const
206  {
207  return this->impl().valid(ref, query);
208  }
214  details::Index3 index3(const float32_t x, const float32_t y, const float32_t z) const
215  {
216  return this->impl().index3_(x, y, z);
217  }
221  Index index(const details::Index3 & idx) const
222  {
223  return this->impl().index_(idx);
224  }
232  template<typename PointT>
234  const float32_t x,
235  const float32_t y,
236  const float32_t z,
237  const PointT & pt) const
238  {
239  return this->impl().distance_squared_(x, y, z, pt);
240  }
241 
242 protected:
246  Index x_index(const float32_t x) const
247  {
248  return static_cast<Index>(
249  std::floor((std::min(std::max(x, m_min_x), m_max_x) - m_min_x) * m_side_length_inv));
250  }
254  Index y_index(const float32_t y) const
255  {
256  return static_cast<Index>(
257  std::floor((std::min(std::max(y, m_min_y), m_max_y) - m_min_y) * m_side_length_inv));
258  }
262  Index z_index(const float32_t z) const
263  {
264  return static_cast<Index>(
265  std::floor((std::min(std::max(z, m_min_z), m_max_z) - m_min_z) * m_side_length_inv));
266  }
268  Index bin_impl(const Index xdx, const Index ydx) const
269  {
270  return xdx + (ydx * m_y_stride);
271  }
273  Index bin_impl(const Index xdx, const Index ydx, const Index zdx) const
274  {
275  return bin_impl(xdx, ydx) + (zdx * m_z_stride);
276  }
277 
282  Index bin_impl(const float32_t x, const float32_t y) const
283  {
284  return bin_impl(x_index(x), y_index(y));
285  }
291  Index bin_impl(const float32_t x, const float32_t y, const float32_t z) const
292  {
293  return bin_impl(x, y) + (z_index(z) * m_z_stride);
294  }
297  float32_t idx_distance(const Index ref_idx, const Index query_idx) const
298  {
300  const Index idist = (ref_idx >= query_idx) ? (ref_idx - query_idx) : (query_idx - ref_idx);
301  float32_t dist = static_cast<float32_t>(idist) - 1.0F;
302  return std::max(dist, 0.0F);
303  }
304 
305 private:
308  Index check_basis_direction(const float32_t min, const float32_t max) const
309  {
310  if (min >= max) {
311  throw std::domain_error("SpatialHash::Config: must have min < max");
312  }
313  // This family of checks is to ensure that you don't get weird casting effects due to huge
314  // floating point values
315  const float64_t dmax = static_cast<float64_t>(max);
316  const float64_t dmin = static_cast<float64_t>(min);
317  const float64_t width = (dmax - dmin) * static_cast<float64_t>(m_side_length_inv);
318  constexpr float64_t fltmax = static_cast<float64_t>(std::numeric_limits<float32_t>::max());
319  if (fltmax <= width) {
320  throw std::domain_error("SpatialHash::Config: voxel size approaching floating point limit");
321  }
322  return static_cast<Index>(width);
323  }
324  float32_t m_min_x;
325  float32_t m_min_y;
326  float32_t m_min_z;
327  float32_t m_max_x;
328  float32_t m_max_y;
329  float32_t m_max_z;
330  float32_t m_side_length;
331  float32_t m_side_length2;
332  float32_t m_side_length_inv;
333  Index m_capacity;
334  Index m_max_x_idx;
335  Index m_max_y_idx;
336  Index m_max_z_idx;
337  Index m_y_stride;
338  Index m_z_stride;
339 }; // class Config
340 
342 class GEOMETRY_PUBLIC Config2d : public Config<Config2d>
343 {
344 public:
352  Config2d(
353  const float32_t min_x,
354  const float32_t max_x,
355  const float32_t min_y,
356  const float32_t max_y,
357  const float32_t radius,
358  const Index capacity);
364  Index bin_(const float32_t x, const float32_t y, const float32_t z) const;
371  bool8_t valid(const details::Index3 & ref, const details::Index3 & query) const;
377  details::Index3 index3_(const float32_t x, const float32_t y, const float32_t z) const;
381  Index index_(const details::Index3 & idx) const;
389  template<typename PointT>
391  const float32_t x,
392  const float32_t y,
393  const float32_t z,
394  const PointT & pt) const
395  {
396  (void)z;
397  const float32_t dx = x - point_adapter::x_(pt);
398  const float32_t dy = y - point_adapter::y_(pt);
399  return (dx * dx) + (dy * dy);
400  }
401 }; // class Config2d
402 
404 class GEOMETRY_PUBLIC Config3d : public Config<Config3d>
405 {
406 public:
416  Config3d(
417  const float32_t min_x,
418  const float32_t max_x,
419  const float32_t min_y,
420  const float32_t max_y,
421  const float32_t min_z,
422  const float32_t max_z,
423  const float32_t radius,
424  const Index capacity);
430  Index bin_(const float32_t x, const float32_t y, const float32_t z) const;
437  bool8_t valid(const details::Index3 & ref, const details::Index3 & query) const;
443  details::Index3 index3_(const float32_t x, const float32_t y, const float32_t z) const;
447  Index index_(const details::Index3 & idx) const;
455  template<typename PointT>
457  const float32_t x,
458  const float32_t y,
459  const float32_t z,
460  const PointT & pt) const
461  {
462  const float32_t dx = x - point_adapter::x_(pt);
463  const float32_t dy = y - point_adapter::y_(pt);
464  const float32_t dz = z - point_adapter::z_(pt);
465  return (dx * dx) + (dy * dy) + (dz * dz);
466  }
467 }; // class Config3d
468 } // namespace spatial_hash
469 } // namespace geometry
470 } // namespace common
471 } // namespace autoware
472 
473 #endif // GEOMETRY__SPATIAL_HASH_CONFIG_HPP_
double float64_t
Definition: types.hpp:37
Internal struct for packing three indices together.
Definition: spatial_hash_config.hpp:59
This file includes common functionality for 2D geometry, such as dot products.
Config(const float32_t min_x, const float32_t max_x, const float32_t min_y, const float32_t max_y, const float32_t min_z, const float32_t max_z, const float32_t radius, const Index capacity)
Constructor for spatial hash.
Definition: spatial_hash_config.hpp:84
Index index(const details::Index3 &idx) const
Compute the composed single index given a decomposed index.
Definition: spatial_hash_config.hpp:221
float float32_t
Definition: types.hpp:36
bool8_t next_bin(const details::BinRange &range, details::Index3 &idx) const
Get next index within a given range.
Definition: spatial_hash_config.hpp:157
Index x_index(const float32_t x) const
Computes the index in the x basis direction.
Definition: spatial_hash_config.hpp:246
Index bin_impl(const float32_t x, const float32_t y) const
The index offset of a point given it&#39;s x and y values.
Definition: spatial_hash_config.hpp:282
dx
Definition: catr_diff.py:38
bool bool8_t
Definition: types.hpp:33
Index z
Definition: spatial_hash_config.hpp:63
This file includes common type definition.
Index bin_impl(const float32_t x, const float32_t y, const float32_t z) const
The index of a point given it&#39;s x, y and z values.
Definition: spatial_hash_config.hpp:291
Index bin(const float32_t x, const float32_t y, const float32_t z) const
Compute the single index given a point.
Definition: spatial_hash_config.hpp:195
The base class for the configuration object for the SpatialHash class.
Definition: spatial_hash_config.hpp:72
Configuration class for a 2d spatial hash.
Definition: spatial_hash_config.hpp:342
float32_t radius2() const
Getter for the side length, equivalently the lookup radius.
Definition: spatial_hash_config.hpp:183
auto z_(const PointT &pt)
Gets the z value for a point.
Definition: common_2d.hpp:65
This file includes common helper functions.
DifferentialState x
Definition: kinematic_bicycle.snippet.hpp:28
float32_t distance_squared_(const float32_t x, const float32_t y, const float32_t z, const PointT &pt) const
Compute the squared distance between the two points, 2d implementation.
Definition: spatial_hash_config.hpp:390
details::BinRange bin_range(const details::Index3 &ref) const
Given a reference index triple, compute the first and last bin.
Definition: spatial_hash_config.hpp:138
Index bin_impl(const Index xdx, const Index ydx, const Index zdx) const
Compose the provided index offsets.
Definition: spatial_hash_config.hpp:273
bool8_t is_candidate_bin(const details::Index3 &ref, const details::Index3 &query) const
Compute whether the query bin and reference bin could possibly contain a pair of points such that the...
Definition: spatial_hash_config.hpp:205
std::size_t Index
Index type for identifying bins of the hash/lattice.
Definition: spatial_hash_config.hpp:49
Index x
Definition: spatial_hash_config.hpp:61
details::Index3 index3(const float32_t x, const float32_t y, const float32_t z) const
Compute the decomposed index given a point.
Definition: spatial_hash_config.hpp:214
Index y
Definition: spatial_hash_config.hpp:62
std::pair< Index3, Index3 > BinRange
Definition: spatial_hash_config.hpp:66
Index get_capacity() const
Get the maximum capacity of the spatial hash.
Definition: spatial_hash_config.hpp:177
DifferentialState y
Definition: kinematic_bicycle.snippet.hpp:28
auto x_(const PointT &pt)
Gets the x value for a point.
Definition: common_2d.hpp:47
float32_t idx_distance(const Index ref_idx, const Index query_idx) const
The distance between two indices as a float, where adjacent indices have zero distance (e...
Definition: spatial_hash_config.hpp:297
float32_t distance_squared(const float32_t x, const float32_t y, const float32_t z, const PointT &pt) const
Compute the squared distance between the two points.
Definition: spatial_hash_config.hpp:233
dy
Definition: catr_diff.py:39
float32_t distance_squared_(const float32_t x, const float32_t y, const float32_t z, const PointT &pt) const
Compute the squared distance between the two points, 3d implementation.
Definition: spatial_hash_config.hpp:456
auto y_(const PointT &pt)
Gets the y value for a point.
Definition: common_2d.hpp:56
Configuration class for a 3d spatial hash.
Definition: spatial_hash_config.hpp:404
Index y_index(const float32_t y) const
Computes the index in the y basis direction.
Definition: spatial_hash_config.hpp:254
Index z_index(const float32_t z) const
Computes the index in the z basis direction.
Definition: spatial_hash_config.hpp:262
Index bin_impl(const Index xdx, const Index ydx) const
Compose the provided index offsets.
Definition: spatial_hash_config.hpp:268
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24