Autoware.Auto
ndt_map.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.
16 
17 #ifndef NDT__NDT_MAP_HPP_
18 #define NDT__NDT_MAP_HPP_
19 
20 #include <ndt/ndt_common.hpp>
21 #include <ndt/ndt_voxel.hpp>
22 #include <ndt/ndt_voxel_view.hpp>
23 #include <sensor_msgs/point_cloud2_iterator.hpp>
25 #include <vector>
26 #include <limits>
27 #include <unordered_map>
28 #include <utility>
29 #include <string>
30 #include "common/types.hpp"
31 
33 
34 namespace autoware
35 {
36 namespace localization
37 {
38 namespace ndt
39 {
47 uint32_t NDT_PUBLIC validate_pcl_map(const sensor_msgs::msg::PointCloud2 & msg);
48 
50 
51 template<typename Derived, typename VoxelT>
53 {
54 public:
55  using Grid = std::unordered_map<uint64_t, VoxelT>;
56  using Point = Eigen::Vector3d;
58  using TimePoint = std::chrono::system_clock::time_point;
59  using VoxelViewVector = std::vector<VoxelView<VoxelT>>;
60 
63  explicit NDTMapBase(const Config & voxel_grid_config)
64  : m_config(voxel_grid_config), m_map(m_config.get_capacity())
65  {
66  m_output_vector.reserve(1U);
67  }
68 
69  // Maps should be moved rather than being copied.
70  NDTMapBase(const NDTMapBase &) = delete;
71  NDTMapBase & operator=(const NDTMapBase &) = delete;
72 
73  // Explicitly declaring to default is needed since we explicitly deleted the copy methods.
74  NDTMapBase(NDTMapBase &&) = default;
75  NDTMapBase & operator=(NDTMapBase &&) = default;
76 
84  {
85  return cell(Point({x, y, z}));
86  }
87 
92  const VoxelViewVector & cell(const Point & pt) const
93  {
94  // TODO(yunus.caliskan): revisit after multi-cell lookup support.
95  m_output_vector.clear();
96  const auto vx_it = m_map.find(m_config.index(pt));
97  // Only return a voxel if it's occupied (i.e. has enough points to compute covariance.)
98  if (vx_it != m_map.end() && vx_it->second.usable()) {
99  m_output_vector.emplace_back(vx_it->second);
100  }
101  return m_output_vector;
102  }
103 
106  void insert(const sensor_msgs::msg::PointCloud2 & msg)
107  {
108  m_stamp = ::time_utils::from_message(msg.header.stamp);
109  m_frame_id = msg.header.frame_id;
110  this->impl().insert_(msg);
111  }
112 
116  uint64_t size() const noexcept
117  {
118  return m_map.size();
119  }
120 
123  auto cell_size() const noexcept
124  {
125  return m_config.get_voxel_size();
126  }
127 
130  typename Grid::const_iterator begin() const noexcept
131  {
132  return cbegin();
133  }
136  typename Grid::iterator begin() noexcept
137  {
138  return m_map.begin();
139  }
142  typename Grid::const_iterator cbegin() const noexcept
143  {
144  return m_map.cbegin();
145  }
148  typename Grid::const_iterator end() const noexcept
149  {
150  return cend();
151  }
154  typename Grid::iterator end() noexcept
155  {
156  return m_map.end();
157  }
160  typename Grid::const_iterator cend() const noexcept
161  {
162  return m_map.cend();
163  }
164 
166  void clear() noexcept
167  {
168  m_map.clear();
169  }
170 
173  TimePoint stamp() const noexcept
174  {
175  return m_stamp;
176  }
177 
180  const std::string & frame_id() const noexcept
181  {
182  return m_frame_id;
183  }
184 
185 protected:
189  auto index(const Point & pt) const
190  {
191  return m_config.index(pt);
192  }
193 
198  VoxelT & voxel(uint64_t idx)
199  {
200  return m_map[idx];
201  }
202 
203  auto emplace(uint64_t key, const VoxelT && vx)
204  {
205  return m_map.emplace(key, std::move(vx));
206  }
207 
208 private:
209  mutable VoxelViewVector m_output_vector;
210  const Config m_config;
211  Grid m_map;
212  TimePoint m_stamp{};
213  std::string m_frame_id{};
214 };
215 
216 
219 class NDT_PUBLIC DynamicNDTMap
220  : public NDTMapBase<DynamicNDTMap, DynamicNDTVoxel>
221 {
222 public:
224  using Grid = std::unordered_map<uint64_t, Voxel>;
226  using Point = Eigen::Vector3d;
227 
229 
233  void insert_(const sensor_msgs::msg::PointCloud2 & msg)
234  {
235  sensor_msgs::PointCloud2ConstIterator<float32_t> x_it(msg, "x");
236  sensor_msgs::PointCloud2ConstIterator<float32_t> y_it(msg, "y");
237  sensor_msgs::PointCloud2ConstIterator<float32_t> z_it(msg, "z");
238 
239  while (x_it != x_it.end() &&
240  y_it != y_it.end() &&
241  z_it != z_it.end())
242  {
243  const auto pt = Point({*x_it, *y_it, *z_it});
244  const auto voxel_idx = index(pt);
245  voxel(voxel_idx).add_observation(pt); // Add or insert new voxel.
246 
247  ++x_it;
248  ++y_it;
249  ++z_it;
250  }
251  // try to stabilizie the covariance after inserting all the points
252  for (auto & vx_it : *this) {
253  auto & vx = vx_it.second;
254  (void) vx.try_stabilize();
255  }
256  }
257 };
258 
262 class NDT_PUBLIC StaticNDTMap
263  : public NDTMapBase<StaticNDTMap, StaticNDTVoxel>
264 {
265 public:
268 
277  void insert_(const sensor_msgs::msg::PointCloud2 & msg)
278  {
279  if (validate_pcl_map(msg) == 0U) {
280  // throwing rather than silently failing since ndt matching cannot be done with an
281  // empty/incorrect map
282  throw std::runtime_error(
283  "Point cloud representing the ndt map is either empty"
284  "or does not have the correct format.");
285  }
286 
287  sensor_msgs::PointCloud2ConstIterator<Real> x_it(msg, "x");
288  sensor_msgs::PointCloud2ConstIterator<Real> y_it(msg, "y");
289  sensor_msgs::PointCloud2ConstIterator<Real> z_it(msg, "z");
290  sensor_msgs::PointCloud2ConstIterator<Real> icov_xx_it(msg, "icov_xx");
291  sensor_msgs::PointCloud2ConstIterator<Real> icov_xy_it(msg, "icov_xy");
292  sensor_msgs::PointCloud2ConstIterator<Real> icov_xz_it(msg, "icov_xz");
293  sensor_msgs::PointCloud2ConstIterator<Real> icov_yy_it(msg, "icov_yy");
294  sensor_msgs::PointCloud2ConstIterator<Real> icov_yz_it(msg, "icov_yz");
295  sensor_msgs::PointCloud2ConstIterator<Real> icov_zz_it(msg, "icov_zz");
296  sensor_msgs::PointCloud2ConstIterator<uint32_t> cell_id_it(msg, "cell_id");
297 
298  while (x_it != x_it.end() &&
299  y_it != y_it.end() &&
300  z_it != z_it.end() &&
301  icov_xx_it != icov_xx_it.end() &&
302  icov_xy_it != icov_xy_it.end() &&
303  icov_xz_it != icov_xz_it.end() &&
304  icov_yy_it != icov_yy_it.end() &&
305  icov_yz_it != icov_yz_it.end() &&
306  icov_zz_it != icov_zz_it.end() &&
307  cell_id_it != cell_id_it.end())
308  {
309  const Point centroid{*x_it, *y_it, *z_it};
310  const auto voxel_idx = index(centroid);
311 
312  // Since no native usigned long support is vailable for a point field
313  // the `cell_id_it` points to an array of two 32 bit integers to represent
314  // a long number. So the assignments must be done via memcpy.
315  Grid::key_type received_idx = 0U;
316  std::memcpy(&received_idx, &cell_id_it[0U], sizeof(received_idx));
317 
318  // If the pointcloud does not represent a voxel grid of identical configuration,
319  // report the error
320  if (voxel_idx != received_idx) {
321  throw std::domain_error(
322  "NDTVoxelMap: Pointcloud representing the ndt map"
323  "does not have a matching grid configuration with "
324  "the map representation it is being inserted to. The cell IDs do not matchb");
325  }
326 
327  Eigen::Matrix3d inv_covariance;
328  inv_covariance << *icov_xx_it, *icov_xy_it, *icov_xz_it,
329  *icov_xy_it, *icov_yy_it, *icov_yz_it,
330  *icov_xz_it, *icov_yz_it, *icov_zz_it;
331  const Voxel vx{centroid, inv_covariance};
332 
333  const auto insert_res = emplace(voxel_idx, Voxel{centroid, inv_covariance});
334  if (!insert_res.second) {
335  // if a voxel already exist at this point, replace.
336  insert_res.first->second = vx;
337  }
338 
339  ++x_it;
340  ++y_it;
341  ++z_it;
342  ++icov_xx_it;
343  ++icov_xy_it;
344  ++icov_xz_it;
345  ++icov_yy_it;
346  ++icov_yz_it;
347  ++icov_zz_it;
348  ++cell_id_it;
349  }
350  }
351 };
352 
353 } // namespace ndt
354 } // namespace localization
355 
356 namespace common
357 {
358 namespace geometry
359 {
360 namespace point_adapter
361 {
365 template<>
366 inline NDT_PUBLIC auto x_(const Eigen::Vector3d & pt)
367 {
368  return static_cast<float32_t>(pt(0));
369 }
370 
371 template<>
372 inline NDT_PUBLIC auto y_(const Eigen::Vector3d & pt)
373 {
374  return static_cast<float32_t>(pt(1));
375 }
376 
377 template<>
378 inline NDT_PUBLIC auto z_(const Eigen::Vector3d & pt)
379 {
380  return static_cast<float32_t>(pt(2));
381 }
382 
383 template<>
384 inline NDT_PUBLIC auto & xr_(Eigen::Vector3d & pt)
385 {
386  return pt(0);
387 }
388 
389 template<>
390 inline NDT_PUBLIC auto & yr_(Eigen::Vector3d & pt)
391 {
392  return pt(1);
393 }
394 
395 template<>
396 inline NDT_PUBLIC auto & zr_(Eigen::Vector3d & pt)
397 {
398  return pt(2);
399 }
400 } // namespace point_adapter
401 } // namespace geometry
402 } // namespace common
403 } // namespace autoware
404 #endif // NDT__NDT_MAP_HPP_
autoware::localization::ndt::NDTMapBase::begin
Grid::iterator begin() noexcept
Returns an iterator to the first element of the map.
Definition: ndt_map.hpp:136
autoware::localization::ndt::NDTMapBase::cend
Grid::const_iterator cend() const noexcept
Returns a const iterator to one past the last element of the map.
Definition: ndt_map.hpp:160
autoware::localization::ndt::NDTMapBase::stamp
TimePoint stamp() const noexcept
Definition: ndt_map.hpp:173
autoware::localization::ndt::NDTMapBase< StaticNDTMap, StaticNDTVoxel >::Point
Eigen::Vector3d Point
Definition: ndt_map.hpp:56
autoware::localization::ndt::NDTMapBase::begin
Grid::const_iterator begin() const noexcept
Returns an const iterator to the first element of the map.
Definition: ndt_map.hpp:130
autoware::localization::ndt::NDTMapBase< StaticNDTMap, StaticNDTVoxel >::TimePoint
std::chrono::system_clock::time_point TimePoint
Definition: ndt_map.hpp:58
autoware::perception::filters::voxel_grid::Config::get_voxel_size
const PointXYZ & get_voxel_size() const
Gets the voxel size of the voxel grid.
Definition: perception/filters/voxel_grid/src/config.cpp:115
autoware::localization::ndt::NDTMapBase::index
auto index(const Point &pt) const
Definition: ndt_map.hpp:189
autoware::localization::ndt::NDTMapBase::emplace
auto emplace(uint64_t key, const VoxelT &&vx)
Definition: ndt_map.hpp:203
autoware::common::geometry::point_adapter::x_
auto x_(const PointT &pt)
Gets the x value for a point.
Definition: common_2d.hpp:47
autoware::localization::ndt::DynamicNDTMap::insert_
void insert_(const sensor_msgs::msg::PointCloud2 &msg)
Definition: ndt_map.hpp:233
types.hpp
This file includes common type definition.
y
DifferentialState y
Definition: kinematic_bicycle.snippet.hpp:28
autoware::localization::ndt::NDTMapBase::end
Grid::iterator end() noexcept
Returns an iterator to one past the last element of the map.
Definition: ndt_map.hpp:154
ndt_voxel_view.hpp
autoware::localization::ndt::NDTMapBase::cell
const VoxelViewVector & cell(float32_t x, float32_t y, float32_t z) const
Definition: ndt_map.hpp:83
autoware::localization::ndt::NDTMapBase::cell_size
auto cell_size() const noexcept
Definition: ndt_map.hpp:123
autoware::localization::ndt::StaticNDTVoxel
Definition: ndt_voxel.hpp:98
autoware::common::geometry::Point
geometry_msgs::msg::Point32 Point
Definition: intersection.hpp:52
autoware::localization::ndt::NDTMapBase::cbegin
Grid::const_iterator cbegin() const noexcept
Returns a const iterator to the first element of the map.
Definition: ndt_map.hpp:142
autoware::localization::ndt::NDTMapBase::end
Grid::const_iterator end() const noexcept
Returns a const iterator to one past the last element of the map.
Definition: ndt_map.hpp:148
autoware
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24
autoware::common::geometry::point_adapter::yr_
auto & yr_(PointT &pt)
Gets a reference to the y value for a point.
Definition: common_2d.hpp:83
autoware::localization::ndt::StaticNDTMap::insert_
void insert_(const sensor_msgs::msg::PointCloud2 &msg)
Definition: ndt_map.hpp:277
autoware::common::helper_functions::crtp::impl
const Derived & impl() const
Definition: crtp.hpp:32
autoware::localization::ndt::NDTMapBase::operator=
NDTMapBase & operator=(const NDTMapBase &)=delete
autoware::localization::ndt::NDTMapBase::Config
autoware::perception::filters::voxel_grid::Config Config
Definition: ndt_map.hpp:57
autoware::common::helper_functions::crtp
Definition: crtp.hpp:29
ndt_common.hpp
autoware::localization::ndt::DynamicNDTMap
Definition: ndt_map.hpp:219
autoware::localization::ndt::NDTMapBase< StaticNDTMap, StaticNDTVoxel >::VoxelViewVector
std::vector< VoxelView< StaticNDTVoxel > > VoxelViewVector
Definition: ndt_map.hpp:59
autoware::localization::ndt::validate_pcl_map
uint32_t NDT_PUBLIC validate_pcl_map(const sensor_msgs::msg::PointCloud2 &msg)
Definition: ndt_map.cpp:28
autoware::localization::ndt::NDTMapBase::voxel
VoxelT & voxel(uint64_t idx)
Definition: ndt_map.hpp:198
autoware::localization::ndt::DynamicNDTMap::Grid
std::unordered_map< uint64_t, Voxel > Grid
Definition: ndt_map.hpp:224
time_utils::from_message
TIME_UTILS_PUBLIC std::chrono::system_clock::time_point from_message(builtin_interfaces::msg::Time t) noexcept
Convert from std::chrono::time_point from time message.
Definition: time_utils.cpp:84
x
DifferentialState x
Definition: kinematic_bicycle.snippet.hpp:28
autoware::localization::ndt::NDTMapBase
Definition: ndt_map.hpp:52
autoware::common::types::float32_t
float float32_t
Definition: types.hpp:36
autoware::perception::filters::voxel_grid::Config
A configuration class for the VoxelGrid data structure, also includes some helper functionality for c...
Definition: perception/filters/voxel_grid/include/voxel_grid/config.hpp:52
autoware::localization::ndt::NDTMapBase< StaticNDTMap, StaticNDTVoxel >::Grid
std::unordered_map< uint64_t, StaticNDTVoxel > Grid
Definition: ndt_map.hpp:55
autoware::common::geometry::point_adapter::xr_
auto & xr_(PointT &pt)
Gets a reference to the x value for a point.
Definition: common_2d.hpp:74
autoware::localization::ndt::NDTMapBase::clear
void clear() noexcept
Clear all voxels in the map.
Definition: ndt_map.hpp:166
autoware::localization::ndt::StaticNDTMap
Definition: ndt_map.hpp:262
time_utils.hpp
ndt_voxel.hpp
autoware::localization::ndt::NDTMapBase::NDTMapBase
NDTMapBase(const Config &voxel_grid_config)
Definition: ndt_map.hpp:63
autoware::localization::ndt::DynamicNDTVoxel
Definition: ndt_voxel.hpp:44
autoware::common::geometry::point_adapter::y_
auto y_(const PointT &pt)
Gets the y value for a point.
Definition: common_2d.hpp:56
autoware::localization::ndt::NDTMapBase::insert
void insert(const sensor_msgs::msg::PointCloud2 &msg)
Definition: ndt_map.hpp:106
autoware::common::geometry::point_adapter::z_
auto z_(const PointT &pt)
Gets the z value for a point.
Definition: common_2d.hpp:65
autoware::localization::ndt::NDTMapBase::size
uint64_t size() const noexcept
Definition: ndt_map.hpp:116
autoware::common::geometry::point_adapter::zr_
auto & zr_(PointT &pt)
Gets a reference to the z value for a point.
Definition: common_2d.hpp:92
autoware::localization::ndt::NDTMapBase::frame_id
const std::string & frame_id() const noexcept
Definition: ndt_map.hpp:180
autoware::perception::filters::voxel_grid::Config::index
uint64_t index(const PointT &pt) const
Computes index for a given point given the voxelgrid configuration parameters.
Definition: perception/filters/voxel_grid/include/voxel_grid/config.hpp:84
autoware::localization::ndt::DynamicNDTMap::Point
Eigen::Vector3d Point
Definition: ndt_map.hpp:226
autoware::localization::ndt::NDTMapBase::cell
const VoxelViewVector & cell(const Point &pt) const
Definition: ndt_map.hpp:92