bb.h
Go to the documentation of this file.
00001 /*
00002  * bb.h
00003  *
00004  *  Created on: 15.08.2012
00005  *      Author: josh
00006  */
00007 
00008 #ifndef BB_H_
00009 #define BB_H_
00010 
00011 #include <pcl/common/pca.h>
00012 
00013 namespace BoundingBox {
00014   struct TransformedFoVBB
00015   {
00016     struct Plane {
00017       Eigen::Vector3f normal_x_,normal_y_, offs_;
00018       Eigen::Vector2f boundary_[4];
00019 
00020       int pnpoly(float x, float y) const
00021       {
00022         int i, j, c = 0;
00023         for (i = 0, j = 4-1; i < 4; j = i++) {
00024           if ((((boundary_[i](1) <= y) && (y < boundary_[j](1))) ||
00025               ((boundary_[j](1) <= y) && (y < boundary_[i](1)))) &&
00026               (x < (boundary_[j](0) - boundary_[i](0)) * (y - boundary_[i](1)) / (boundary_[j](1) - boundary_[i](1)) + boundary_[i](0)))
00027             c = !c;
00028         }
00029         return c;
00030       }
00031 
00032       bool intersectRay(const Eigen::Vector3f &a, const Eigen::Vector3f &b) const
00033       {
00034         Eigen::Matrix3f M;
00035         Eigen::Vector3f v;
00036         M.col(0) = a-b;
00037         M.col(1) = normal_x_;
00038         M.col(2) = normal_y_;
00039         //        std::cout<<"M\n"<<M<<"\n";
00040         v = M.inverse()*(a-offs_);
00041         //        std::cout<<a<<"\n\n";
00042         //        std::cout<<b<<"\n\n";
00043         //        ROS_INFO("%f %f %f", v(0),v(1),v(2));
00044         if(std::abs(v(0))<=1)
00045         {
00046           //          for(int i=0; i<4; i++)
00047           //            std::cout<<boundary_[i]<<"\n\n";
00048 
00049           return pnpoly(v(1),v(2));
00050         }
00051         return false;//TODO: check
00052       }
00053 
00054       bool sidePt(const Eigen::Vector3f &a) const
00055       {
00056         //        std::cout<<"BB\n"<<a<<"\n\n";
00057         //        std::cout<<offs_<<"\n\n";
00058         //        std::cout<<normal_x_<<"\n\n";
00059         //        std::cout<<normal_y_<<"\n\n";
00060         //        std::cout<<normal_x_.cross(normal_y_)<<"\n\n";
00061         //        std::cout<<(a-offs_).dot(normal_x_.cross(normal_y_))<<"\n\n";
00062         return (a-offs_).dot(normal_x_.cross(normal_y_))>0;
00063       }
00064 
00065     };
00066 
00067     Plane planes_[6];
00068     Eigen::Vector3f p_[8];
00069 
00070     bool check(const TransformedFoVBB &o) const {
00071       for(int j=0; j<6; j++)
00072         for(int i=0; i<4; i++)
00073         {
00074           if(planes_[j].intersectRay(o.p_[i],o.p_[(i+1)%4]))
00075             return true;
00076           if(planes_[j].intersectRay(o.p_[i+4],o.p_[(i+1)%4+4]))
00077             return true;
00078           if(planes_[j].intersectRay(o.p_[i+4],o.p_[i]))
00079             return true;
00080         }
00081       return false;
00082     }
00083 
00084     bool operator&(const TransformedFoVBB &o) const
00085     {
00086       return check(o) || o.check(*this);
00087     }
00088 
00089     bool operator&(const Eigen::Vector3f &o) const
00090     {
00091       if(planes_[0].sidePt(o)!=planes_[1].sidePt(o)) return false;
00092       if(planes_[2].sidePt(o)!=planes_[4].sidePt(o)) return false;
00093       if(planes_[3].sidePt(o)!=planes_[5].sidePt(o)) return false;
00094       return true;
00095     }
00096   };
00097 
00098 
00099 
00100   template<typename _TYPE>
00101   class FoVBB 
00102   {
00103   public:
00104     typedef _TYPE TYPE;
00105 
00106   protected:
00107     TYPE min_dist_, max_dist_;
00108     TYPE min_x_, min_y_, max_x_, max_y_;
00109 
00110   public:
00111 
00112     //for testing
00113     void update(const Eigen::Vector3f &mi, const Eigen::Vector3f &ma) {
00114       min_dist_ = min_x_ = min_y_ = std::numeric_limits<float>::max();
00115       max_dist_ = max_x_ = max_y_ = -std::numeric_limits<float>::max();
00116 
00117       min_dist_ = std::min(min_dist_, mi(2));
00118       min_x_ = std::min(min_x_, mi(0)/mi(2));
00119       min_y_ = std::min(min_y_, mi(1)/mi(2));
00120       max_dist_ = std::max(max_dist_, ma(2));
00121       max_x_ = std::max(max_x_, ma(0)/ma(2));
00122       max_y_ = std::max(max_y_, ma(1)/ma(2));
00123     }
00124 
00125     TransformedFoVBB transform(const Eigen::Matrix3f &R, const Eigen::Vector3f t) const {
00126       TransformedFoVBB r;
00127       r.p_[0](0) = min_x_;
00128       r.p_[0](1) = min_y_;
00129       r.p_[1](0) = max_x_;
00130       r.p_[1](1) = min_y_;
00131       r.p_[2](0) = max_x_;
00132       r.p_[2](1) = max_y_;
00133       r.p_[3](0) = min_x_;
00134       r.p_[3](1) = max_y_;
00135 
00136       Eigen::Vector3f p[8];
00137       for(int i=0; i<4; i++)
00138         r.p_[i+4] = r.p_[i];
00139       for(int i=0; i<8; i++)
00140       {
00141         r.p_[i](2) = 1;
00142         r.p_[i] *= i<4 ? min_dist_:max_dist_;
00143         p[i] = r.p_[i];
00144         r.p_[i] = R*r.p_[i] + t;
00145       }
00146 
00147       Eigen::Vector3f x,y,z;
00148       x=y=z=Eigen::Vector3f::Zero();
00149       x(0)=1;
00150       y(1)=1;
00151       z(2)=1;
00152 
00153       r.planes_[0].offs_ = R*min_dist_*z+t;
00154       r.planes_[1].offs_ = R*max_dist_*z+t;
00155       r.planes_[0].normal_x_ = R*x;
00156       r.planes_[0].normal_y_ = R*y;
00157       r.planes_[1].normal_x_ = -R*x;
00158       r.planes_[1].normal_y_ = R*y;
00159       for(int i=0; i<4; i++)
00160       {
00161         r.planes_[0].boundary_[i] = (p[i].head(2));
00162         r.planes_[1].boundary_[i] = (p[i+4].head(2));
00163       }
00164 
00165       //        for(int i=0; i<8; i++)
00166       //        {
00167       //          std::cout<<"p\n"<<r.p_[i]<<"\n";
00168       //        }
00169 
00170       for(int i=0; i<4; i++)
00171       {
00172         r.planes_[2+i].normal_x_ = r.p_[i+4]+r.p_[(i+1)%4+4]-r.p_[i]-r.p_[(i+1)%4];
00173         r.planes_[2+i].normal_x_.normalize();
00174         r.planes_[2+i].normal_y_ = r.p_[(i+1)%4]-r.p_[i];
00175         r.planes_[2+i].normal_y_.normalize();
00176 
00177         r.planes_[2+i].boundary_[0](0) = p[i](2);
00178         r.planes_[2+i].boundary_[1](0) = p[(i+1)%4](2);
00179         r.planes_[2+i].boundary_[2](0) = p[(i+1)%4](2);
00180         r.planes_[2+i].boundary_[3](0) = p[i+4](2);
00181 
00182         r.planes_[2+i].boundary_[0](1) = p[i](i%2);
00183         r.planes_[2+i].boundary_[1](1) = p[(i+1)%4](i%2);
00184         r.planes_[2+i].boundary_[2](1) = p[(i+1)%4](i%2);
00185         r.planes_[2+i].boundary_[3](1) = p[i+4](i%2);
00186 
00187         r.planes_[2+i].offs_ = t;
00188       }
00189 
00190       return r;
00191     }
00192 
00193     void get8Edges(Eigen::Vector3f *edges) const {
00194       for(int i=0; i<4; i++) {
00195         edges[i+4](0) = edges[i](0) = (i&1?min_x_:max_x_);
00196         edges[i+4](1) = edges[i](1) = (i&2?min_y_:max_y_);
00197         edges[i+4](2) = edges[i](2) = 1;
00198         edges[i+4] *= max_dist_;
00199         edges[i] *= min_dist_;
00200       }
00201     }
00202 
00203   };
00204 
00205 
00206   class AABB {
00207     Eigen::Vector3f mi_, ma_;
00208   public:
00209     AABB() {}
00210     AABB(const Eigen::Vector3f &v):mi_(v),ma_(v) {}
00211 
00212     bool operator&(const AABB &o) const {
00213       return mi_(0)<=o.ma_(0) && ma_(0)>=o.mi_(0) &&
00214           mi_(1)<=o.ma_(1) && ma_(1)>=o.mi_(1) &&
00215           mi_(2)<=o.ma_(2) && ma_(2)>=o.mi_(2) ;
00216     }
00217 
00218     AABB increaseIfNec(const float rot, const float tr) const {
00219       AABB r = *this;
00220       return r;
00221     }
00222 
00223     AABB transform(const Eigen::Matrix3f &R, const Eigen::Vector3f &tr) const {
00224       AABB r = *this;
00225       r.mi_ = R*mi_ + tr;
00226       r.ma_ = R*ma_ + tr;
00227       return r;
00228     }
00229 
00230     void get8Edges(Eigen::Vector3f *edges) const {
00231       for(int i=0; i<8; i++) {
00232         edges[i](0) = (i&1?mi_(0):ma_(0));
00233         edges[i](1) = (i&2?mi_(1):ma_(1));
00234         edges[i](2) = (i&4?mi_(2):ma_(2));
00235       }
00236     }
00237 
00238     float extension() const {
00239       return (ma_-mi_).norm();
00240     }
00241 
00242     void minmax(Eigen::Vector3f &mi, Eigen::Vector3f &ma) const {
00243       mi = mi_;
00244       ma = ma_;
00245     }
00246   };
00247 
00248   class OOBB {
00249     Eigen::Vector3f m_, e_;
00250     Eigen::Matrix3f axis_;
00251   public:
00252     void debug() const {
00253       std::cout<<"mid\n"<<m_<<"\n";
00254       std::cout<<"ex\n"<<e_<<"\n";
00255       std::cout<<"axis\n"<<axis_<<"\n";
00256     }
00257 
00258     OOBB() {}
00259 
00260     OOBB(const Eigen::Vector3f &v):axis_(Eigen::Matrix3f::Identity()), m_(v) {for(int i=0; i<3; i++) e_(i)=0.001f;}
00261 
00262     void set(const pcl::PointCloud<pcl::PointXYZ> &pc) {
00263       pcl::PCA<pcl::PointXYZ> pca;
00264       pca.compute(pc);
00265 
00266       m_ = pca.getMean().head<3>();
00267       axis_ = pca.getEigenVectors();
00268       e_ = Eigen::Vector3f::Zero();
00269 
00270       Eigen::Vector3f t;
00271       for(size_t i=0; i<pc.size(); i++) {
00272         t = axis_.transpose()*(pc[i].getVector3fMap()-m_);
00273         t(0)=std::abs(t(0));t(1)=std::abs(t(1));t(2)=std::abs(t(2));
00274         if(t(0)>e_(0))
00275           e_(0)=t(0);
00276         if(t(1)>e_(1))
00277           e_(1)=t(1);
00278         if(t(2)>e_(2))
00279           e_(2)=t(2);
00280       }
00281 
00282       for(int i=0; i<3; i++) e_(i)=std::max(e_(i),0.001f);
00283     }
00284 
00285     Eigen::Vector3f getCenter() const {return m_;}
00286     Eigen::Vector3f getExtension() const {return e_;}
00287     Eigen::Matrix3f getAxis() const {return axis_;}
00288 
00289     float preassumption(const OOBB &o) const {
00290       //preassumption
00291       int m1=0;
00292       if(e_(1)<e_(m1)) m1=1;
00293       if(e_(2)<e_(m1)) m1=2;
00294       int m2=0;
00295       if(o.e_(1)<o.e_(m2)) m2=1;
00296       if(o.e_(2)<o.e_(m2)) m2=2;
00297       return std::abs(axis_.col(m1).dot(o.axis_.col(m2)));
00298     }
00299 
00300     bool operator&(const OOBB &o) const {
00301       float ra, rb;
00302       Eigen::Matrix3f R, AbsR;
00303       // Compute rotation matrix expressing b in a’s coordinate frame
00304       for (int i = 0; i < 3; i++)
00305         for (int j = 0; j < 3; j++)
00306           R(i,j) = axis_.col(i).dot(o.axis_.col(j));
00307       // Compute translation vector t
00308       Eigen::Vector3f t2 = o.m_-m_, t;
00309       // Bring translation into a’s coordinate frame
00310       t(0) = t2.dot(axis_.col(0));
00311       t(1) = t2.dot(axis_.col(1));
00312       t(2) = t2.dot(axis_.col(2));
00313       // Compute common subexpressions. Add in an epsilon term to
00314       // counteract arithmetic errors when two edges are parallel and
00315       // their cross product is (near) null (see text for details)
00316       for (int i = 0; i < 3; i++)
00317         for (int j = 0; j < 3; j++)
00318           AbsR(i,j) = std::abs(R(i,j)) + 0.00001f;
00319       // Test axes L = A0, L = A1, L = A2
00320       for (int i = 0; i < 3; i++) {
00321         ra = e_(i);
00322         rb = o.e_(0) * AbsR(i,0) + o.e_(1) * AbsR(i,1) + o.e_(2) * AbsR(i,2);
00323         //std::cout<<"a "<<t(i)<<" "<< ra + rb<<"\n";
00324         if (std::abs(t(i)) > ra + rb) return false;
00325       }
00326       // Test axes L = B0, L = B1, L = B2
00327       for (int i = 0; i < 3; i++) {
00328         ra = e_(0) * AbsR(0,i) + e_(1) * AbsR(1,i) + e_(2) * AbsR(2,i);
00329         rb = o.e_(i);
00330         //std::cout<<"b "<<t(0)*R(0,i)+t(1)*R(1,i)+t(2)*R(2,i)<<" "<< ra + rb<<"\n";
00331         if (std::abs(t(0)*R(0,i)+t(1)*R(1,i)+t(2)*R(2,i)) > ra + rb) return false;
00332       }
00333       // Test axis L = A0 x B0
00334       ra = e_(1) * AbsR(2,0) + e_(2) * AbsR(1,0);
00335       rb = o.e_(1) * AbsR(0,2) + o.e_(2) * AbsR(0,1);
00336       if (std::abs(t(2) * R(1,0) - t(1) * R(2,0)) > ra + rb) return false;
00337       // Test axis L = A0 x B1
00338       ra = e_(1) * AbsR(2,1) + e_(2) * AbsR(1,1);
00339       rb = o.e_(0) * AbsR(0,2) + o.e_(2) * AbsR(0,0);
00340       if (std::abs(t(2) * R(1,1) - t(1) * R(2,1)) > ra + rb) return false;
00341       // Test axis L = A0 x B2
00342       ra = e_(1) * AbsR(2,2) + e_(2) * AbsR(1,2);
00343       rb = o.e_(0) * AbsR(0,1) + o.e_(1) * AbsR(0,0);
00344       if (std::abs(t(2) * R(1,2) - t(1) * R(2,2)) > ra + rb) return false;
00345       // Test axis L = A1 x B0
00346       ra = e_(0) * AbsR(2,0) + e_(2) * AbsR(0,0);
00347       rb = o.e_(1) * AbsR(1,2) + o.e_(2) * AbsR(1,1);
00348       if (std::abs(t(0) * R(2,0) - t(2) * R(0,0)) > ra + rb) return false;
00349       // Test axis L = A1 x B1
00350       ra = e_(0) * AbsR(2,1) + e_(2) * AbsR(0,1);
00351       rb = o.e_(0) * AbsR(1,2) + o.e_(2) * AbsR(1,0);
00352       if (std::abs(t(0) * R(2,1) - t(2) * R(0,1)) > ra + rb) return false;
00353       // Test axis L = A1 x B2
00354       ra = e_(0) * AbsR(2,2) + e_(2) * AbsR(0,2);
00355       rb = o.e_(0) * AbsR(1,1) + o.e_(1) * AbsR(1,0);
00356       if (std::abs(t(0) * R(2,2) - t(2) * R(0,2)) > ra + rb) return false;
00357       // Test axis L = A2 x B0
00358       ra = e_(0) * AbsR(1,0) + e_(1) * AbsR(0,0);
00359       rb = o.e_(1) * AbsR(2,2) + o.e_(2) * AbsR(2,1);
00360       if (std::abs(t(1) * R(0,0) - t(0) * R(1,0)) > ra + rb) return false;
00361       // Test axis L = A2 x B1
00362       ra = e_(0) * AbsR(1,1) + e_(1) * AbsR(0,1);
00363       rb = o.e_(0) * AbsR(2,2) + o.e_(2) * AbsR(2,0);
00364       if (std::abs(t(1) * R(0,1) - t(0) * R(1,1)) > ra + rb) return false;
00365       // Test axis L = A2 x B2
00366       ra = e_(0) * AbsR(1,2) + e_(1) * AbsR(0,2);
00367       rb = o.e_(0) * AbsR(2,1) + o.e_(1) * AbsR(2,0);
00368       if (std::abs(t(1) * R(0,2) - t(0) * R(1,2)) > ra + rb) return false;
00369       // Since no separating axis is found, the OBBs must be intersecting
00370       return true;
00371     }
00372 
00373     OOBB changeSize(const float fact) const {
00374       OOBB r = *this;
00375       for(int i=0; i<3; i++)
00376         r.e_(i) *= fact;
00377       return r;
00378     }
00379 
00380     OOBB setMinSize(const float s) const {
00381       OOBB r = *this;
00382       for(int i=0; i<3; i++)
00383         r.e_(i) = std::max(s,r.e_(i));
00384       return r;
00385     }
00386 
00387     OOBB increaseIfNec(const float rot, const float tr) const {
00388       OOBB r = *this;
00389       Eigen::Vector3f z;
00390       z(0)=z(1)=0;
00391       z(2)=1;
00392       const float a = r.m_.norm()*rot;
00393       const float l = a + tr;
00394       for(int i=0; i<3; i++)
00395         r.e_(i) = std::max(l-a*r.axis_.col(i).dot(z),r.e_(i));
00396       return r;
00397     }
00398 
00399     OOBB transform(const Eigen::Matrix3f &R, const Eigen::Vector3f &tr) const {
00400       OOBB r = *this;
00401       r.m_ = R*r.m_ + tr;
00402       r.axis_ = R*r.axis_;
00403       return r;
00404     }
00405 
00406     void get8Edges(Eigen::Vector3f *edges) const {
00407       for(int i=0; i<8; i++)
00408         edges[i] = m_ + (i&1?1:-1)*e_(0)*axis_.col(0) + (i&2?1:-1)*e_(1)*axis_.col(1) + (i&4?1:-1)*e_(2)*axis_.col(2);
00409     }
00410 
00411     float extension() const {
00412       return std::max(e_(0),std::max(e_(1),e_(2)));
00413     }
00414 
00415     void minmax(Eigen::Vector3f &mi, Eigen::Vector3f &ma) const {
00416       Eigen::Vector3f e[8];
00417       get8Edges(e);
00418       ma = mi = e[0];
00419       for(size_t i=1; i<8; i++)
00420       {
00421         if(e[i](2)>ma(2)) ma = e[i];
00422         if(e[i](2)<mi(2)) mi = e[i];
00423       }
00424     }
00425 
00426     float ratio() const {
00427       int m1=0;
00428       if(e_(1)<e_(m1)) m1=1;
00429       if(e_(2)<e_(m1)) m1=2;
00430       int m2=(m1+1)%3;
00431       for(int i=0; i<3; i++) {
00432         if(i==m1) continue;
00433         if(e_(i)<e_(m2)) m2=i;
00434       }
00435 
00436       return e_(m1)/e_(m2);
00437     }
00438 
00439   };
00440 
00441 }
00442 
00443 #endif /* BB_H_ */


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