rodrigues.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007-13 Andrea Vedaldi and Brian Fulkerson.
00008 All rights reserved.
00009 
00010 This file is part of the VLFeat library and is made available under
00011 the terms of the BSD license (see the COPYING file).
00012 */
00013 
00014 #include "generic.h"
00015 #include "mathop.h"
00016 #include "rodrigues.h"
00017 
00018 #include <math.h>
00019 
00026 void
00027 vl_rodrigues(double* R_pt, double* dR_pt, const double* om_pt)
00028 {
00029   /*
00030     Let
00031 
00032        th = |om|,  r=w/th,
00033        sth=sin(th),  cth=cos(th),
00034        ^om = hat(om)
00035 
00036     Then the rodrigues formula is an expansion of the exponential
00037     function:
00038 
00039      rodrigues(om) = exp ^om = I + ^r sth + ^r^2 (1 - cth).
00040 
00041     The derivative can be computed by elementary means and
00042     results:
00043 
00044     d(vec rodrigues(om))    sth  d ^r    1 - cth  d (^r)^2
00045     -------------------- =  ---- ----- + -------  -------- +
00046           d om^T             th  d r^T     th      d r^T
00047 
00048                           sth                     1 - cth
00049           + vec^r (cth - -----) + vec^r^2 (sth - 2-------)r^T
00050                           th                         th
00051   */
00052 
00053 #define OM(i)   om_pt[(i)]
00054 #define R(i,j)  R_pt[(i)+3*(j)]
00055 #define DR(i,j) dR_pt[(i)+9*(j)]
00056 #undef small
00057 
00058   const double small = 1e-6 ;
00059 
00060   double th = sqrt( OM(0)*OM(0) +
00061                     OM(1)*OM(1) +
00062                     OM(2)*OM(2) ) ;
00063 
00064   if( th < small ) {
00065     R(0,0) = 1.0 ; R(0,1) = 0.0 ; R(0,2) = 0.0 ;
00066     R(1,0) = 0.0 ; R(1,1) = 1.0 ; R(1,2) = 0.0 ;
00067     R(2,0) = 0.0 ; R(2,1) = 0.0 ; R(2,2) = 1.0 ;
00068 
00069     if(dR_pt) {
00070       DR(0,0) = 0  ; DR(0,1) = 0   ; DR(0,2) = 0 ;
00071       DR(1,0) = 0  ; DR(1,1) = 0   ; DR(1,2) = 1 ;
00072       DR(2,0) = 0  ; DR(2,1) = -1  ; DR(2,2) = 0 ;
00073 
00074       DR(3,0) = 0  ; DR(3,1) = 0   ; DR(3,2) = -1 ;
00075       DR(4,0) = 0  ; DR(4,1) = 0   ; DR(4,2) = 0 ;
00076       DR(5,0) = 1  ; DR(5,1) = 0   ; DR(5,2) = 0 ;
00077 
00078       DR(6,0) = 0  ; DR(6,1) = 1   ; DR(6,2) = 0 ;
00079       DR(7,0) = -1 ; DR(7,1) = 0   ; DR(7,2) = 0 ;
00080       DR(8,0) = 0  ; DR(8,1) = 0   ; DR(8,2) = 0 ;
00081     }
00082     return ;
00083   }
00084 
00085   {
00086     double x = OM(0) / th ;
00087     double y = OM(1) / th ;
00088     double z = OM(2) / th ;
00089 
00090     double xx = x*x ;
00091     double xy = x*y ;
00092     double xz = x*z ;
00093     double yy = y*y ;
00094     double yz = y*z ;
00095     double zz = z*z ;
00096 
00097     const double yx = xy ;
00098     const double zx = xz ;
00099     const double zy = yz ;
00100 
00101     double sth  = sin(th) ;
00102     double cth  = cos(th) ;
00103     double mcth = 1.0 - cth ;
00104 
00105     R(0,0) = 1          - mcth * (yy+zz) ;
00106     R(1,0) =     sth*z  + mcth * xy ;
00107     R(2,0) =   - sth*y  + mcth * xz ;
00108 
00109     R(0,1) =   - sth*z  + mcth * yx ;
00110     R(1,1) = 1          - mcth * (zz+xx) ;
00111     R(2,1) =     sth*x  + mcth * yz ;
00112 
00113     R(0,2) =     sth*y  + mcth * xz ;
00114     R(1,2) =   - sth*x  + mcth * yz ;
00115     R(2,2) = 1          - mcth * (xx+yy) ;
00116 
00117     if(dR_pt) {
00118       double a =  sth / th ;
00119       double b = mcth / th ;
00120       double c = cth - a ;
00121       double d = sth - 2*b ;
00122 
00123       DR(0,0) =                         - d * (yy+zz) * x ;
00124       DR(1,0) =        b*y   + c * zx   + d * xy      * x ;
00125       DR(2,0) =        b*z   - c * yx   + d * xz      * x ;
00126 
00127       DR(3,0) =        b*y   - c * zx   + d * xy      * x ;
00128       DR(4,0) =     -2*b*x              - d * (zz+xx) * x ;
00129       DR(5,0) =  a           + c * xx   + d * yz      * x ;
00130 
00131       DR(6,0) =        b*z   + c * yx   + d * zx      * x ;
00132       DR(7,0) = -a           - c * xx   + d * zy      * x ;
00133       DR(8,0) =     -2*b*x              - d * (yy+xx) * x ;
00134 
00135       DR(0,1) =     -2*b*y              - d * (yy+zz) * y ;
00136       DR(1,1) =        b*x   + c * zy   + d * xy      * y ;
00137       DR(2,1) = -a           - c * yy   + d * xz      * y ;
00138 
00139       DR(3,1) =        b*x   - c * zy   + d * xy      * y ;
00140       DR(4,1) =                         - d * (zz+xx) * y ;
00141       DR(5,1) =        b*z   + c * xy   + d * yz      * y ;
00142 
00143       DR(6,1) = a            + c * yy   + d * zx      * y ;
00144       DR(7,1) =        b*z   - c * xy   + d * zy      * y ;
00145       DR(8,1) =     -2*b*y              - d * (yy+xx) * y ;
00146 
00147       DR(0,2) =     -2*b*z              - d * (yy+zz) * z ;
00148       DR(1,2) =  a           + c * zz   + d * xy      * z ;
00149       DR(2,2) =        b*x   - c * yz   + d * xz      * z ;
00150 
00151       DR(3,2) =  -a          - c * zz   + d * xy      * z ;
00152       DR(4,2) =     -2*b*z              - d * (zz+xx) * z ;
00153       DR(5,2) =        b*y   + c * xz   + d * yz      * z ;
00154 
00155       DR(6,2) =        b*x   + c * yz   + d * zx      * z ;
00156       DR(7,2) =        b*y   - c * xz   + d * zy      * z ;
00157       DR(8,2) =                         - d * (yy+xx) * z ;
00158     }
00159   }
00160 
00161 #undef OM
00162 #undef R
00163 #undef DR
00164 
00165 }
00166 
00178 VL_EXPORT
00179 void vl_irodrigues(double* om_pt, double* dom_pt, const double* R_pt)
00180 {
00181   /*
00182                     tr R - 1          1    [ R32 - R23 ]
00183       th = cos^{-1} --------,  r =  ------ [ R13 - R31 ], w = th r.
00184                         2           2 sth  [ R12 - R21 ]
00185 
00186       sth = sin(th)
00187 
00188        dw    th*cth-sth      dw     th   [di3 dj2 - di2 dj3]
00189       ---- = ---------- r,  ---- = ----- [di1 dj3 - di3 dj1].
00190       dRii     2 sth^2      dRij   2 sth [di1 dj2 - di2 dj1]
00191 
00192       trace(A) < -1 only for small num. errors.
00193   */
00194 
00195 #define OM(i)    om_pt[(i)]
00196 #define DOM(i,j) dom_pt[(i)+3*(j)]
00197 #define R(i,j)   R_pt[(i)+3*(j)]
00198 #define W(i,j)   W_pt[(i)+3*(j)]
00199 
00200   const double small = 1e-6 ;
00201 
00202   double th = acos
00203     (0.5*(VL_MAX(R(0,0)+R(1,1)+R(2,2),-1.0) - 1.0)) ;
00204 
00205   double sth = sin(th) ;
00206   double cth = cos(th) ;
00207 
00208   if(fabs(sth) < small && cth < 0) {
00209     /*
00210       we have this singularity when the rotation  is about pi (or -pi)
00211       we use the fact that in this case
00212 
00213       hat( sqrt(1-cth) * r )^2 = W = (0.5*(R+R') - eye(3))
00214 
00215       which gives
00216 
00217       (1-cth) rx^2 = 0.5 * (W(1,1)-W(2,2)-W(3,3))
00218       (1-cth) ry^2 = 0.5 * (W(2,2)-W(3,3)-W(1,1))
00219       (1-cth) rz^2 = 0.5 * (W(3,3)-W(1,1)-W(2,2))
00220     */
00221 
00222     double W_pt [9], x, y, z ;
00223     W_pt[0] = 0.5*( R(0,0) + R(0,0) ) - 1.0 ;
00224     W_pt[1] = 0.5*( R(1,0) + R(0,1) ) ;
00225     W_pt[2] = 0.5*( R(2,0) + R(0,2) );
00226 
00227     W_pt[3] = 0.5*( R(0,1) + R(1,0) );
00228     W_pt[4] = 0.5*( R(1,1) + R(1,1) ) - 1.0;
00229     W_pt[5] = 0.5*( R(2,1) + R(1,2) );
00230 
00231     W_pt[6] =  0.5*( R(0,2) + R(2,0) ) ;
00232     W_pt[7] =  0.5*( R(1,2) + R(2,1) ) ;
00233     W_pt[8] =  0.5*( R(2,2) + R(2,2) ) - 1.0 ;
00234 
00235     /* these are only absolute values */
00236     x = sqrt( 0.5 * (W(0,0)-W(1,1)-W(2,2)) ) ;
00237     y = sqrt( 0.5 * (W(1,1)-W(2,2)-W(0,0)) ) ;
00238     z = sqrt( 0.5 * (W(2,2)-W(0,0)-W(1,1)) ) ;
00239 
00240     /* set the biggest component to + and use the element of the
00241     ** matrix W to determine the sign of the other components
00242     ** then the solution is either (x,y,z) or its opposite */
00243     if( x >= y && x >= z ) {
00244       y = (W(1,0) >=0) ? y : -y ;
00245       z = (W(2,0) >=0) ? z : -z ;
00246     } else if( y >= x && y >= z ) {
00247       z = (W(2,1) >=0) ? z : -z ;
00248       x = (W(1,0) >=0) ? x : -x ;
00249     } else {
00250       x = (W(2,0) >=0) ? x : -x ;
00251       y = (W(2,1) >=0) ? y : -y ;
00252     }
00253 
00254     /* we are left to chose between (x,y,z) and (-x,-y,-z)
00255     ** unfortunately we cannot (as the rotation is too close to pi) and
00256     ** we just keep what we have. */
00257     {
00258       double scale = th / sqrt( 1 - cth ) ;
00259       OM(0) = scale * x ;
00260       OM(1) = scale * y ;
00261       OM(2) = scale * z ;
00262 
00263       if( dom_pt ) {
00264         int k ;
00265         for(k=0; k<3*9; ++k)
00266           dom_pt [k] = VL_NAN_D ;
00267       }
00268       return ;
00269     }
00270 
00271   } else {
00272     double a = (fabs(sth) < small) ? 1 : th/sin(th) ;
00273     double b ;
00274     OM(0) = 0.5*a*(R(2,1) - R(1,2)) ;
00275     OM(1) = 0.5*a*(R(0,2) - R(2,0)) ;
00276     OM(2) = 0.5*a*(R(1,0) - R(0,1)) ;
00277 
00278     if( dom_pt ) {
00279       if( fabs(sth) < small ) {
00280         a = 0.5 ;
00281         b = 0 ;
00282       } else {
00283         a = th/(2*sth) ;
00284         b = (th*cth - sth)/(2*sth*sth)/th ;
00285       }
00286 
00287       DOM(0,0) = b*OM(0) ;
00288       DOM(1,0) = b*OM(1) ;
00289       DOM(2,0) = b*OM(2) ;
00290 
00291       DOM(0,1) = 0 ;
00292       DOM(1,1) = 0 ;
00293       DOM(2,1) = a ;
00294 
00295       DOM(0,2) = 0 ;
00296       DOM(1,2) = -a ;
00297       DOM(2,2) = 0 ;
00298 
00299       DOM(0,3) = 0 ;
00300       DOM(1,3) = 0 ;
00301       DOM(2,3) = -a ;
00302 
00303       DOM(0,4) = b*OM(0) ;
00304       DOM(1,4) = b*OM(1) ;
00305       DOM(2,4) = b*OM(2) ;
00306 
00307       DOM(0,5) = a ;
00308       DOM(1,5) = 0 ;
00309       DOM(2,5) = 0 ;
00310 
00311       DOM(0,6) = 0 ;
00312       DOM(1,6) = a ;
00313       DOM(2,6) = 0 ;
00314 
00315       DOM(0,7) = -a ;
00316       DOM(1,7) = 0 ;
00317       DOM(2,7) = 0 ;
00318 
00319       DOM(0,8) = b*OM(0) ;
00320       DOM(1,8) = b*OM(1) ;
00321       DOM(2,8) = b*OM(2) ;
00322     }
00323   }
00324 
00325 #undef OM
00326 #undef DOM
00327 #undef R
00328 #undef W
00329 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51