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
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
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
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
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
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
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);
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
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
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
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
00454 vec3 u(v);
00455 ublasExtra::normalize(u);
00456 mat U_v(3, 3);
00457 jmath::ublasExtra::normalizeJac(v, U_v);
00458
00459
00460
00461 mat A_v(1, 3);
00462 row(A_v, 0) = u;
00463
00464
00465
00466
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
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
00485 Q_v = prod(Q_a, A_v) + prod(Q_u, U_v);
00486
00487 }
00488 else {
00489
00490
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
00655 e(0) = atan2(y1, x1);
00656 e(1) = asin(z2);
00657 e(2) = atan2(y3, x3);
00658
00659
00660
00661 vec4 dx1dq;
00662 vec4 dy1dq;
00663 vec4 dz2dq;
00664 vec4 dx3dq;
00665 vec4 dy3dq;
00666
00667
00668
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
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
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);
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);
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
00941
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
00967
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
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);
01124 }
01125
01126
01127 }
01128 }
01129 }
01130
01131 #endif