/** * @file Dcm.hpp * * A direction cosine matrix class. * All rotations and axis systems follow the right-hand rule. * * This library uses the convention that premultiplying a three dimensional * vector represented in coordinate system 1 will apply a rotation from coordinate system * 1 to coordinate system 2 to the vector. * Likewise, a matrix instance of this class also represents a coordinate transformation * from frame 2 to frame 1. * * @author James Goppert */ #pragma once #include "math.hpp" namespace matrix { template class Quaternion; template class Euler; /** * Direction cosine matrix class * * The rotation between two coordinate frames is * described by this class. */ template class Dcm : public Matrix { public: virtual ~Dcm() {}; typedef Matrix Vector3; /** * Standard constructor * * Initializes to identity */ Dcm() : Matrix() { (*this) = eye(); } /** * Constructor from array * * @param _data pointer to array */ Dcm(const Type *data_) : Matrix(data_) { } /** * Copy constructor * * @param other Matrix33 to set dcm to */ Dcm(const Matrix &other) : Matrix(other) { } /** * Constructor from quaternion * * Instance is initialized from quaternion representing * coordinate transformation from frame 2 to frame 1. * * @param q quaternion to set dcm to */ Dcm(const Quaternion & q) { Dcm &dcm = *this; Type a = q(0); Type b = q(1); Type c = q(2); Type d = q(3); Type aSq = a*a; Type bSq = b*b; Type cSq = c*c; Type dSq = d*d; dcm(0, 0) = aSq + bSq - cSq - dSq; dcm(0, 1) = 2 * (b * c - a * d); dcm(0, 2) = 2 * (a * c + b * d); dcm(1, 0) = 2 * (b * c + a * d); dcm(1, 1) = aSq - bSq + cSq - dSq; dcm(1, 2) = 2 * (c * d - a * b); dcm(2, 0) = 2 * (b * d - a * c); dcm(2, 1) = 2 * (a * b + c * d); dcm(2, 2) = aSq - bSq - cSq + dSq; } /** * Constructor from euler angles * * This sets the transformation matrix from frame 2 to frame 1 where the rotation * from frame 1 to frame 2 is described by a 3-2-1 intrinsic Tait-Bryan rotation sequence. * * * @param euler euler angle instance */ Dcm(const Euler & euler) { Dcm &dcm = *this; Type cosPhi = Type(cos(euler.phi())); Type sinPhi = Type(sin(euler.phi())); Type cosThe = Type(cos(euler.theta())); Type sinThe = Type(sin(euler.theta())); Type cosPsi = Type(cos(euler.psi())); Type sinPsi = Type(sin(euler.psi())); dcm(0, 0) = cosThe * cosPsi; dcm(0, 1) = -cosPhi * sinPsi + sinPhi * sinThe * cosPsi; dcm(0, 2) = sinPhi * sinPsi + cosPhi * sinThe * cosPsi; dcm(1, 0) = cosThe * sinPsi; dcm(1, 1) = cosPhi * cosPsi + sinPhi * sinThe * sinPsi; dcm(1, 2) = -sinPhi * cosPsi + cosPhi * sinThe * sinPsi; dcm(2, 0) = -sinThe; dcm(2, 1) = sinPhi * cosThe; dcm(2, 2) = cosPhi * cosThe; } Vector vee() const { // inverse to Vector.hat() operation const Dcm &A(*this); Vector v; v(0) = -A(1,2); v(1) = A(0,2); v(2) = -A(0,1); return v; } }; typedef Dcm Dcmf; } // namespace matrix /* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */