#ifndef GEOMETRY_UTILS_ROTATION3_H #define GEOMETRY_UTILS_ROTATION3_H #include #include "GeometryUtilsMath.h" #include "RotationNBase.h" #include "Vector3.h" #include "Quaternion.h" #include "Rotation2.h" #include "Matrix2x2.h" namespace geometry_utils { template struct Rotation3Base : RotationNBase { Rotation3Base() : RotationNBase() {} Rotation3Base(const Rotation3Base& in) : RotationNBase(in.data) {} Rotation3Base(const boost::array& in) : RotationNBase(in) {} Rotation3Base(T (&in)[9]) : RotationNBase(in) {} Rotation3Base(const Eigen::Matrix& in) : RotationNBase(in) {} Rotation3Base(const Eigen::AngleAxis& in) : RotationNBase(in.toRotationMatrix()) {} Rotation3Base(const RotationNBase& in) : RotationNBase(in) {} Rotation3Base(const Matrix2x2Base& in) : RotationNBase(in) {} Rotation3Base(const MatrixNxMBase& in) : RotationNBase(in) {} Rotation3Base(T R11, T R12, T R13, T R21, T R22, T R23, T R31, T R32, T R33) { this->data[0] = R11; this->data[1] = R12; this->data[2] = R13; this->data[3] = R21; this->data[4] = R22; this->data[5] = R23; this->data[6] = R31; this->data[7] = R32; this->data[8] = R33; } Rotation3Base(const Vector3Base& in) { FromEulerZYX(in(0), in(1), in(2)); } Rotation3Base(T euler_x, T euler_y, T euler_z) { FromEulerZYX(euler_x, euler_y, euler_z); } Rotation3Base(const Rotation2Base& rot) { this->Zeros(); this->data[0] = rot(0); this->data[1] = rot(1); this->data[3] = rot(2); this->data[4] = rot(3); this->data[8] = static_cast(1); } Rotation3Base(const QuaternionBase& quat) { QuaternionBase q(quat); if (math::fabs(1 - q.Norm()) > static_cast(1e-6)) q = q.Normalize(); T a = q.W(); T b = q.X(); T c = q.Y(); T d = q.Z(); T a2 = a * a; T b2 = b * b; T c2 = c * c; T d2 = d * d; T ab = a * b; T ac = a * c; T ad = a * d; T bc = b * c; T bd = b * d; T cd = c * d; (*this)(0, 0) = a2 + b2 - c2 - d2; (*this)(0, 1) = static_cast(2) * (bc - ad); (*this)(0, 2) = static_cast(2) * (bd + ac); (*this)(1, 0) = static_cast(2) * (bc + ad); (*this)(1, 1) = a2 - b2 + c2 - d2; (*this)(1, 2) = static_cast(2) * (cd - ab); (*this)(2, 0) = static_cast(2) * (bd - ac); (*this)(2, 1) = static_cast(2) * (cd + ab); (*this)(2, 2) = a2 - b2 - c2 + d2; } virtual inline bool Equals(const Rotation3Base& that, const T ptol = 1e-8) const { return Error(that) < ptol; } inline T Error(const Rotation3Base& r) const { return 0; /*Norm( static_cast(0.5) * Rotation3Base(this->Trans() * r - r.Trans() * (*this)).Vee());*/ } inline Vector3Base Vee() const { return Vector3Base((*this)(2, 1), (*this)(0, 2), (*this)(1, 0)); } inline void FromEulerZYX(T euler_x, T euler_y, T euler_z) { T cph = math::cos(euler_x); T sph = math::sin(euler_x); T ct = math::cos(euler_y); T st = math::sin(euler_y); T cps = math::cos(euler_z); T sps = math::sin(euler_z); (*this)(0, 0) = ct * cps; (*this)(0, 1) = cps * st * sph - cph * sps; (*this)(0, 2) = cph * cps * st + sph * sps; (*this)(1, 0) = ct * sps; (*this)(1, 1) = cph * cps + st * sph * sps; (*this)(1, 2) = -cps * sph + cph * st * sps; (*this)(2, 0) = -st; (*this)(2, 1) = ct * sph; (*this)(2, 2) = ct * cph; } inline Vector3Base GetEulerZYX() const { return ToEulerZYX(); } inline Vector3Base ToEulerZYX() const { T theta = -math::asin((*this)(2, 0)); T phi = 0; T psi = 0; if (math::fabs(cos(theta)) > static_cast(1e-6)) { phi = math::atan2((*this)(2, 1), (*this)(2, 2)); psi = math::atan2((*this)(1, 0), (*this)(0, 0)); } return Vector3Base(phi, theta, psi); } inline T Roll() const { T theta = -math::asin((*this)(2, 0)); return math::fabs(cos(theta)) > static_cast(1e-6) ? math::atan2((*this)(2, 1), (*this)(2, 2)) : 0; } inline T Pitch() const { return -math::asin((*this)(2, 0)); } inline T Yaw() const { T theta = -math::asin((*this)(2, 0)); return math::fabs(cos(theta)) > static_cast(1e-6) ? math::atan2((*this)(1, 0), (*this)(0, 0)) : 0; } }; inline Rotation3Base operator*(const float& lhs, const Rotation3Base& rhs) { return Rotation3Base(rhs.Scale(lhs)); } inline Rotation3Base operator*(const double& lhs, const Rotation3Base& rhs) { return Rotation3Base(rhs.Scale(lhs)); } template inline Rotation3Base Hat(const Vector3Base& v) { return Rotation3Base(0, -v(2), v(1), v(2), 0, -v(0), -v(1), v(0), 0); } template inline Vector3Base Vee(const MatrixNxMBase& m) { return Rotation3Base(m).Vee(); } typedef Rotation3Base Rotation3f; typedef Rotation3Base Rot3f; typedef Rotation3Base Rotation3d; typedef Rotation3Base Rot3d; typedef Rotation3Base Rotation3; typedef Rotation3Base Rot3; } #endif