Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
quatTools.hpp
Go to the documentation of this file.
00001 
00014 #ifndef QUATTOOLS_HPP_
00015 #define QUATTOOLS_HPP_
00016 
00017 #include "jmath/ublasExtra.hpp"
00018 #include "jmath/jblas.hpp"
00019 
00020 namespace jafar {
00021   namespace rtslam {
00026     namespace quaternion {
00027 
00028       using namespace jblas;
00029       using namespace jafar::jmath;
00030 
00031 
00036       vec4 identQ();
00037 
00038 
00044       template<class VecQ>
00045       vec4 q2qc(const VecQ & q) {
00046         vec4 qc;
00047         qc(0) = +q(0);
00048         qc(1) = -q(1);
00049         qc(2) = -q(2);
00050         qc(3) = -q(3);
00051         return qc;
00052       }
00053 
00054 
00062       template<class VecQ, class MatQC_q>
00063       void q2qc_by_dq(const VecQ & q, MatQC_q & QC_q) {
00064         QC_q.clear();
00065         QC_q(0, 0) = 1.0;
00066         QC_q(1, 1) = -1.0;
00067         QC_q(2, 2) = -1.0;
00068         QC_q(3, 3) = -1.0;
00069       }
00070 
00071 
00075       template<class VecQ, class VecQc, class MatQC_q>
00076       void q2qc(const VecQ & q, VecQc & qc, MatQC_q & QC_q) {
00077         qc = q2qc(q);
00078         q2qc_by_dq(q, QC_q);
00079       }
00080 
00081 
00085       template<class VecQ>
00086       mat33 q2R(const VecQ & q) {
00087         double qw = q(0);
00088         double qx = q(1);
00089         double qy = q(2);
00090         double qz = q(3);
00091 
00092         double ww = qw * qw;
00093         double wx = 2 * qw * qx;
00094         double wy = 2 * qw * qy;
00095         double wz = 2 * qw * qz;
00096         double xx = qx * qx;
00097         double xy = 2 * qx * qy;
00098         double xz = 2 * qx * qz;
00099         double yy = qy * qy;
00100         double yz = 2 * qy * qz;
00101         double zz = qz * qz;
00102 
00103         mat33 R;
00104         R(0, 0) = ww + xx - yy - zz;
00105         R(0, 1) = xy - wz;
00106         R(0, 2) = xz + wy;
00107         R(1, 0) = xy + wz;
00108         R(1, 1) = ww - xx + yy - zz;
00109         R(1, 2) = yz - wx;
00110         R(2, 0) = xz - wy;
00111         R(2, 1) = yz + wx;
00112         R(2, 2) = ww - xx - yy + zz;
00113         return R;
00114       }
00115 
00119       template<class MatR>
00120       vec4 R2q(const MatR & R) {
00121         vec4 q;
00122         q(0) = sqrt(R(0,0)+R(1,1)+R(2,2)+1) / 2.;
00123         double d1 = 4*q(0);
00124         q(1) = (R(2,1) - R(1,2)) / d1;
00125         q(2) = (R(0,2) - R(2,0)) / d1;
00126         q(3) = (R(1,0) - R(0,1)) / d1;
00127         return q;
00128       }
00129       
00135       template<class VecQ>
00136       mat33 q2Rt(const VecQ & q) {
00137         return q2R(q2qc(q));
00138       }
00139 
00140 
00147       template<class VecQ, class Vec>
00148       vec3 rotate(const VecQ & q, const Vec & v) {
00149         using namespace ublas;
00150         return prod(q2R(q), v);
00151       }
00152 
00153 
00160       template<class VecQ, class Vec, class MatVO_q>
00161       void rotate_by_dq(const VecQ & q, const Vec & v, MatVO_q & VO_q) {
00162         // split q and v
00163         double qw = q(0);
00164         double qx = q(1);
00165         double qy = q(2);
00166         double qz = q(3);
00167         double x = v(0);
00168         double y = v(1);
00169         double z = v(2);
00170 
00171 
00172         // temporary
00173         double t1 = 2 * (qw * x - qz * y + qy * z);
00174         double t2 = 2 * (qx * x + qy * y + qz * z);
00175         double t3 = 2 * (qy * x - qx * y - qw * z);
00176         double t4 = 2 * (qz * x + qw * y - qx * z);
00177 
00178 
00179         // Jacobian
00180         VO_q(0, 0) = t1;
00181         VO_q(0, 1) = t2;
00182         VO_q(0, 2) = -t3;
00183         VO_q(0, 3) = -t4;
00184         VO_q(1, 0) = t4;
00185         VO_q(1, 1) = t3;
00186         VO_q(1, 2) = t2;
00187         VO_q(1, 3) = t1;
00188         VO_q(2, 0) = -t3;
00189         VO_q(2, 1) = t4;
00190         VO_q(2, 2) = -t1;
00191         VO_q(2, 3) = t2;
00192       }
00193 
00194 
00200       template<class VecQ, class MatVO_v>
00201       void rotate_by_dv(const VecQ & q, MatVO_v & VO_v) {
00202         VO_v = q2R(q);
00203       }
00204 
00205 
00214       template<class VecQ, class Vec, class VecO, class MatVO_q, class MatVO_v>
00215       void rotate(const VecQ & q, const Vec & v, VecO & vo, MatVO_q & VO_q, MatVO_v & VO_v) {
00216         vo = rotate(q, v);
00217         rotate_by_dq(q, v, VO_q);
00218         rotate_by_dv(q, VO_v);
00219       }
00220 
00221 
00228       template<class VecQ, class Vec>
00229       vec3 rotateInv(const VecQ & q, const Vec & v) {
00230         using namespace ublas;
00231         return prod(q2Rt(q), v);
00232       }
00233 
00234 
00241       template<class VecQ, class Vec, class MatVO_q>
00242       void rotateInv_by_dq(const VecQ & q, const Vec & v, MatVO_q & VO_q) {
00243         // split q and v
00244         double qw = q(0);
00245         double qx = q(1);
00246         double qy = q(2);
00247         double qz = q(3);
00248         double x = v(0);
00249         double y = v(1);
00250         double z = v(2);
00251 
00252 
00253         // temporary
00254         double s1 = 2 * (qw * x + qz * y - qy * z);
00255         double s2 = 2 * (qx * x + qy * y + qz * z);
00256         double s3 = 2 * (qy * x - qx * y + qw * z);
00257         double s4 = 2 * (qz * x - qw * y - qx * z);
00258 
00259 
00260         // Jacobian
00261         VO_q(0, 0) = s1;
00262         VO_q(0, 1) = s2;
00263         VO_q(0, 2) = -s3;
00264         VO_q(0, 3) = -s4;
00265         VO_q(1, 0) = -s4;
00266         VO_q(1, 1) = s3;
00267         VO_q(1, 2) = s2;
00268         VO_q(1, 3) = -s1;
00269         VO_q(2, 0) = s3;
00270         VO_q(2, 1) = s4;
00271         VO_q(2, 2) = s1;
00272         VO_q(2, 3) = s2;
00273       }
00274 
00275 
00281       template<class VecQ, class MatVO_v>
00282       void rotateInv_by_dv(const VecQ & q, MatVO_v & VO_v) {
00283         VO_v = q2Rt(q);
00284       }
00285 
00286 
00295       template<class VecQ, class Vec, class VecO, class MatVO_q, class MatVO_v>
00296       void rotateInv(const VecQ & q, const Vec & v, VecO & vo, MatVO_q & VO_q, MatVO_v & VO_v) {
00297         VO_v = q2Rt(q); // this is Rt !
00298         vo = prod(VO_v, v);
00299         rotateInv_by_dq(q, v, VO_q);
00300       }
00301 
00302 
00309       template<class VecQ1, class VecQ2>
00310       vec4 qProd(const VecQ1 & q1, const VecQ2 & q2) {
00311         // split quaternions
00312         double q1w = q1(0);
00313         double q1x = q1(1);
00314         double q1y = q1(2);
00315         double q1z = q1(3);
00316         double q2w = q2(0);
00317         double q2x = q2(1);
00318         double q2y = q2(2);
00319         double q2z = q2(3);
00320 
00321         vec4 q;
00322         q(0) = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
00323         q(1) = q1w * q2x + q1x * q2w + q1y * q2z - q1z * q2y;
00324         q(2) = q1w * q2y - q1x * q2z + q1y * q2w + q1z * q2x;
00325         q(3) = q1w * q2z + q1x * q2y - q1y * q2x + q1z * q2w;
00326         return q;
00327       }
00328 
00329 
00337       template<class VecQ2, class MatQ_q1>
00338       void qProd_by_dq1(const VecQ2 & q2, MatQ_q1 & Q_q1) {
00339 
00340 
00341         // split quaternion
00342         double q2w = q2(0);
00343         double q2x = q2(1);
00344         double q2y = q2(2);
00345         double q2z = q2(3);
00346 
00347         Q_q1(0, 0) = q2w;
00348         Q_q1(0, 1) = -q2x;
00349         Q_q1(0, 2) = -q2y;
00350         Q_q1(0, 3) = -q2z;
00351         Q_q1(1, 0) = q2x;
00352         Q_q1(1, 1) = q2w;
00353         Q_q1(1, 2) = q2z;
00354         Q_q1(1, 3) = -q2y;
00355         Q_q1(2, 0) = q2y;
00356         Q_q1(2, 1) = -q2z;
00357         Q_q1(2, 2) = q2w;
00358         Q_q1(2, 3) = q2x;
00359         Q_q1(3, 0) = q2z;
00360         Q_q1(3, 1) = q2y;
00361         Q_q1(3, 2) = -q2x;
00362         Q_q1(3, 3) = q2w;
00363 
00364       }
00365 
00366 
00374       template<class VecQ1, class MatQ_q2>
00375       void qProd_by_dq2(const VecQ1 & q1, MatQ_q2 & Q_q2) {
00376 
00377 
00378         // split quaternion
00379         double q1w = q1(0);
00380         double q1x = q1(1);
00381         double q1y = q1(2);
00382         double q1z = q1(3);
00383 
00384         Q_q2(0, 0) = q1w;
00385         Q_q2(0, 1) = -q1x;
00386         Q_q2(0, 2) = -q1y;
00387         Q_q2(0, 3) = -q1z;
00388         Q_q2(1, 0) = q1x;
00389         Q_q2(1, 1) = q1w;
00390         Q_q2(1, 2) = -q1z;
00391         Q_q2(1, 3) = q1y;
00392         Q_q2(2, 0) = q1y;
00393         Q_q2(2, 1) = q1z;
00394         Q_q2(2, 2) = q1w;
00395         Q_q2(2, 3) = -q1x;
00396         Q_q2(3, 0) = q1z;
00397         Q_q2(3, 1) = -q1y;
00398         Q_q2(3, 2) = q1x;
00399         Q_q2(3, 3) = q1w;
00400       }
00401 
00402 
00411       template<class VecQ1, class VecQ2, class VecQ, class MatQ_q1, class MatQ_q2>
00412       void qProd(const VecQ1 & q1, const VecQ2 & q2, VecQ & q, MatQ_q1 & Q_q1, MatQ_q2 & Q_q2) {
00413         q = qProd(q1, q2);
00414         qProd_by_dq1(q2, Q_q1);
00415         qProd_by_dq2(q1, Q_q2);
00416       }
00417 
00418 
00424       template<class Vec>
00425       vec4 v2q(const Vec & v) {
00426         double a = boost::numeric::ublas::norm_2(v);
00427         if (a < 1e-6)
00428           return identQ();
00429 
00430         double san = sin(a / 2) / a;
00431         vec4 q;
00432         q(0) = cos(a / 2);
00433         q(1) = v(0) * san;
00434         q(2) = v(1) * san;
00435         q(3) = v(2) * san;
00436         return q;
00437       }
00438 
00439 
00445       template<class Vec, class MatQ_v>
00446       void v2q_by_dv(const Vec & v, MatQ_v & Q_v) {
00447 
00448         double a = norm_2(v);
00449 
00450         if (a > jmath::ublasExtra::details::EPSILON) {
00451 
00452 
00453           // u = v/norm(v) and U_v
00454           vec3 u(v);
00455           ublasExtra::normalize(u);
00456           mat U_v(3, 3);
00457           jmath::ublasExtra::normalizeJac(v, U_v);
00458 
00459 
00460           // Av = u';
00461           mat A_v(1, 3);
00462           row(A_v, 0) = u;
00463 
00464 
00465           //  Qa = [  -sin(a/2)/2
00466           //         u*cos(a/2)/2];
00467           mat Q_a(4, 1);
00468           double sa2 = sin(a / 2);
00469           double ca22 = cos(a / 2) / 2;
00470           Q_a(0, 0) = -sa2 / 2;
00471           Q_a(1, 0) = u(0) * ca22;
00472           Q_a(2, 0) = u(1) * ca22;
00473           Q_a(3, 0) = u(2) * ca22;
00474 
00475 
00476           //  Qu = [0 0 0;eye(3)*sin(a/2)];
00477           mat Q_u(4, 3);
00478           Q_u.clear();
00479           Q_u(1, 0) = sa2;
00480           Q_u(2, 1) = sa2;
00481           Q_u(3, 2) = sa2;
00482 
00483 
00484           // chain rule
00485           Q_v = prod(Q_a, A_v) + prod(Q_u, U_v);
00486 
00487         }
00488         else {
00489           //        v = -v / 4;
00490           //        v /= -4.0;
00491           Q_v.clear();
00492           Q_v(0, 0) = v(0) / 4;
00493           Q_v(0, 1) = v(1) / 4;
00494           Q_v(0, 2) = v(2) / 4;
00495           Q_v(1, 0) = 0.5;
00496           Q_v(2, 1) = 0.5;
00497           Q_v(3, 2) = 0.5;
00498         }
00499       }
00500 
00501 
00507       template<class Vec, class VecQ, class MatQ_v>
00508       void v2q(const Vec & v, VecQ & q, MatQ_v & Q_v) {
00509         q = v2q(v);
00510         v2q_by_dv(v, Q_v);
00511       }
00512 
00513 
00519       template<class Vec>
00520       vec4 e2q(const Vec & e) {
00521         vec3 ex;
00522         vec3 ey;
00523         vec3 ez;
00524         ex.clear();
00525         ex(0) = e(0);
00526         vec4 qx = v2q(ex);
00527         ey.clear();
00528         ey(1) = e(1);
00529         vec4 qy = v2q(ey);
00530         ez.clear();
00531         ez(2) = e(2);
00532         vec4 qz = v2q(ez);
00533 
00534         vec4 q;
00535         q = qProd(qProd(qz, qy), qx);
00536         return q;
00537       }
00538 
00544       template<class Vec, class MatQ_e>
00545       void e2q_by_de(const Vec & e, MatQ_e & Q_e) {
00546         double sr = sin(e(0) / 2);
00547         double sp = sin(e(1) / 2);
00548         double sy = sin(e(2) / 2);
00549 
00550         double cr = cos(e(0) / 2);
00551         double cp = cos(e(1) / 2);
00552         double cy = cos(e(2) / 2);
00553 
00554         Q_e(0, 0) = (-cy * cp * sr + sy * sp * cr) / 2;
00555         Q_e(0, 1) = (-cy * sp * cr + sy * cp * sr) / 2;
00556         Q_e(0, 2) = (-sy * cp * cr + cy * sp * sr) / 2;
00557         Q_e(1, 0) = (cy * cp * cr + sy * sp * sr) / 2;
00558         Q_e(1, 1) = (-cy * sp * sr - sy * cp * cr) / 2;
00559         Q_e(1, 2) = (-sy * cp * sr - cy * sp * cr) / 2;
00560         Q_e(2, 0) = (-cy * sp * sr + sy * cp * cr) / 2;
00561         Q_e(2, 1) = (cy * cp * cr - sy * sp * sr) / 2;
00562         Q_e(2, 2) = (-sy * sp * cr + cy * cp * sr) / 2;
00563         Q_e(3, 0) = (-sy * cp * sr - cy * sp * cr) / 2;
00564         Q_e(3, 1) = (-cy * cp * sr - sy * sp * cr) / 2;
00565         Q_e(3, 2) = (cy * cp * cr + sy * sp * sr) / 2;
00566       }
00567 
00568 
00574       template<class Vec, class VecQ, class MatQ_e>
00575       void e2q(const Vec & e, VecQ & q, MatQ_e & Q_e) {
00576         q = e2q(e);
00577         e2q_by_de(e, Q_e);
00578       }
00579 
00587       template<class VecXE, class MatPE, class VecXQ, class MatPQ>
00588       void e2q(const VecXE & e, const MatPE & E, VecXQ & q, MatPQ & Q) {
00589         jblas::mat Q_e(4,3);
00590         e2q(e, q, Q_e);
00591         Q = jmath::ublasExtra::prod_JPJt(E, Q_e);
00592       }
00593 
00594 
00595       template<class VecE>
00596       vec7 e2q_frame(const VecE & e) {
00597         vec7 q;
00598         subrange(q,0,3) = subrange(e,0,3);
00599         subrange(q,3,7) = e2q(subrange(e,3,6));
00600         return q;
00601       }
00602 
00603       template<class VecXE, class MatPE, class VecXQ, class MatPQ>
00604       void e2q_frame(const VecXE & e, const MatPE & E, VecXQ & q, MatPQ & Q) {
00605         jblas::mat Q_e = jblas::zero_mat(7,6), Q_e_(4,3);
00606         jblas::vec q_(4);
00607 
00608         subrange(q,0,3) = subrange(e,0,3);
00609         quaternion::e2q(ublas::subrange(e,3,6), q_, Q_e_);
00610         subrange(q,3,7) = q_;
00611 
00612         ublas::subrange(Q_e,0,3,0,3) = jblas::identity_mat(3);
00613         ublas::subrange(Q_e,3,7,3,6) = Q_e_;
00614         Q = ublasExtra::prod_JPJt(E, Q_e);
00615       }
00616 
00617 
00623       template<class VecQ>
00624       vec3 q2e(const VecQ & q) {
00625         vec3 e;
00626 
00627         double y1 = 2 * q(2) * q(3) + 2 * q(0) * q(1);
00628         double x1 = q(0) * q(0) - q(1) * q(1) - q(2) * q(2) + q(3) * q(3);
00629         double z2 = -2 * q(1) * q(3) + 2 * q(0) * q(2);
00630         double y3 = 2 * q(1) * q(2) + 2 * q(0) * q(3);
00631         double x3 = q(0) * q(0) + q(1) * q(1) - q(2) * q(2) - q(3) * q(3);
00632         e(0) = atan2(y1, x1);
00633         e(1) = asin(z2);
00634         e(2) = atan2(y3, x3);
00635         return e;
00636       }
00637 
00644       template<class VecQ, class VecE, class MatE_q>
00645       void q2e(const VecQ & q, VecE & e, MatE_q & E_q) {
00646 
00647         double y1 = 2 * q(2) * q(3) + 2 * q(0) * q(1);
00648         double x1 = q(0) * q(0) - q(1) * q(1) - q(2) * q(2) + q(3) * q(3);
00649         double z2 = -2 * q(1) * q(3) + 2 * q(0) * q(2);
00650         double y3 = 2 * q(1) * q(2) + 2 * q(0) * q(3);
00651         double x3 = q(0) * q(0) + q(1) * q(1) - q(2) * q(2) - q(3) * q(3);
00652 
00653 
00654         // Euler angles
00655         e(0) = atan2(y1, x1);
00656         e(1) = asin(z2);
00657         e(2) = atan2(y3, x3);
00658 
00659 
00660         // Jacobians start here
00661         vec4 dx1dq;
00662         vec4 dy1dq;
00663         vec4 dz2dq;
00664         vec4 dx3dq;
00665         vec4 dy3dq;
00666 
00667 
00668         // derivatives of XYZ wrt q
00669         dx1dq(0) = 2 * q(0);
00670         dx1dq(1) = -2 * q(1);
00671         dx1dq(2) = -2 * q(2);
00672         dx1dq(3) = 2 * q(3);
00673         dy1dq(0) = 2 * q(1);
00674         dy1dq(1) = 2 * q(0);
00675         dy1dq(2) = 2 * q(3);
00676         dy1dq(3) = 2 * q(2);
00677         dz2dq(0) = 2 * q(2);
00678         dz2dq(1) = -2 * q(3);
00679         dz2dq(2) = 2 * q(0);
00680         dz2dq(3) = -2 * q(1);
00681         dx3dq(0) = 2 * q(0);
00682         dx3dq(1) = 2 * q(1);
00683         dx3dq(2) = -2 * q(2);
00684         dx3dq(3) = -2 * q(3);
00685         dy3dq(0) = 2 * q(3);
00686         dy3dq(1) = 2 * q(2);
00687         dy3dq(2) = 2 * q(1);
00688         dy3dq(3) = 2 * q(0);
00689 
00690         double sx2y2 = (x1 * x1 + y1 * y1);
00691         double sx3y3 = (x3 * x3 + y3 * y3);
00692 
00693 
00694         // derivatives of E wrt XYZ
00695         double de1dx1 = -y1 / sx2y2;
00696         double de1dy1 = x1 / sx2y2;
00697         double de2dz2 = 1 / sqrt(1 - z2 * z2);
00698         double de3dx3 = -y3 / sx3y3;
00699         double de3dy3 = x3 / sx3y3;
00700 
00701 
00702         // the chain rule, de/dq = de/dXYZ * dXYZ/dq
00703         row(E_q, 0) = de1dx1 * dx1dq + de1dy1 * dy1dq;
00704         row(E_q, 1) = de2dz2 * dz2dq;
00705         row(E_q, 2) = de3dx3 * dx3dq + de3dy3 * dy3dq;
00706       }
00707 
00715       template<class VecXQ, class MatPQ, class VecXE, class MatPE>
00716       void q2e(const VecXQ & q, const MatPQ & Q, VecXE & e, MatPE & E) {
00717         jblas::mat E_q(3,4);
00718         q2e(q, e, E_q);
00719         E = jmath::ublasExtra::prod_JPJt(Q, E_q);
00720       }
00721 
00722 
00723       template<class VecQ>
00724       vec6 q2e_frame(const VecQ & q) {
00725         vec6 e;
00726         subrange(e,0,3) = subrange(q,0,3);
00727         subrange(e,3,6) = q2e(subrange(q,3,7));
00728         return e;
00729       }
00730 
00731 
00732       template<class VecXQ, class MatPQ, class VecXE, class MatPE>
00733       void q2e_frame(const VecXQ & q, const MatPQ & Q, VecXE & e, MatPE & E) {
00734         jblas::mat E_q = jblas::zero_mat(6,7), E_q_(3,4);
00735         jblas::vec e_(3);
00736 
00737         subrange(e,0,3) = subrange(q,0,3);
00738         quaternion::q2e(ublas::subrange(q,3,7), e_, E_q_);
00739         subrange(e,3,6) = e_;
00740 
00741         ublas::subrange(E_q,0,3,0,3) = jblas::identity_mat(3);
00742         ublas::subrange(E_q,3,6,3,7) = E_q_;
00743         E = ublasExtra::prod_JPJt(Q, E_q);
00744       }
00745 
00750       vec7 originFrame();
00751 
00759       vec4 flu2rdfQuat();
00760 
00765       vec7 flu2rdfFrame();
00766 
00773       template<class VecF, class Pnt>
00774       vec3 eucToFrame(const VecF & F, const Pnt & p) {
00775 
00776         using namespace ublas;
00777 
00778         vec4 q = project(F, range(3, 7));
00779         vec3 t = project(F, range(0, 3));
00780         vec3 v = p - t;
00781         vec3 pf;
00782         pf = rotateInv(q, v);
00783         return pf;
00784       }
00785 
00786 
00795       template<class VecF, class Pnt, class PntF, class MatPF_f, class MatPF_p>
00796       void eucToFrame(const VecF & F, const Pnt & p, PntF & pf, MatPF_f & PF_f, MatPF_p & PF_p, jblas::vec p_fej = jblas::vec(0)) {
00797 
00798         using namespace ublas;
00799 
00800         vec4 q = project(F, range(3, 7));
00801         vec3 t = project(F, range(0, 3));
00802         vec3 v = p - t;
00803         mat_range PF_q(PF_f, range(0, 3), range(3, 7));
00804         rotateInv(q, v, pf, PF_q, PF_p);
00805         if (p_fej.size() != 0) { p_fej -= t; rotateInv_by_dq(q, p_fej, PF_q); }
00806         project(PF_f, range(0, 3), range(0, 3)) = -PF_p;
00807       }
00808 
00809 
00816       template<class VecF, class Vec>
00817       vec3 vecToFrame(const VecF & F, const Vec & v) {
00818         return rotateInv(subrange(F, 3, 7), v);
00819       }
00820 
00821 
00830       template<class VecF, class Vec, class Vecf, class MatVF_f, class MatVF_v>
00831       void vecToFrame(const VecF & F, const Vec & v, Vecf & vf, MatVF_f & VF_f, MatVF_v & VF_v) {
00832 
00833         using namespace ublas;
00834 
00835         vec4 q = project(F, range(3, 7));
00836         mat_range VF_q(VF_f, range(0, 3), range(3, 7));
00837         rotateInv(q, v, vf, VF_q, VF_v);
00838         project(VF_f, range(0, 3), range(0, 3)) = zero_mat(3, 3);
00839       }
00840 
00841 
00848       template<class VecF, class Pnt>
00849       vec3 eucFromFrame(const VecF & F, const Pnt & pf) {
00850 
00851         using namespace ublas;
00852 
00853         return rotate(project(F, range(3, 7)), pf) + project(F, range(0, 3));
00854       }
00855 
00856 
00865       template<class VecF, class PntF, class Pnt, class MatP_f, class MatP_pf>
00866       void eucFromFrame(const VecF & F, const PntF & pf, Pnt & p, MatP_f & P_f, MatP_pf & P_pf) {
00867 
00868         using namespace ublas;
00869 
00870         vec4 q = project(F, range(3, 7));
00871         vec3 t = project(F, range(0, 3));
00872         mat_range P_q(P_f, range(0, 3), range(3, 7));
00873         rotate(q, pf, p, P_q, P_pf);
00874         p += t;
00875         project(P_f, range(0, 3), range(0, 3)) = identity_mat(3); // dp/dt = I
00876       }
00877 
00878 
00885       template<class VecF, class Vec>
00886       vec3 vecFromFrame(const VecF & F, const Vec & vf) {
00887 
00888         using namespace ublas;
00889 
00890         return rotate(subrange(F, 3, 7), vf);
00891       }
00892 
00893 
00902       template<class VecF, class Vecf, class Vec, class MatV_f, class MatV_vf>
00903       void vecFromFrame(const VecF & F, const Vecf & vf, Vec & v, MatV_f & V_f, MatV_vf & V_vf) {
00904         using namespace ublas;
00905         vec4 q = project(F, range(3, 7));
00906         project(V_f, range(0, 3), range(0, 3)) = zero_mat(3, 3); // dv/dt = 0
00907         mat_range V_q(V_f, range(0, 3), range(3, 7));
00908         rotate(q, vf, v, V_q, V_vf);
00909       }
00910 
00911 
00918       template<class VecG, class VecF>
00919       jblas::vec7 composeFrames(const VecG & G, const VecF & F) {
00920         vec4 q1 = subrange(G, 3, 7);
00921         vec3 t2 = subrange(F, 0, 3);
00922         vec4 q2 = subrange(F, 3, 7);
00923         vec3 t = eucFromFrame(G, t2);
00924         vec4 q = qProd(q1, q2);
00925         vec7 H;
00926         subrange(H, 0, 3) = t;
00927         subrange(H, 3, 7) = q;
00928         return H;
00929       }
00930 
00937       template<class VecG, class VecL, class MatC_g>
00938       void composeFrames_by_dglobal(const VecG & G, const VecL & L, MatC_g & C_g) {
00939         /*
00940          * C_g = [ I_3   rotate_by_dq ]
00941          *       [  0    qProd_by_dq1 ]
00942          */
00943         vec4 qg = subrange(G, 3, 7);
00944         vec3 tl = subrange(L, 0, 3);
00945         vec4 ql = subrange(L, 3, 7);
00946         mat T_qg(3, 4);
00947         mat Q_qg(4, 4);
00948         C_g.clear();
00949         ublas::subrange(C_g, 0, 3, 0, 3) = jblas::identity_mat(3);
00950         rotate_by_dq(qg, tl, T_qg);
00951         ublas::subrange(C_g, 0, 3, 3, 7) = T_qg;
00952         qProd_by_dq1(ql, Q_qg);
00953         ublas::subrange(C_g, 3, 7, 3, 7) = Q_qg;
00954       }
00955 
00956 
00963       template<class VecG, class VecL, class MatC_l>
00964       void composeFrames_by_dlocal(const VecG & G, const VecL & L, MatC_l & C_l) {
00965         /*
00966          * C_l = [ rotate_by_dv       0      ]
00967          *       [      0       qProd_by_dq2 ]
00968          */
00969         vec4 qg = subrange(G, 3, 7);
00970         mat_range T_tl(C_l, 0, 3, 0, 3);
00971         mat_range Q_ql(C_l, 4, 7, 4, 7);
00972         C_l.clear();
00973         rotate_by_dv(qg, T_tl);
00974         qProd_by_dq2(qg, Q_ql);
00975       }
00976 
00977 
00986       template<class VecG, class VecL, class VecC, class MatC_g, class MatC_l>
00987       void composeFrames(const VecG & G, const VecL & L, VecC & C, MatC_g & C_g, MatC_l & C_l) {
00988         vec4 qg = subrange(G, 3, 7);
00989         vec3 tl = subrange(L, 0, 3);
00990         vec4 ql = subrange(L, 3, 7);
00991         mat Q_qg(4, 4), Q_ql(4, 4);
00992         mat T_g(3, 7), T_tl(3, 3);
00993         vec3 t;
00994         vec4 q;
00995         eucFromFrame(G, tl, t, T_g, T_tl);
00996         qProd(qg, ql, q, Q_qg, Q_ql);
00997         subrange(C, 0, 3) = t;
00998         subrange(C, 3, 7) = q;
00999         C_g.clear();
01000         subrange(C_g, 0, 3, 0, 7) = T_g;
01001         subrange(C_g, 3, 7, 3, 7) = Q_qg;
01002         C_l.clear();
01003         subrange(C_l, 0, 3, 0, 3) = T_tl;
01004         subrange(C_l, 3, 7, 3, 7) = Q_ql;
01005       }
01006 
01007 
01013       template<class VecF>
01014       jblas::vec7 invertFrame(const VecF & F) {
01015         vec3 t = subrange(F, 0, 3);
01016         vec4 q = subrange(F, 3, 7);
01017         vec7 res;
01018         subrange(res, 0, 3) = -rotateInv(q, t);
01019         subrange(res, 3, 7) = q2qc(q);
01020         return res;
01021       }
01022 
01023 
01030       template<class VecF, class VecI, class MatI_f>
01031       void invertFrame(const VecF & F, VecI & I, MatI_f & I_f) {
01032 
01033         vec3 Ft = subrange(F, 0, 3);
01034         vec4 Fq = subrange(F, 3, 7);
01035         vec3 nt;
01036         vec4 q;
01037         jblas::mat NT_q(3, 4);
01038         jblas::mat NT_t(3, 3);
01039         jblas::mat Q_q(4, 4);
01040 
01041         rotateInv(Fq, Ft, nt, NT_q, NT_t);
01042         q2qc(Fq, q, Q_q);
01043         subrange(I, 0, 3) = -nt;
01044         subrange(I, 3, 7) = q;
01045         I_f.clear();
01046         subrange(I_f, 0, 3, 0, 3) = -NT_t;
01047         subrange(I_f, 0, 3, 3, 7) = -NT_q;
01048         subrange(I_f, 3, 7, 3, 7) = Q_q;
01049 
01050       }
01051 
01059       template<class VecF1, class VecF2>
01060       jblas::vec7 frameIncrement(const VecF1 & F1, const VecF2 & F2){
01061           return composeFrames(invertFrame(F1), F2);
01062       }
01063 
01070       template<class VecF1, class VecF2, class MatF_f1>
01071       void frameIncrement_by_f1(const VecF1 & F1, const VecF2 & F2, MatF_f1 & F_f1){
01072           jblas::vec7 IF1;
01073           jblas::mat IF1_f1(7,7), F_if1(7,7);
01074           invertFrame(F1, IF1, IF1_f1);
01075           composeFrames_by_dglobal(IF1, F2, F_if1);
01076           F_f1 = ublas::prod(F_if1, IF1_f1);
01077       }
01078 
01085       template<class VecF1, class VecF2, class MatF_f2>
01086       void frameIncrement_by_f2(const VecF1 & F1, const VecF2 & F2, MatF_f2 & F_f2){
01087           composeFrames_by_dlocal(invertFrame(F1), F2, F_f2);
01088       }
01089 
01098       template<class VecF1, class VecF2, class VecF, class MatF_f1, class MatF_f2>
01099       void frameIncrement(const VecF1 & F1, const VecF2 & F2, VecF & F, MatF_f1 & F_f1, MatF_f2 & F_f2){
01100           jblas::vec7 IF1;
01101           jblas::mat IF1_f1(7,7), F_if1(7,7);
01102           invertFrame(F1, IF1, IF1_f1);
01103           composeFrames(IF1, F2, F, F_if1, F_f2);
01104           F_f1 = ublas::prod(F_if1, IF1_f1);
01105       }
01106       
01107 
01111     template<class Vec1, class Vec2, class VecL>
01112     void getZoomRotation(const Vec1 &sensorPose1, const Vec2 &sensorPose2, const VecL &landmarkPosition, double &zoom, double &rotation)
01113     {
01114           // First implementation: zoom and rotation
01115       vec3 position1 = ublas::subrange(sensorPose1, 0, 3);
01116       vec3 position2 = ublas::subrange(sensorPose2, 0, 3);
01117       vec4 quat1 = ublas::subrange(sensorPose1, 3, 7);
01118       vec4 quat2 = ublas::subrange(sensorPose2, 3, 7);
01119 
01120       zoom = (norm_2(landmarkPosition - position1))/(norm_2(landmarkPosition-position2));
01121       vec4 quat12 = qProd(q2qc(quat1),quat2);
01122       vec3 euler12 = q2e(quat12);
01123       rotation = euler12(2); // take negative yaw angle
01124     }
01125 
01126 
01127     }
01128   }
01129 }
01130 
01131 #endif /* QUATTOOLS_HPP_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:27 for Jafar by doxygen 1.7.6.1
LAAS-CNRS