You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

187 lines
4.7 KiB

/**
* @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 <james.goppert@gmail.com>
*/
#pragma once
#include "math.hpp"
namespace matrix
{
template<typename Type>
class Quaternion;
template<typename Type>
class Euler;
template<typename Type>
class AxisAngle;
/**
* Direction cosine matrix class
*
* The rotation between two coordinate frames is
* described by this class.
*/
template<typename Type>
class Dcm : public SquareMatrix<Type, 3>
{
public:
using Vector3 = Matrix<Type, 3, 1>;
/**
* Standard constructor
*
* Initializes to identity
*/
Dcm() : SquareMatrix<Type, 3>(eye<Type, 3>()) {}
/**
* Constructor from array
*
* @param _data pointer to array
*/
explicit Dcm(const Type data_[3][3]) : SquareMatrix<Type, 3>(data_)
{
}
/**
* Constructor from array
*
* @param _data pointer to array
*/
explicit Dcm(const Type data_[9]) : SquareMatrix<Type, 3>(data_)
{
}
/**
* Copy constructor
*
* @param other Matrix33 to set dcm to
*/
Dcm(const Matrix<Type, 3, 3> &other) : SquareMatrix<Type, 3>(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<Type> &q)
{
Dcm &dcm = *this;
const Type a = q(0);
const Type b = q(1);
const Type c = q(2);
const Type d = q(3);
const Type aa = a * a;
const Type ab = a * b;
const Type ac = a * c;
const Type ad = a * d;
const Type bb = b * b;
const Type bc = b * c;
const Type bd = b * d;
const Type cc = c * c;
const Type cd = c * d;
const Type dd = d * d;
dcm(0, 0) = aa + bb - cc - dd;
dcm(0, 1) = Type(2) * (bc - ad);
dcm(0, 2) = Type(2) * (ac + bd);
dcm(1, 0) = Type(2) * (bc + ad);
dcm(1, 1) = aa - bb + cc - dd;
dcm(1, 2) = Type(2) * (cd - ab);
dcm(2, 0) = Type(2) * (bd - ac);
dcm(2, 1) = Type(2) * (ab + cd);
dcm(2, 2) = aa - bb - cc + dd;
}
/**
* 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<Type> &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;
}
/**
* Constructor from axis angle
*
* 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 AxisAngle<Type> &aa)
{
Dcm &dcm = *this;
dcm = Quaternion<Type>(aa);
}
Vector<Type, 3> vee() const // inverse to Vector.hat() operation
{
const Dcm &A(*this);
Vector<Type, 3> v;
v(0) = -A(1, 2);
v(1) = A(0, 2);
v(2) = -A(0, 1);
return v;
}
void renormalize()
{
/* renormalize rows */
for (size_t r = 0; r < 3; r++) {
matrix::Vector3<Type> rvec(Matrix<Type,1,3>(this->Matrix<Type,3,3>::row(r)).transpose());
this->Matrix<Type,3,3>::row(r) = rvec.normalized();
}
}
};
using Dcmf = Dcm<float>;
using Dcmd = Dcm<double>;
} // namespace matrix
/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */