17 #ifndef NDT__UTILS_HPP_
18 #define NDT__UTILS_HPP_
21 #include <Eigen/Geometry>
22 #include <geometry_msgs/msg/transform.hpp>
23 #include <geometry_msgs/msg/pose.hpp>
24 #include <Eigen/Eigenvalues>
29 namespace localization
44 template<
typename Derived>
46 Eigen::MatrixBase<Derived> & covariance,
47 typename Derived::PlainMatrix::Scalar scaling_factor = 0.01)
49 using CovMatrixT =
typename Derived::PlainMatrix;
50 using ScalarT =
typename CovMatrixT::Scalar;
52 constexpr
auto TOL = std::numeric_limits<ScalarT>::epsilon();
53 Eigen::SelfAdjointEigenSolver<CovMatrixT> solver;
54 solver.compute(covariance);
56 CovMatrixT evecs = solver.eigenvectors();
57 typename decltype(solver)::RealVectorType evals = solver.eigenvalues();
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) {
64 auto stabilized =
false;
65 for (
auto i = IndexT{0}; i < evals.size(); ++i) {
66 ScalarT & e_val = evals(i);
71 if (e_val < min_e_val) {
77 covariance = evecs * evals.asDiagonal() * evecs.inverse();
85 using EigenTransform = Eigen::Transform<T, 3, Eigen::Affine, Eigen::ColMajor>;
88 namespace transform_adapters
96 template<
typename PoseT,
typename TransformT>
105 template<
typename PoseT,
typename TransformT>
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()));
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();
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());
137 decltype(RosTransform::translation) trans;
138 decltype(RosTransform::rotation) rot;
140 trans.set__x(pose(0)).set__y(pose(1)).set__z(pose(2));
141 transform.set__translation(trans);
143 rot.set__x(eig_rot.x()).
147 transform.set__rotation(rot);
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()};
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());
166 decltype(RosPose::position) trans;
167 decltype(RosTransform::rotation) rot;
169 trans.set__x(pose(0)).set__y(pose(1)).set__z(pose(2));
170 ros_pose.set__position(trans);
172 rot.set__x(eig_rot.x()).
176 ros_pose.set__orientation(rot);
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;
192 const auto rot = eig_rot.matrix().eulerAngles(0, 1, 2);
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;
213 const auto rot = eig_rot.matrix().eulerAngles(0, 1, 2);
224 #endif // NDT__UTILS_HPP_