Spaces:
Sleeping
Sleeping
| template <typename Scalar> | |
| class SE3 { | |
| public: | |
| const static int constexpr K = 6; // manifold dimension | |
| const static int constexpr N = 7; // embedding dimension | |
| using Vector3 = Eigen::Matrix<Scalar,3,1>; | |
| using Vector4 = Eigen::Matrix<Scalar,4,1>; | |
| using Matrix3 = Eigen::Matrix<Scalar,3,3>; | |
| using Tangent = Eigen::Matrix<Scalar,K,1>; | |
| using Point = Eigen::Matrix<Scalar,3,1>; | |
| using Point4 = Eigen::Matrix<Scalar,4,1>; | |
| using Data = Eigen::Matrix<Scalar,N,1>; | |
| using Transformation = Eigen::Matrix<Scalar,4,4>; | |
| using Adjoint = Eigen::Matrix<Scalar,K,K>; | |
| EIGEN_DEVICE_FUNC SE3() { translation = Vector3::Zero(); } | |
| EIGEN_DEVICE_FUNC SE3(SO3<Scalar> const& so3, Vector3 const& t) : so3(so3), translation(t) {}; | |
| EIGEN_DEVICE_FUNC SE3(const Scalar *data) : translation(data), so3(data+3) {}; | |
| EIGEN_DEVICE_FUNC SE3<Scalar> inv() { | |
| return SE3(so3.inv(), -(so3.inv()*translation)); | |
| } | |
| EIGEN_DEVICE_FUNC Data data() const { | |
| Data data_vec; data_vec << translation, so3.data(); | |
| return data_vec; | |
| } | |
| EIGEN_DEVICE_FUNC SE3<Scalar> operator*(SE3<Scalar> const& other) { | |
| return SE3(so3 * other.so3, translation + so3 * other.translation); | |
| } | |
| EIGEN_DEVICE_FUNC Point operator*(Point const& p) const { | |
| return so3 * p + translation; | |
| } | |
| EIGEN_DEVICE_FUNC Point4 act4(Point4 const& p) const { | |
| Point4 p1; p1 << so3 * p.template segment<3>(0) + translation * p(3), p(3); | |
| return p1; | |
| } | |
| EIGEN_DEVICE_FUNC Adjoint Adj() const { | |
| Matrix3 R = so3.Matrix(); | |
| Matrix3 tx = SO3<Scalar>::hat(translation); | |
| Matrix3 Zer = Matrix3::Zero(); | |
| Adjoint Ad; | |
| Ad << R, tx*R, Zer, R; | |
| return Ad; | |
| } | |
| EIGEN_DEVICE_FUNC Transformation Matrix() const { | |
| Transformation T = Transformation::Identity(); | |
| T.template block<3,3>(0,0) = so3.Matrix(); | |
| T.template block<3,1>(0,3) = translation; | |
| return T; | |
| } | |
| EIGEN_DEVICE_FUNC Transformation Matrix4x4() const { | |
| return Matrix(); | |
| } | |
| EIGEN_DEVICE_FUNC Tangent Adj(Tangent const& a) const { | |
| return Adj() * a; | |
| } | |
| EIGEN_DEVICE_FUNC Tangent AdjT(Tangent const& a) const { | |
| return Adj().transpose() * a; | |
| } | |
| EIGEN_DEVICE_FUNC static Transformation hat(Tangent const& tau_phi) { | |
| Vector3 tau = tau_phi.template segment<3>(0); | |
| Vector3 phi = tau_phi.template segment<3>(3); | |
| Transformation TauPhi = Transformation::Zero(); | |
| TauPhi.template block<3,3>(0,0) = SO3<Scalar>::hat(phi); | |
| TauPhi.template block<3,1>(0,3) = tau; | |
| return TauPhi; | |
| } | |
| EIGEN_DEVICE_FUNC static Adjoint adj(Tangent const& tau_phi) { | |
| Vector3 tau = tau_phi.template segment<3>(0); | |
| Vector3 phi = tau_phi.template segment<3>(3); | |
| Matrix3 Tau = SO3<Scalar>::hat(tau); | |
| Matrix3 Phi = SO3<Scalar>::hat(phi); | |
| Matrix3 Zer = Matrix3::Zero(); | |
| Adjoint ad; | |
| ad << Phi, Tau, Zer, Phi; | |
| return ad; | |
| } | |
| EIGEN_DEVICE_FUNC Eigen::Matrix<Scalar,7,7> orthogonal_projector() const { | |
| // jacobian action on a point | |
| Eigen::Matrix<Scalar,7,7> J = Eigen::Matrix<Scalar,7,7>::Zero(); | |
| J.template block<3,3>(0,0) = Matrix3::Identity(); | |
| J.template block<3,3>(0,3) = SO3<Scalar>::hat(-translation); | |
| J.template block<4,4>(3,3) = so3.orthogonal_projector(); | |
| return J; | |
| } | |
| EIGEN_DEVICE_FUNC Tangent Log() const { | |
| Vector3 phi = so3.Log(); | |
| Matrix3 Vinv = SO3<Scalar>::left_jacobian_inverse(phi); | |
| Tangent tau_phi; | |
| tau_phi << Vinv * translation, phi; | |
| return tau_phi; | |
| } | |
| EIGEN_DEVICE_FUNC static SE3<Scalar> Exp(Tangent const& tau_phi) { | |
| Vector3 tau = tau_phi.template segment<3>(0); | |
| Vector3 phi = tau_phi.template segment<3>(3); | |
| SO3<Scalar> so3 = SO3<Scalar>::Exp(phi); | |
| Vector3 t = SO3<Scalar>::left_jacobian(phi) * tau; | |
| return SE3<Scalar>(so3, t); | |
| } | |
| EIGEN_DEVICE_FUNC static Matrix3 calcQ(Tangent const& tau_phi) { | |
| // Q matrix | |
| Vector3 tau = tau_phi.template segment<3>(0); | |
| Vector3 phi = tau_phi.template segment<3>(3); | |
| Matrix3 Tau = SO3<Scalar>::hat(tau); | |
| Matrix3 Phi = SO3<Scalar>::hat(phi); | |
| Scalar theta = phi.norm(); | |
| Scalar theta_pow2 = theta * theta; | |
| Scalar theta_pow4 = theta_pow2 * theta_pow2; | |
| Scalar coef1 = (theta < EPS) ? | |
| Scalar(1.0/6.0) - Scalar(1.0/120.0) * theta_pow2 : | |
| (theta - sin(theta)) / (theta_pow2 * theta); | |
| Scalar coef2 = (theta < EPS) ? | |
| Scalar(1.0/24.0) - Scalar(1.0/720.0) * theta_pow2 : | |
| (theta_pow2 + 2*cos(theta) - 2) / (2 * theta_pow4); | |
| Scalar coef3 = (theta < EPS) ? | |
| Scalar(1.0/120.0) - Scalar(1.0/2520.0) * theta_pow2 : | |
| (2*theta - 3*sin(theta) + theta*cos(theta)) / (2 * theta_pow4 * theta); | |
| Matrix3 Q = Scalar(0.5) * Tau + | |
| coef1 * (Phi*Tau + Tau*Phi + Phi*Tau*Phi) + | |
| coef2 * (Phi*Phi*Tau + Tau*Phi*Phi - 3*Phi*Tau*Phi) + | |
| coef3 * (Phi*Tau*Phi*Phi + Phi*Phi*Tau*Phi); | |
| return Q; | |
| } | |
| EIGEN_DEVICE_FUNC static Adjoint left_jacobian(Tangent const& tau_phi) { | |
| // left jacobian | |
| Vector3 phi = tau_phi.template segment<3>(3); | |
| Matrix3 J = SO3<Scalar>::left_jacobian(phi); | |
| Matrix3 Q = SE3<Scalar>::calcQ(tau_phi); | |
| Matrix3 Zer = Matrix3::Zero(); | |
| Adjoint J6x6; | |
| J6x6 << J, Q, Zer, J; | |
| return J6x6; | |
| } | |
| EIGEN_DEVICE_FUNC static Adjoint left_jacobian_inverse(Tangent const& tau_phi) { | |
| // left jacobian inverse | |
| Vector3 tau = tau_phi.template segment<3>(0); | |
| Vector3 phi = tau_phi.template segment<3>(3); | |
| Matrix3 Jinv = SO3<Scalar>::left_jacobian_inverse(phi); | |
| Matrix3 Q = SE3<Scalar>::calcQ(tau_phi); | |
| Matrix3 Zer = Matrix3::Zero(); | |
| Adjoint J6x6; | |
| J6x6 << Jinv, -Jinv * Q * Jinv, Zer, Jinv; | |
| return J6x6; | |
| } | |
| EIGEN_DEVICE_FUNC static Eigen::Matrix<Scalar,3,6> act_jacobian(Point const& p) { | |
| // jacobian action on a point | |
| Eigen::Matrix<Scalar,3,6> J; | |
| J.template block<3,3>(0,0) = Matrix3::Identity(); | |
| J.template block<3,3>(0,3) = SO3<Scalar>::hat(-p); | |
| return J; | |
| } | |
| EIGEN_DEVICE_FUNC static Eigen::Matrix<Scalar,4,6> act4_jacobian(Point4 const& p) { | |
| // jacobian action on a point | |
| Eigen::Matrix<Scalar,4,6> J = Eigen::Matrix<Scalar,4,6>::Zero(); | |
| J.template block<3,3>(0,0) = p(3) * Matrix3::Identity(); | |
| J.template block<3,3>(0,3) = SO3<Scalar>::hat(-p.template segment<3>(0)); | |
| return J; | |
| } | |
| private: | |
| SO3<Scalar> so3; | |
| Vector3 translation; | |
| }; | |