00001
00059 #include <ros/console.h>
00060 #include "cob_3d_mapping_common/cylinder.h"
00061 #include <math.h>
00062 #include <pcl/io/pcd_io.h>
00063
00064 namespace cob_3d_mapping {
00065
00066
00067 double
00068 radiusAndOriginFromCloud(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr in_cloud ,
00069 std::vector<int>& indices,
00070 Eigen::Vector3f& origin,
00071 const Eigen::Vector3f& sym_axis)
00072 {
00073
00074 Eigen::Affine3f t;
00075 pcl::getTransformationFromTwoUnitVectorsAndOrigin(sym_axis.unitOrthogonal(), sym_axis, origin, t);
00076 pcl::PointCloud<pcl::PointXYZRGB>::Ptr pc_trans( new pcl::PointCloud<pcl::PointXYZRGB>() );
00077 pcl::transformPointCloud(*in_cloud, indices, *pc_trans, t);
00078
00079
00080 pcl::PointIndices inliers;
00081
00082 pcl::ModelCoefficients coeff;
00083
00084 pcl::SACSegmentation<pcl::PointXYZRGB> seg;
00085
00086 seg.setOptimizeCoefficients (true);
00087
00088
00089 seg.setMethodType (pcl::SAC_RANSAC);
00090
00091 seg.setMaxIterations (10);
00092
00093 seg.setModelType (pcl::SACMODEL_CIRCLE2D);
00094
00095 seg.setDistanceThreshold (0.010);
00096
00097 seg.setInputCloud (pc_trans);
00098
00099
00100
00101 seg.segment(inliers, coeff);
00102
00103
00104
00105 Eigen::Vector3f l_origin;
00106 l_origin << coeff.values[0],coeff.values[1],0;
00107 origin = t.inverse() * l_origin;
00108
00109 return coeff.values[2];
00110 }
00111
00112
00113
00114
00115 Cylinder::Cylinder(unsigned int id,
00116 Eigen::Vector3f origin,
00117 Eigen::Vector3f sym_axis,
00118 double radius,
00119 std::vector<std::vector<Eigen::Vector3f> >& contours_3d,
00120 std::vector<bool> holes,
00121 std::vector<float> color)
00122 : Polygon()
00123 {
00124
00125 id_ = id;
00126 sym_axis_ = sym_axis;
00127 r_ = radius;
00128 holes_ = holes;
00129 color_ = color;
00130 if (sym_axis_[2] < 0 )
00131 {
00132 sym_axis_ = sym_axis_ * -1;
00133 }
00134 computePose(origin, contours_3d);
00135 setContours3D(contours_3d);
00136 computeHeight();
00137 }
00138
00139 Cylinder::Cylinder(unsigned int id,
00140 Eigen::Vector3f origin,
00141 Eigen::Vector3f sym_axis,
00142 double radius,
00143 std::vector<pcl::PointCloud<pcl::PointXYZ> >& contours_3d,
00144 std::vector<bool> holes,
00145 std::vector<float> color)
00146 : Polygon()
00147 {
00148 std::vector<std::vector<Eigen::Vector3f> > contours_eigen;
00149 for(unsigned int i = 0; i < contours_3d.size(); i++)
00150 {
00151 std::vector<Eigen::Vector3f> c_eigen;
00152 for(unsigned int j = 0; j < contours_3d[i].size(); j++)
00153 {
00154 Eigen::Vector3f pt = contours_3d[i].points[j].getVector3fMap();
00155 c_eigen.push_back(pt);
00156 }
00157 contours_eigen.push_back(c_eigen);
00158 }
00159 id_ = id;
00160 sym_axis_ = sym_axis;
00161 r_ = radius;
00162
00163
00164 holes_ = holes;
00165 color_ = color;
00166 if (sym_axis_[2] < 0 )
00167 {
00168 sym_axis_ = sym_axis_ * -1;
00169 }
00170 computePose(origin, contours_eigen);
00171 setContours3D(contours_eigen);
00172 computeHeight();
00173
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 void
00186 Cylinder::setContours3D(std::vector<std::vector<Eigen::Vector3f> >& contours_3d)
00187 {
00188 contours_.clear();
00189 for(unsigned int i = 0; i < contours_3d.size(); i++)
00190 {
00191 std::vector<Eigen::Vector2f> c;
00192 for(unsigned int j = 0; j < contours_3d[i].size(); j++)
00193 {
00194 Eigen::Vector3f pt = (pose_.inverse()*contours_3d[i][j]);
00195
00196
00197 float alpha = atan2(pt(0),pt(2));
00198 Eigen::Vector2f pt_2d;
00199 pt_2d(0) = r_*alpha;
00200 pt_2d(1) = pt(1);
00201
00202 c.push_back(pt_2d);
00203 }
00204 contours_.push_back(c);
00205 }
00206
00207
00208
00209
00210
00211
00212
00213 }
00214
00215 std::vector<std::vector<Eigen::Vector3f> >
00216 Cylinder::getContours3D()
00217 {
00218 std::vector<std::vector<Eigen::Vector3f> > contours_3d;
00219 for(unsigned int i = 0; i < contours_.size(); i++)
00220 {
00221 std::vector<Eigen::Vector3f> c;
00222 for(unsigned int j = 0; j < contours_[i].size(); j++)
00223 {
00224 Eigen::Vector3f pt;
00225 double alpha = contours_[i][j](0) / r_;
00226 pt(0) = sin(alpha)*r_;
00227 pt(1) = contours_[i][j](1);
00228 pt(2) = cos(alpha)*r_;
00229 c.push_back(pose_*pt);
00230 }
00231 contours_3d.push_back(c);
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 return contours_3d;
00241 }
00242
00243 void
00244 Cylinder::computePose(Eigen::Vector3f origin, std::vector<std::vector<Eigen::Vector3f> >& contours_3d)
00245 {
00246 Eigen::Affine3f t;
00247 pcl::getTransformationFromTwoUnitVectorsAndOrigin(sym_axis_, sym_axis_.unitOrthogonal(), origin, t);
00248 Eigen::Vector3f z_cyl = t * contours_3d[0][0];
00249 z_cyl(1) = 0;
00250 Eigen::Vector3f z_axis = t.inverse().rotation() * z_cyl;
00251 computePose(origin, z_axis.normalized());
00252 }
00253
00254 void
00255 Cylinder::computePose(Eigen::Vector3f origin, Eigen::Vector3f z_axis)
00256 {
00257 Eigen::Affine3f t;
00258 pcl::getTransformationFromTwoUnitVectorsAndOrigin(sym_axis_, z_axis, origin, t);
00259 pose_ = t.inverse();
00260 }
00261
00262 void Cylinder::computeHeight()
00263 {
00264
00265 double min,max;
00266 min = 1000;
00267 max = -1000;
00268
00269
00270 for (size_t i = 0; i < contours_.size(); ++i) {
00271 for (size_t j = 0; j < contours_[i].size(); ++j) {
00272 if (contours_[i][j][1] < min) min = contours_[i][j][1];
00273 if (contours_[i][j][1] > max) max = contours_[i][j][1];
00274 }
00275 }
00276 h_max_ = max;
00277 h_min_ = min;
00278 }
00279
00280 void
00281 Cylinder::updateAttributes(const Eigen::Vector3f& sym_axis, const Eigen::Vector3f& origin, const Eigen::Vector3f& z_axis)
00282 {
00283
00284 sym_axis_ = sym_axis;
00285 if (sym_axis_[2] < 0 )
00286 {
00287 sym_axis_ = sym_axis_ * -1;
00288 }
00289 computePose(origin, z_axis.normalized());
00290
00291
00292
00293
00294
00295
00296 }
00297
00298 void Cylinder::setParamsFrom(Polygon::Ptr& p)
00299 {
00300 Cylinder::Ptr c(boost::dynamic_pointer_cast<Cylinder>(p));
00301 BOOST_ASSERT(c);
00302 this->pose_ = c->pose_;
00303 this->r_ = c->r_;
00304 this->sym_axis_ = c->sym_axis_;
00305 this->h_max_ = c->h_max_;
00306 this->h_min_ = c->h_min_;
00307 if(this->merged_ < 9) { this->merged_ = c->merged_; }
00308 else { this->merged_ = 9; }
00309 }
00310
00311 void
00312 Cylinder::transform(Eigen::Affine3f & trafo)
00313 {
00314
00315
00316 pose_ = trafo * pose_;
00317
00318
00319 sym_axis_ = trafo.rotation() * sym_axis_;
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 }
00334
00335 void
00336 Cylinder::triangulate(list<TPPLPoly>& tri_list) const
00337 {
00338 TPPLPartition pp;
00339 list<TPPLPoly> polys;
00340 TPPLPoly poly;
00341 TPPLPoint pt;
00342
00343 double d_alpha = 0.5;
00344 double alpha_max = 0, alpha_min = std::numeric_limits<double>::max();
00345 for(size_t i = 0; i < contours_[0].size(); ++i)
00346 {
00347 double alpha = contours_[0][i](0) / r_;
00348 if (alpha > alpha_max) alpha_max = alpha;
00349 if (alpha < alpha_min) alpha_min = alpha;
00350 }
00351 std::cout << "r " << r_ << std::endl;
00352 std::cout << "alpha " << alpha_min << "," << alpha_max << std::endl;
00353 std::vector<std::vector<std::vector<Eigen::Vector2f> > > contours_split;
00354 for(size_t j = 0; j < contours_.size(); j++)
00355 {
00356 for(double i = alpha_min + d_alpha; i <= alpha_max; i += d_alpha)
00357 {
00358 std::vector<Eigen::Vector2f> contour_segment;
00359 for(size_t k = 0; k < contours_[j].size(); ++k)
00360 {
00361 double alpha = contours_[j][k](0) / r_;
00362 if( alpha >= i - d_alpha - 0.25 && alpha < i + 0.25)
00363 {
00364 contour_segment.push_back(contours_[j][k]);
00365 }
00366 }
00367
00368 if(contour_segment.size() < 3) continue;
00369 poly.Init(contour_segment.size());
00370 poly.SetHole(holes_[j]);
00371 for( unsigned int l = 0; l < contour_segment.size(); l++)
00372 {
00373 pt.x = contour_segment[l](0);
00374 pt.y = contour_segment[l](1);
00375 poly[l] = pt;
00376 }
00377 if (holes_[j])
00378 poly.SetOrientation(TPPL_CW);
00379 else
00380 poly.SetOrientation(TPPL_CCW);
00381 polys.push_back(poly);
00382 }
00383 }
00384
00385 pp.Triangulate_EC (&polys, &tri_list);
00386 }
00387
00388 void
00389 Cylinder::getMergeCandidates(const std::vector<Polygon::Ptr>& cylinder_array,
00390 std::vector<int>& intersections)
00391 {
00392
00393 for (size_t i = 0; i < cylinder_array.size(); i++)
00394 {
00395 Cylinder::Ptr c(boost::dynamic_pointer_cast<Cylinder>(cylinder_array[i]));
00396 BOOST_ASSERT(c);
00397 Cylinder& c_map = *c;
00398 Eigen::Vector3f connection = c_map.pose_.translation() - pose_.translation();
00399
00400
00401
00402
00403 if(fabs(c_map.sym_axis_.dot(sym_axis_)) > merge_settings_.angle_thresh && (fabs(c_map.r_ - r_) < (0.1 )))
00404 {
00405
00406 if( connection.norm() < (c_map.r_ + 0.1) || fabs(c_map.sym_axis_.dot(connection.normalized())) > merge_settings_.angle_thresh )
00407 {
00408
00409
00410
00411
00412
00413
00414
00415
00416 if(isIntersectedWith(cylinder_array[i]))
00417
00418 {
00419 intersections.push_back(i);
00420 }
00421 }
00422 }
00423 }
00424 }
00425
00426
00427 void
00428 Cylinder::computeAverage(const std::vector<Polygon::Ptr>& poly_vec, Polygon::Ptr& p_average)
00429 {
00430 std::cout << merge_weight_ << "," << merged_ << std::endl;
00431 Eigen::Vector3f temp_sym_axis,temp_origin,temp_z_axis;
00432 temp_sym_axis = this->merge_weight_ * this->sym_axis_;
00433 temp_origin = this->merge_weight_ * this->pose_.translation();
00434 temp_z_axis = this->merge_weight_ * this->pose_.rotation() * Eigen::Vector3f(0, 0, 1);
00435
00436
00437 double merge_weight_sum = this ->merge_weight_;
00438 double temp_r = merge_weight_sum * this->r_;
00439 int merged_sum = this->merged_;
00440
00441 double temp_h_max = h_max_, temp_h_min = h_min_;
00442 for (int i = 0; i < (int)poly_vec.size(); ++i)
00443 {
00444 Cylinder::Ptr c(boost::dynamic_pointer_cast<Cylinder>(poly_vec[i]));
00445 BOOST_ASSERT(c);
00446 std::cout << c->merge_weight_ << "," << c->merged_ << std::endl;
00447 temp_sym_axis += c->merge_weight_ * c->sym_axis_;
00448
00449 temp_z_axis += c->merge_weight_ * c->pose_.rotation() * Eigen::Vector3f(0, 0, 1);
00450 temp_origin += c->merge_weight_ * c->pose_.translation();
00451 temp_r += c->merge_weight_ * c->r_;
00452 merge_weight_sum += c->merge_weight_;
00453 merged_sum += c->merged_;
00454
00455 if (c->h_max_ > temp_h_max) temp_h_max = c->h_max_;
00456 if (c->h_min_ < temp_h_min) temp_h_min = c->h_min_;
00457
00458 }
00459 Cylinder::Ptr c_avg(boost::dynamic_pointer_cast<Cylinder>(p_average));
00460 BOOST_ASSERT(c_avg);
00461
00462
00463
00464 c_avg->sym_axis_.normalize();
00465 c_avg->r_ = temp_r / merge_weight_sum;
00466 c_avg->h_max_ = temp_h_max;
00467 c_avg->h_min_ = temp_h_min;
00468
00469 if (merged_sum < merged_limit_)
00470 {
00471 c_avg->merged_ = merged_sum;
00472
00473 }
00474 else
00475 {
00476 c_avg->merged_ = merged_limit_;
00477 }
00478 c_avg->updateAttributes(temp_sym_axis / merge_weight_sum, temp_origin / merge_weight_sum, temp_z_axis / merge_weight_sum);
00479 }
00480
00481 void
00482 Cylinder::merge(std::vector<Polygon::Ptr>& poly_vec)
00483 {
00484 assignID(poly_vec);
00485
00486 Polygon::Ptr p_average = Polygon::Ptr(new Cylinder);
00487 computeAverage(poly_vec, p_average);
00488 mergeUnion(poly_vec, p_average);
00489 std::cout << "c_merged (r, hmax, hmin, sym_axis): " << r_ << "," << h_max_ << "," << h_min_ << "," << sym_axis_ << std::endl;
00490 for(unsigned int i=0; i<contours_[0].size(); i++)
00491 {
00492 std::cout << contours_[0][i](0) << "," << contours_[0][i](1) << std::endl;
00493 }
00494 assignWeight();
00495
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 void
00635 Cylinder::dbgOut(pcl::PointCloud<pcl::PointXYZRGB>::Ptr points,std::string & name){
00636
00637 std::ofstream os;
00638 std::string path = "/home/goa-tz/debug/";
00639 path.append(name.c_str());
00640 os.open(path.c_str());
00641
00642 for (int i = 0; i < (int)points->width; ++i) {
00643 os << points->points[i].x;
00644 os <<" ";
00645 os << points->points[i].y;
00646 os <<" ";
00647 os << points->points[i].z;
00648 os <<"\n";
00649 }
00650
00651 os.close();
00652 }
00653
00654
00655 void
00656 Cylinder::dumpParams(std::string name)
00657 {
00658
00659 std::string path = "/home/goa-tz/eval/params/";
00660 path.append(name.c_str());
00661 std::ofstream os(path.c_str(),std::ofstream::app );
00662
00663 os<<frame_stamp_<<" "<<r_<<" "<<
00664
00665
00666
00667 this->sym_axis_[0]<<" "<<this->sym_axis_[1]<<" "<<this->sym_axis_[2]<<"\n";
00668 os.close();
00669 }
00670
00671
00672 void
00673 Cylinder::printAttributes(std::string & name)
00674 {
00675 ROS_DEBUG_STREAM( "_______"<<name.c_str() <<"______\n");
00676
00677
00678 ROS_DEBUG_STREAM("radius = "<< this->r_<<"\n");
00679
00680 ROS_DEBUG_STREAM("sym_axis = "<< this->sym_axis_<<"\n");
00681 ROS_DEBUG_STREAM("merged = " << this->merged_<<"\n");
00682 ROS_DEBUG_STREAM("merge_weight = "<<this->merge_weight_<<"\n");
00683 ROS_DEBUG_STREAM( "_________________\n");
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 }