Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef CQuaternion_H
00030 #define CQuaternion_H
00031
00032 #include <mrpt/math/CMatrixTemplateNumeric.h>
00033 #include <mrpt/math/CVectorTemplate.h>
00034 #include <mrpt/math/CArray.h>
00035
00036 namespace mrpt
00037 {
00038 namespace math
00039 {
00040
00041
00042
00043
00044
00045
00046 template <class T>
00047 class CQuaternion : public CArrayNumeric<T,4>
00048 {
00049 typedef CArrayNumeric<T,4> BASE;
00050 public:
00051
00052
00053
00054
00055 CQuaternion() { }
00056
00057
00058 inline CQuaternion(const T r,const T x,const T y,const T z)
00059 {
00060 (*this)[0] = r;
00061 (*this)[1] = x;
00062 (*this)[2] = y;
00063 (*this)[3] = z;
00064 }
00065
00066
00067
00068 template <class ARRAYLIKE>
00069 inline CQuaternion(const ARRAYLIKE &in)
00070 {
00071 fromRodriguesVector(in);
00072 }
00073
00074
00075
00076
00077
00078 inline T r()const {return (*this)[0];}
00079 inline T x()const {return (*this)[1];}
00080 inline T y()const {return (*this)[2];}
00081 inline T z()const {return (*this)[3];}
00082 inline void r(const T r) {(*this)[0]=r;}
00083 inline void x(const T x) {(*this)[1]=x;}
00084 inline void y(const T y) {(*this)[2]=y;}
00085 inline void z(const T z) {(*this)[3]=z;}
00086
00087
00088
00089 template <class ARRAYLIKE>
00090 void fromRodriguesVector(const ARRAYLIKE &in)
00091 {
00092 if (in.size()!=3) THROW_EXCEPTION("Wrong Dimension in input vector for quaternion Constructor");
00093
00094 const T x = in[0];
00095 const T y = in[1];
00096 const T z = in[2];
00097 if ((x==0)&&(y==0)&&(z==0))
00098 {
00099 (*this)[0] = 1;
00100 (*this)[1] = 0;
00101 (*this)[2] = 0;
00102 (*this)[3] = 0;
00103 }
00104 else
00105 {
00106 const T angle = sqrt(x*x+y*y+z*z);
00107 const T s = (sin(angle/2))/angle;
00108 const T c = cos(angle/2);
00109 (*this)[0] = c;
00110 (*this)[1] = x * s;
00111 (*this)[2] = y * s;
00112 (*this)[3] = z * s;
00113 }
00114 }
00115
00116
00117
00118 inline void crossProduct(const CQuaternion &qin1, const CQuaternion &qin2)
00119 {
00120 T q1r = qin1.r();
00121 T q1x = qin1.x();
00122 T q1y = qin1.y();
00123 T q1z = qin1.z();
00124
00125 T q2r = qin2.r();
00126 T q2x = qin2.x();
00127 T q2y = qin2.y();
00128 T q2z = qin2.z();
00129
00130 r( q1r*q2r - q1x*q2x - q1y*q2y - q1z*q2z );
00131 x( q1r*q2x + q2r*q1x + q1y*q2z - q2y*q1z );
00132 y( q1r*q2y + q2r*q1y + q1z*q2x - q2z*q1x );
00133 z( q1r*q2z + q2r*q1z + q1x*q2y - q2x*q1y );
00134
00135 normalize();
00136 }
00137
00138
00139
00140 inline void normalize()
00141 {
00142 const T qq = 1.0/sqrt( square(r())+square(x())+square(y())+square(z()));
00143 for (unsigned int i=0;i<4;i++)
00144 (*this)[i] *= qq;
00145 }
00146
00147
00148
00149
00150
00151 template <class MATRIXLIKE>
00152 void normalizedJacobian(MATRIXLIKE &J) const
00153 {
00154 const T n = square(r()) + square(x()) + square(y()) + square(z());
00155 n = 1.0 / (n*sqrt(n));
00156
00157 J.setSize(4,4);
00158 J.get_unsafe(0,0)=x()*x()+y()*y()+z()*z();
00159 J.get_unsafe(0,1)=-r()*x();
00160 J.get_unsafe(0,2)=-r()*y();
00161 J.get_unsafe(0,3)=-r()*z();
00162
00163 J.get_unsafe(1,0)=-x()*r();
00164 J.get_unsafe(1,1)=r()*r()+y()*y()+z()*z();
00165 J.get_unsafe(1,2)=-x()*y();
00166 J.get_unsafe(1,3)=-x()*z();
00167
00168 J.get_unsafe(2,0)=-y()*r();
00169 J.get_unsafe(2,1)=-y()*x();
00170 J.get_unsafe(2,2)=r()*r()+x()*x()+z()*z();
00171 J.get_unsafe(2,3)=-y()*z();
00172
00173 J.get_unsafe(3,0)=-z()*r();
00174 J.get_unsafe(3,1)=-z()*x();
00175 J.get_unsafe(3,2)=-z()*y();
00176 J.get_unsafe(3,3)=r()*r()+x()*x()+y()*y();
00177 J *=n;
00178 }
00179
00180
00181 template <class MATRIXLIKE>
00182 inline void rotationMatrix(MATRIXLIKE &M) const
00183 {
00184 M.setSize(3,3);
00185 M.get_unsafe(0,0)=r()*r()+x()*x()-y()*y()-z()*z(); M.get_unsafe(0,1)=2*(x()*y() -r()*z()); M.get_unsafe(0,2)=2*(z()*x()+r()*y());
00186 M.get_unsafe(1,0)=2*(x()*y()+r()*z()); M.get_unsafe(1,1)=r()*r()-x()*x()+y()*y()-z()*z(); M.get_unsafe(1,2)=2*(y()*z()-r()*x());
00187 M.get_unsafe(2,0)=2*(z()*x()-r()*y()); M.get_unsafe(2,1)=2*(y()*z()+r()*x()); M.get_unsafe(2,2)=r()*r()-x()*x()-y()*y()+z()*z();
00188 }
00189
00190
00191 inline void conj(CQuaternion &q_out) const
00192 {
00193 q_out.r( r() );
00194 q_out.x(-x() );
00195 q_out.y(-y() );
00196 q_out.z(-z() );
00197 }
00198
00199
00200 inline CQuaternion conj() const
00201 {
00202 CQuaternion q_aux;
00203 conj(q_aux);
00204 return q_aux;
00205 }
00206
00207
00208
00209 inline void rpy(T &roll, T &pitch, T &yaw) const
00210 {
00211
00212
00213 roll=atan2(2*(y()*z()+r()*x()),r()*r()-x()*x()-y()*y()+z()*z());
00214 pitch=asin(-2*(x()*z()-r()*y()));
00215 yaw=atan2(2*(x()*y()+r()*z()),r()*r()+x()*x()-y()*y()-z()*z());
00216 }
00217
00218 inline CQuaternion operator * (const T &factor)
00219 {
00220 CQuaternion q = *this;
00221 q*=factor;
00222 return q;
00223 }
00224
00225 };
00226
00227 typedef CQuaternion<double> CQuaternionDouble;
00228 typedef CQuaternion<float> CQuaternionFloat;
00229
00230 }
00231
00232 }
00233
00234 #endif