Autoware.Auto
localization/ndt/include/ndt/utils.hpp
Go to the documentation of this file.
1 // Copyright 2020 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__UTILS_HPP_
18 #define NDT__UTILS_HPP_
19 
20 #include <Eigen/Core>
21 #include <Eigen/Geometry>
22 #include <geometry_msgs/msg/transform.hpp>
23 #include <geometry_msgs/msg/pose.hpp>
24 #include <Eigen/Eigenvalues>
25 #include <limits>
26 
27 namespace autoware
28 {
29 namespace localization
30 {
31 namespace ndt
32 {
33 
44 template<typename Derived>
46  Eigen::MatrixBase<Derived> & covariance,
47  typename Derived::PlainMatrix::Scalar scaling_factor = 0.01)
48 {
49  using CovMatrixT = typename Derived::PlainMatrix;
50  using ScalarT = typename CovMatrixT::Scalar;
51  using IndexT = typename CovMatrixT::Index;
52  constexpr auto TOL = std::numeric_limits<ScalarT>::epsilon();
53  Eigen::SelfAdjointEigenSolver<CovMatrixT> solver;
54  solver.compute(covariance);
55 
56  CovMatrixT evecs = solver.eigenvectors();
57  typename decltype(solver)::RealVectorType evals = solver.eigenvalues();
58  // Cap the minimum eigen values to scale times the largest eigen value.
59  const ScalarT max_e_val = *std::max_element(evals.data(), evals.data() + evals.size());
60  const ScalarT min_e_val = max_e_val * scaling_factor;
61  if (min_e_val < TOL) {
62  return false;
63  }
64  auto stabilized = false;
65  for (auto i = IndexT{0}; i < evals.size(); ++i) {
66  ScalarT & e_val = evals(i);
67  if (e_val < TOL) {
68  // Covariance is not full rank.
69  return false;
70  }
71  if (e_val < min_e_val) {
72  e_val = min_e_val;
73  stabilized = true;
74  }
75  }
76  if (stabilized) {
77  covariance = evecs * evals.asDiagonal() * evecs.inverse();
78  }
79  return true;
80 }
81 
82 template<typename T>
83 using EigenPose = Eigen::Matrix<T, 6U, 1U>;
84 template<typename T>
85 using EigenTransform = Eigen::Transform<T, 3, Eigen::Affine, Eigen::ColMajor>;
87 using RosPose = geometry_msgs::msg::Pose;
88 namespace transform_adapters
89 {
96 template<typename PoseT, typename TransformT>
97 void pose_to_transform(const PoseT & pose, TransformT & transform);
98 
105 template<typename PoseT, typename TransformT>
106 void transform_to_pose(const TransformT & transform, PoseT & pose);
107 
108 
109 template<typename T>
111  const EigenPose<T> & pose,
112  EigenTransform<T> & transform)
113 {
114  static_assert(std::is_floating_point<T>::value, "Eigen transform should use floating points");
115  transform.setIdentity();
116  transform.translation() = pose.head(3);
117  transform.rotate(Eigen::AngleAxis<T>(pose(3), Eigen::Vector3d::UnitX()));
118  transform.rotate(Eigen::AngleAxis<T>(pose(4), Eigen::Vector3d::UnitY()));
119  transform.rotate(Eigen::AngleAxis<T>(pose(5), Eigen::Vector3d::UnitZ()));
120 }
121 
124 template<typename T>
126  const EigenPose<T> & pose,
127  RosTransform & transform)
128 {
129  static_assert(std::is_floating_point<T>::value, "Eigen pose should use floating points");
130  Eigen::Quaternion<T> eig_rot{Eigen::Quaternion<T>{}.setIdentity()};
131  eig_rot.setIdentity();
132  eig_rot =
133  Eigen::AngleAxis<T>(pose(3), Eigen::Matrix<T, 3, 1>::UnitX()) *
134  Eigen::AngleAxis<T>(pose(4), Eigen::Matrix<T, 3, 1>::UnitY()) *
135  Eigen::AngleAxis<T>(pose(5), Eigen::Matrix<T, 3, 1>::UnitZ());
136 
137  decltype(RosTransform::translation) trans;
138  decltype(RosTransform::rotation) rot;
139 
140  trans.set__x(pose(0)).set__y(pose(1)).set__z(pose(2));
141  transform.set__translation(trans);
142 
143  rot.set__x(eig_rot.x()).
144  set__y(eig_rot.y()).
145  set__z(eig_rot.z()).
146  set__w(eig_rot.w());
147  transform.set__rotation(rot);
148 }
149 
154 template<typename T>
156  const EigenPose<T> & pose,
157  RosPose & ros_pose)
158 {
159  static_assert(std::is_floating_point<T>::value, "Eigen pose should use floating points");
160  Eigen::Quaternion<T> eig_rot{Eigen::Quaternion<T>{}.setIdentity()};
161  eig_rot =
162  Eigen::AngleAxis<T>(pose(3), Eigen::Matrix<T, 3, 1>::UnitX()) *
163  Eigen::AngleAxis<T>(pose(4), Eigen::Matrix<T, 3, 1>::UnitY()) *
164  Eigen::AngleAxis<T>(pose(5), Eigen::Matrix<T, 3, 1>::UnitZ());
165 
166  decltype(RosPose::position) trans;
167  decltype(RosTransform::rotation) rot;
168 
169  trans.set__x(pose(0)).set__y(pose(1)).set__z(pose(2));
170  ros_pose.set__position(trans);
171 
172  rot.set__x(eig_rot.x()).
173  set__y(eig_rot.y()).
174  set__z(eig_rot.z()).
175  set__w(eig_rot.w());
176  ros_pose.set__orientation(rot);
177 }
178 
181 template<typename T>
182 void transform_to_pose(const RosTransform & transform, EigenPose<T> & pose)
183 {
184  static_assert(std::is_floating_point<T>::value, "Eigen pose should use floating points");
185  const auto & ros_rot = transform.rotation;
186  const auto & ros_trans = transform.translation;
187  Eigen::Quaternion<T> eig_rot{ros_rot.w, ros_rot.x, ros_rot.y, ros_rot.z};
188  pose(0) = ros_trans.x;
189  pose(1) = ros_trans.y;
190  pose(2) = ros_trans.z;
191 
192  const auto rot = eig_rot.matrix().eulerAngles(0, 1, 2);
193  pose(3) = rot(0);
194  pose(4) = rot(1);
195  pose(5) = rot(2);
196 }
197 
202 template<typename T>
203 void transform_to_pose(const RosPose & ros_pose, EigenPose<T> & pose)
204 {
205  static_assert(std::is_floating_point<T>::value, "Eigen pose should use floating points");
206  const auto & ros_rot = ros_pose.orientation;
207  const auto & ros_trans = ros_pose.position;
208  Eigen::Quaternion<T> eig_rot{ros_rot.w, ros_rot.x, ros_rot.y, ros_rot.z};
209  pose(0) = ros_trans.x;
210  pose(1) = ros_trans.y;
211  pose(2) = ros_trans.z;
212 
213  const auto rot = eig_rot.matrix().eulerAngles(0, 1, 2);
214  pose(3) = rot(0);
215  pose(4) = rot(1);
216  pose(5) = rot(2);
217 }
218 
219 } // namespace transform_adapters
220 } // namespace ndt
221 } // namespace localization
222 } // namespace autoware
223 
224 #endif // NDT__UTILS_HPP_
autoware::localization::ndt::try_stabilize_covariance
bool try_stabilize_covariance(Eigen::MatrixBase< Derived > &covariance, typename Derived::PlainMatrix::Scalar scaling_factor=0.01)
Definition: localization/ndt/include/ndt/utils.hpp:45
autoware::localization::ndt::RosTransform
geometry_msgs::msg::Transform RosTransform
Definition: localization/ndt/include/ndt/utils.hpp:86
autoware::localization::ndt::RosPose
geometry_msgs::msg::Pose RosPose
Definition: localization/ndt/include/ndt/utils.hpp:87
autoware::localization::ndt::EigenPose
Eigen::Matrix< T, 6U, 1U > EigenPose
Definition: localization/ndt/include/ndt/utils.hpp:83
autoware
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24
motion::planning::recordreplay_planner_nodes::Transform
geometry_msgs::msg::TransformStamped Transform
Definition: recordreplay_planner_node.hpp:56
autoware::localization::ndt::transform_adapters::transform_to_pose
void transform_to_pose(const TransformT &transform, PoseT &pose)
autoware::localization::ndt::transform_adapters::pose_to_transform
void pose_to_transform(const PoseT &pose, TransformT &transform)
autoware::localization::ndt::EigenTransform
Eigen::Transform< T, 3, Eigen::Affine, Eigen::ColMajor > EigenTransform
Definition: localization/ndt/include/ndt/utils.hpp:85
autoware::common::geometry::spatial_hash::Index
std::size_t Index
Index type for identifying bins of the hash/lattice.
Definition: spatial_hash_config.hpp:49