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.
160 lines
3.4 KiB
160 lines
3.4 KiB
/** |
|
* @file AxisAngle.hpp |
|
* |
|
* @author James Goppert <james.goppert@gmail.com> |
|
*/ |
|
|
|
#pragma once |
|
|
|
#include "math.hpp" |
|
|
|
namespace matrix |
|
{ |
|
|
|
template <typename Type> |
|
class Dcm; |
|
|
|
template <typename Type> |
|
class Euler; |
|
|
|
template <typename Type> |
|
class AxisAngle; |
|
|
|
/** |
|
* AxisAngle class |
|
* |
|
* The rotation between two coordinate frames is |
|
* described by this class. |
|
*/ |
|
template<typename Type> |
|
class AxisAngle : public Vector<Type, 3> |
|
{ |
|
public: |
|
using Matrix31 = Matrix<Type, 3, 1>; |
|
|
|
/** |
|
* Constructor from array |
|
* |
|
* @param data_ array |
|
*/ |
|
explicit AxisAngle(const Type data_[3]) : |
|
Vector<Type, 3>(data_) |
|
{ |
|
} |
|
|
|
/** |
|
* Standard constructor |
|
*/ |
|
AxisAngle() = default; |
|
|
|
/** |
|
* Constructor from Matrix31 |
|
* |
|
* @param other Matrix31 to copy |
|
*/ |
|
AxisAngle(const Matrix31 &other) : |
|
Vector<Type, 3>(other) |
|
{ |
|
} |
|
|
|
/** |
|
* Constructor from quaternion |
|
* |
|
* This sets the instance from a quaternion representing coordinate transformation 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 q quaternion |
|
*/ |
|
AxisAngle(const Quaternion<Type> &q) |
|
{ |
|
AxisAngle &v = *this; |
|
Type mag = q.imag().norm(); |
|
if (fabs(mag) >= Type(1e-10)) { |
|
v = q.imag() * Type(Type(2) * atan2(mag, q(0)) / mag); |
|
} else { |
|
v = q.imag() * Type(Type(2) * Type(sign(q(0)))); |
|
} |
|
} |
|
|
|
/** |
|
* Constructor from dcm |
|
* |
|
* Instance is initialized from a dcm representing coordinate transformation |
|
* from frame 2 to frame 1. |
|
* |
|
* @param dcm dcm to set quaternion to |
|
*/ |
|
AxisAngle(const Dcm<Type> &dcm) |
|
{ |
|
AxisAngle &v = *this; |
|
v = AxisAngle<Type>(Quaternion<Type>(dcm)); |
|
} |
|
|
|
/** |
|
* Constructor from euler angles |
|
* |
|
* This sets the instance to a quaternion representing coordinate transformation 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 |
|
*/ |
|
AxisAngle(const Euler<Type> &euler) |
|
{ |
|
AxisAngle &v = *this; |
|
v = AxisAngle<Type>(Quaternion<Type>(euler)); |
|
} |
|
|
|
/** |
|
* Constructor from 3 axis angle values (unit vector * angle) |
|
* |
|
* @param x r_x*angle |
|
* @param y r_y*angle |
|
* @param z r_z*angle |
|
*/ |
|
AxisAngle(Type x, Type y, Type z) |
|
{ |
|
AxisAngle &v = *this; |
|
v(0) = x; |
|
v(1) = y; |
|
v(2) = z; |
|
} |
|
|
|
/** |
|
* Constructor from axis and angle |
|
* |
|
* @param axis An axis of rotation, normalized if not unit length |
|
* @param angle The amount to rotate |
|
*/ |
|
AxisAngle(const Matrix31 & axis_, Type angle_) |
|
{ |
|
AxisAngle &v = *this; |
|
// make sure axis is a unit vector |
|
Vector<Type, 3> a = axis_; |
|
a = a.unit(); |
|
v(0) = a(0)*angle_; |
|
v(1) = a(1)*angle_; |
|
v(2) = a(2)*angle_; |
|
} |
|
|
|
|
|
Vector<Type, 3> axis() { |
|
if (Vector<Type, 3>::norm() > 0) { |
|
return Vector<Type, 3>::unit(); |
|
} else { |
|
return Vector3<Type>(1, 0, 0); |
|
} |
|
} |
|
|
|
Type angle() { |
|
return Vector<Type, 3>::norm(); |
|
} |
|
}; |
|
|
|
using AxisAnglef = AxisAngle<float>; |
|
using AxisAngled = AxisAngle<double>; |
|
|
|
} // namespace matrix |
|
|
|
/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
|
|
|