6 ROS_INFO (
"HectorStairDetection started");
49 if(
setup_.compare(std::string(
"argo"))==0){
83 pcl::IndicesClustersPtr cluster_indices, std::vector<int> final_cluster_idx, Eigen::Vector3f base, Eigen::Vector3f point){
85 geometry_msgs::PoseStamped position_and_orientaion;
86 Eigen::Vector3f directionStairs;
88 hector_stair_detection_msgs::PositionAndOrientaion pos_and_orientaion_message;
89 pos_and_orientaion_message.orientation_of_stairs=position_and_orientaion;
90 pos_and_orientaion_message.directionX=directionStairs(0);
91 pos_and_orientaion_message.directionY=directionStairs(1);
92 pos_and_orientaion_message.directionZ=directionStairs(2);
95 pcl::PointCloud<pcl::PointXYZ>::Ptr final_stairsCloud(
new pcl::PointCloud<pcl::PointXYZ>);
96 visualization_msgs::MarkerArray stairs_boarder_marker;
97 getFinalStairsCloud_and_position(input_surface_cloud->header.frame_id, directionStairs, input_surface_cloud, planeCloud, cluster_indices, final_cluster_idx, final_stairsCloud, stairs_boarder_marker, base);
106 hector_stair_detection_msgs::BorderAndOrientationOfStairs border_and_orientation_msg;
107 border_and_orientation_msg.header.frame_id=input_surface_cloud->header.frame_id;
108 border_and_orientation_msg.border_of_stairs= stairs_boarder_marker;
109 border_and_orientation_msg.orientation_of_stairs=position_and_orientaion;
110 border_and_orientation_msg.number_of_points= final_cluster_idx.size();
111 border_and_orientation_msg.directionX=directionStairs(0);
112 border_and_orientation_msg.directionY=directionStairs(1);
113 border_and_orientation_msg.directionZ=directionStairs(2);
128 Eigen::Vector3f stairs_position= 0.5*(base + point);
130 position_and_orientaion.header.frame_id=frameID;
131 position_and_orientaion.pose.position.x=stairs_position(0);
132 position_and_orientaion.pose.position.y=stairs_position(1);
133 position_and_orientaion.pose.position.z=stairs_position(2);
135 if(point(2) >=base(2)){
136 direction=point-base;
138 direction=base-point;
141 float stairs_yaw=
atan2(direction(1), direction(0));
142 float staris_pitch=
atan2(direction(1)*
sin(stairs_yaw)+direction(0)*
cos(stairs_yaw), direction(2))+M_PI_2;
145 position_and_orientaion.pose.orientation.x=temp.getX();
146 position_and_orientaion.pose.orientation.y=temp.getY();
147 position_and_orientaion.pose.orientation.z=temp.getZ();
148 position_and_orientaion.pose.orientation.w=temp.
getW();
151 void HectorStairDetection::getFinalStairsCloud_and_position(std::string frameID, Eigen::Vector3f directionS, pcl::PointCloud<pcl::PointNormal>::Ptr &input_surface_cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &planeCloud, pcl::IndicesClustersPtr cluster_indices, std::vector<int> final_cluster_idx,
152 pcl::PointCloud<pcl::PointXYZ>::Ptr &final_stairsCloud, visualization_msgs::MarkerArray &stairs_boarder_marker, Eigen::Vector3f base){
153 int cluster_counter=0;
155 float maxZ= -FLT_MAX;
158 final_stairsCloud->header.frame_id=frameID;
190 for (
int i = 0; i < cluster_indices->size (); ++i){
191 std::vector<int>::iterator idx_it;
193 idx_it = find (final_cluster_idx.begin(), final_cluster_idx.end(), cluster_counter);
194 if (idx_it != final_cluster_idx.end()){
195 for (
int j = 0; j < (*cluster_indices)[i].indices.size (); ++j){
197 tempP.x=input_surface_cloud->points[(*cluster_indices)[i].indices[j]].x;
198 tempP.y=input_surface_cloud->points[(*cluster_indices)[i].indices[j]].y;
199 tempP.z=input_surface_cloud->points[(*cluster_indices)[i].indices[j]].z;
200 final_stairsCloud->points.push_back(tempP);
213 cluster_counter=cluster_counter+1;
216 Eigen::Vector3f minStepAVG;
220 Eigen::Vector3f maxStepAVG;
226 for (
int j = 0; j < (*cluster_indices)[minZIndex].indices.size (); ++j){
227 minStepAVG(0)=minStepAVG(0)+input_surface_cloud->points[(*cluster_indices)[minZIndex].indices[j]].x;
228 minStepAVG(1)=minStepAVG(1)+input_surface_cloud->points[(*cluster_indices)[minZIndex].indices[j]].y;
229 minStepAVG(2)=minStepAVG(2)+input_surface_cloud->points[(*cluster_indices)[minZIndex].indices[j]].z;
232 minStepAVG=minStepAVG/(*cluster_indices)[minZIndex].indices.size ();
234 for (
int j = 0; j < (*cluster_indices)[maxZIndex].indices.size (); ++j){
235 maxStepAVG(0)=maxStepAVG(0)+input_surface_cloud->points[(*cluster_indices)[maxZIndex].indices[j]].x;
236 maxStepAVG(1)=maxStepAVG(1)+input_surface_cloud->points[(*cluster_indices)[maxZIndex].indices[j]].y;
237 maxStepAVG(2)=maxStepAVG(2)+input_surface_cloud->points[(*cluster_indices)[maxZIndex].indices[j]].z;
240 maxStepAVG=maxStepAVG/(*cluster_indices)[maxZIndex].indices.size ();
243 for(
int i=0; i<4; i++){
244 visualization_msgs::Marker marker;
245 marker.header.frame_id = frameID;
246 marker.type = visualization_msgs::Marker::SPHERE;
247 marker.action = visualization_msgs::Marker::ADD;
248 marker.ns =
"hector_stair_detection";
250 if((directionS(0)> 0 && directionS(1) >0) || (directionS(0)< 0 && directionS(1) <0)){
252 marker.pose.position.x = minStepAVG(0) - 0.5*
sin(
atan2(directionS(1), directionS(0)));
253 marker.pose.position.y = minStepAVG(1) + 0.5*
cos(
atan2(directionS(1), directionS(0)));
254 marker.pose.position.z=minStepAVG(2);
258 marker.pose.position.x = minStepAVG(0) + 0.5*
sin(
atan2(directionS(1), directionS(0)));
259 marker.pose.position.y = minStepAVG(1) - 0.5*
cos(
atan2(directionS(1), directionS(0)));
260 marker.pose.position.z=minStepAVG(2);
264 marker.pose.position.x = maxStepAVG(0) - 0.5*
sin(
atan2(directionS(1), directionS(0)));
265 marker.pose.position.y = maxStepAVG(1) + 0.5*
cos(
atan2(directionS(1), directionS(0)));
266 marker.pose.position.z=maxStepAVG(2);
270 marker.pose.position.x = maxStepAVG(0) + 0.5*
sin(
atan2(directionS(1), directionS(0)));
271 marker.pose.position.y = maxStepAVG(1) - 0.5*
cos(
atan2(directionS(1), directionS(0)));
272 marker.pose.position.z=maxStepAVG(2);
276 marker.pose.position.x = minStepAVG(0) + 0.5*
sin(
atan2(directionS(1), directionS(0)));
277 marker.pose.position.y = minStepAVG(1) + 0.5*
cos(
atan2(directionS(1), directionS(0)));
278 marker.pose.position.z=minStepAVG(2);
282 marker.pose.position.x = minStepAVG(0) - 0.5*
sin(
atan2(directionS(1), directionS(0)));
283 marker.pose.position.y = minStepAVG(1) - 0.5*
cos(
atan2(directionS(1), directionS(0)));
284 marker.pose.position.z=minStepAVG(2);
288 marker.pose.position.x = maxStepAVG(0) + 0.5*
sin(
atan2(directionS(1), directionS(0)));
289 marker.pose.position.y = maxStepAVG(1) + 0.5*
cos(
atan2(directionS(1), directionS(0)));
290 marker.pose.position.z=maxStepAVG(2);
294 marker.pose.position.x = maxStepAVG(0) - 0.5*
sin(
atan2(directionS(1), directionS(0)));
295 marker.pose.position.y = maxStepAVG(1) - 0.5*
cos(
atan2(directionS(1), directionS(0)));
296 marker.pose.position.z=maxStepAVG(2);
300 marker.pose.orientation.x = 0.0;
301 marker.pose.orientation.y = 0.0;
302 marker.pose.orientation.z = 0.0;
303 marker.pose.orientation.w = 1.0;
304 marker.scale.x = 0.2;
305 marker.scale.y = 0.2;
306 marker.scale.z = 0.2;
307 marker.color.a = 1.0;
308 marker.color.r = 0.0;
309 marker.color.g = 1.0;
310 marker.color.b = 0.0;
312 stairs_boarder_marker.markers.push_back(marker);
319 float first_step_z=0.05;
323 for(
int i=0; i<stairs_boarder_marker.markers.size(); i++){
324 if(stairs_boarder_marker.markers.at(i).pose.position.z <minZ){
325 minZ=stairs_boarder_marker.markers.at(i).pose.position.z;
331 for(
int i=0; i<stairs_boarder_marker.markers.size(); i++){
332 if(i != minPos1 && stairs_boarder_marker.markers.at(i).pose.position.z <minZ){
333 minZ=stairs_boarder_marker.markers.at(i).pose.position.z;
338 stairs_boarder_marker.markers.at(minPos1).pose.position.x=stairs_boarder_marker.markers.at(minPos1).pose.position.x+(first_step_z-stairs_boarder_marker.markers.at(minPos1).pose.position.z)/direction(2)*direction(0);
339 stairs_boarder_marker.markers.at(minPos1).pose.position.y=stairs_boarder_marker.markers.at(minPos1).pose.position.y+(first_step_z-stairs_boarder_marker.markers.at(minPos1).pose.position.z)/direction(2)*direction(1);
340 stairs_boarder_marker.markers.at(minPos1).pose.position.z=first_step_z;
341 stairs_boarder_marker.markers.at(minPos2).pose.position.x=stairs_boarder_marker.markers.at(minPos2).pose.position.x+(first_step_z-stairs_boarder_marker.markers.at(minPos2).pose.position.z)/direction(2)*direction(0);
342 stairs_boarder_marker.markers.at(minPos2).pose.position.y=stairs_boarder_marker.markers.at(minPos2).pose.position.y+(first_step_z-stairs_boarder_marker.markers.at(minPos2).pose.position.z)/direction(2)*direction(1);
343 stairs_boarder_marker.markers.at(minPos2).pose.position.z=first_step_z;
347 Eigen::Vector2f direction1;
348 Eigen::Vector2f direction2;
349 Eigen::Vector2f direction3;
350 Eigen::Vector2f direction4;
352 direction1=maxXminY-minXminY;
353 direction2=minXmaxY-minXminY;
354 direction3=minXminY-maxXminY;
355 direction4=minXminY-minXmaxY;
357 float angle1=
acos((directionStairs.dot(direction1))/(directionStairs.norm()*direction1.norm()));
358 float angle2=
acos((directionStairs.dot(direction2))/(directionStairs.norm()*direction2.norm()));
359 float angle3=
acos((directionStairs.dot(direction3))/(directionStairs.norm()*direction3.norm()));
360 float angle4=
acos((directionStairs.dot(direction4))/(directionStairs.norm()*direction4.norm()));
362 if(angle1>=angle2 && angle1>=angle3 && angle1>=angle4){
366 if(angle2>=angle1 && angle2>=angle3 && angle2>=angle4){
370 if(angle3>=angle2 && angle3>=angle1 && angle3>=angle4){
374 if(angle4>=angle2 && angle4>=angle3 && angle4>=angle1){
380 ROS_INFO(
"Hector Stair Detection get Surface");
381 pcl::PointCloud<pcl::PointXYZ>::Ptr processCloud_v1(
new pcl::PointCloud<pcl::PointXYZ>());
382 pcl::PointCloud<pcl::PointXYZ>::Ptr processCloud_v2(
new pcl::PointCloud<pcl::PointXYZ>());
386 pcl::PassThrough<pcl::PointXYZ> pass;
387 pass.setInputCloud(input_cloud);
388 pass.setFilterFieldName(
"z");
390 pass.filter(*processCloud_v1);
404 pcl::VoxelGrid<pcl::PointXYZ> vox;
405 vox.setInputCloud(processCloud_v1);
407 vox.setDownsampleAllData(
false);
408 vox.filter(*processCloud_v2);
412 pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls;
413 mls.setSearchRadius(0.05);
414 mls.setPolynomialOrder(1);
415 mls.setComputeNormals(
true);
416 mls.setInputCloud(processCloud_v2);
419 point_cloud_mls_normal.reset(
new pcl::PointCloud<pcl::PointNormal>);
420 mls.process(*point_cloud_mls_normal);
437 output_cloud->clear();
438 output_cloud->header.frame_id=input_cloud->header.frame_id;
440 output_cloud.reset(
new pcl::PointCloud<pcl::PointNormal>(*point_cloud_mls_normal));
443 std::vector<int> indices;
444 pcl::removeNaNFromPointCloud(*output_cloud,*output_cloud, indices);
445 pcl::removeNaNNormalsFromPointCloud(*output_cloud,*output_cloud, indices);
452 bool customRegionGrowing (
const pcl::PointNormal& point_a,
const pcl::PointNormal& point_b,
float squared_distance){
453 Eigen::Map<const Eigen::Vector3f> point_b_normal = point_b.normal;
455 Eigen::Vector3f d1(1,0,0);
456 Eigen::Vector3f
d2(0,1,0);
458 if(fabs(d1.dot(point_b_normal)) < 0.2 && fabs(d2.dot(point_b_normal)) < 0.2){
466 ROS_INFO(
"stairs position callback enterd");
467 pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
468 pcl::PCLPointCloud2 pcl_pc2;
470 pcl::fromPCLPointCloud2(pcl_pc2,*input_cloud);
478 time, transform_cloud_to_map);
481 ROS_ERROR(
"Lookup Transform failed: %s",ex.what());
489 pcl::transformPointCloud(*input_cloud, *cloud_tmp,
to_map_);
490 input_cloud = cloud_tmp;
491 input_cloud->header.frame_id= transform_cloud_to_map.
frame_id_;
496 pcl::PointCloud<pcl::PointNormal>::Ptr input_surface_cloud(
new pcl::PointCloud<pcl::PointNormal>);
497 pcl::PointCloud<pcl::PointXYZI>::Ptr possible_stairsCloud(
new pcl::PointCloud<pcl::PointXYZI>);
498 pcl::PointCloud<pcl::PointXYZI>::Ptr cluster_cloud_debug(
new pcl::PointCloud<pcl::PointXYZI>);
502 possible_stairsCloud->header.frame_id=input_surface_cloud->header.frame_id;
505 pcl::IndicesClustersPtr clusters (
new pcl::IndicesClusters);
506 pcl::ConditionalEuclideanClustering<pcl::PointNormal> cec (
false);
507 cec.setInputCloud (input_surface_cloud);
512 cec.segment (*clusters);
515 std::vector<Eigen::Vector3f> avg_point_per_cluster;
520 float max_x=-FLT_MAX;
522 float max_y=-FLT_MAX;
524 float max_z=-FLT_MAX;
528 int clusterCounter=0;
530 ROS_INFO(
"number cluster: %i", clusters->size ());
531 std::vector<int> cluster_idx_corresponding_to_avg_point;
532 for (
int i = 0; i < clusters->size (); ++i){
533 clusterSize= (*clusters)[i].indices.size ();
543 pcl::PointNormal point;
544 for (
int j = 0; j < (*clusters)[i].indices.size (); ++j){
545 point=input_surface_cloud->points[(*clusters)[i].indices[j]];
546 sum_x=sum_x + point.x;
547 sum_y=sum_y + point.y;
548 sum_z=sum_z + point.z;
570 clusterCounter=clusterCounter+1;
574 Eigen::Vector3f avg_point;
575 avg_point(0)=sum_x/clusterSize;
576 avg_point(1)=sum_y/clusterSize;
577 avg_point(2)=sum_z/clusterSize;
579 if(fabs(max_z-min_z)/2<clusterHeightTresh){
580 avg_point_per_cluster.push_back(avg_point);
581 cluster_idx_corresponding_to_avg_point.push_back(clusterCounter);
583 pcl::PointXYZI tempP;
584 tempP.x=avg_point(0);
585 tempP.y=avg_point(1);
586 tempP.z=avg_point(2);
587 tempP.intensity=clusterColor;
588 possible_stairsCloud->points.push_back(tempP);
589 cluster_cloud_debug->clear();
591 for (
int j = 0; j < (*clusters)[i].indices.size (); ++j){
592 pcl::PointXYZI tempP;
593 tempP.x=input_surface_cloud->points[(*clusters)[i].indices[j]].x;
594 tempP.y=input_surface_cloud->points[(*clusters)[i].indices[j]].y;
595 tempP.z=input_surface_cloud->points[(*clusters)[i].indices[j]].z;
596 tempP.intensity=clusterColor;
597 possible_stairsCloud->points.push_back(tempP);
598 cluster_cloud_debug->points.push_back(tempP);
600 clusterColor=clusterColor+1;
602 clusterCounter=clusterCounter+1;
608 ROS_INFO(
"number final cluster: %i", avg_point_per_cluster.size());
610 if(avg_point_per_cluster.size()>=2){
614 int pointsAtLineCounter=0;
616 Eigen::Vector3f direction;
617 Eigen::Vector3f base;
618 Eigen::Vector3f point;
619 std::vector<int> point_in_line_counter;
620 point_in_line_counter.resize(avg_point_per_cluster.size());
621 for(
int i=0; i< point_in_line_counter.size(); i++){
622 point_in_line_counter.at(i)=0;
626 int maxPointOnLineCounter=0;
629 pcl::PointCloud<pcl::PointXYZI>::Ptr debug_line_cloud(
new pcl::PointCloud<pcl::PointXYZI>());
630 if(avg_point_per_cluster.size() != 0){
631 for(
int i=0; i<avg_point_per_cluster.size()-1; i++){
632 for(
int j=i+1; j<avg_point_per_cluster.size(); j++){
633 debug_line_cloud->clear();
634 debug_line_cloud->header.frame_id=input_surface_cloud->header.frame_id;
636 base(0)= avg_point_per_cluster.at(i)(0);
637 base(1)= avg_point_per_cluster.at(i)(1);
638 base(2)= avg_point_per_cluster.at(i)(2);
640 direction(0)= avg_point_per_cluster.at(j)(0) - base(0);
641 direction(1)= avg_point_per_cluster.at(j)(1) - base(1);
642 direction(2)= avg_point_per_cluster.at(j)(2) - base(2);
644 pcl::PointXYZI pushbackPoint;
645 pushbackPoint.x=base(0);
646 pushbackPoint.y=base(1);
647 pushbackPoint.z=base(2);
648 pushbackPoint.intensity=10;
649 debug_line_cloud->push_back(pushbackPoint);
650 pushbackPoint.x=direction(0)+base(0);
651 pushbackPoint.y=direction(1)+base(1);
652 pushbackPoint.z=direction(2)+base(2);
653 pushbackPoint.intensity=10;
654 debug_line_cloud->push_back(pushbackPoint);
656 pointsAtLineCounter=0;
657 for(
int p=0; p<avg_point_per_cluster.size(); p++){
658 point(0)=avg_point_per_cluster.at(p)(0);
659 point(1)=avg_point_per_cluster.at(p)(1);
660 point(2)=avg_point_per_cluster.at(p)(2);
662 float tempA= std::sqrt(direction.cross(point-base).dot(direction.cross(point-base)));
663 float lengthDirection= std::sqrt(direction.dot(direction));
664 float distance= tempA/lengthDirection;
666 if(distance <= distanceToLineThreshold){
667 pointsAtLineCounter=pointsAtLineCounter+1;
668 pushbackPoint.x=point(0);
669 pushbackPoint.y=point(1);
670 pushbackPoint.z=point(2);
671 pushbackPoint.intensity=distance;
672 debug_line_cloud->push_back(pushbackPoint);
674 point_in_line_counter.at(p)=point_in_line_counter.at(p)+1;
678 if(pointsAtLineCounter >= maxPointOnLineCounter){
679 maxPointOnLineCounter=pointsAtLineCounter;
690 int iterationCounter=0;
693 maxPointOnLineCounter=0;
696 for(
int p=0; p<point_in_line_counter.size(); p++){
697 if(point_in_line_counter.at(p) > maxPointOnLineCounter){
698 maxPointOnLineCounter=point_in_line_counter.at(p);
699 best_pair_idx2=best_pair_idx1;
704 if(best_pair_idx1==-1 || best_pair_idx2==-1){
708 point_in_line_counter.at(best_pair_idx1)=0;
712 base=avg_point_per_cluster.at(best_pair_idx1);
714 direction(0)= avg_point_per_cluster.at(best_pair_idx2)(0) - base(0);
715 direction(1)= avg_point_per_cluster.at(best_pair_idx2)(1) - base(1);
716 direction(2)= avg_point_per_cluster.at(best_pair_idx2)(2) - base(2);
718 pcl::PointXYZI pushbackPoint;
719 debug_line_cloud->clear();
720 debug_line_cloud->header.frame_id=input_cloud->header.frame_id;
721 pushbackPoint.x=base(0);
722 pushbackPoint.y=base(1);
723 pushbackPoint.z=base(2);
725 debug_line_cloud->push_back(pushbackPoint);
726 pushbackPoint.x=avg_point_per_cluster.at(best_pair_idx2)(0);
727 pushbackPoint.y=avg_point_per_cluster.at(best_pair_idx2)(1);
728 pushbackPoint.z=avg_point_per_cluster.at(best_pair_idx2)(2);
730 debug_line_cloud->push_back(pushbackPoint);
732 pointsAtLineCounter=2;
733 std::vector<int> final_cluster_idx;
734 for(
int p=0; p<avg_point_per_cluster.size(); p++){
735 if(p==best_pair_idx1 || p== best_pair_idx2) {
736 final_cluster_idx.push_back(cluster_idx_corresponding_to_avg_point.at(p));
739 pushbackPoint.x=point(0)=avg_point_per_cluster.at(p)(0);
740 pushbackPoint.y=point(1)=avg_point_per_cluster.at(p)(1);
741 pushbackPoint.z=point(2)=avg_point_per_cluster.at(p)(2);
744 float tempA= std::sqrt(direction.cross(point-base).dot(direction.cross(point-base)));
745 float lengthDirection= std::sqrt(direction.dot(direction));
746 float distance= tempA/lengthDirection;
748 if(distance <= distanceToLineThreshold){
749 pointsAtLineCounter=pointsAtLineCounter+1;
750 final_cluster_idx.push_back(cluster_idx_corresponding_to_avg_point.at(p));
751 debug_line_cloud->push_back(pushbackPoint);
756 if(pointsAtLineCounter >= minCountPointsAtLine){
762 ROS_INFO(
"Staris; number points on line: %i", pointsAtLineCounter);
765 if(avg_point_per_cluster.at(best_pair_idx2)(2) >=base(2)){
766 dir=avg_point_per_cluster.at(best_pair_idx2)-base;
768 dir=base-avg_point_per_cluster.at(best_pair_idx2);
770 pcl::PointCloud<pcl::PointXYZ>::Ptr planeCloud(
new pcl::PointCloud<pcl::PointXYZ>());
773 publishResults(input_surface_cloud, planeCloud, clusters, final_cluster_idx, base, direction+base);
775 ROS_INFO(
"No stairs, distance between points to large, or heightDistance between point too small");
782 iterationCounter=iterationCounter+1;
785 ROS_INFO(
"No more possible stairs");
789 void HectorStairDetection::stairsSreachPlaneDetection(pcl::PointCloud<pcl::PointNormal>::Ptr &input_surface_cloud, pcl::PointCloud<pcl::PointXYZI>::Ptr points_on_line, Eigen::Vector3f base, Eigen::Vector3f dir, pcl::PointCloud<pcl::PointXYZ>::Ptr &planeCloud){
792 Eigen::Vector3f temp=dir.cross(Eigen::Vector3f(0,0,1));
793 Eigen::Vector3f searchAxes=dir.cross(temp);
794 searchAxes=searchAxes/searchAxes.squaredNorm();
796 visualization_msgs::Marker line_list;
799 line_list.type = visualization_msgs::Marker::LINE_LIST;
800 line_list.scale.x = 0.1;
801 line_list.color.r = 1.0;
802 line_list.color.a = 1.0;
804 geometry_msgs::Point p;
809 line_list.points.push_back(p);
810 p.x = base(0) + searchAxes(0);
811 p.y = base(1) + searchAxes(1);
812 p.z = base(2) + searchAxes(2);
813 line_list.points.push_back(p);
817 pcl::PointCloud<pcl::PointXYZ>::Ptr searchCloud(
new pcl::PointCloud<pcl::PointXYZ>());
818 searchCloud->resize(input_surface_cloud->size());
820 for (
size_t i = 0; i < input_surface_cloud->points.size(); ++i)
822 const pcl::PointNormal &mls_pt = input_surface_cloud->points[i];
823 pcl::PointXYZ pt(mls_pt.x, mls_pt.y, mls_pt.z);
824 searchCloud->push_back(pt);
828 Eigen::Vector2f xAxes;
831 Eigen::Vector2f dir2f;
834 float angleXToStairs=
acos((dir2f.dot(xAxes))/(dir2f.norm()*xAxes.norm()));
836 pcl::PointCloud<pcl::PointXYZ>::Ptr processCloud_v1(
new pcl::PointCloud<pcl::PointXYZ>());
837 pcl::PointCloud<pcl::PointXYZ>::Ptr processCloud_v2(
new pcl::PointCloud<pcl::PointXYZ>());
838 pcl::PassThrough<pcl::PointXYZ> pass;
839 pass.setInputCloud(searchCloud);
840 pass.setFilterFieldName(
"z");
842 pass.filter(*processCloud_v1);
844 pass.setInputCloud(processCloud_v1);
845 pass.setFilterFieldName(
"y");
847 pass.filter(*processCloud_v2);
849 pass.setInputCloud(processCloud_v2);
850 pass.setFilterFieldName(
"x");
852 pass.filter(*searchCloud);
857 pcl::ModelCoefficients::Ptr coefficients (
new pcl::ModelCoefficients);
858 pcl::PointIndices::Ptr inliers (
new pcl::PointIndices);
860 pcl::SACSegmentation<pcl::PointXYZ> seg;
861 seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
862 seg.setMethodType (pcl::SAC_RANSAC);
864 seg.setAxis(searchAxes);
867 seg.setInputCloud (searchCloud);
868 seg.segment (*inliers, *coefficients);
870 if (inliers->indices.size () == 0)
872 PCL_ERROR (
"Could not estimate more planar models for the given dataset.");
875 ROS_DEBUG(
"extract plane and rest potins");
876 pcl::ExtractIndices<pcl::PointXYZ> extract;
877 extract.setInputCloud (searchCloud);
878 extract.setIndices (inliers);
879 extract.setNegative(
false);
880 extract.filter (*planeCloud);
884 Eigen::Vector3f normal;
885 normal(0)=coefficients->values[0];
886 normal(1)=coefficients->values[1];
887 normal(2)=coefficients->values[2];
889 Eigen::Vector3f point;
892 point(2)=-(coefficients->values[3]/coefficients->values[2]);
894 Eigen::Vector3f normal_0;
895 normal_0= normal/normal.squaredNorm();
897 float d_hesse= point.dot(normal_0);
899 bool isPossiblePlane=
true;
900 Eigen::Vector3f stairs_point;
901 for(
int i=0; i<points_on_line->size(); i++){
902 stairs_point(0)=points_on_line->at(i).x;
903 stairs_point(1)=points_on_line->at(i).y;
904 stairs_point(2)=points_on_line->at(i).z;
906 if(fabs(stairs_point.dot(normal_0)-d_hesse) >
hesseTresh_){
907 isPossiblePlane=
false;
916 planeCloud->resize(0);
923 for(
int i=0; i<input_cloud->size(); i++){
924 for(
int j=i; j<input_cloud->size(); j++){
925 temp_dist= std::sqrt(std::pow(input_cloud->at(i).x-input_cloud->at(j).x, 2)+std::pow(input_cloud->at(i).y-input_cloud->at(j).y, 2)+std::pow(input_cloud->at(i).z-input_cloud->at(j).z, 2));
926 if(temp_dist>max_dist){
935 float min_dist=FLT_MAX;
937 for(
int i=0; i<input_cloud->size(); i++){
938 for(
int j=i+1; j<input_cloud->size(); j++){
939 temp_dist= fabs(input_cloud->at(i).z-input_cloud->at(j).z);
940 if(temp_dist<min_dist){
void getStairsPositionAndOrientation(Eigen::Vector3f &base, Eigen::Vector3f point, std::string frameID, Eigen::Vector3f &direction, geometry_msgs::PoseStamped &position_and_orientaion)
ros::Publisher line_marker_pub_
ros::Publisher final_stairs_cloud_pub_
virtual ~HectorStairDetection()
ros::Publisher border_of_stairs_pub_
void publish(const boost::shared_ptr< M > &message) const
void transformTFToEigen(const tf::Transform &t, Eigen::Affine3d &e)
ros::Publisher temp_orginal_pub_
void projectStairsToFloor(Eigen::Vector3f direction, visualization_msgs::MarkerArray &stairs_boarder_marker)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Publisher cloud_after_plane_detection_debug_pub_
void stairsSreachPlaneDetection(pcl::PointCloud< pcl::PointNormal >::Ptr &input_surface_cloud, pcl::PointCloud< pcl::PointXYZI >::Ptr points_on_line, Eigen::Vector3f base, Eigen::Vector3f dir, pcl::PointCloud< pcl::PointXYZ >::Ptr &planeCloud)
tf::TransformListener listener_
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
double maxClusterXYDimension_
TFSIMD_FORCE_INLINE const tfScalar & getW() const
bool refineSurfaceRequired_
int minRequiredPointsOnLine_
void getPreprocessedCloud(pcl::PointCloud< pcl::PointXYZ >::Ptr &input_cloud, pcl::PointCloud< pcl::PointNormal >::Ptr &output_cloud)
ros::Publisher stairs_position_and_orientaion_with_direction_pub_
ros::Publisher possible_stairs_cloud_pub_
double planeSegDistTresh_
ros::Publisher surfaceCloud_pub_debug_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
float maxDistBetweenPoints(pcl::PointCloud< pcl::PointXYZI >::Ptr input_cloud)
double maxDistBetweenStairsPoints_
ros::Publisher points_on_line_cloud_debug_
void setEulerZYX(const tfScalar &yaw, const tfScalar &pitch, const tfScalar &roll) __attribute__((deprecated))
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double clusterHeightTresh_
int getZComponent(Eigen::Vector2f directionStairs, Eigen::Vector2f minXminY, Eigen::Vector2f maxXminY, Eigen::Vector2f minXmaxY)
void PclCallback(const sensor_msgs::PointCloud2::ConstPtr &pc_msg)
uint32_t getNumSubscribers() const
INLINE Rall1d< T, V, S > acos(const Rall1d< T, V, S > &x)
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
float minHightDistBetweenPoints(pcl::PointCloud< pcl::PointXYZI >::Ptr input_cloud)
ros::Publisher temp_after_pass_trough_pub_
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
bool customRegionGrowing(const pcl::PointNormal &point_a, const pcl::PointNormal &point_b, float squared_distance)
void getFinalStairsCloud_and_position(std::string frameID, Eigen::Vector3f directionS, pcl::PointCloud< pcl::PointNormal >::Ptr &input_surface_cloud, pcl::PointCloud< pcl::PointXYZ >::Ptr &planeCloud, pcl::IndicesClustersPtr cluster_indices, std::vector< int > final_cluster_idx, pcl::PointCloud< pcl::PointXYZ >::Ptr &final_stairsCloud, visualization_msgs::MarkerArray &stairs_boarder_marker, Eigen::Vector3f base)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
ros::Publisher stairs_position_and_orientaion_pub_
ros::Publisher border_and_orientation_stairs_combined_pub_
ros::Publisher temp_after_voxel_grid_pub_
void toPCL(const ros::Time &stamp, pcl::uint64_t &pcl_stamp)
ros::Publisher temp_after_mls_pub_
void publishResults(pcl::PointCloud< pcl::PointNormal >::Ptr &input_surface_cloud, pcl::PointCloud< pcl::PointXYZ >::Ptr &planeCloud, pcl::IndicesClustersPtr cluster_indices, std::vector< int > final_cluster_idx, Eigen::Vector3f base, Eigen::Vector3f point)
double minHightDistBetweenAllStairsPoints_
double distanceToLineTresh_