00001
00059
00060
00061
00062
00063
00064
00065
00066 #ifndef SCP_EXTENDED_CURVED_POLYGON_H_
00067 #define SCP_EXTENDED_CURVED_POLYGON_H_
00068
00069 #define DEBUG_LEVEL 30
00070
00071
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
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
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
00137 for(size_t i=0; i<data_.score.size(); i++)
00138 {
00139
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
00217
00218
00219
00220
00221
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
00231
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
00250
00251
00252
00253
00254
00255
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)
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
00335
00336
00337
00338
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
00350
00351
00352
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
00385
00386 return surface_->fitsCurvature(*o.surface_, thr);
00387 }
00388
00389
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
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
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
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
00449
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
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
00469
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
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 outline_ = p1+p2;
00486
00487
00488
00489
00490
00491
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
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
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
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
00587
00588
00589
00590
00591
00592
00593 Slam_Surface::Surface::SWINDOW w1 = getWindow(), w2 = o.getWindow();
00594 if(sw)
00595 {
00596
00597
00598
00599
00600
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
00620
00621
00622
00623
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
00645
00646 #ifdef DEBUG_OUT_
00647 ROS_INFO("could not merge4");
00648 #endif
00649 status=3;
00650 return false;
00651 }
00652
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
00682
00683
00684
00685
00686
00687
00688
00689
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
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 TPPLPartition pp;
00765 list<TPPLPoly> polys,result;
00766
00767
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
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
00823
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
00832
00833
00834
00835
00836
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
00860
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
00874 if( n2.squaredNorm()>0.5f && normal.squaredNorm()>0.5f &&
00875
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 = (v2-t).norm() *dist2 /(1+((t+n)*0.5f).squaredNorm());
00906 er2 += erlast;
00907 er += l*erlast;
00908 lges += 2*l;
00909
00910
00911
00912 if(i==0) lfirst = l;
00913
00914 }
00915
00916 if(bad_ctr>0)
00917 return false;
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
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