00001
00059
00060
00061
00062
00063
00064
00065
00066 #ifndef POLYGON_H_
00067 #define POLYGON_H_
00068
00069 #include "sub_structures.h"
00070 #include <eigen3/Eigen/Dense>
00071 #include <unsupported/Eigen/NonLinearOptimization>
00072 #include <cob_3d_mapping_msgs/CurvedPolygon.h>
00073 #include <polypartition/polypartition.h>
00074
00075 namespace Segmentation
00076 {
00077
00078 #ifdef USE_BOOST_POLYGONS_
00079 #include <boost/polygon/polygon.hpp>
00080 #include <boost/geometry.hpp>
00081 #include <boost/geometry/geometries/geometries.hpp>
00082 #include <boost/geometry/multi/geometries/multi_polygon.hpp>
00083 #include <boost/geometry/algorithms/envelope.hpp>
00084 #include <boost/geometry/geometries/polygon.hpp>
00085 #include <boost/geometry/geometries/point_xy.hpp>
00086 using namespace boost::polygon::operators;
00087
00088 typedef boost::polygon::polygon_with_holes_data<int> BoostPolygon;
00089 typedef BoostPolygon::point_type BoostPoint;
00090 typedef std::vector<BoostPolygon> BoostPolygonSet;
00091 typedef boost::polygon::polygon_90_set_traits<BoostPolygonSet> BoostTraits;
00092 #endif
00093
00094 template<int Degree>
00095 struct S_POLYGON {
00096 enum {DEGREE=Degree};
00097 typedef SubStructure::Model<Degree> Model;
00098
00099 std::vector<std::vector<Eigen::Vector3f> > segments_;
00100 std::vector<std::vector<Eigen::Vector2i> > segments2d_;
00101 #ifdef USE_BOOST_POLYGONS_
00102 std::vector<std::vector<BoostPoint> > segments2d_;
00103 #endif
00104 float weight_;
00105 #ifdef CHECK_CONNECTIVITY
00106 S_POLYGON_CONNECTIVITY connectivity_;
00107 #endif
00108 SubStructure::Model<Degree> model_;
00109 Eigen::Vector3f middle_;
00110 int mark_;
00111
00112 typename SubStructure::Param<Degree>::VectorU param_xy_;
00113 sensor_msgs::ImagePtr img_;
00114 float color_[3];
00115
00116 #ifdef USE_CLASSIFICATION_
00117 Classification::Form::Ptr form_;
00118 #endif
00119
00120 Eigen::Vector3f feature_;
00121
00122 S_POLYGON()
00123 #ifdef USE_CLASSIFICATION_
00124 :form_(new Classification::Form)
00125 #endif
00126 {
00127 int color = rand();
00128 color_[0] = ((color>>0)&0xff)/255.f;
00129 color_[1] = ((color>>8)&0xff)/255.f;
00130 color_[2] = ((color>>16)&0xff)/255.f;
00131 }
00132
00133 bool isLinear() const
00134 {
00135 for(size_t i=3; i<SubStructure::Param<Degree>::NUM; i++)
00136 if(std::abs(model_.p(i))>0.01f) return false;
00137 return true;
00138 }
00139
00140 void buildForm(const bool debug=false) {
00141 if(segments_.size()<1)
00142 return;
00143
00144 std::vector<Eigen::Vector3f> pts;
00145 for(size_t i=0; i<segments_[0].size(); i++)
00146 {
00147 Eigen::Vector3f v;
00148 #ifdef USE_BOOST_POLYGONS_
00149 v(0)=segments2d_[0][i].x();
00150 v(1)=segments2d_[0][i].y();
00151 #endif
00152 pts.push_back(v);
00153
00154 }
00155
00156 #ifdef USE_CLASSIFICATION_
00157 Classification::Classification cl;
00158 Classification::QuadBB qbb;
00159
00160 form_->curvature_ = getInvariantCurvature();
00161 cl.setPoints(segments_[0]);
00162
00163
00164 int mains[2];
00165 form_->n_=cl.buildLocalTree(debug,&qbb,&form_->compressed_energy_,mains);
00166 form_->outline_ = qbb.getOutline();
00167
00168 feature_ = project2world(segments_[0][mains[0]].head<2>());
00169 feature_-= project2world(segments_[0][mains[1]].head<2>());
00170
00171
00172 if(feature_(0)<0) feature_=-feature_;
00173 #endif
00174 }
00175
00176 Eigen::Vector2f project2plane(const float x, const float y, const SubStructure::Model<Degree> &model) {
00177 ROS_ERROR("TODO:");
00178 Eigen::Vector2f mv;
00179 mv(0)=x;
00180 mv(1)=y;
00181 float mz;
00182 mz=model.intersect(mv(0), mv(1));
00183
00184 Eigen::Vector3f v;
00185 v.head<2>() = mz * mv;
00186 v(2) = mz;
00187
00188
00189 return mv;
00190 }
00191
00192 #ifdef USE_BOOST_POLYGONS_
00193 BoostPolygonSet getBoostPolygon2D() const {
00194
00195 BoostPolygon poly;
00196 BoostPolygonSet r;
00197 if(segments2d_.size()==0) return r;
00198 poly.set(segments2d_[0].begin(), segments2d_[0].end());
00199
00200 r.push_back(poly);
00201 return r;
00202 }
00203
00204 BoostPolygonSet getBoostPolygon2D_Centered() const {
00205
00206 BoostPolygon poly;
00207 BoostPolygonSet r;
00208 if(segments2d_.size()==0) return r;
00209 {
00210 poly.set(segments2d_[0].begin(), segments2d_[0].end());
00211
00212
00213 BoostPoint cnt;
00214 boost::polygon::center(cnt,poly);
00215 std::vector<BoostPoint> temp;
00216
00217 for(size_t i=0; i<segments2d_[0].size(); i++) {
00218 temp.push_back( BoostPoint(segments2d_[0][i].x()-cnt.x(), segments2d_[0][i].y()-cnt.y()));
00219 }
00220
00221 poly.set(temp.begin(), temp.end());
00222
00223 r.push_back(poly);
00224 }
00225 return r;
00226 }
00227 #endif
00228
00229 Eigen::Vector3f project2plane(const float x, const float y, const float mz, const float b) {
00230 ROS_ERROR("TODO:");
00231 return Eigen::Vector3f::Zero();
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 }
00253
00254 Eigen::Vector3f project2plane(const float x, const float y, const SubStructure::Model<Degree> &model, const float b) {
00255 Eigen::Vector2f mv;
00256 Eigen::Vector3f mv3;
00257 mv(0)=x;
00258 mv(1)=y;
00259 float mz;
00260 mz=model.intersect(mv(0), mv(1));
00261
00262 mv3(0) = mv(0)*mz;
00263 mv3(1) = mv(1)*mz;
00264 mv3(2) = mz;
00265
00266 return mv3;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 Eigen::Vector3f project2world(const Eigen::Vector2f &pt) const {
00277 Eigen::Vector3f v;
00278 v.head<2>() = pt;
00279 v(2) = model_.model(pt(0),pt(1));
00280 return v;
00281 }
00282
00288 inline Eigen::Quaternionf get_orientation() const {
00289 Eigen::Vector2f mid, dir, mean; mid(0) = model_.x(); mid(1) = model_.y();
00290 mean(0) = model_.param.model_(0,1);
00291 mean(1) = model_.param.model_(0,2);
00292 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> evd (model_.param.model_.block(1,1, 2,2)-mean*mean.transpose()/model_.param.model_(0,0));
00293 Eigen::Vector3f x = model_.getNormal(model_.x(), model_.y());
00294 dir(0) = evd.eigenvectors().col(1)(1);
00295 dir(1) = evd.eigenvectors().col(1)(0);
00296
00297 Eigen::Vector3f y = project2world(0.1f*dir+mid)-project2world(mid);
00298 y.normalize();
00299
00300 Eigen::Matrix3f M;
00301 M.col(0) = -x.cross(y).normalized();
00302 M.col(1) = y;
00303 M.col(2) = x;
00304
00305 return Eigen::Quaternionf(M);
00306 }
00307
00308 Eigen::Vector3f normalAt(const Eigen::Vector2f &v) const {
00309 return model_.getNormal(v(0),v(1));
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 void update() {
00351 Eigen::Vector3f x,y;
00352 x(0)=1.f;
00353 y(1)=1.f;
00354 x(1)=x(2)=y(0)=y(2)=0.f;
00355 }
00356
00357 void operator=(const SubStructure::Model<Degree> &model) {
00358 feature_.fill(0);
00359 param_xy_ = model.p;
00360 model_ = model;
00361 weight_ = model.param.model_(0,0);
00362
00363 update();
00364
00365 middle_(0) = model_.x();
00366 middle_(1) = model_.y();
00367 middle_(2) = model_.z();
00368
00369 middle_ = project2world(nextPoint(middle_));
00370 }
00371
00372 void print() {
00373 for(size_t j=0; j<segments_.size(); j++){
00374 std::cout<<"---------------\n";
00375 for(size_t i=0; i<segments_[j].size(); i++)
00376 std::cout<<segments_[j][i]<<"\n";
00377 }
00378 }
00379
00380 void toRosMsg(cob_3d_mapping_msgs::CurvedPolygon *msg, const ros::Time &time) const
00381 {
00382 static int nextID = 0;
00383 msg->stamp = time;
00384 msg->ID = nextID++;
00385 msg->weight = model_.param.model_(0,0);
00386
00387 for(int i=0; i<model_.p.rows(); i++)
00388 msg->parameter[i] = model_.p(i);
00389
00390 msg->polyline.clear();
00391 if(segments_.size()>0) {
00392 for(size_t i=0; i<segments_[0].size(); i++) {
00393 cob_3d_mapping_msgs::PolylinePoint pt;
00394 pt.x=segments_[0][i](0);
00395 pt.y=segments_[0][i](1);
00396 pt.edge_prob=segments_[0][i](2);
00397 msg->polyline.push_back(pt);
00398 }
00399 }
00400
00401 cob_3d_mapping_msgs::Feature ft;
00402
00403
00404 ft.ID = 1;
00405 Eigen::Vector3f nxtPt = project2world(nextPoint(Eigen::Vector3f::Zero()));
00406 ft.x=nxtPt(0);
00407 ft.y=nxtPt(1);
00408 ft.z=nxtPt(2);
00409 msg->features.push_back(ft);
00410
00411
00412 ft.ID = 2;
00413 ft.x=feature_(0);
00414 ft.y=feature_(1);
00415 ft.z=feature_(2);
00416 msg->features.push_back(ft);
00417
00418
00419 ft.ID = 3;
00420 ft.x=middle_(0);
00421 ft.y=middle_(1);
00422 ft.z=middle_(2);
00423 msg->features.push_back(ft);
00424
00425 Eigen::Vector2f ft1,ft2;
00426 Eigen::Vector3f ft3,n=model_.getNormal(middle_(0),middle_(1)),ft1p,ft2p;
00427
00428
00429 ft1p(0)=ft1(0);
00430 ft1p(1)=ft1(1);
00431 ft2p(0)=ft2(0);
00432 ft2p(1)=ft2(1);
00433 ft1p(2)=ft2p(2)=0.f;
00434
00435
00436 ft.ID = 4;
00437 ft3=ft1p.cross(n);
00438 ft.x = ft3(0);
00439 ft.y = ft3(1);
00440 ft.z = ft3(2);
00441
00442 msg->features.push_back(ft);
00443
00444
00445 ft.ID = 5;
00446 ft3=ft2p.cross(n);
00447 ft.x = ft3(0);
00448 ft.y = ft3(1);
00449 ft.z = ft3(2);
00450
00451 msg->features.push_back(ft);
00452
00453 }
00454
00455
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 struct MyFunctor
00492 {
00493 const SubStructure::Model<Degree> &model;
00494 const float x0,y0,z0;
00495
00496 int operator()(const Eigen::VectorXf &x, Eigen::VectorXf &fvec) const
00497 {
00498
00499 fvec(0) = std::pow(model.model(x(0),x(1))-z0,2)+std::pow(x(1)-y0,2)+std::pow(x(0)-x0,2);
00500 fvec(1) = 0;
00501
00502
00503 return 0;
00504 }
00505
00506 int df(const Eigen::VectorXf &x, Eigen::MatrixXf &fjac) const
00507 {
00508
00509 const float delta = model.model(x(0),x(1))-z0;
00510 const Eigen::Vector3f n = model.getNormal_(x(0),x(1));
00511 fjac(0,0) = n(0)*delta+2*(x(0)-x0);
00512 fjac(0,1) = n(1)*delta+2*(x(1)-y0);
00513 fjac(1,0) = fjac(1,1) = 0;
00514 return 0;
00515 }
00516
00517 int inputs() const { return 2; }
00518 int values() const { return 2; }
00519 };
00520
00522 Eigen::Vector2f _nextPoint(const Eigen::Vector3f &v, Eigen::Vector3f p, const int depth=0) const
00523 {
00524 Eigen::VectorXf r(2);
00525 r = v.head<2>();
00526 MyFunctor functor={model_,
00527 p(0),p(1),p(2)};
00528 Eigen::LevenbergMarquardt<MyFunctor, float> lm(functor);
00529 lm.parameters.maxfev = 50;
00530 lm.minimize(r);
00531
00532 return r;
00533 }
00534
00536 Eigen::Vector2f nextPoint(const Eigen::Vector3f &v) const
00537 {
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 Eigen::Vector2f r = _nextPoint(v, v);
00551
00552 float e1 = (v-project2world(v.head<2>())).norm();
00553 float e2 = (v-project2world(r)).norm();
00554
00555 if(e1<e2)
00556 {
00557 return v.head<2>();
00558 }
00559
00560 return r;
00561 }
00562
00563 bool getPose(Eigen::Matrix3f &P, Eigen::Vector3f &origin, float &h, float &w) const {
00564 if(segments_.size()<1)
00565 return false;
00566
00567 Eigen::Matrix2f A, C;
00568 Eigen::Vector2f B, v1, v2;
00569
00570 A(0,0) = model_.param.model_(1,1);
00571 A(1,1) = model_.param.model_(3,3);
00572 A(0,1) = A(1,0) = model_.param.model_(1,3);
00573
00574 B(0) = model_.param.model_(0,1);
00575 B(1) = model_.param.model_(0,3);
00576
00577 C = A-C*C.transpose();
00578
00579 Eigen::EigenSolver<Eigen::Matrix2f> es(C);
00580
00581
00582
00583
00584 v1 = es.eigenvectors().col(0).real();
00585 v2 = es.eigenvectors().col(1).real();
00586
00587 v1.normalize();
00588 v2.normalize();
00589
00590 P.col(0) = project2world(v1)-project2world(Eigen::Vector2f::Zero());
00591 P.col(1) = project2world(v2)-project2world(Eigen::Vector2f::Zero());
00592 P.col(0).normalize();
00593 P.col(1).normalize();
00594 P.col(2) = P.col(0).cross(P.col(1));
00595
00596 float h_ma = -std::numeric_limits<float>::max(), h_mi = std::numeric_limits<float>::max();
00597 float w_ma = -std::numeric_limits<float>::max(), w_mi = std::numeric_limits<float>::max();
00598
00599 for(size_t i=0; i<segments_[0].size(); i++)
00600 {
00601 float f=segments_[0][i].head<2>().dot(v1);
00602 h_ma = std::max(h_ma, f);
00603 h_mi = std::min(h_mi, f);
00604
00605 f=segments_[0][i].head<2>().dot(v2);
00606 w_ma = std::max(w_ma, f);
00607 w_mi = std::min(w_mi, f);
00608 }
00609
00610 origin = middle_;
00611 w = (project2world(v1*h_ma)-project2world(v1*h_mi)).norm();
00612 h = (project2world(v2*w_ma)-project2world(v2*w_mi)).norm();
00613
00614
00615
00616 return true;
00617 }
00618
00619 float area() const {
00620
00621 TPPLPartition pp;
00622 list<TPPLPoly> polys,result;
00623
00624
00625
00626
00627 for(size_t i=0; i<segments_.size(); i++) {
00628 pcl::PointCloud<pcl::PointXYZ> pc;
00629 TPPLPoly poly;
00630
00631 poly.Init(segments_[i].size());
00632 poly.SetHole(i!=0);
00633
00634 for(size_t j=0; j<segments_[i].size(); j++) {
00635 poly[j].x = segments_[i][j](0);
00636 poly[j].y = segments_[i][j](1);
00637 }
00638 if(i!=0)
00639 poly.SetOrientation(TPPL_CW);
00640 else
00641 poly.SetOrientation(TPPL_CCW);
00642
00643 polys.push_back(poly);
00644 }
00645
00646 pp.Triangulate_EC(&polys,&result);
00647
00648 TPPLPoint p1,p2,p3;
00649 Eigen::Vector3f v1,v2,v3;
00650
00651 float a=0.f;
00652 for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
00653 if(it->GetNumPoints()!=3) continue;
00654
00655 p1 = it->GetPoint(0);
00656 p2 = it->GetPoint(1);
00657 p3 = it->GetPoint(2);
00658
00659 v1(0) = p1.x;
00660 v1(1) = p1.y;
00661 v2(0) = p2.x;
00662 v2(1) = p2.y;
00663 v3(0) = p3.x;
00664 v3(1) = p3.y;
00665
00666 v1 = project2world(v1.head<2>());
00667 v2 = project2world(v2.head<2>());
00668 v3 = project2world(v3.head<2>());
00669
00670 a += (v2-v1).cross(v3-v1).norm();
00671 }
00672
00673 return a;
00674 }
00675
00676 };
00677
00678 #ifdef QPPF_SPECIALIZATION_2
00679 template< >
00680 struct S_POLYGON<2> {
00681 Eigen::Matrix3f param_;
00682 std::vector<std::vector<Eigen::Vector3f> > segments_;
00683 std::vector<std::vector<Eigen::Vector2i> > segments2d_;
00684 #ifdef USE_BOOST_POLYGONS_
00685 std::vector<std::vector<BoostPoint> > segments2d_;
00686 #endif
00687 float weight_;
00688 #ifdef CHECK_CONNECTIVITY
00689 S_POLYGON_CONNECTIVITY connectivity_;
00690 #endif
00691 SubStructure::Model<2> model_;
00692 Eigen::Vector3f middle_;
00693 int mark_;
00694
00695 Eigen::Matrix<float,3,2> proj2plane_;
00696 typename SubStructure::Param<2>::VectorU param_xy_;
00697 sensor_msgs::ImagePtr img_;
00698 float color_[3];
00699
00700 #ifdef USE_CLASSIFICATION_
00701 Classification::Form::Ptr form_;
00702 #endif
00703
00704 Eigen::Vector3f feature_;
00705
00706 S_POLYGON()
00707 #ifdef USE_CLASSIFICATION_
00708 :form_(new Classification::Form)
00709 #endif
00710 {
00711 int color = rand();
00712 color_[0] = ((color>>0)&0xff)/255.f;
00713 color_[1] = ((color>>8)&0xff)/255.f;
00714 color_[2] = ((color>>16)&0xff)/255.f;
00715 }
00716
00717 bool isLinear() const
00718 {
00719 std::cout<<model_.p<<"\n";
00720 return std::abs(model_.p(2))<0.01f && std::abs(model_.p(4))<0.01f && std::abs(model_.p(5))<0.01f;
00721 }
00722
00723 void buildForm(const bool debug=false) {
00724 if(segments_.size()<1)
00725 return;
00726
00727 std::vector<Eigen::Vector3f> pts;
00728 for(size_t i=0; i<segments_[0].size(); i++)
00729 {
00730 Eigen::Vector3f v;
00731 #ifdef USE_BOOST_POLYGONS_
00732 v(0)=segments2d_[0][i].x();
00733 v(1)=segments2d_[0][i].y();
00734 #endif
00735 pts.push_back(v);
00736
00737 }
00738
00739 #ifdef USE_CLASSIFICATION_
00740 Classification::Classification cl;
00741 Classification::QuadBB qbb;
00742
00743 form_->curvature_ = getInvariantCurvature();
00744 cl.setPoints(segments_[0]);
00745
00746
00747 int mains[2];
00748 form_->n_=cl.buildLocalTree(debug,&qbb,&form_->compressed_energy_,mains);
00749 form_->outline_ = qbb.getOutline();
00750
00751 feature_ = project2world(segments_[0][mains[0]].head<2>());
00752 feature_-= project2world(segments_[0][mains[1]].head<2>());
00753
00754
00755 if(feature_(0)<0) feature_=-feature_;
00756 #endif
00757 }
00758
00759 Eigen::Vector2f project2plane(const float x, const float y, const SubStructure::Model<2> &model) {
00760 Eigen::Vector2f mv;
00761 mv(0)=x;
00762 mv(1)=y;
00763 float mz;
00764 mz=model.intersect(mv(0), mv(1));
00765
00766 Eigen::Vector3f v;
00767 v.head<2>() = mz * mv;
00768 v(2) = mz;
00769 mv(0) = (v-param_.col(0)).dot(proj2plane_.col(0))/proj2plane_.col(0).squaredNorm();
00770 mv(1) = (v-param_.col(0)).dot(proj2plane_.col(1))/proj2plane_.col(1).squaredNorm();
00771 #if DEBUG_LEVEL >70
00772 if(!pcl_isfinite(mv(0))) {
00773 ROS_ERROR("mist");
00774 std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00775 std::cerr<<mv<<"\np\n";
00776 std::cerr<<model.p<<"\n";
00777 std::cerr<<"mz: "<<mz<<"\nmv:\n";
00778
00779 }
00780 #endif
00781 return mv;
00782 }
00783
00784 #ifdef USE_BOOST_POLYGONS_
00785 BoostPolygonSet getBoostPolygon2D() const {
00786
00787 BoostPolygon poly;
00788 BoostPolygonSet r;
00789 if(segments2d_.size()==0) return r;
00790 poly.set(segments2d_[0].begin(), segments2d_[0].end());
00791
00792 r.push_back(poly);
00793 return r;
00794 }
00795
00796 BoostPolygonSet getBoostPolygon2D_Centered() const {
00797
00798 BoostPolygon poly;
00799 BoostPolygonSet r;
00800 if(segments2d_.size()==0) return r;
00801 {
00802 poly.set(segments2d_[0].begin(), segments2d_[0].end());
00803
00804
00805 BoostPoint cnt;
00806 boost::polygon::center(cnt,poly);
00807 std::vector<BoostPoint> temp;
00808
00809 for(size_t i=0; i<segments2d_[0].size(); i++) {
00810 temp.push_back( BoostPoint(segments2d_[0][i].x()-cnt.x(), segments2d_[0][i].y()-cnt.y()));
00811 }
00812
00813 poly.set(temp.begin(), temp.end());
00814
00815 r.push_back(poly);
00816 }
00817 return r;
00818 }
00819 #endif
00820
00821 Eigen::Vector3f project2plane(const float x, const float y, const float mz, const float b) {
00822 Eigen::Vector2f mv;
00823 Eigen::Vector3f mv3;
00824 mv(0)=x;
00825 mv(1)=y;
00826 mv=mv*mz-getCenter();
00827
00828
00829 #if DEBUG_LEVEL >70
00830 if(!pcl_isfinite(mv(0))) {
00831 ROS_ERROR("mistXYZ");
00832 std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00833 std::cerr<<mv<<"\np\n";
00834 std::cerr<<"mz: "<<mz<<"\nmv:\n";
00835
00836 }
00837 #endif
00838 mv3(2)=b;
00839 mv3(0)=mv(0);
00840 mv3(1)=mv(1);
00841 return mv3;
00842 }
00843
00844 Eigen::Vector3f project2plane(const float x, const float y, const SubStructure::Model<2> &model, const float b) {
00845 Eigen::Vector2f mv;
00846 Eigen::Vector3f mv3;
00847 mv(0)=x;
00848 mv(1)=y;
00849 mv3(2)=b;
00850 float mz;
00851 mz=model.intersect(mv(0), mv(1));
00852
00853
00854
00855
00856
00857 mv=mv*mz-param_.col(0).head<2>();
00858
00859
00860
00861
00862
00863 #if DEBUG_LEVEL >70
00864 if(!pcl_isfinite(mv(0))) {
00865 ROS_ERROR("mist");
00866 std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00867 std::cerr<<mv<<"\np\n";
00868 std::cerr<<model.p<<"\n";
00869 std::cerr<<"mz: "<<mz<<"\n";
00870
00871 }
00872 #endif
00873 mv3(0)=mv(0);
00874 mv3(1)=mv(1);
00875 return mv3;
00876 }
00877
00878 Eigen::Vector2f getCenter() const {
00879 Eigen::Vector2f r;
00880 r(0)=param_(0,0);
00881 r(1)=param_(1,0);
00882 return r;
00883 }
00884
00885 Eigen::Vector3f project2world(const Eigen::Vector2f &pt) const {
00886 Eigen::Vector3f pt2;
00887 pt2(0)=pt(0)*pt(0);
00888 pt2(1)=pt(1)*pt(1);
00889 pt2(2)=pt(0)*pt(1);
00890
00891 return param_.col(0) + proj2plane_*pt + proj2plane_.col(0).cross(proj2plane_.col(1)) * (pt2.dot(param_.col(2)) + pt.dot(param_.col(1).head<2>()));
00892 }
00893
00894 Eigen::Vector3f normalAt(const Eigen::Vector2f &v) const {
00895 Eigen::Vector3f r;
00896
00897 r(0) = -(param_.col(1)(0) + 2*v(0)*param_.col(2)(0)+v(1)*param_.col(2)(2));
00898 r(1) = -(param_.col(1)(1) + 2*v(1)*param_.col(2)(1)+v(0)*param_.col(2)(2));
00899 r(2) = 1;
00900
00901 r.normalize();
00902
00903 Eigen::Matrix3f M;
00904 M.col(0) = proj2plane_.col(0);
00905 M.col(1) = proj2plane_.col(1);
00906 M.col(2) = proj2plane_.col(0).cross(proj2plane_.col(1));
00907
00908 return M*r;
00909 }
00910
00911 float getFeature(Eigen::Vector2f &ra,Eigen::Vector2f &rb,Eigen::Vector3f &rc) const {
00912
00913 rc=feature_;
00914
00915 float a=param_(0,2), b=param_(1,2), c=param_(2,2);
00916
00917 float x1 = sqrtf((a-b)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00918 float x2 = -sqrtf((b-a)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00919 float y1=sqrtf(1-x1*x1);
00920 float y2=sqrtf(1-x2*x2);
00921
00922 ra(0)=x1;
00923 ra(1)=y1;
00924
00925 rb(0)=x2;
00926 rb(1)=y2;
00927
00928 Eigen::Vector3f t=getInvariantCurvature();
00929
00930 return std::max( std::abs(t(0)), std::max(std::abs(t(1)),std::abs(t(2))) );
00931 }
00932
00933 Eigen::Vector3f getInvariantCurvature() const {
00934 Eigen::Vector3f r;
00935 float a=param_(0,2), b=param_(1,2), c=param_(2,2);
00936
00937 float x1 = sqrtf((a-b)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00938 float x2 = -sqrtf((b-a)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00939 float y1=sqrtf(1-x1*x1);
00940 float y2=sqrtf(1-x2*x2);
00941
00942 r(0)=atanf( (a*x1*x1+b*y1*y1+c*x1*y1) /30.f);
00943 r(1)=atanf( (a*x2*x2+b*y2*y2+c*x2*y2) /30.f);
00944 r(2)=0.f;
00945
00946 return r;
00947 }
00948
00949 void update() {
00950 Eigen::Vector3f x,y;
00951 x(0)=1.f;
00952 y(1)=1.f;
00953 x(1)=x(2)=y(0)=y(2)=0.f;
00954
00955 proj2plane_.col(0)=x;
00956 proj2plane_.col(1)=y;
00957
00958
00959
00960
00961
00962
00963
00964 }
00965
00966 void operator=(const SubStructure::Model<2> &model) {
00967 feature_.fill(0);
00968 param_xy_ = model.p;
00969 model_ = model;
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 param_.col(0) = Eigen::Vector3f::Zero();
00991 param_.col(0)(2) = model.p(0);
00992
00993 param_.col(1)(0)=model.p(1);
00994 param_.col(1)(1)=model.p(3);
00995 param_.col(1)(2)=0;
00996
00997
00998 param_.col(2)(0)=model.p(2);
00999 param_.col(2)(1)=model.p(4);
01000 param_.col(2)(2)=model.p(5);
01001
01002 weight_ = model.param.model_(0,0);
01003
01004 update();
01005
01006 middle_(0) = model_.x();
01007 middle_(1) = model_.y();
01008 middle_(2) = model_.z();
01009
01010 middle_ = project2world(nextPoint(middle_));
01011 }
01012
01013 void print() {
01014 std::cout<<"parameter:\n"<<param_<<"\n";
01015 for(size_t j=0; j<segments_.size(); j++){
01016 std::cout<<"---------------\n";
01017 for(size_t i=0; i<segments_[j].size(); i++)
01018 std::cout<<segments_[j][i]<<"\n";
01019 }
01020 }
01021
01022 void toRosMsg(cob_3d_mapping_msgs::CurvedPolygon *msg, const ros::Time &time) const
01023 {
01024 static int nextID = 0;
01025 msg->stamp = time;
01026 msg->ID = nextID++;
01027 msg->weight = model_.param.model_(0,0);
01028
01029 for(int i=0; i<model_.p.rows(); i++)
01030 msg->parameter[i] = model_.p(i);
01031
01032 msg->polyline.clear();
01033 if(segments_.size()>0) {
01034 for(size_t i=0; i<segments_[0].size(); i++) {
01035 cob_3d_mapping_msgs::PolylinePoint pt;
01036 pt.x=segments_[0][i](0);
01037 pt.y=segments_[0][i](1);
01038 pt.edge_prob=segments_[0][i](2);
01039 msg->polyline.push_back(pt);
01040 }
01041 }
01042
01043 cob_3d_mapping_msgs::Feature ft;
01044
01045
01046 ft.ID = 1;
01047 Eigen::Vector3f nxtPt = project2world(nextPoint(Eigen::Vector3f::Zero()));
01048 ft.x=nxtPt(0);
01049 ft.y=nxtPt(1);
01050 ft.z=nxtPt(2);
01051 msg->features.push_back(ft);
01052
01053
01054 ft.ID = 2;
01055 ft.x=feature_(0);
01056 ft.y=feature_(1);
01057 ft.z=feature_(2);
01058 msg->features.push_back(ft);
01059
01060
01061 ft.ID = 3;
01062 ft.x=middle_(0);
01063 ft.y=middle_(1);
01064 ft.z=middle_(2);
01065 msg->features.push_back(ft);
01066
01067 Eigen::Vector2f ft1,ft2;
01068 Eigen::Vector3f ft3,n=model_.getNormal(middle_(0),middle_(1)),ft1p,ft2p;
01069 getFeature(ft1,ft2,ft3);
01070
01071 ft1p(0)=ft1(0);
01072 ft1p(1)=ft1(1);
01073 ft2p(0)=ft2(0);
01074 ft2p(1)=ft2(1);
01075 ft1p(2)=ft2p(2)=0.f;
01076
01077
01078 ft.ID = 4;
01079 ft3=ft1p.cross(n);
01080 ft.x = ft3(0);
01081 ft.y = ft3(1);
01082 ft.z = ft3(2);
01083
01084 msg->features.push_back(ft);
01085
01086
01087 ft.ID = 5;
01088 ft3=ft2p.cross(n);
01089 ft.x = ft3(0);
01090 ft.y = ft3(1);
01091 ft.z = ft3(2);
01092
01093 msg->features.push_back(ft);
01094
01095 }
01096
01097
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 struct MyFunctor
01134 {
01135 const float a,b,c, d,e;
01136 const float x0,y0,z0;
01137
01138 int operator()(const Eigen::VectorXf &x, Eigen::VectorXf &fvec) const
01139 {
01140
01141 fvec(0) = std::pow((-z0+b*x(1)*x(1)+c*x(0)*x(1)+a*x(0)*x(0)+d*x(0)+e*x(1)),2)+std::pow(x(1)-y0,2)+std::pow(x(0)-x0,2);
01142 fvec(1) = 0;
01143
01144
01145 return 0;
01146 }
01147
01148 int df(const Eigen::VectorXf &x, Eigen::MatrixXf &fjac) const
01149 {
01150
01151
01152 fjac(0,0) = 2*(c*x(1)+2*a*x(0)+d)*(-z0+b*x(1)*x(1)+c*x(0)*x(1)+a*x(0)*x(0)+d*x(0)+e*x(1))+2*(x(0)-x0);
01153 fjac(0,1) = 2*(2*b*x(1)+c*x(0)+e)*(-z0+b*x(1)*x(1)+c*x(0)*x(1)+a*x(0)*x(0)+d*x(0)+e*x(1))+2*(x(1)-y0);
01154 fjac(1,0) = fjac(1,1) = 0;
01155 return 0;
01156 }
01157
01158 int inputs() const { return 2; }
01159 int values() const { return 2; }
01160 };
01161
01163 Eigen::Vector2f _nextPoint(const Eigen::Vector3f &v, Eigen::Vector3f p, const int depth=0) const
01164 {
01165 Eigen::VectorXf r(2);
01166 r = v.head<2>();
01167 MyFunctor functor={param_.col(2)(0),param_.col(2)(1),param_.col(2)(2),
01168 param_.col(1)(0),param_.col(1)(1),
01169 p(0),p(1),p(2)};
01170 Eigen::LevenbergMarquardt<MyFunctor, float> lm(functor);
01171 lm.parameters.maxfev = 50;
01172 lm.minimize(r);
01173
01174 return r;
01175 }
01176
01178 Eigen::Vector2f nextPoint(const Eigen::Vector3f &v) const
01179 {
01180 Eigen::Vector3f p;
01181
01182 p(0) = (v-param_.col(0)).dot(proj2plane_.col(0));
01183 p(1) = (v-param_.col(0)).dot(proj2plane_.col(1));
01184 p(2) = (v-param_.col(0)).dot(proj2plane_.col(0).cross(proj2plane_.col(1)));
01185
01186 Eigen::Vector2f r = _nextPoint(p, p);
01187
01188 float e1 = (v-project2world(p.head<2>())).norm();
01189 float e2 = (v-project2world(r)).norm();
01190
01191 if(e1<e2)
01192 {
01193 return p.head<2>();
01194 }
01195
01196 return r;
01197 }
01198
01199 bool getPose(Eigen::Matrix3f &P, Eigen::Vector3f &origin, float &h, float &w) const {
01200 if(segments_.size()<1)
01201 return false;
01202
01203 Eigen::Matrix2f A, C;
01204 Eigen::Vector2f B, v1, v2;
01205
01206 A(0,0) = model_.param.model_(1,1);
01207 A(1,1) = model_.param.model_(3,3);
01208 A(0,1) = A(1,0) = model_.param.model_(1,3);
01209
01210 B(0) = model_.param.model_(0,1);
01211 B(1) = model_.param.model_(0,3);
01212
01213 C = A-C*C.transpose();
01214
01215 Eigen::EigenSolver<Eigen::Matrix2f> es(C);
01216
01217
01218
01219
01220 v1 = es.eigenvectors().col(0).real();
01221 v2 = es.eigenvectors().col(1).real();
01222
01223 v1.normalize();
01224 v2.normalize();
01225
01226 P.col(0) = project2world(v1)-project2world(Eigen::Vector2f::Zero());
01227 P.col(1) = project2world(v2)-project2world(Eigen::Vector2f::Zero());
01228 P.col(0).normalize();
01229 P.col(1).normalize();
01230 P.col(2) = P.col(0).cross(P.col(1));
01231
01232 float h_ma = -std::numeric_limits<float>::max(), h_mi = std::numeric_limits<float>::max();
01233 float w_ma = -std::numeric_limits<float>::max(), w_mi = std::numeric_limits<float>::max();
01234
01235 for(size_t i=0; i<segments_[0].size(); i++)
01236 {
01237 float f=segments_[0][i].head<2>().dot(v1);
01238 h_ma = std::max(h_ma, f);
01239 h_mi = std::min(h_mi, f);
01240
01241 f=segments_[0][i].head<2>().dot(v2);
01242 w_ma = std::max(w_ma, f);
01243 w_mi = std::min(w_mi, f);
01244 }
01245
01246 origin = middle_;
01247 w = (project2world(v1*h_ma)-project2world(v1*h_mi)).norm();
01248 h = (project2world(v2*w_ma)-project2world(v2*w_mi)).norm();
01249
01250
01251
01252 return true;
01253 }
01254
01255 float area() const {
01256
01257 TPPLPartition pp;
01258 list<TPPLPoly> polys,result;
01259
01260
01261
01262
01263 for(size_t i=0; i<segments_.size(); i++) {
01264 pcl::PointCloud<pcl::PointXYZ> pc;
01265 TPPLPoly poly;
01266
01267 poly.Init(segments_[i].size());
01268 poly.SetHole(i!=0);
01269
01270 for(size_t j=0; j<segments_[i].size(); j++) {
01271 poly[j].x = segments_[i][j](0);
01272 poly[j].y = segments_[i][j](1);
01273 }
01274 if(i!=0)
01275 poly.SetOrientation(TPPL_CW);
01276 else
01277 poly.SetOrientation(TPPL_CCW);
01278
01279 polys.push_back(poly);
01280 }
01281
01282 pp.Triangulate_EC(&polys,&result);
01283
01284 TPPLPoint p1,p2,p3;
01285 Eigen::Vector3f v1,v2,v3;
01286
01287 float a=0.f;
01288 for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
01289 if(it->GetNumPoints()!=3) continue;
01290
01291 p1 = it->GetPoint(0);
01292 p2 = it->GetPoint(1);
01293 p3 = it->GetPoint(2);
01294
01295 v1(0) = p1.x;
01296 v1(1) = p1.y;
01297 v2(0) = p2.x;
01298 v2(1) = p2.y;
01299 v3(0) = p3.x;
01300 v3(1) = p3.y;
01301
01302 v1 = project2world(v1.head<2>());
01303 v2 = project2world(v2.head<2>());
01304 v3 = project2world(v3.head<2>());
01305
01306 a += (v2-v1).cross(v3-v1).norm();
01307 }
01308
01309 return a;
01310 }
01311
01312 };
01313 #endif
01314 }
01315
01316 #endif
01317