Autoware.Auto
ndt_localizer.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_LOCALIZER_HPP_
18 #define NDT__NDT_LOCALIZER_HPP_
19 
22 #include <sensor_msgs/msg/point_cloud2.hpp>
23 #include <geometry_msgs/msg/transform.hpp>
24 #include <geometry_msgs/msg/pose_with_covariance_stamped.hpp>
25 #include <ndt/ndt_common.hpp>
27 #include <ndt/constraints.hpp>
29 #include <experimental/optional>
30 #include <utility>
31 #include <string>
32 
33 namespace autoware
34 {
35 namespace localization
36 {
37 namespace ndt
38 {
39 using CloudT = sensor_msgs::msg::PointCloud2;
40 
46 template<
47  typename ScanT,
48  typename NDTOptimizationProblemT,
49  typename OptimizationProblemConfigT,
50  typename OptimizerT>
51 class NDT_PUBLIC NDTLocalizerBase
52 {
53 public:
55  using PoseWithCovarianceStamped = geometry_msgs::msg::PoseWithCovarianceStamped;
57 
67  explicit NDTLocalizerBase(
68  const NDTLocalizerConfigBase & config,
69  const OptimizationProblemConfigT & optimization_problem_config,
70  const OptimizerT & optimizer,
71  ScanT && scan)
72  : m_config{config},
73  m_optimization_problem_config{optimization_problem_config},
74  m_optimizer{optimizer},
75  m_scan{std::forward<ScanT>(scan)} {}
76 
91  template<typename MapT,
94  const CloudT & msg,
95  const Transform & transform_initial,
96  const MapT & map,
97  Summary * const summary = nullptr)
98  {
99  PoseWithCovarianceStamped pose_out{};
100  validate_msg(msg, map);
101  validate_guess(msg, transform_initial);
102  // Initial checks passed, proceed with initialization
103  // Eigen representations to be used for internal computations.
104  EigenPose<Real> eig_pose_initial, eig_pose_result;
105  eig_pose_initial.setZero();
106  eig_pose_result.setZero();
107  // Convert the ros transform/pose to eigen pose vector
108  transform_adapters::transform_to_pose(transform_initial.transform, eig_pose_initial);
109 
110  // Set the scan
111  m_scan.clear();
112  m_scan.insert(msg);
113 
114  // Define and solve the problem.
115  NDTOptimizationProblemT problem(m_scan, map, m_optimization_problem_config);
116  const auto opt_summary = m_optimizer.solve(problem, eig_pose_initial, eig_pose_result);
117 
118  if (opt_summary.termination_type() == common::optimization::TerminationType::FAILURE) {
119  throw std::runtime_error(
120  "NDT localizer has likely encountered a numerical "
121  "error during optimization.");
122  }
123 
124  // Convert eigen pose back to ros pose/transform
126  eig_pose_result,
127  pose_out.pose.pose);
128 
129  pose_out.header.stamp = msg.header.stamp;
130  pose_out.header.frame_id = map.frame_id();
131 
132  // Populate covariance information. It is implementation defined.
133  set_covariance(problem, eig_pose_initial, eig_pose_result, pose_out);
134  if (summary != nullptr) {
136  }
137  return pose_out;
138  }
139 
140 
142  const ScanT & scan() const noexcept
143  {
144  return m_scan;
145  }
147  const OptimizerT & optimizer() const noexcept
148  {
149  return m_optimizer;
150  }
152  const NDTLocalizerConfigBase & config() const noexcept
153  {
154  return m_config;
155  }
157  const OptimizationProblemConfigT & optimization_problem_config() const noexcept
158  {
159  return m_optimization_problem_config;
160  }
161 
162 protected:
169  virtual void set_covariance(
170  const NDTOptimizationProblemT & problem,
171  const EigenPose<Real> & initial_guess,
172  const EigenPose<Real> & pose_result,
173  PoseWithCovarianceStamped & solution) const
174  {
175  (void) problem;
176  (void) initial_guess;
177  (void) pose_result;
178  (void) solution;
179  // For now, do nothing.
180  }
181 
187  template<typename MapT>
188  void validate_msg(const CloudT & msg, const MapT & map) const
189  {
190  const auto message_time = ::time_utils::from_message(msg.header.stamp);
191  // Map shouldn't be newer than a measurement.
192  if (message_time < map.stamp()) {
193  throw std::logic_error(
194  "Lidar scan should not have a timestamp older than the timestamp of"
195  "the current map.");
196  }
197  }
198 
204  virtual void validate_guess(const CloudT & msg, const Transform & transform_initial) const
205  {
206  const auto message_time = ::time_utils::from_message(msg.header.stamp);
207 
208  const auto guess_scan_diff = ::time_utils::from_message(transform_initial.header.stamp) -
209  message_time;
210  const auto stamp_tol = m_config.guess_time_tolerance();
211  // An initial estimate should be comparable in time to the measurement's time stamp
212  if (std::abs(
213  std::chrono::duration_cast<std::decay_t<decltype(stamp_tol)>>(guess_scan_diff).
214  count()) >
215  std::abs(stamp_tol.count()))
216  {
217  throw std::domain_error(
218  "Initial guess is not within: " + std::to_string(stamp_tol.count()) +
219  "ns range of the scan's time stamp. Either increase the tolerance range or"
220  "make sure the localizer takes in timely initial pose guesses.");
221  }
222  }
223 
224 private:
225  NDTLocalizerConfigBase m_config;
226  OptimizationProblemConfigT m_optimization_problem_config;
227  OptimizerT m_optimizer;
228  ScanT m_scan;
229 };
230 
236 template<typename OptimizerT, typename MapT = StaticNDTMap>
237 class NDT_PUBLIC P2DNDTLocalizer : public NDTLocalizerBase<
238  P2DNDTScan, P2DNDTOptimizationProblem<MapT>, P2DNDTOptimizationConfig, OptimizerT>
239 {
240 public:
241  using CloudT = sensor_msgs::msg::PointCloud2;
242  using ParentT = NDTLocalizerBase<
244  using Transform = typename ParentT::Transform;
246  using ScanT = P2DNDTScan;
247 
248  explicit P2DNDTLocalizer(
249  const P2DNDTLocalizerConfig & config,
250  const OptimizerT & optimizer,
251  const Real outlier_ratio)
252  : ParentT{
253  config,
254  P2DNDTOptimizationConfig{outlier_ratio},
255  optimizer,
256  ScanT{config.scan_capacity()}} {}
257 
258 protected:
260  const P2DNDTOptimizationProblem<MapT> &,
261  const EigenPose<Real> &,
262  const EigenPose<Real> &,
263  PoseWithCovarianceStamped &) const override
264  {
265  // For now, do nothing.
266  }
267 };
268 
269 } // namespace ndt
270 } // namespace localization
271 } // namespace autoware
272 
273 #endif // NDT__NDT_LOCALIZER_HPP_
const ScanT & scan() const noexcept
Get the last used scan.
Definition: ndt_localizer.hpp:142
This constraint expresses the map interface requirements for the localizer.
Definition: ndt/include/ndt/constraints.hpp:36
geometry_msgs::msg::TransformStamped TransformStamped
Definition: motion_testing_publisher.hpp:37
Definition: ndt_scan.hpp:99
NDTLocalizerBase(const NDTLocalizerConfigBase &config, const OptimizationProblemConfigT &optimization_problem_config, const OptimizerT &optimizer, ScanT &&scan)
Definition: ndt_localizer.hpp:67
typename ParentT::Transform Transform
Definition: ndt_localizer.hpp:244
const NDTLocalizerConfigBase & config() const noexcept
Get the localizer configuration.
Definition: ndt_localizer.hpp:152
typename ParentT::PoseWithCovarianceStamped PoseWithCovarianceStamped
Definition: ndt_localizer.hpp:245
Eigen::Matrix< T, 6U, 1U > EigenPose
Definition: localization/ndt/include/ndt/utils.hpp:83
void set_covariance(const P2DNDTOptimizationProblem< MapT > &, const EigenPose< Real > &, const EigenPose< Real > &, PoseWithCovarianceStamped &) const override
Definition: ndt_localizer.hpp:259
Config class for p2d optimziation problem.
Definition: ndt_config.hpp:54
const OptimizerT & optimizer() const noexcept
Get the optimizer.
Definition: ndt_localizer.hpp:147
Definition: optimized_registration_summary.hpp:32
void transform_to_pose(const TransformT &transform, PoseT &pose)
Requires
Definition: ndt/include/ndt/constraints.hpp:29
void pose_to_transform(const PoseT &pose, TransformT &transform)
float64_t Real
Definition: ndt_common.hpp:39
Definition: ndt_localizer.hpp:51
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:80
config class for p2d ndt localizer
Definition: ndt_config.hpp:73
sensor_msgs::msg::PointCloud2 CloudT
Definition: ndt_localizer.hpp:241
P2DNDTLocalizer(const P2DNDTLocalizerConfig &config, const OptimizerT &optimizer, const Real outlier_ratio)
Definition: ndt_localizer.hpp:248
virtual void set_covariance(const NDTOptimizationProblemT &problem, const EigenPose< Real > &initial_guess, const EigenPose< Real > &pose_result, PoseWithCovarianceStamped &solution) const
Definition: ndt_localizer.hpp:169
geometry_msgs::msg::TransformStamped Transform
Definition: recordreplay_planner_node.hpp:56
void validate_msg(const CloudT &msg, const MapT &map) const
Definition: ndt_localizer.hpp:188
uint32_t scan_capacity() const noexcept
Definition: ndt_config.hpp:89
sensor_msgs::msg::PointCloud2 CloudT
Definition: ndt_localizer.hpp:39
virtual void validate_guess(const CloudT &msg, const Transform &transform_initial) const
Definition: ndt_localizer.hpp:204
PoseWithCovarianceStamped register_measurement(const CloudT &msg, const Transform &transform_initial, const MapT &map, Summary *const summary=nullptr)
Definition: ndt_localizer.hpp:93
Definition: ndt_localizer.hpp:237
const OptimizationProblemConfigT & optimization_problem_config() const noexcept
Get the optimization problem configuration.
Definition: ndt_localizer.hpp:157
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24