extended_curved_polygon.h
Go to the documentation of this file.
00001 
00059 /*
00060  * object.h
00061  *
00062  *  Created on: 29.05.2012
00063  *      Author: josh
00064  */
00065 
00066 #ifndef SCP_EXTENDED_CURVED_POLYGON_H_
00067 #define SCP_EXTENDED_CURVED_POLYGON_H_
00068 
00069 #define DEBUG_LEVEL 30
00070 
00071 //#define DEBUG_SVG 1
00072 #define PROB_FACT(x)       1
00073 
00074 #include <cob_3d_mapping_msgs/CurvedPolygon.h>
00075 #include <cob_3d_mapping_msgs/Shape.h>
00076 #include "/home/josh/workspace/dynamic_tutorials/common/include/registration/object.hpp"
00077 //#include "sac_model_correspondence.h"
00078 #include "form.h"
00079 #include "polygon_merger.h"
00080 #include <unsupported/Eigen/NonLinearOptimization>
00081 #include "surface.h"
00082 #include "id.h"
00083 #include "bb.h"
00084 
00085 #include "cob_3d_mapping_slam/lib/polypartition.h"
00086 #include "cob_3d_mapping_slam/dof/feature.h"
00087 
00088 namespace Slam_CurvedPolygon
00089 {
00090 
00091   class ex_curved_polygon
00092   {
00093   public:
00094 
00095     //typedef Slam_Surface::SurfaceNurbs SURFACE;
00096     typedef Slam_Surface::SurfaceTriSpline SURFACE;
00097     typedef BoundingBox::OOBB BB;
00098 
00099     Slam_Surface::Surface::SWINDOW getWindow() const {
00100       Slam_Surface::Surface::SWINDOW w;
00101       w.min_x = w.min_y = std::numeric_limits<float>::max();
00102       w.max_x = w.max_y = -std::numeric_limits<float>::max();
00103       for(size_t i=0; i<data_.polyline.size(); i++)
00104       {
00105         w.min_x = std::min(w.min_x,data_.polyline[i].x);
00106         w.min_y = std::min(w.min_y,data_.polyline[i].y);
00107         w.max_x = std::max(w.max_x,data_.polyline[i].x);
00108         w.max_y = std::max(w.max_y,data_.polyline[i].y);
00109       }
00110       return w;
00111     }
00112 
00113   private:
00114 
00115     S_ID ID_;
00116     Eigen::Vector3f mid_point_;
00117     cob_3d_mapping_msgs::CurvedPolygon data_;
00118     Classification::Form form_;
00119 
00120     boost::shared_ptr<SURFACE> surface_;
00121 
00122     Outline outline_;
00123     std::vector<Eigen::Vector3f> points3d_;
00124     BB bb_;
00125 
00126     ::std_msgs::ColorRGBA color_;
00127 
00128     inline float modelAt(const float x, const float y)
00129     {
00130       return data_.parameter[0]+data_.parameter[1]*x+data_.parameter[2]*x*x+data_.parameter[3]*y+data_.parameter[4]*y*y+data_.parameter[5]*x*y;
00131     }
00132 
00133     void update() {
00134       ID_ += data_.ID;
00135 
00136       //std::cout<<"ID: "<<data_.ID<<"\n";
00137       for(size_t i=0; i<data_.score.size(); i++)
00138       {
00139         //std::cout<<data_.score[i].ID<<"\n";
00140         ID_ += data_.score[i].ID;
00141       }
00142 
00143       outline_.segments_.clear();
00144       for(size_t i=0; i<data_.polyline.size(); i++)
00145       {
00146         Eigen::Vector3f pt3;
00147         pt3(0) = data_.polyline[i].x;
00148         pt3(1) = data_.polyline[i].y;
00149         pt3(2) = PROB_FACT(data_.polyline[i].edge_prob);
00150         outline_ += pt3;
00151       }
00152 
00153       Classification::Classification::MainPoints mains;
00154       mains.size_ = 4;
00155       Classification::Classification cl;
00156       Classification::QuadBB qbb;
00157       cl.setPoints(outline_.segments_);
00158       Classification::Classification::MainPoints compressed;
00159       form_.n_ = cl.buildLocalTree(false,&qbb,&compressed,NULL,&mains);
00160       if(form_.n_)
00161         form_.n_->clean(1,form_.n_->energy_sum_*0.01f);
00162 
00163 #ifdef DEBUG_OUTPUT_
00164       ROS_INFO("COMPRESSION %d %d",data_.polyline.size(),compressed.points_.size());
00165 #endif
00166 
00167       data_.polyline.clear();
00168 
00169       for(size_t i=0; i<compressed.points_.size(); i++)
00170       {
00171         cob_3d_mapping_msgs::polyline_point pt;
00172         pt.x = outline_.segments_[compressed.points_[i].index_](0);
00173         pt.y = outline_.segments_[compressed.points_[i].index_](1);
00174         pt.edge_prob = compressed.points_[i].edge_;
00175         data_.polyline.push_back(pt);
00176       }
00177 
00178       {
00179         Slam_Surface::Surface::SWINDOW w=getWindow();
00180 #ifdef INIT0
00181         if(data_.polyline.size())
00182           surface_->init(data_.parameter ,w.min_x,w.max_x, w.min_y,w.max_y, data_.weight);
00183         else {
00184           surface_->init(data_.parameter ,0,1,0,1,data_.weight);
00185           ROS_WARN("empty");
00186         }
00187 
00188         Slam_Surface::PolynomialSurface ps;
00189         ps.init(data_.parameter ,w.min_x,w.max_x, w.min_y,w.max_y, data_.weight);
00190         for(size_t i=0; i<data_.polyline.size(); i++)
00191         {
00192           Eigen::Vector2f p;
00193           p(0) = data_.polyline[i].x;
00194           p(1) = data_.polyline[i].y;
00195           p = surface_->nextPoint(ps.project2world(p));
00196           data_.polyline[i].x = p(0);
00197           data_.polyline[i].y = p(1);
00198         }
00199 
00200         PolygonData p1;
00201         for(size_t i=0; i<data_.polyline.size(); i++)
00202         {
00203           p1.add(data_.polyline[i].x,data_.polyline[i].y);
00204         }
00205         data_.weight *= 100*100/area(p1);
00206 #else
00207         Slam_Surface::PolynomialSurface ps;
00208         ps.init(data_.parameter ,w.min_x,w.max_x, w.min_y,w.max_y, data_.weight);
00209 
00210         surface_->init(&ps, outline_.get(), data_.weight);
00211 #endif
00212       }
00213 
00214       update_points3d();
00215 
00216       //      Eigen::Vector3f n,z=Eigen::Vector3f::Zero();
00217       //      z(2)=1;
00218       //      n=z;
00219       //      n(0)=-data_.parameter[1];
00220       //      n(1)=-data_.parameter[3];
00221       //      n.normalize();
00222 
00223 #ifdef DEBUG_SVG
00224       char buf[128];
00225       static int cnt=0;
00226       sprintf(buf,"dbg%d.svg",cnt++);
00227       outline_.debug_svg(buf);
00228 #endif
00229 
00230       //      std::cout<<"NP\n"<<nearest_point_<<"\n";
00231       //      std::cout<<"NP*\n"<<data_.features[0].x<<"\n"<<data_.features[0].y<<"\n"<<data_.features[0].z<<"\n";
00232     }
00233 
00234     void update_points3d()
00235     {
00236       points3d_.clear();
00237       outline_.segments_.clear();
00238 
00239       mid_point_ = Eigen::Vector3f::Zero();
00240       for(size_t i=0; i<data_.polyline.size(); i++)
00241       {
00242         Eigen::Vector2f pt;
00243         Eigen::Vector3f pt3;
00244         pt3(0) = pt(0) = data_.polyline[i].x;
00245         pt3(1) = pt(1) = data_.polyline[i].y;
00246         pt3(2) = PROB_FACT(data_.polyline[i].edge_prob);
00247         outline_ += pt3;
00248         points3d_.push_back( surface_->project2world(pt) );
00249         //        ROS_ERROR("%f %f",pt(0),pt(1));
00250         //        ROS_ERROR("%f %f %f %f %f %f",data_.parameter[0],data_.parameter[1],data_.parameter[2],data_.parameter[3],data_.parameter[4],data_.parameter[5]);
00251         //        ROS_ERROR("%f %f",points3d_.back()(2), modelAt(pt(0),pt(1)));
00252         //        ROS_ASSERT( std::abs(points3d_.back()(2)-modelAt(pt(0),pt(1))) < 0.01f );
00253 //        std::cout<<"uv\n"<<pt<<std::endl;
00254 //        std::cout<<"pt\n"<<points3d_.back()<<std::endl;
00255         //ROS_ASSERT( points3d_.back().squaredNorm()<2 || points3d_.back()(2)>0 );
00256         if(! (points3d_.back().squaredNorm()<2 || points3d_.back()(2)>0) )
00257           ROS_ERROR("points3d_.back().squaredNorm()<2 || points3d_.back()(2)>0");
00258         mid_point_ += points3d_.back();
00259       }
00260       mid_point_/=data_.polyline.size();
00261 
00262       update_BB();
00263     }
00264 
00265     void update_BB()
00266     {
00267       pcl::PointCloud<pcl::PointXYZ> pc;
00268       pcl::PointXYZ pt;
00269 
00270       for(size_t i=0; i<outline_.size(); i++)
00271       {
00272         Eigen::Vector3f v = surface_->project2world(outline_[i].head<2>());
00273         pt.x = v(0);
00274         pt.y = v(1);
00275         pt.z = v(2);
00276         pc.push_back(pt);
00277 
00278         v = surface_->project2world((outline_[(i+1)%outline_.size()].head<2>()+outline_[i].head<2>())/2);
00279         pt.x = v(0);
00280         pt.y = v(1);
00281         pt.z = v(2);
00282         pc.push_back(pt);
00283       }
00284 
00285       bb_.set(pc);
00286     }
00287 
00288   public:
00289     ex_curved_polygon(const cob_3d_mapping_msgs::CurvedPolygon& data):
00290       data_(data), surface_(new SURFACE) //, form_(data.energy)
00291     {
00292       update();
00293 
00294       int rnd = rand();
00295       color_.r = ((rnd>>0)&0xff)/255.f;
00296       color_.g = ((rnd>>8)&0xff)/255.f;
00297       color_.b = ((rnd>>16)%0xff)/255.f;
00298       color_.a = 1.f;
00299     }
00300 
00301     ex_curved_polygon(const ex_curved_polygon &o)
00302     {
00303       *this = o;
00304     }
00305 
00306     ex_curved_polygon &operator=(const ex_curved_polygon &o)
00307     {
00308       color_ = o.color_;
00309       ID_ = o.ID_;
00310       data_ = o.data_;
00311       form_ = o.form_;
00312       mid_point_ = o.mid_point_;
00313       outline_ = o.outline_;
00314       points3d_ = o.points3d_;
00315       bb_ = o.bb_;
00316       surface_.reset(new SURFACE(*o.surface_));
00317 
00318       return *this;
00319     }
00320 
00321     virtual ~ex_curved_polygon()
00322     {
00323     }
00324 
00325     const BB &getBB() const
00326     {
00327       return bb_;
00328     }
00329 
00330     void transform(const Eigen::Matrix3f &rot, const Eigen::Vector3f &tr, const float var_R, const float var_T)
00331     {
00332       surface_->transform(rot,tr);
00333 
00334       //TODO:
00335       //nearest_point_ = rot*nearest_point_;
00336       //      for(size_t i=0; i<points3d_.size(); i++)
00337       //      {
00338       //        points3d_[i] = rot*points3d_[i];
00339       //      }
00340 
00341       for(size_t i=0; i<points3d_.size(); i++)
00342       {
00343         points3d_[i] = rot*points3d_[i]+tr;
00344       }
00345 
00346       mid_point_ = rot*mid_point_ + tr;
00347 
00348       update_BB();
00349       //      bb_min_ = rot*bb_min_;
00350       //      bb_max_ = rot*bb_max_;
00351       //      bb_min_+=tr;
00352       //      bb_max_+=tr;
00353     }
00354 
00355     inline const S_ID &getID() const {return ID_;}
00356 
00357     Eigen::Vector3f getNearestPoint() const {return mid_point_;}
00358     Eigen::Vector3f getNearestTransformedPoint(const Eigen::Matrix3f &rot, const Eigen::Vector3f &tr) const
00359     {
00360       return rot*mid_point_+tr;
00361     }
00362 
00363     const std::vector<cob_3d_mapping_msgs::simalarity_score> &getScore() const {return data_.score;}
00364 
00382     bool fitsCurvature(const ex_curved_polygon &o, const float thr) const
00383     {
00384       //      if( param_.col(2).squaredNorm()<0.1 && o.param_.col(2).squaredNorm()<0.1)
00385       //        return true;
00386       return surface_->fitsCurvature(*o.surface_, thr);
00387     }
00388 
00389     //TODO: do it more accurately? but its fast
00390     bool extensionMatch(const ex_curved_polygon &o, const float thr, const float var) const
00391     {
00392       const float l1 = bb_.extension();
00393       const float l2 = o.bb_.extension();
00394 
00395       return std::max(std::abs(l1-l2)-var,0.f) < std::min(l1,l2) * thr;
00396     }
00397 
00398     bool merge(const ex_curved_polygon &o1, const ex_curved_polygon &o2) {
00399       //      PolygonData p1, p2, p3;
00400       //
00401       //      for(size_t i=0; i<o1.outline_.segments_.size(); i++)
00402       //      {
00403       //        //if(o1.segments_[i](2)>0.5f)
00404       //        {
00405       //          Eigen::Vector2f p = surface_->nextPoint(o1.surface_->project2world(o1.outline_.segments_[i].head<2>() ));
00406       //          p1.add(p(0), p(1));
00407       //          //          std::cout<<"p1\n"<<p<<"\n";
00408       //          //          std::cout<<"s1\n"<<o1.segments_[i]<<"\n";
00409       //          //          std::cout<<"w1\n"<<surface_->project2world(p )<<"\n";
00410       //        }
00411       //      }
00412       //      std::cout<<"PARAMS\n"<<proj2plane_<<"\n";
00413       //      std::cout<<param_<<"\n";
00414       //      for(size_t i=0; i<o2.outline_.segments_.size(); i++)
00415       //      {
00416       //        //if(o2.segments_[i](2)>0.5f)
00417       //        {
00418       //          Eigen::Vector2f p = surface_->nextPoint(o2.surface_->project2world(o2.outline_.segments_[i].head<2>() ));
00419       //          p2.add(p(0), p(1));
00420       //          //          std::cout<<"p2\n"<<p<<"\n";
00421       //          //          std::cout<<"s2\n"<<o2.segments_[i]<<"\n";
00422       //          //          std::cout<<"w2\n"<<surface_->project2world(p )<<"\n";
00423       //        }
00424       //      }
00425       //
00426       //      mergePolygons(p1,p2, p3);
00427       //
00428       //      if(p3.get().size()<=0)
00429       //        return false;
00430 
00431       Outline p1, p2;
00432 
00433       p1.weight_ = std::pow(o1.data_.weight,0.5f);
00434       p2.weight_ = std::pow(o2.data_.weight,0.5f);
00435 
00436       for(size_t i=0; i<o1.outline_.segments_.size(); i++)
00437       {
00438         //if(o1.segments_[i](2)>0.5f)
00439         {
00440           Eigen::Vector3f p = o1.surface_->project2world(o1.outline_.segments_[i].head<2>());
00441           if( (p-surface_->project2world(o1.outline_.segments_[i].head<2>())).squaredNorm()<0.005f*0.005f)
00442             p.head<2>() = o1.outline_.segments_[i].head<2>();
00443           else
00444             p.head<2>() = surface_->nextPoint(p);
00445           p(2) = p1.weight_*PROB_FACT(o1.outline_.segments_[i](2));
00446           p1 += p;
00447 
00448           //ROS_INFO("distA1 %f", (o1.surface_->project2world(o1.outline_.segments_[i].head<2>())-surface_->project2world(p.head<2>())).norm() );
00449           //ROS_ASSERT( (surface_->project2world(p.head<2>())-o1.surface_->project2world(o1.outline_.segments_[i].head<2>())).squaredNorm()<0.1f );
00450           if(!((surface_->project2world(p.head<2>())-o1.surface_->project2world(o1.outline_.segments_[i].head<2>())).squaredNorm()<0.1f))
00451             ROS_ERROR("(surface_->project2world(p.head<2>())-o1.surface_->project2world(o1.outline_.segments_[i].head<2>())).squaredNorm()<0.1f");
00452 
00453         }
00454       }
00455 
00456       for(size_t i=0; i<o2.outline_.segments_.size(); i++)
00457       {
00458         //if(o2.segments_[i](2)>0.5f)
00459         {
00460           Eigen::Vector3f p = o2.surface_->project2world(o2.outline_.segments_[i].head<2>());
00461           if( (p-surface_->project2world(o2.outline_.segments_[i].head<2>())).squaredNorm()<0.005f*0.005f)
00462             p.head<2>() = o2.outline_.segments_[i].head<2>();
00463           else
00464             p.head<2>() = surface_->nextPoint(p);
00465           p(2) = p2.weight_*PROB_FACT(o2.outline_.segments_[i](2));
00466           p2 += p;
00467 
00468           //ROS_INFO("distA2 %f", (o2.surface_->project2world(o2.outline_.segments_[i].head<2>())-surface_->project2world(p.head<2>())).norm() );
00469           //ROS_ASSERT( (surface_->project2world(p.head<2>())-o2.surface_->project2world(o2.outline_.segments_[i].head<2>())).squaredNorm()<0.1f );
00470           if(!((surface_->project2world(p.head<2>())-o2.surface_->project2world(o2.outline_.segments_[i].head<2>())).squaredNorm()<0.1f))
00471             ROS_ERROR("(surface_->project2world(p.head<2>())-o2.surface_->project2world(o2.outline_.segments_[i].head<2>())).squaredNorm()<0.1f");
00472         }
00473       }
00474 
00475 //      static int cnt=0;
00476 //      ++cnt;
00477 //      char buffer[128];
00478 //            sprintf(buffer,"%dA.svg",cnt);
00479 //            p1.debug_svg(buffer,300,600);
00480 //            sprintf(buffer,"%dB.svg",cnt);
00481 //            p2.debug_svg(buffer,300,600);
00482 
00483       //      p1.reverse(); //TODO: change alog. instead of this
00484       //      p2.reverse();
00485       outline_ = p1+p2;
00486       //      outline_.reverse();
00487 //      sprintf(buffer,"%dC.svg",cnt);
00488 //      outline_.debug_svg(buffer,300,600);
00489 
00490       //      for(size_t i=0; i<outline_.segments_.size(); i++)
00491       //        outline_.segments_[i](2) /= std::max(o1.data_.weight, o2.data_.weight);
00492 
00493 #ifdef DEBUG_
00494       if(!outline_.check()) {
00495         char buffer[128];
00496         static int n=0;
00497         sprintf(buffer, "error%dA1.svg",n*2);
00498         o1.outline_.debug_svg(buffer,300,600);
00499         sprintf(buffer, "error%dA2.svg",n*2);
00500         p1.debug_svg(buffer,300,600);
00501         sprintf(buffer, "error%dB1.svg",n*2);
00502         o2.outline_.debug_svg(buffer,300,600);
00503         sprintf(buffer, "error%dB2.svg",n*2);
00504         p2.debug_svg(buffer,300,600);
00505         ++n;
00506       }
00507 #endif
00508 
00509 #ifdef DEBUG_SVG
00510       sprintf(buffer,"%f %dC.svg",Debug::Interface::get().getTime(), cnt);
00511       p1.debug_svg(p2.debug_svg(outline_.debug_svg(buffer,200,500,"red"),200,500,"green"),200,500);
00512 #endif
00513 
00514       Classification::Classification::MainPoints compressed;
00515       Classification::Classification::MainPoints mains;
00516       mains.size_ = 4;
00517       Classification::Classification cl;
00518       Classification::QuadBB qbb;
00519       cl.setPoints(outline_.segments_);
00520       form_.n_ = cl.buildLocalTree(false,&qbb,&compressed,NULL,&mains);
00521       if(form_.n_)
00522         form_.n_->clean(1,form_.n_->energy_sum_*0.01f);
00523 
00524 #ifdef DEBUG_OUTPUT_
00525       ROS_INFO("COMPRESSION %d %d",data_.polyline.size(),compressed.points_.size());
00526 #endif
00527 
00528       data_.polyline.clear();
00529 
00530       for(size_t i=0; i<compressed.points_.size(); i++)
00531       {
00532         cob_3d_mapping_msgs::polyline_point pt;
00533         pt.x = outline_.segments_[compressed.points_[i].index_](0);
00534         pt.y = outline_.segments_[compressed.points_[i].index_](1);
00535         pt.edge_prob = compressed.points_[i].edge_;
00536         data_.polyline.push_back(pt);
00537       }
00538       //      for(size_t i=0; i<outline_.segments_.size(); i++)
00539       //      {
00540       //        //        Eigen::Vector2f v1;
00541       //        ::cob_3d_mapping_msgs::polyline_point pt;
00542       //        //        v1(0)=p3.get()[i*2+0];
00543       //        //        v1(1)=p3.get()[i*2+1];
00544       //        //#error teile durch 2
00545       //
00546       //        //        std::cout<<"p3\n"<<v1<<"\n";
00547       //
00548       //        pt.x = outline_.segments_[i](0);
00549       //        pt.y = outline_.segments_[i](1);
00550       //        pt.edge_prob = outline_.segments_[i](2);
00551       //
00552       //        data_.polyline.push_back(pt);
00553       //      }
00554 
00555       update_points3d();
00556 
00557       return true;
00558     }
00559 
00563     bool operator+=(ex_curved_polygon o) {
00564       int st;
00565       return op_plus(o,st);
00566     }
00567 
00568     bool op_plus(ex_curved_polygon o, int &status) {
00569       if(o.outline_.segments_.size()<1 || outline_.segments_.size()<1) {
00570         status=0;
00571         return false;
00572       }
00573 
00574       //merge parameters to third manifold
00575       ex_curved_polygon o2 = *this;
00576 
00577       bool sw = false;
00578       if(!canMerge(o, 0.1f, &sw)) {
00579 #ifdef DEBUG_OUT_
00580         ROS_INFO("could not merge1");
00581 #endif
00582         status=1;
00583         return false;
00584       }
00585 
00586       //      if(sw)
00587       //      {
00588       //        surface_ = o.surface_;
00589       //        data_.parameter = o.data_.parameter;
00590       //      }
00591 
00592       //combine outline
00593       Slam_Surface::Surface::SWINDOW w1 = getWindow(), w2 = o.getWindow();
00594       if(sw)
00595       {
00596         //        SURFACE s = o.surface_;
00597         //        float dist = s.merge(surface_, o.data_.weight, data_.weight,w2,w1);
00598         //        if(dist > 0.03f + 0.03f*getNearestPoint().squaredNorm()) {
00599         //          ROS_INFO("could not merge %f",dist);
00600         //          //return false;
00601         //        }
00602         float dist;
00603         surface_.reset( new SURFACE(*o.surface_) );
00604         if((dist=surface_->merge(*o2.surface_, o.data_.weight, data_.weight,w2,w1)) > 0.03f + 0.05f*std::max(1.f,getNearestPoint().squaredNorm())) {
00605           surface_.reset( new SURFACE(*o2.surface_) );
00606 #ifndef DEBUG_OUT_
00607           ROS_INFO("could not merge2 %f",dist);
00608 #endif
00609           status=2;
00610           return false;
00611         }
00612         ROS_INFO("merge2 %f",dist);
00613 
00614 #ifdef DEBUG_
00615         Debug::Interface::get().addArrow(o2.getNearestPoint(), o.getNearestPoint(), 255,0,0);
00616 #endif
00617       }
00618       else {
00619         //        SURFACE s = surface_;
00620         //        float dist = s.merge(o.surface_, data_.weight, o.data_.weight,w1,w2);
00621         //        if(dist > 0.03f + 0.03f*getNearestPoint().squaredNorm()) {
00622         //          ROS_INFO("could not merge %f",dist);
00623         //          //return false;
00624         //        }
00625         float dist;
00626         if((dist=surface_->merge(*o.surface_, data_.weight, o.data_.weight,w1,w2)) > 0.03f + 0.05f*std::max(1.f,getNearestPoint().squaredNorm())) {
00627           surface_.reset( new SURFACE(*o2.surface_) );
00628 #ifndef DEBUG_OUT_
00629           ROS_INFO("could not merge3 %f",dist);
00630 #endif
00631           status=2;
00632           return false;
00633         }
00634         ROS_INFO("merge2 %f",dist);
00635 
00636 #ifdef DEBUG_
00637         Debug::Interface::get().addArrow(o2.getNearestPoint(), o.getNearestPoint(), 0,0,255);
00638 #endif
00639       }
00640 
00641       if(!merge(o,o2) || invalid())
00642       {
00643         *this = o2;
00644         //        surface_ = o2.surface_;
00645         //        data_.parameter = o2.data_.parameter;
00646 #ifdef DEBUG_OUT_
00647         ROS_INFO("could not merge4");
00648 #endif
00649         status=3;
00650         return false;
00651       }
00652       //ROS_ASSERT(invalid());
00653 
00654       color_.r = (data_.weight*color_.r+o.data_.weight*o.color_.r)/(data_.weight + o.data_.weight);
00655       color_.g = (data_.weight*color_.g+o.data_.weight*o.color_.g)/(data_.weight + o.data_.weight);
00656       color_.b = (data_.weight*color_.b+o.data_.weight*o.color_.b)/(data_.weight + o.data_.weight);
00657 
00658       ID_ += o.ID_;
00659 
00660       data_.weight += o.data_.weight;
00661 
00662       ROS_INFO("succesfully merged");
00663 
00664       return true;
00665     }
00666 
00667     void debug_form() const
00668     {
00669       Classification::Classification cl;
00670       Classification::QuadBB qbb;
00671       cl.setPoints(outline_.segments_);
00672       cl.buildLocalTree(true,&qbb);
00673     }
00674 
00675     bool matchForm(const ex_curved_polygon &o) const {
00676       if(!form_.n_ || ! o.form_.n_)
00677         return false;
00678 
00679       float e = form_.n_->search(*o.form_.n_,0.8);
00680 
00681       //if(e>std::max(form_.n_->energy_sum_, o.form_.n_->energy_sum_))
00682       //      if(e<0.4*std::min(form_.n_->energy_sum_, o.form_.n_->energy_sum_)&&std::min(form_.n_->energy_sum_, o.form_.n_->energy_sum_)>1)
00683       //      {
00684       //        debug_form();
00685       //        o.debug_form();
00686       //
00687       //        form_.n_->print();
00688       //        o.form_.n_->print();
00689       //        ROS_INFO("could");
00690       //      }
00691 
00692 #ifdef DEBUG_OUT_
00693       ROS_INFO("match %f %f",e,0.2f*std::min(form_.n_->energy_sum_, o.form_.n_->energy_sum_));
00694 #endif
00695 
00696       return e<0.4f*std::min(form_.n_->energy_sum_, o.form_.n_->energy_sum_);
00697     }
00698 
00699     float matchFormf(const ex_curved_polygon &o) const {
00700       if(!form_.n_ || ! o.form_.n_)
00701         return false;
00702 
00703       return std::max(0.2f,1.2f-form_.n_->search(*o.form_.n_, 0.8f)/std::min(form_.n_->energy_sum_, o.form_.n_->energy_sum_));
00704     }
00705 
00706     float getEnergy() const {return form_.n_->energy_;}
00707     float getWeight() const {return data_.weight;}
00708     void printEnergy() const {form_.n_->print();}
00709 
00710     void triangle(std::vector<Eigen::Vector3f> &tri, const TPPLPoint &p1, const TPPLPoint &p2, const TPPLPoint &p3, const int depth=0) const {
00711       if(depth>1)
00712       {
00713         Eigen::Vector2f p;
00714         p(0) = p1.x;
00715         p(1) = p1.y;
00716         tri.push_back(surface_->project2world(p));
00717         p(0) = p2.x;
00718         p(1) = p2.y;
00719         tri.push_back(surface_->project2world(p));
00720         p(0) = p3.x;
00721         p(1) = p3.y;
00722         tri.push_back(surface_->project2world(p));
00723       }
00724       else
00725       {
00726         TPPLPoint p4, p12,p23,p31;
00727 
00728         p4.x = (p1.x+p2.x+p3.x)/3;
00729         p4.y = (p1.y+p2.y+p3.y)/3;
00730         p12.x = (p1.x+p2.x)/2;
00731         p12.y = (p1.y+p2.y)/2;
00732         p23.x = (p3.x+p2.x)/2;
00733         p23.y = (p3.y+p2.y)/2;
00734         p31.x = (p1.x+p3.x)/2;
00735         p31.y = (p1.y+p3.y)/2;
00736 
00737         triangle(tri,p1,p12,p4,depth+1);
00738         triangle(tri,p1,p31,p4,depth+1);
00739         triangle(tri,p3,p23,p4,depth+1);
00740 
00741         triangle(tri,p12,p2,p4,depth+1);
00742         triangle(tri,p31,p3,p4,depth+1);
00743         triangle(tri,p23,p2,p4,depth+1);
00744       }
00745     }
00746 
00747     void getTriangles(std::vector<Eigen::Vector3f> &tri) const
00748     {
00749       //      for(size_t i=0; i<features_.size(); i++)
00750       //      {
00751       //        if(features_[i].ID_!=-1 || !pcl_isfinite(features_[2].v_.sum()) || !pcl_isfinite(features_[i].v_.sum())) continue;
00752       //        if(tri.size()>2)
00753       //          tri.push_back( tri[tri.size()-1] );
00754       //        else
00755       //          tri.push_back( features_[i].v_ );
00756       //        tri.push_back( features_[2].v_ );
00757       //        tri.push_back( features_[i].v_ );
00758       //      }
00759       //      if(tri.size()>2)
00760       //        tri[0] = tri[tri.size()-1];
00761 
00762       //triangulate
00763 
00764       TPPLPartition pp;
00765       list<TPPLPoly> polys,result;
00766 
00767       //fill polys
00768       TPPLPoly poly;
00769       poly.Init(outline_.size());
00770       poly.SetHole(false);
00771 
00772       for(size_t i=0; i<outline_.size(); i++) {
00773         TPPLPoint p;
00774         p.x = outline_[i](0);
00775         p.y = outline_[i](1);
00776         poly[i] = p;
00777       }
00778       poly.SetOrientation(TPPL_CCW);
00779 
00780       polys.push_back(poly);
00781 
00782       pp.Triangulate_EC(&polys,&result);
00783 
00784       TPPLPoint p1,p2,p3,p4, p12,p23,p31;
00785 
00786       for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
00787         //draw each triangle
00788         if(it->GetNumPoints()!=3) continue;
00789 
00790         p1 = it->GetPoint(0);
00791         p2 = it->GetPoint(1);
00792         p3 = it->GetPoint(2);
00793 
00794         triangle(tri,p1,p2,p3);
00795       }
00796     }
00797 
00798     void getControlPoints(std::vector<std::vector<Eigen::Vector3f> > &pts) const
00799     {
00800 #ifdef SURFACE_NURBS
00801       for(int i=0; i<surface_->getNurbs().ctrlPnts().rows(); i++) {
00802         pts.push_back(std::vector<Eigen::Vector3f>());
00803         for(int j=0; j<surface_->getNurbs().ctrlPnts().cols(); j++) {
00804           Eigen::Vector2f v2;
00805           v2(0)=i/(float)(surface_->getNurbs().ctrlPnts().rows()-1);
00806           v2(1)=j/(float)(surface_->getNurbs().ctrlPnts().cols()-1);
00807           pts.back().push_back(surface_->_project2world(v2));
00808         }
00809       }
00810 #endif
00811     }
00812 
00813     bool canMerge(const ex_curved_polygon &o, const float diff=0.001f, bool *sw=NULL) const {
00814 
00815       PolygonData p1, p2, p3;
00816 
00817       for(size_t i=0; i<o.outline_.segments_.size(); i++)
00818       {
00819         Eigen::Vector2f p = surface_->nextPoint(o.surface_->project2world(o.outline_.segments_[i].head<2>() ));
00820         p1.add(
00821             p(0),p(1)
00822             //            ((o.segments_[i](0) * o.proj2plane_(0,0)+o.param_.col(0)(0))-param_.col(0)(0))/proj2plane_(0,0),
00823             //            ((o.segments_[i](1) * o.proj2plane_(1,1)+o.param_.col(0)(1))-param_.col(0)(1))/proj2plane_(1,1)
00824         );
00825       }
00826       for(size_t i=0; i<outline_.segments_.size(); i++)
00827       {
00828         p2.add(outline_.segments_[i](0),outline_.segments_[i](1));
00829       }
00830 
00831       //      std::cout<<"off1\n"<<param_.col(0)<<"\n";
00832       //      std::cout<<"off2\n"<<o.param_.col(0)<<"\n";
00833       //      std::cout<<"n1\n"<<param_.col(1)<<"\n";
00834       //      std::cout<<"n2\n"<<o.param_.col(1)<<"\n";
00835       //      std::cout<<"p1\n"<<param_.col(2)<<"\n";
00836       //      std::cout<<"p2\n"<<o.param_.col(2)<<"\n";
00837 
00838       const float rel = unionPolygons(p1,p2, p3, sw);
00839       if(rel<0.1f)
00840       {
00841 #ifndef DEBUG_OUT_
00842         ROS_INFO("merge break 1 %f",rel);
00843 #endif
00844         return false;
00845       }
00846 
00847       float lges=0.f, er=0.f, erlast=0.f, lfirst=0.f;
00848       float er2=0;
00849       int bad_ctr = 0;
00850 
00851       Eigen::Vector3f _last1_, _last2_;
00852 
00853       for(size_t i=0; i<p3.get().size()/2; i++)
00854       {
00855         Eigen::Vector2f v1, v3;
00856         Eigen::Vector3f t, n, v2, normal, n2;
00857         v1(0)=p3.get()[i*2+0];
00858         v1(1)=p3.get()[i*2+1];
00859         //        v2(0) = ((v1(0)*proj2plane_(0,0)+param_.col(0)(0))-o.param_.col(0)(0))/o.proj2plane_(0,0);
00860         //        v2(1) = ((v1(1)*proj2plane_(1,1)+param_.col(0)(1))-o.param_.col(0)(1))/o.proj2plane_(1,1);
00861 
00862         t = surface_->project2world(v1);
00863         Eigen::Vector2f np = o.surface_->nextPoint(t);
00864         v2 = o.surface_->project2world(np);
00865         normal = surface_->normalAt(v1);
00866         n2= o.surface_->normalAt(np);
00867 
00868         v1(0)=p3.get()[(i*2+2)%p3.get().size()];
00869         v1(1)=p3.get()[(i*2+3)%p3.get().size()];
00870         n = surface_->project2world(v1);
00871 
00872         int color=255;
00873         //ROS_INFO("merge (%f %f %f)  (%f %f %f)",t(0),t(1),t(2), v2(0),v2(1),v2(2));
00874         if( n2.squaredNorm()>0.5f && normal.squaredNorm()>0.5f &&
00875             //(t-v2).norm() > 0.03f+diff*getNearestPoint().squaredNorm() ||
00876             n2.dot(normal) < 0.88f
00877         )
00878         {
00879           color=0;
00880           ++bad_ctr;
00881           if(bad_ctr>0)
00882           {
00883 #ifndef DEBUG_OUT_
00884             ROS_INFO("merge break 2 %f %f %f (%f %f %d)",n2.dot(normal),
00885                      n2.squaredNorm(), normal.squaredNorm(), np(0),np(1),i);
00886 #endif
00887             return false;
00888           }
00889         }
00890 
00891         if(i>0) {
00892           Debug::Interface::get().addArrow(_last1_, t, color, 0, 0);
00893           Debug::Interface::get().addArrow(_last2_, v2, color, 0, 0);
00894         }
00895         Debug::Interface::get().addArrow(t,t+normal*0.1, color, 0, 0);
00896         Debug::Interface::get().addArrow(v2,v2+n2*0.1, color, 0, 0);
00897 
00898         _last1_ = t;
00899         _last2_ = v2;
00900 
00901         float dist2 = 1/(std::max(0.1f,  o.surface_->normalAt(np).dot(normal) ) + 0.1f);
00902 
00903         const float l = (t-n).norm();
00904         er += l*erlast;
00905         erlast = /*(t-v2).norm()*/ (v2-t).norm() *dist2 /(1+((t+n)*0.5f).squaredNorm());
00906         er2 += erlast;
00907         er += l*erlast;
00908         lges += 2*l;
00909 
00910         //        std::cout<<"coord\t\t"<<erlast<<"  "<<l<<"\n"<<t<<"\n\n"<<v2<<"\n\n";
00911 
00912         if(i==0) lfirst = l;
00913 
00914       }
00915 
00916       if(bad_ctr>0)
00917         return false;
00918       //      Outline p3 = outline_|o.outline_;
00919       //
00920       //      float lges=0.f, er=0.f, erlast=0.f, lfirst=0.f;
00921       //      float er2=0;
00922       //
00923       //      for(size_t i=0; i<p3.segments_.size(); i++)
00924       //      {
00925       //        Eigen::Vector2f v1=p3.segments_[i].head<2>(), v3;
00926       //        Eigen::Vector3f t, n, v2;
00927       //        //        v2(0) = ((v1(0)*proj2plane_(0,0)+param_.col(0)(0))-o.param_.col(0)(0))/o.proj2plane_(0,0);
00928       //        //        v2(1) = ((v1(1)*proj2plane_(1,1)+param_.col(0)(1))-o.param_.col(0)(1))/o.proj2plane_(1,1);
00929       //
00930       //        t = surface_->project2world(v1);
00931       //        v2 = o.surface_->project2world(o.surface_->nextPoint(t));
00932       //
00933       //        v1=p3.segments_[(i+1)%p3.segments_.size()].head<2>();
00934       //        n = surface_->project2world(v1);
00935       //
00936       //        const float l = (t-n).norm();
00937       //        er += l*erlast;
00938       //        erlast = (t-v2).norm();
00939       //        er2 += erlast;
00940       //        er += l*erlast;
00941       //        lges += 2*l;
00942       //
00943       //        //        std::cout<<"coord\t\t"<<erlast<<"  "<<l<<"\n"<<t<<"\n\n"<<v2<<"\n\n";
00944       //
00945       //        if(i==0) lfirst = l;
00946       //
00947       //      }
00948 
00949       er += lfirst*erlast;
00950 
00951 #ifndef DEBUG_OUTPUT_
00952       if(std::abs(er)/lges>=0.03f+diff)
00953       ROS_INFO("merge break proj %f", er/lges);
00954 #endif
00955 
00956       return std::abs(er)/lges<0.03f+diff;
00957     }
00958 
00959     bool invalid() const
00960     {
00961       if(!pcl_isfinite(getNearestPoint().sum())) {
00962         ROS_ERROR("rm3");
00963         return true;
00964       }
00965 
00966       if(data_.polyline.size()<3)
00967       {
00968         ROS_ERROR("rm4");
00969         return true;
00970       }
00971 
00972       for(size_t i=0; i<points3d_.size(); i++)
00973       {
00974         if(!pcl_isfinite(points3d_[i].sum()) || points3d_[i](2)<0.f)
00975         {
00976           ROS_ERROR("rm2");
00977           return true;
00978         }
00979       }
00980 
00981       if(!outline_.check())
00982         return true;
00983 
00984       return false;
00985     }
00986 
00987     inline const Outline &getOutline() const {return outline_;}
00988     inline const SURFACE &getSurface() const {return *surface_;}
00989 
00990     const ::std_msgs::ColorRGBA &getColor() const {return color_;}
00991     void setColor(const ::std_msgs::ColorRGBA &c) {color_=c;}
00992 
00993     const std::vector<Eigen::Vector3f> &getPoints3D() const {return points3d_;}
00994   };
00995 
00996 }
00997 
00998 
00999 #endif /* OBJECT_H_ */


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