rotation.h
Go to the documentation of this file.
00001 
00059 #pragma once
00060 
00061 #include <eigen3/Eigen/Dense>
00062 
00064 namespace DOF6
00065 {
00066 
00067 
00068   template<typename TYPE>
00069   class RotationAxis
00070   {
00071     typedef Eigen::Matrix<TYPE,3,3> Matrix;
00072     typedef Eigen::Matrix<TYPE,3,1> Vector;
00073     typedef Eigen::Matrix<TYPE,2,1> Vector2;
00075     typedef Eigen::EigenSolver<Matrix> EigenSolver;
00076 
00077     Matrix variance_;
00078     Matrix axis_;
00079     Vector var_;
00080 #ifdef DEBUG_
00081     bool initialized_;
00082 #endif
00083 
00084   public:
00085     RotationAxis()
00086 #ifdef DEBUG_
00087     :initialized_(false)
00088 #endif
00089     {
00090       axis_.fill(0);
00091     }
00092     RotationAxis(const Vector &n_old, const Vector &n_new, const Vector &var)
00093 #ifdef DEBUG_
00094     :initialized_(false)
00095 #endif
00096     {
00097       set(n_old,n_new,var);
00098     }
00099 
00100     void set(const Vector &n_old, const Vector &n_new, const Vector &var) {
00101 #ifdef DEBUG_
00102       initialized_ = false;
00103 #endif
00104       Matrix V,Q;
00105       Vector v,u,w;
00106 
00107       //Eigen composition: eigenvalues
00108       V.fill(0);
00109       V(0,0) = var(0);
00110       V(1,1) = var(1);
00111       V(2,2) = var(2);
00112 
00113       //Eigen composition: eigenvectors
00114       v=n_new-n_old;
00115       u=n_old+v/2;
00116       w=v.cross(u);
00117 
00118       v.normalize();
00119       u.normalize();
00120       w.normalize();
00121 
00122       variance_.col(0)=v;
00123       variance_.col(1)=u;
00124       variance_.col(2)=w;
00125 
00126       //Eigen composition: final
00127       variance_ = variance_*V*variance_.inverse();
00128     }
00129 
00135     void operator+=(const RotationAxis &r)
00136     {
00137 #ifdef DEBUG_
00138       initialized_ = false;
00139 #endif
00140       variance_ = (variance_ - variance_*(variance_+r.variance_).inverse()*variance_);
00141     }
00142 
00149     void calc() {
00150       EigenSolver solver(variance_);
00151 /*
00152       std::cout << "The eigenvalues of A are:\n" << solver.eigenvalues() << std::endl;
00153       std::cout << "Here's a matrix whose columns are eigenvectors of A \n"
00154           << "corresponding to these eigenvalues:\n"
00155           << solver.eigenvectors() << std::endl;
00156 */
00157       var_ = solver.eigenvalues().real();
00158       axis_= solver.eigenvectors().real();
00159 
00160 #ifdef DEBUG_
00161       initialized_ = true;
00162 #endif
00163     }
00164 
00165     inline const Matrix &getRotationAxis() const {
00166 #ifdef DEBUG_
00167       ROS_ASSERT(initialized_);
00168 #endif
00169       return axis_;
00170     }
00171 
00172     int getMainAxis() const {
00173       if(var_(0)>var_(1) && var_(0)>var_(2))
00174         return 0;
00175       else if(var_(1)>var_(2))
00176         return 1;
00177       return 2;
00178     }
00179 
00180     Vector getVariance() const {return var_;}
00181   };
00182 
00183   typedef RotationAxis<float> RotationAxisf;
00184   typedef RotationAxis<double> RotationAxisd;
00185 
00186 
00187   template<typename TYPE>
00188   class RotationAngle
00189   {
00190     typedef Eigen::Matrix<TYPE,3,3> Matrix;
00191     typedef Eigen::Matrix<TYPE,3,1> Vector;
00192 
00193     Matrix var_;
00194 
00195     const RotationAxis<TYPE> * const axis_;
00196 
00197   public:
00198     RotationAngle(const RotationAxis<TYPE> * const axis):axis_(axis) {
00199       var_.fill(0);
00200     }
00201 
00202     void add(const Vector &n_old, const Vector &n_new, const TYPE weight=1) {
00203 
00204       for(int i=0; i<3; i++) {
00205         Vector r = axis_->getRotationAxis().col(i);
00206         Vector a=r.cross(n_old), b=r.cross(n_new);
00207         a.normalize();
00208         b.normalize();
00209         const float alpha = std::acos( a.dot(b) );
00210         if(!pcl_isfinite(alpha))
00211           continue;
00212         //std::cout <<"alpha"<<i<<": "<< alpha<<"\n";
00213 
00214         var_.col(i)(0)+=weight;
00215         var_.col(i)(1)+=weight*alpha;
00216         var_.col(i)(2)+=weight*alpha*alpha;//todo: check
00217       }
00218     }
00219 
00220     Vector getAngles() const {
00221       Vector a;
00222       a(0) = var_.col(0)(1)/var_.col(0)(0);
00223       a(1) = var_.col(1)(1)/var_.col(1)(0);
00224       a(2) = var_.col(2)(1)/var_.col(2)(0);
00225       return a;
00226     }
00227 
00228     Vector getVariances() const {
00229       Vector a;
00230      /*TODO a(0) = var_.col(0)(1)/var_.col(0)(0);
00231       a(1) = var_.col(1)(1)/var_.col(1)(0);
00232       a(2) = var_.col(2)(1)/var_.col(2)(0);*/
00233       return a;
00234     }
00235 
00236   };
00237 
00238   typedef RotationAngle<float> RotationAnglef;
00239   typedef RotationAngle<double> RotationAngled;
00240 
00241   template<typename TYPE>
00242   class Rotation
00243   {
00244     typedef Eigen::Matrix<TYPE,3,3> Matrix;
00245     typedef Eigen::Matrix<TYPE,3,1> Vector;
00246 
00247     RotationAngle<TYPE> angle_;
00248     RotationAxis<TYPE> axis_;
00249     int num_;
00250   public:
00251     Rotation():
00252       angle_(&axis_), num_(0)
00253     {}
00254 
00255     void add1(const Vector &n_old, const Vector &n_new, const Vector &var)
00256     {
00257       if(num_==0)
00258         axis_.set(n_old,n_new,var);
00259       else
00260         axis_+=RotationAxis<TYPE>(n_old,n_new,var);
00261       ++num_;
00262     }
00263 
00264     void finish1() {
00265       axis_.calc();
00266     }
00267 
00268     void add2(const Vector &n_old, const Vector &n_new, const TYPE weight=1)
00269     {
00270       angle_.add(n_old,n_new, weight);
00271     }
00272 
00273     Matrix toRotationMatrix() const {
00274       const int axis=axis_.getMainAxis();
00275 
00276       std::cout <<"alpha: "<<angle_.getAngles()(axis)<<"\n";
00277       std::cout <<"r:\n"<<axis_.getRotationAxis().col(axis)<<"\n";
00278       std::cout <<"e:\n"<<axis_.getVariance()<<"\n";
00279 
00280       if(axis_.getRotationAxis().col(axis).squaredNorm()<0.01
00281           || !pcl_isfinite(axis_.getRotationAxis().col(axis).sum())
00282           || !pcl_isfinite(angle_.getAngles()(axis)))
00283         return Matrix::Identity();
00284 
00285       Eigen::AngleAxis<TYPE> aa(angle_.getAngles()(axis),axis_.getRotationAxis().col(axis));
00286 
00287       return aa.toRotationMatrix();
00288     }
00289   };
00290 
00291   typedef Rotation<float> Rotationf;
00292   typedef Rotation<double> Rotationd;
00293 
00294 
00295 
00296   template<typename TYPE>
00297   class Rotation2
00298   {
00299     typedef Eigen::Matrix<TYPE,3,3> Matrix;
00300     typedef Eigen::Matrix<TYPE,3,1> Vector;
00301     typedef Eigen::Matrix<TYPE,2,1> Vector2;
00303     typedef Eigen::EigenSolver<Matrix> EigenSolver;
00304 
00305     Matrix variance_, covariance_;
00306     Matrix axis_;
00307     Vector var_;
00308     TYPE accumulated_weight_;
00309 #ifdef DEBUG_
00310     bool initialized_;
00311 #endif
00312 
00313   public:
00314     Rotation2()
00315     :accumulated_weight_(0)
00316 #ifdef DEBUG_
00317     ,initialized_(false)
00318 #endif
00319     {
00320       axis_.fill(0);
00321     }
00322     Rotation2(const Vector &n_old, const Vector &n_new, const Vector &var, const float weight):
00323       accumulated_weight_(0)
00324 #ifdef DEBUG_
00325     ,initialized_(false)
00326 #endif
00327     {
00328       set(n_old,n_new,var,weight);
00329     }
00330 
00331     void set(const Vector &n_old, const Vector &n_new, const Vector &var, const float weight) {
00332 #ifdef DEBUG_
00333       initialized_ = false;
00334 #endif
00335       Matrix V,Q;
00336       Vector v,u,w;
00337 
00338       //Eigen composition: eigenvalues
00339       V.fill(0);
00340       V(0,0) = var(0);
00341       V(1,1) = var(1);
00342       V(2,2) = var(2);
00343 
00344       //Eigen composition: eigenvectors
00345       v=n_new-n_old;
00346       u=n_old+v/2;
00347       w=v.cross(u);
00348 
00349       v.normalize();
00350       u.normalize();
00351       w.normalize();
00352 
00353       variance_.col(0)=v;
00354       variance_.col(1)=u;
00355       variance_.col(2)=w;
00356 
00357       //Eigen composition: final
00358       variance_ = variance_*V*variance_.inverse();
00359 
00360       //calc covariance
00361       covariance_ = weight*n_old*n_new.transpose();
00362       accumulated_weight_+=weight;
00363     }
00364 
00370     void operator+=(const Rotation2 &r)
00371     {
00372 #ifdef DEBUG_
00373       initialized_ = false;
00374 #endif
00375       variance_ = (variance_ - variance_*(variance_+r.variance_).inverse()*variance_);
00376 
00377       accumulated_weight_ += r.accumulated_weight_;
00378       float alpha = r.accumulated_weight_/accumulated_weight_;
00379 
00380       covariance_ = (1.0-alpha)*(covariance_ + r.covariance_);
00381     }
00382 
00389     void calc() {
00390       EigenSolver solver(variance_);
00391 /*
00392       std::cout << "The eigenvalues of A are:\n" << solver.eigenvalues() << std::endl;
00393       std::cout << "Here's a matrix whose columns are eigenvectors of A \n"
00394           << "corresponding to these eigenvalues:\n"
00395           << solver.eigenvectors() << std::endl;
00396 */
00397       var_ = solver.eigenvalues().real();
00398       axis_= solver.eigenvectors().real();
00399 
00400 #ifdef DEBUG_
00401       initialized_ = true;
00402 #endif
00403     }
00404 
00405     inline const Matrix &getRotationAxis() const {
00406 #ifdef DEBUG_
00407       ROS_ASSERT(initialized_);
00408 #endif
00409       return axis_;
00410     }
00411 
00412     int getMainAxis() const {
00413       if(var_(0)>var_(1) && var_(0)>var_(2))
00414         return 0;
00415       else if(var_(1)>var_(2))
00416         return 1;
00417       return 2;
00418     }
00419 
00420     Vector getVariance() const {return var_;}
00421   };
00422 
00423   typedef Rotation2<float> Rotation2f;
00424   typedef Rotation2<double> Rotation2d;
00425 
00426 #include "impl/rotation.hpp"
00427 
00428 }


cob_3d_mapping_slam
Author(s): Joshua Hampp
autogenerated on Wed Aug 26 2015 11:04:51