model.h
Go to the documentation of this file.
00001 
00059 /*
00060  * model.h
00061  *
00062  *  Created on: 11.06.2012
00063  *      Author: josh
00064  */
00065 
00066 #ifndef MODEL_H_
00067 #define MODEL_H_
00068 
00069 namespace intern {
00070 
00072   template<int Degree2>
00073   inline float _intersect(const float mx, const float my, const typename Param<Degree2>::VectorU &p) {
00074     Eigen::Matrix<float, Degree2+1, 1> _p;
00075 
00076     int n = 0;
00077     _p.fill(0);
00078     _p(1) = -1.f;
00079     for(int i=0; i<=Degree2; i++)
00080       for(int j=0; j<=i; j++) {
00081         _p(i) += p(i*(i+1)/2+j)*std::pow(mx,j)*std::pow(my,i-j);
00082         if(std::abs(_p(i))>0.000001f) n=i;
00083       }
00084 
00085     std::vector<double> realRoots;
00086     if(n==Degree2) {
00087       Eigen::PolynomialSolver<float, Degree2> ps(_p);
00088       ps.realRoots( realRoots );
00089     }
00090     else if(n==0)
00091       return _p(0);
00092     else if(n==1)
00093       return -_p(0)/_p(1);
00094     else {
00095       Eigen::PolynomialSolver<float, Eigen::Dynamic> ps(_p.head(n+1));    //reduce degree to n
00096       ps.realRoots( realRoots );
00097     }
00098 
00099     for(size_t i=0; i<realRoots.size(); i++)
00100       if(realRoots[i]>0) return realRoots[i];
00101 
00102     return 0.f;
00103   }
00104 
00106   template<>
00107   inline float _intersect<1>(const float mx, const float my, const typename Param<1>::VectorU &p) {
00108     return -p(0)/(my*p(1)+mx*p(2)-1);
00109   }
00110 }
00111 
00112 
00116 template <int Degree>
00117 struct Model {
00118   typedef Eigen::Matrix<float, 2*Degree+1, 1>    VectorU1D;
00119   typedef Eigen::Matrix<float, 2*Degree+1, 2*Degree+1>    MatrixU1D;
00120   
00121   Param<Degree> param;
00122   typename Param<Degree>::VectorU p;
00123 
00124   Model() {p.fill(0.f);}
00125   Model(const Param<Degree> &pa) {p.fill(0.f); *this+=pa;}
00126   
00128   inline VectorU1D transformation_1D(const Eigen::Vector2f &dir, const Eigen::Vector2f &off, const Eigen::Vector3f &at) {
00129           Eigen::Matrix<float, Degree+1, 1> t; t.fill(0);
00130       typename Param<Degree>::VectorU pp = p;
00131       pp(0) -= at(2);
00132       
00133       for(int i=0; i<=Degree; i++)
00134         for(int j=0; j<=i; j++)
00135                         for(int k=0; k<=j; k++)
00136                                 for(int kk=0; kk<=i-j; kk++)
00137                                         t(k+kk) += pp(i*(i+1)/2+j)*
00138                                         boost::math::binomial_coefficient<float>(j, k)*   std::pow(dir(0),k)* std::pow(off(0),j-k)*
00139                                         boost::math::binomial_coefficient<float>(i-j, kk)*std::pow(dir(1),kk)*std::pow(off(1),i-j-kk);
00140 
00141           const Eigen::Matrix<float, Degree+1, Degree+1> M = t*t.transpose();
00142           VectorU1D r;
00143           r.fill(0);
00144           
00145       for(int i=0; i<=Degree; i++)
00146                   for(int ii=0; ii<=Degree; ii++)
00147                                 r(i+ii) += M(i, ii);
00148                         
00149           const float x0=off(0)-at(0), y0=off(1)-at(1); 
00150           r(0) += x0*x0 + y0*y0;
00151           r(1) += 2*x0*dir(0) + 2*y0*dir(1);
00152           r(2) += dir(0)*dir(0) + dir(1)*dir(1);
00153           
00154       return r;
00155   }
00156 
00160   /*inline bool checkZ(const Param<Degree> &para, const float thr) const {
00161     float d=std::abs((para.model_.row(0)*p)(0)-para.z_(0));
00162     return d<thr*para.model_(0,0);
00163   }*/
00164 
00168   bool isLinearAndTo()
00169   {
00170     if(Degree==1) return true;
00171     
00172     //Variance for both axis (spare small objects)
00173     const float Vx = x();
00174     const float Vy = y();
00175 
00176     if(Vx<0.001f && Vy<0.001f)
00177     {
00178       //      ROS_INFO("np1 %f %f", Vx, Vy);
00179       return false;
00180     }
00181 
00182     Model temp=*this;
00183     temp.getLinear2();
00184 
00185     //const float error1 = (model_.param.z_ - model_.param.model_*model_.p).squaredNorm();
00186     const float error2 = (temp.param.z_ - temp.param.model_*temp.p).norm();
00187     const float d=temp.param.z_(0)/temp.param.model_(0,0);
00188 
00189     float delta = 0.f;
00190     for(int i=3; i<p.cols(); i++)
00191       delta += std::abs(p(i));
00192 
00193     if(//std::abs(param.model_.determinant())*std::abs(param.z_(0))>0.0001f*param.model_(0,0)*param.model_(0,0) &&
00194         (error2 > (temp.param.model_(0,0)*temp.param.model_(0,0))/(1<<13)*d*d || (delta)/(std::abs(p(1))+std::abs(p(2)))>1.f))
00195     {
00196       //      ROS_INFO("np2 %f",std::abs(param.model_.determinant()/param.model_(0,0)));
00197       return false;
00198     }
00199 
00200     *this = temp;
00201 
00202     //    ROS_INFO("plane");
00203 
00204     return true;
00205   }
00206 
00210   inline float get_max_gradient(const Param<Degree> &para) const {
00211     const float x = this->x();
00212     const float y = this->y();
00213     float dx=0.f, dy=0.f;
00214     for(int i=1; i<=Degree; i++)
00215       for(int j=0; j<=i; j++) {
00216         if(i!=j) dy += (i-j)* p(i*(i+1)/2+j)*std::pow(x,j) * std::pow(y,i-j-1);
00217         if(j!=0) dx += j* p(i*(i+1)/2+j)*std::pow(y,i-j) * std::pow(x,j-1);
00218       }
00219 
00220     return std::abs(dx) + std::abs(dy);
00221   }
00222 
00226   inline bool check_tangent(const Param<Degree> &para, const float thr) const {
00227     const float t=(para.z_(0)-(para.model_.row(0)*p)(0))/para.model_(0,0);
00228 
00229     const float x = this->x();
00230     const float y = this->y();
00231     float dx=0.f, dy=0.f;
00232     for(int i=1; i<=Degree; i++)
00233       for(int j=0; j<=i; j++) {
00234         //if(i!=j) dy += p(i*(i+1)/2+j)*(j-1<=0?1:std::pow(x,j-1))*(i-j-1<=0?1:std::pow(y,i-j-1));        //not the correct derivate (on purpose)
00235         //if(j!=0) dx += p(i*(i+1)/2+j)*(j-1<=0?1:std::pow(x,j-1))*(i-j-1<=0?1:std::pow(y,i-j-1));
00236 
00237         if(i!=j) dy += (i-j)*p(i*(i+1)/2+j)*std::pow(x,j) * std::pow(y,i-j-1);
00238         if(j!=0) dx += i*p(i*(i+1)/2+j)*std::pow(y,i-j) * std::pow(x,j-1);
00239       }
00240 
00241     Eigen::Vector3f r;
00242     r(0)=dx;
00243     r(1)=dy;
00244     r(2)=1.f;
00245 
00246     return t*t<thr*thr*r.squaredNorm();
00247   }
00248 
00252   float model(const float x, const float y) const {
00253     float r=0.f;
00254     for(int i=0; i<=Degree; i++)
00255       for(int j=0; j<=i; j++)
00256         r += p(i*(i+1)/2+j)*std::pow(x,j)*std::pow(y,i-j);
00257     return r;
00258   }
00259 
00264   void get() {
00265     if(param.model_(0,0)==0) {
00266       p.fill(0.f);
00267     }
00268     else {
00269       p.head(Param<Degree>::NUM)=param.model_.topLeftCorner(Param<Degree>::NUM,Param<Degree>::NUM).fullPivLu().solve(param.z_.head(Param<Degree>::NUM));
00270 
00271       if(!pcl_isfinite(p(1))) {
00272         p.head(Param<Degree>::NUM)=param.model_.topLeftCorner(Param<Degree>::NUM,Param<Degree>::NUM).ldlt().solve(param.z_.head(Param<Degree>::NUM));
00273 
00274         if(!pcl_isfinite(p(1))) {
00275           ROS_ERROR("failure 0x0176");
00276           std::cerr<<param.model_<<"\n";
00277           std::cerr<<param.z_<<"\n";
00278         }
00279       }
00280 
00281     }
00282   }
00283 
00285   Eigen::Vector3f getLinear() const {
00286     Eigen::Vector3f r;
00287 
00288     if(param.model_(0,0)!=0) {
00289       Eigen::Matrix3f M = param.model_.topLeftCorner(3,3);
00290       Eigen::Vector3f z = param.z_.head(3);
00291       r=M.fullPivLu().solve(z);
00292     }
00293     else r.fill(0);
00294 
00295     return r;
00296   }
00297 
00299   void getLinear2()
00300   {
00301     Eigen::Vector3f r=getLinear();
00302     p.fill(0);
00303     p(0)=r(0);
00304     p(1)=r(1);
00305     p(2)=r(2);
00306   }
00307 
00309   Eigen::Vector3f getNormal_(const float x, const float y) const {
00310     Eigen::Vector3f n;
00311     n(2)=1;
00312     n(0)=n(1)=0;
00313     for(int i=1; i<=Degree; i++)
00314       for(int j=0; j<=i; j++) {
00315         if(i!=j) n(1) -= (i-j)* p(i*(i+1)/2+j)*std::pow(x,j) * std::pow(y,i-j-1);
00316         if(j!=0) n(0) -= j* p(i*(i+1)/2+j)*std::pow(y,i-j) * std::pow(x,j-1);
00317       }
00318     return n;
00319   }
00320 
00322   Eigen::Vector3f getNormal(const float x, const float y) const {
00323     Eigen::Vector3f n = getNormal_(x,y);
00324     n.normalize();
00325     return n;
00326   }
00327 
00329   void operator+=(const Model &m) {
00330     param+=m.param;
00331   }
00332 
00334   void operator+=(const Param<Degree> &m) {
00335     param+=m;
00336   }
00337 
00339   inline float intersect(const float mx, const float my) const {
00340     return intern::_intersect<Degree>(mx,my,p);
00341   }
00342 
00344   inline float x() const {return param.model_(0,2)/param.model_(0,0);}
00346   inline float y() const {return param.model_(0,1)/param.model_(0,0);}
00348   inline float z() const {return param.z_(0)/param.model_(0,0);}
00349 };
00350 
00351 #ifdef QPPF_SPECIALIZATION_2
00352 
00355 template <>
00356 struct Model<2> {
00357   Param<2> param;
00358   typename Param<2>::VectorU p;
00359 
00360   Model() {p.fill(0.f);}
00361   Model(const Param<2> &pa) {p.fill(0.f); *this+=pa;}
00362 
00366   inline bool checkZ(const Param<2> &para, const float thr) const {
00367     float d=std::abs((para.model_.row(0)*p)(0)-para.z_(0));
00368     return d<thr*para.model_(0,0);
00369   }
00370 
00374   bool isLinearAndTo()
00375   {
00376     //Variance for both axis (spare small objects)
00377     const float Vx = (param.model_(1,1)-param.model_(0,1)*param.model_(0,1)/param.model_(0,0))/param.model_(0,0);
00378     const float Vy = (param.model_(3,3)-param.model_(0,3)*param.model_(0,3)/param.model_(0,0))/param.model_(0,0);
00379 
00380     if(Vx<0.001f && Vy<0.001f)
00381     {
00382       //      ROS_INFO("np1 %f %f", Vx, Vy);
00383       return false;
00384     }
00385 
00386     Model temp=*this;
00387     temp.getLinear2();
00388 
00389     //const float error1 = (model_.param.z_ - model_.param.model_*model_.p).squaredNorm();
00390     const float error2 = (temp.param.z_ - temp.param.model_*temp.p).norm();
00391     const float d=temp.param.z_(0)/temp.param.model_(0,0);
00392 
00393     if(//std::abs(param.model_.determinant())*std::abs(param.z_(0))>0.0001f*param.model_(0,0)*param.model_(0,0) &&
00394         (error2 > (temp.param.model_(0,0)*temp.param.model_(0,0))/(1<<13)*d*d || (std::abs(p(2))+std::abs(p(4))+std::abs(p(5)))/(std::abs(p(1))+std::abs(p(3)))>1.f))
00395     {
00396       //      ROS_INFO("np2 %f",std::abs(param.model_.determinant()/param.model_(0,0)));
00397       return false;
00398     }
00399 
00400     *this = temp;
00401 
00402     //    ROS_INFO("plane");
00403 
00404     return true;
00405   }
00406 
00410   inline float get_max_gradient(const Param<2> &para) const {
00411     return
00412         std::abs(2.f*para.model_(0,1)/para.model_(0,0)*p(2)+p(1)+para.model_(0,3)/para.model_(0,0)*p(5))
00413     + std::abs(2.f*para.model_(0,3)/para.model_(0,0)*p(4)+p(3)+para.model_(0,1)/para.model_(0,0)*p(5));
00414   }
00415 
00419   inline bool check_tangent(const Param<2> &para, const float thr) const {
00420     const float t=(para.z_(0)-(para.model_.row(0)*p)(0))/para.model_(0,0);
00421     //std::cout<<t<<" "<<(para.z_(0)/para.model_(0,0)-model(para.model_(0,1)/para.model_(0,0),para.model_(0,3)/para.model_(0,0)))<<" "<<thr<<"\n";
00422     Eigen::Vector3f r;
00423     r(0)=2.f*para.model_(0,1)/para.model_(0,0)*p(2)+p(1)+para.model_(0,3)/para.model_(0,0)*p(5);
00424     r(1)=2.f*para.model_(0,3)/para.model_(0,0)*p(4)+p(3)+para.model_(0,1)/para.model_(0,0)*p(5);
00425     r(2)=1.f;
00426 
00427     return t*t<thr*thr*r.squaredNorm();
00428   }
00429 
00433   /*float model(const Param<2> &para) const {
00434     //return (p(2)*para.model_(0,2)+p(4)*para.model_(0,4) + p(1)*para.model_(0,1)+p(3)*para.model_(0,3))/para.model_(0,0) + p(0);
00435     return (para.model_.row(0)*p)(0)/para.model_(0,0);
00436   }*/
00437 
00441   float model(const float x, const float y) const {
00442     return p(0)+p(1)*x+p(2)*x*x+p(3)*y+p(4)*y*y+p(5)*x*y;
00443   }
00444 
00445   float getCorrelation() const { //TODO: not correct
00446     return (
00447         param.model_(1,3)-param.model_(0,1)*param.model_(0,3)/param.model_(0,0)
00448     )
00449     /sqrtf(
00450         (param.model_(1,1)-param.model_(0,1)*param.model_(0,1)/param.model_(0,0))*
00451         (param.model_(3,3)-param.model_(0,3)*param.model_(0,3)/param.model_(0,0))
00452     );
00453   }
00454 
00459   void get() {
00460     if(param.model_(0,0)==0) {
00461       p.fill(0.f);
00462     }
00463     //    else if(param.model_(0,0)>1000 && std::abs(param.model_.determinant()/param.model_(0,0))<0.00001f)
00464     //    {
00465     //      getLinear2();
00466     //    }
00467     else {
00468 
00469       p.head<Param<2>::NUM>()=param.model_.topLeftCorner<Param<2>::NUM,Param<2>::NUM>().fullPivLu().solve(param.z_.head<Param<2>::NUM>());
00470 
00471       if(!pcl_isfinite(p(1))) {
00472         p.head<Param<2>::NUM>()=param.model_.topLeftCorner<Param<2>::NUM,Param<2>::NUM>().ldlt().solve(param.z_.head<Param<2>::NUM>());
00473 
00474         if(!pcl_isfinite(p(1))) {
00475           ROS_ERROR("failure 0x0176");
00476           std::cerr<<param.model_<<"\n";
00477           std::cerr<<param.z_<<"\n";
00478         }
00479       }
00480       
00481     }
00482   }
00483 
00484   Eigen::Matrix3f getLinearMatrix() const {
00485     Eigen::Matrix3f M;
00486     for(int i=0; i<3; i++)
00487       for(int j=0; j<3; j++)
00488         M(i,j)=param.model_(i>1?3:i, j>1?3:j);
00489     return M;
00490   }
00491 
00492   Eigen::Vector3f getLinear() const {
00493     Eigen::Vector3f r;
00494     r.fill(0);
00495     if(param.model_(0,0)!=0) {
00496       Eigen::Matrix3f M;
00497       Eigen::Vector3f z;
00498       z(0)=param.z_(0);
00499       z(1)=param.z_(1);
00500       z(2)=param.z_(3);
00501       for(int i=0; i<3; i++)
00502         for(int j=0; j<3; j++)
00503           M(i,j)=param.model_(i>1?3:i, j>1?3:j);
00504       //_p=M.inverse()*z;
00505       r=M.fullPivLu().solve(z);
00506 
00507       //r=M.inverse()*z;
00508     }
00509 
00510     return r;
00511   }
00512 
00513   void getLinear2()
00514   {
00515     Eigen::Vector3f r=getLinear();
00516     p(0)=r(0);
00517     p(1)=r(1);
00518     p(2)=0;
00519     p(3)=r(2);
00520     p(4)=0;
00521     p(5)=0;
00522   }
00523 
00524   Eigen::Vector3f getLinearNormal() {
00525     Eigen::Vector3f n,t=getLinear();
00526     n(2)=1;
00527     n(0)=t(1);
00528     n(1)=t(2);
00529     n.normalize();
00530     return n;
00531   }
00532 
00533   Eigen::Vector3f getNormal(const float x, const float y) const {
00534     Eigen::Vector3f n;
00535     n(2)=1;
00536     n(0)=-(p(1)+2*x*p(2)+p(5)*y);
00537     n(1)=-(p(3)+2*x*p(4)+p(5)*x);
00538     n.normalize();
00539     return n;
00540   }
00541 
00542   void operator+=(const Model &m) {
00543     param+=m.param;
00544   }
00545   void operator+=(const Param<2> &m) {
00546     param+=m;
00547   }
00548 
00549   float intersect(const float mx, const float my) const {
00550     float a=mx*mx*p(2) + my*my*p(4) + mx*my*p(5);
00551     float b=mx*p(1) + my*p(3) - 1;
00552 
00553     if(std::abs(a)<0.00001f) {
00554       return -p(0)/b;
00555     }
00556 
00557     float t,z2;
00558     //if(t<0.f && t>-0.1)
00559     //  return (-b)/(2*a);
00560     t=b*b-4*a*p(0);
00561     z2=(-b-sqrtf(t))/(2*a);
00562     /*if(!pcl_isfinite(z2)) {
00563           a*=0.95f;
00564           t=b*b-4*a*p(0);
00565           z2=(-b-sqrtf(t))/(2*a);
00566         }*/
00567 
00568 #if DEBUG_LEVEL >70
00569     if(!pcl_isfinite(z2)) {
00570       std::cerr<<"t: "<<t<<"\n";
00571       std::cerr<<"a: "<<a<<"\n";
00572     }
00573 #endif
00574     /*
00575         float z1=(-b+sqrtf(b*b-4*a*p(0)))/(2*a);
00576 
00577         std::cout<<"a: "<<a<<" b: "<<b<<" c: "<<p(0)<<"\n";
00578         std::cout<<"mx: "<<mx<<" my: "<<my<<"\n";
00579         std::cout<<"z: "<<z2<<" z: "<<z1<<"\n";
00580         std::cout<<"m: "<<<<"\n";*/
00581 
00582     return z2;
00583   }
00584 
00585   inline float x() const {return param.model_(0,1)/param.model_(0,0);}
00586   inline float y() const {return param.model_(0,3)/param.model_(0,0);}
00587   inline float z() const {return param.z_(0)/param.model_(0,0);}
00588 };
00589 #endif
00590 
00591 #endif /* MODEL_H_ */


cob_3d_segmentation
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:03:03