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
00108 V.fill(0);
00109 V(0,0) = var(0);
00110 V(1,1) = var(1);
00111 V(2,2) = var(2);
00112
00113
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
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
00153
00154
00155
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
00213
00214 var_.col(i)(0)+=weight;
00215 var_.col(i)(1)+=weight*alpha;
00216 var_.col(i)(2)+=weight*alpha*alpha;
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
00231
00232
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
00339 V.fill(0);
00340 V(0,0) = var(0);
00341 V(1,1) = var(1);
00342 V(2,2) = var(2);
00343
00344
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
00358 variance_ = variance_*V*variance_.inverse();
00359
00360
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
00393
00394
00395
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 }