hector_stair_detection.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
3 
4 namespace hector_stair_detection{
6  ROS_INFO ("HectorStairDetection started");
7  ros::NodeHandle nh("");
8 
9  //load params
10  nh.param("passThroughZMin", passThroughZMin_, 0.1);
11  nh.param("passThroughZMax", passThroughZMax_, 2.5);
12  nh.param("voxelGridX", voxelGridX_, 0.04);
13  nh.param("voxelGridY", voxelGridY_, 0.04);
14  nh.param("voxelGridZ", voxelGridZ_, 0.04);
15  nh.param("minRequiredPointsOnLine", minRequiredPointsOnLine_, 3);
16  nh.param("distanceToLineTresh", distanceToLineTresh_, 0.1);
17  nh.param("refineSurfaceRequired", refineSurfaceRequired_, false);
18  nh.param("worldFrame", worldFrame_, std::string("/world")); //has to be true in hector-setup
19  nh.param("culsterHeightTresh", clusterHeightTresh_, 0.1);
20  nh.param("clusterTolerance", clusterTolerance_, 0.075);
21  nh.param("clusterMinSize", clusterMinSize_, 50);
22  nh.param("clusterMaxSize", clusterMaxSize_, 200);
23  nh.param("setup", setup_, std::string("argo"));
24  nh.param("maxClusterXYDimension", maxClusterXYDimension_, 1.0);
25  nh.param("minHightDistBetweenAllStairsPoints", minHightDistBetweenAllStairsPoints_, 0.2);
26  nh.param("maxDistBetweenStairsPoints", maxDistBetweenStairsPoints_, 3.0);
27  nh.param("planeSegDistTresh", planeSegDistTresh_, 0.01);
28  nh.param("planeSegAngleEps", planeSegAngleEps_, 0.1);
29  nh.param("hesseTresh", hesseTresh_, 0.1);
30 
31  possible_stairs_cloud_pub_= nh.advertise<pcl::PointCloud<pcl::PointXYZI> >("/hector_stair_detection/possible_stairs_cloud", 100, true);
32  points_on_line_cloud_debug_= nh.advertise<pcl::PointCloud<pcl::PointXYZI> >("/hector_stair_detection/point_on_line_debug", 100, true);
33  surfaceCloud_pub_debug_= nh.advertise<pcl::PointCloud<pcl::PointXYZ> >("/hector_stair_detection/surfaceCloud_debug", 100, true);
34  final_stairs_cloud_pub_= nh.advertise<pcl::PointCloud<pcl::PointXYZ> >("/hector_stair_detection/final_stairs_cloud", 100, true);
35  border_of_stairs_pub_= nh.advertise<visualization_msgs::MarkerArray>("/hector_stair_detection/boarder_of_stairs", 100, true);
36  stairs_position_and_orientaion_pub_= nh.advertise<geometry_msgs::PoseStamped>("/hector_stair_detection/stairs_orientation", 100, true);
37  stairs_position_and_orientaion_with_direction_pub_= nh.advertise<hector_stair_detection_msgs::PositionAndOrientaion>("/hector_stair_detection/stairs_orientaion_as_vector", 100, true);
38  border_and_orientation_stairs_combined_pub_= nh.advertise<hector_stair_detection_msgs::BorderAndOrientationOfStairs>("/hector_stair_detection/border_and_orientation_of_stairs", 100, true);
39  cloud_after_plane_detection_debug_pub_= nh.advertise<pcl::PointCloud<pcl::PointXYZ> >("/hector_stair_detection/cloud_after_plane_detection_debug_", 100, true);
40  line_marker_pub_= nh.advertise<visualization_msgs::Marker>("/hector_stair_detection/stairs_normal", 100, true);
41 
42  temp_orginal_pub_=nh.advertise<pcl::PointCloud<pcl::PointXYZ> >("/hector_stair_detection/temp_original", 100, true);
43  temp_after_pass_trough_pub_=nh.advertise<pcl::PointCloud<pcl::PointXYZ> >("/hector_stair_detection/temp_after_pass_trough", 100, true);
44  temp_after_voxel_grid_pub_=nh.advertise<pcl::PointCloud<pcl::PointXYZ> >("/hector_stair_detection/temp_after_voxel_grid", 100, true);
45  temp_after_mls_pub_=nh.advertise<pcl::PointCloud<pcl::PointNormal> >("/hector_stair_detection/temp_after_mls", 100, true);
46 
47 
48 
49  if(setup_.compare(std::string("argo"))==0){
50  //TODO:: get pointcloud from Service
51  // pointcloud_srv_client_ = nh.serviceClient<vigir_perception_msgs::PointCloudRegionRequest>("/flor/worldmodel/pointcloud_roi");
52  // vigir_perception_msgs::PointCloudRegionRequest srv;
53  // vigir_perception_msgs::EnvironmentRegionRequest erreq;
54  // erreq.header=worldFrame_;
55  // erreq.bounding_box_max.x=;
56  // erreq.bounding_box_max.y=;
57  // erreq.bounding_box_max.z=passThroughZMax_;
58  // erreq.bounding_box_min.x=;
59  // erreq.bounding_box_min.y=;
60  // erreq.bounding_box_min.z=passThroughZMin_;
61  // erreq.resolution=voxelGridX_;
62  // erreq.request_augment=0;
63  // srv.request.region_req=erreq;
64  // srv.request.aggregation_size=500;
65  // if(!pointcloud_srv_client_.call(srv)){
66  // ROS_ERROR("/flor/worldmodel/pointcloud_roi is not working");
67  // }else{
68  // sensor_msgs::PointCloud2 pointCloud_world;
69  // pointCloud_world=srv.response.cloud;
70  pcl_sub = nh.subscribe("/worldmodel_main/pointcloud_vis", 10, &HectorStairDetection::PclCallback, this);
71  }else{
72  // pcl_sub = nh.subscribe("/openni/depth/points", 1, &HectorStairDetection::PclCallback, this);
73  // pcl_sub = nh.subscribe("/hector_octomap_server/octomap_point_cloud_centers", 1, &HectorStairDetection::PclCallback, this);
74  pcl_sub = nh.subscribe("/hector_aggregate_cloud/aggregated_cloud", 1, &HectorStairDetection::PclCallback, this);
75  }
76 
77 }
78 
80 {}
81 
82 void HectorStairDetection::publishResults(pcl::PointCloud<pcl::PointNormal>::Ptr &input_surface_cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &planeCloud,
83  pcl::IndicesClustersPtr cluster_indices, std::vector<int> final_cluster_idx, Eigen::Vector3f base, Eigen::Vector3f point){
84 
85  geometry_msgs::PoseStamped position_and_orientaion;
86  Eigen::Vector3f directionStairs;
87  getStairsPositionAndOrientation(base, point, input_surface_cloud->header.frame_id, directionStairs, position_and_orientaion);
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);
93 
94  //compute and pubish max and min boarder of the stairs
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);
98 
100  final_stairs_cloud_pub_.publish(final_stairsCloud);
101  }
103  border_of_stairs_pub_.publish(stairs_boarder_marker);
104  }
105 
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);
114 
116  border_and_orientation_stairs_combined_pub_.publish(border_and_orientation_msg);
117  }
118 
121  }
123  stairs_position_and_orientaion_pub_.publish(position_and_orientaion);
124  }
125 }
126 
127 void HectorStairDetection::getStairsPositionAndOrientation(Eigen::Vector3f &base, Eigen::Vector3f point, std::string frameID, Eigen::Vector3f &direction, geometry_msgs::PoseStamped &position_and_orientaion){
128  Eigen::Vector3f stairs_position= 0.5*(base + point);
129 
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);
134 
135  if(point(2) >=base(2)){
136  direction=point-base;
137  }else{
138  direction=base-point;
139  base=point;
140  }
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;
143  tf::Quaternion temp;
144  temp.setEulerZYX(stairs_yaw,staris_pitch,0.0);
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();
149 }
150 
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;
154  float minZ= FLT_MAX;
155  float maxZ= -FLT_MAX;
156  int minZIndex=-1;
157  int maxZIndex=-1;
158  final_stairsCloud->header.frame_id=frameID;
159 // make use of the plane cloud
160 // if(planeCloud->size() !=0){
161 // Eigen::Vector3f orthogonalDir=directionS.cross(Eigen::Vector3f(0,0,1));
162 // Eigen::Vector3f point;
163 // pcl::PointCloud<pcl::PointXYZ>::Ptr testCloud(new pcl::PointCloud<pcl::PointXYZ>());
164 // testCloud->header.frame_id=frameID;
165 // for(int i=0; i<planeCloud->size(); i++){
166 // point(0)=planeCloud->points.at(i).x;
167 // point(1)=planeCloud->points.at(i).y;
168 // point(2)=planeCloud->points.at(i).z;
169 // //TODO:: check angle
171 // float angle=acos((orthogonalDir.dot(point-base))/(orthogonalDir.norm()*(point-base).norm()));
172 
173 // ROS_INFO("ange: %f", angle);
174 // if(angle < M_PI_2){
175 // testCloud->push_back(planeCloud->points.at(i));
176 // }
177 
178 // //compute distance
179 // float tempA= std::sqrt(directionS.cross(point-base).dot(directionS.cross(point-base)));
180 // float lengthDirection= std::sqrt(directionS.dot(directionS));
181 // float distance= tempA/lengthDirection;
182 
183 // //save max depening on sign
184 
185 
186 // }
187 // cloud_after_plane_detection_debug_pub_.publish(testCloud);
188 // }
189 
190  for (int i = 0; i < cluster_indices->size (); ++i){
191  std::vector<int>::iterator idx_it;
192 
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){
196  pcl::PointXYZ tempP;
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);
201 
202  if(tempP.z < minZ){
203  minZ=tempP.z;
204  minZIndex=i;
205  }
206 
207  if(tempP.z > maxZ){
208  maxZ=tempP.z;
209  maxZIndex=i;
210  }
211  }
212  }
213  cluster_counter=cluster_counter+1;
214  }
215 
216  Eigen::Vector3f minStepAVG;
217  minStepAVG(0)=0;
218  minStepAVG(1)=0;
219  minStepAVG(2)=0;
220  Eigen::Vector3f maxStepAVG;
221  maxStepAVG(0)=0;
222  maxStepAVG(1)=0;
223  maxStepAVG(2)=0;
224 
225 
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;
230  }
231 
232  minStepAVG=minStepAVG/(*cluster_indices)[minZIndex].indices.size ();
233 
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;
238  }
239 
240  maxStepAVG=maxStepAVG/(*cluster_indices)[maxZIndex].indices.size ();
241 
242 
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";
249  marker.id = i;
250  if((directionS(0)> 0 && directionS(1) >0) || (directionS(0)< 0 && directionS(1) <0)){
251  if(i==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);
255  }
256 
257  if(i==1){
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);
261  }
262 
263  if(i==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);
267  }
268 
269  if(i==3){
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);
273  }
274  }else{
275  if(i==0){
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);
279  }
280 
281  if(i==1){
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);
285  }
286 
287  if(i==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);
291  }
292 
293  if(i==3){
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);
297  }
298  }
299 
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;
311 
312  stairs_boarder_marker.markers.push_back(marker);
313 
314  }
315  projectStairsToFloor(directionS, stairs_boarder_marker);
316 }
317 
318 void HectorStairDetection::projectStairsToFloor(Eigen::Vector3f direction, visualization_msgs::MarkerArray &stairs_boarder_marker){
319  float first_step_z=0.05;
320  float minZ= FLT_MAX;
321  int minPos1;
322  int minPos2;
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;
326  minPos1=i;
327  }
328  }
329 
330  minZ= FLT_MAX;
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;
334  minPos2=i;
335  }
336  }
337 
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;
344 }
345 
346 int HectorStairDetection::getZComponent(Eigen::Vector2f directionStairs, Eigen::Vector2f minXminY, Eigen::Vector2f maxXminY, Eigen::Vector2f minXmaxY){
347  Eigen::Vector2f direction1;
348  Eigen::Vector2f direction2;
349  Eigen::Vector2f direction3;
350  Eigen::Vector2f direction4;
351 
352  direction1=maxXminY-minXminY;
353  direction2=minXmaxY-minXminY;
354  direction3=minXminY-maxXminY;
355  direction4=minXminY-minXmaxY;
356 
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()));
361 
362  if(angle1>=angle2 && angle1>=angle3 && angle1>=angle4){
363  return 1;
364  }
365 
366  if(angle2>=angle1 && angle2>=angle3 && angle2>=angle4){
367  return 2;
368  }
369 
370  if(angle3>=angle2 && angle3>=angle1 && angle3>=angle4){
371  return 3;
372  }
373 
374  if(angle4>=angle2 && angle4>=angle3 && angle4>=angle1){
375  return 4;
376  }
377 }
378 
379 void HectorStairDetection::getPreprocessedCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr &input_cloud, pcl::PointCloud<pcl::PointNormal>::Ptr &output_cloud){
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>());
383 
384  temp_orginal_pub_.publish(input_cloud);
385 
386  pcl::PassThrough<pcl::PointXYZ> pass;
387  pass.setInputCloud(input_cloud);
388  pass.setFilterFieldName("z");
389  pass.setFilterLimits(passThroughZMin_, passThroughZMax_);
390  pass.filter(*processCloud_v1);
391 
392 // pass.setInputCloud(processCloud_v1);
393 // pass.setFilterFieldName("y");
394 // pass.setFilterLimits(-1.0, 1.0);
395 // pass.filter(*processCloud_v1);
396 
397 // pass.setInputCloud(processCloud_v1);
398 // pass.setFilterFieldName("x");
399 // pass.setFilterLimits(0.0, 3.5);
400 // pass.filter(*processCloud_v1);
401 
402  temp_after_pass_trough_pub_.publish(processCloud_v1);
403 
404  pcl::VoxelGrid<pcl::PointXYZ> vox;
405  vox.setInputCloud(processCloud_v1);
406  vox.setLeafSize(voxelGridX_, voxelGridY_, voxelGridZ_);
407  vox.setDownsampleAllData(false);
408  vox.filter(*processCloud_v2);
409 
410  temp_after_voxel_grid_pub_.publish(processCloud_v2);
411 
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);
417 
419  point_cloud_mls_normal.reset(new pcl::PointCloud<pcl::PointNormal>);
420  mls.process(*point_cloud_mls_normal);
421 
422  temp_after_mls_pub_.publish(point_cloud_mls_normal);
423 
424  // pcl::NormalEstimation<pcl::PointXYZ, pcl::PointNormal> ne;
425  // ne.setInputCloud (processCloud_v2);
426  // pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
427  // ne.setSearchMethod (tree);
428  // // Output datasets
429  // pcl::PointCloud<pcl::PointNormal>::Ptr point_cloud_mls_normal (new pcl::PointCloud<pcl::PointNormal>);
430  // // Use all neighbors in a sphere of radius 3cm
431  // ne.setRadiusSearch (0.03);
432  // // Compute the features
433  // ne.compute (*point_cloud_mls_normal);
434 
435  // temp_after_mls_pub_.publish(point_cloud_mls_normal);
436 
437  output_cloud->clear();
438  output_cloud->header.frame_id=input_cloud->header.frame_id;
439 
440  output_cloud.reset(new pcl::PointCloud<pcl::PointNormal>(*point_cloud_mls_normal));
441 
442 
443  std::vector<int> indices;
444  pcl::removeNaNFromPointCloud(*output_cloud,*output_cloud, indices);
445  pcl::removeNaNNormalsFromPointCloud(*output_cloud,*output_cloud, indices);
446 
448  surfaceCloud_pub_debug_.publish(output_cloud);
449  }
450 }
451 
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;
454 
455  Eigen::Vector3f d1(1,0,0);
456  Eigen::Vector3f d2(0,1,0);
457 
458  if(fabs(d1.dot(point_b_normal)) < 0.2 && fabs(d2.dot(point_b_normal)) < 0.2){
459  return true;
460  }
461  return false;
462 }
463 
464 
465 void HectorStairDetection::PclCallback(const sensor_msgs::PointCloud2::ConstPtr& pc_msg){
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;
469  pcl_conversions::toPCL(*pc_msg,pcl_pc2);
470  pcl::fromPCLPointCloud2(pcl_pc2,*input_cloud);
471  //transform cloud to /world
472  tf::StampedTransform transform_cloud_to_map;
473  try{
474  ros::Time time = pc_msg->header.stamp;
475  listener_.waitForTransform(worldFrame_, pc_msg->header.frame_id,
476  time, ros::Duration(3.0));
477  listener_.lookupTransform(worldFrame_, pc_msg->header.frame_id,
478  time, transform_cloud_to_map);
479  }
480  catch (tf::TransformException ex){
481  ROS_ERROR("Lookup Transform failed: %s",ex.what());
482  return;
483  }
484 
485  tf::transformTFToEigen(transform_cloud_to_map, to_map_);
486 
487  // Transform to /world
488  boost::shared_ptr<pcl::PointCloud<pcl::PointXYZ> > cloud_tmp(new pcl::PointCloud<pcl::PointXYZ>);
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_;
492 
493  float clusterHeightTresh=clusterHeightTresh_;
494 
495  //try find planes with pcl::segmentation
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>);
499 
500  this->getPreprocessedCloud(input_cloud, input_surface_cloud);
501 
502  possible_stairsCloud->header.frame_id=input_surface_cloud->header.frame_id;
503 
504  // try conditional clustering
505  pcl::IndicesClustersPtr clusters (new pcl::IndicesClusters);
506  pcl::ConditionalEuclideanClustering<pcl::PointNormal> cec (false);
507  cec.setInputCloud (input_surface_cloud);
508  cec.setConditionFunction (&customRegionGrowing);
509  cec.setClusterTolerance (clusterTolerance_);
510  cec.setMinClusterSize (clusterMinSize_);
511  cec.setMaxClusterSize (clusterMaxSize_);
512  cec.segment (*clusters);
513 
514  //Clustering
515  std::vector<Eigen::Vector3f> avg_point_per_cluster;
516  float sum_x;
517  float sum_y;
518  float sum_z;
519  float min_x=FLT_MAX;
520  float max_x=-FLT_MAX;
521  float min_y=FLT_MAX;
522  float max_y=-FLT_MAX;
523  float min_z=FLT_MAX;
524  float max_z=-FLT_MAX;
525  int clusterSize;
526 
527  int clusterColor=0;
528  int clusterCounter=0;
529 
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 ();
534  sum_x=0;
535  sum_y=0;
536  sum_z=0;
537  min_x=FLT_MAX;
538  max_x=-FLT_MAX;
539  min_y=FLT_MAX;
540  max_y=-FLT_MAX;
541  min_z=FLT_MAX;
542  max_z=-FLT_MAX;
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;
549  if(min_x > point.x){
550  min_x=point.x;
551  }
552  if(max_x < point.x){
553  max_x=point.x;
554  }
555  if(min_y > point.y){
556  min_y=point.y;
557  }
558  if(max_y < point.y){
559  max_y=point.y;
560  }
561  if(min_z > point.z){
562  min_z=point.z;
563  }
564  if(max_z < point.z){
565  max_z=point.z;
566  }
567  }
568 
569  if(fabs(max_x-min_x)>maxClusterXYDimension_ || fabs(max_y-min_y)>maxClusterXYDimension_){
570  clusterCounter=clusterCounter+1;
571  continue;
572  }
573 
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;
578 
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);
582 
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();
590  cluster_cloud_debug->header.frame_id=worldFrame_;
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);
599  }
600  clusterColor=clusterColor+1;
601  }
602  clusterCounter=clusterCounter+1;
603  }
604 
606  possible_stairs_cloud_pub_.publish(possible_stairsCloud);
607  }
608  ROS_INFO("number final cluster: %i", avg_point_per_cluster.size());
609 
610  if(avg_point_per_cluster.size()>=2){
611 
612  //jeder punkt mit jedem Grade bilden und Abstände berechnen
613  int minCountPointsAtLine=minRequiredPointsOnLine_; //number points to stay at line
614  int pointsAtLineCounter=0;
615  float distanceToLineThreshold=distanceToLineTresh_;
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;
623  }
624 
625 
626  int maxPointOnLineCounter=0;
627  int best_pair_idx1;
628  int best_pair_idx2;
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;
635 
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);
639 
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);
643 
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);
655 
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);
661 
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;
665 
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);
673 
674  point_in_line_counter.at(p)=point_in_line_counter.at(p)+1;
675  }
676  }
677 
678  if(pointsAtLineCounter >= maxPointOnLineCounter){
679  maxPointOnLineCounter=pointsAtLineCounter;
680  best_pair_idx1=i;
681  best_pair_idx2=j;
682  }
683 
684 
685 
686  }
687  }
688  }
689 
690  int iterationCounter=0;
691  while(1){
692  //get best pair index depending on iteration
693  maxPointOnLineCounter=0;
694  best_pair_idx1=-1;
695  best_pair_idx2=-1;
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;
700  best_pair_idx1=p;
701  }
702  }
703 
704  if(best_pair_idx1==-1 || best_pair_idx2==-1){
705  break;
706  }
707 
708  point_in_line_counter.at(best_pair_idx1)=0;
709 
710  //construct line form most used points, middel is the position of the stairs
711 
712  base=avg_point_per_cluster.at(best_pair_idx1);
713 
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);
717 
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);
724 
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);
729 
730  debug_line_cloud->push_back(pushbackPoint);
731 
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));
737  continue;
738  }
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);
742 
743 
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;
747 
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);
752 
753  }
754  }
755  points_on_line_cloud_debug_.publish(debug_line_cloud);
756  if(pointsAtLineCounter >= minCountPointsAtLine){
757  //publish results
759  points_on_line_cloud_debug_.publish(debug_line_cloud);
760  }
762  ROS_INFO("Staris; number points on line: %i", pointsAtLineCounter);
763 
764  Eigen::Vector3f dir;
765  if(avg_point_per_cluster.at(best_pair_idx2)(2) >=base(2)){
766  dir=avg_point_per_cluster.at(best_pair_idx2)-base;
767  }else{
768  dir=base-avg_point_per_cluster.at(best_pair_idx2);
769  }
770  pcl::PointCloud<pcl::PointXYZ>::Ptr planeCloud(new pcl::PointCloud<pcl::PointXYZ>());
771  //is not needed while detecting stairs on unfilterd scancloud
772 // stairsSreachPlaneDetection(input_surface_cloud, debug_line_cloud, base, dir, planeCloud);
773  publishResults(input_surface_cloud, planeCloud, clusters, final_cluster_idx, base, direction+base);
774  }else{
775  ROS_INFO("No stairs, distance between points to large, or heightDistance between point too small");
776  }
777 
778  }else{
779  ROS_INFO("No stairs");
780  }
781 // sleep(2);
782  iterationCounter=iterationCounter+1;
783  }
784  }
785  ROS_INFO("No more possible stairs");
786 
787 }
788 
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){
790  ROS_INFO("run plane segmentation");
791 
792  Eigen::Vector3f temp=dir.cross(Eigen::Vector3f(0,0,1));
793  Eigen::Vector3f searchAxes=dir.cross(temp);
794  searchAxes=searchAxes/searchAxes.squaredNorm();
795 
796  visualization_msgs::Marker line_list;
797  line_list.header.frame_id=worldFrame_;
798  line_list.id = 42;
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;
803 
804  geometry_msgs::Point p;
805  p.x = base(0);
806  p.y = base(1);
807  p.z = base(2);
808 
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);
814 
815  line_marker_pub_.publish(line_list);
816 
817  pcl::PointCloud<pcl::PointXYZ>::Ptr searchCloud(new pcl::PointCloud<pcl::PointXYZ>());
818  searchCloud->resize(input_surface_cloud->size());
819  searchCloud->header.frame_id=worldFrame_;
820  for (size_t i = 0; i < input_surface_cloud->points.size(); ++i)
821  {
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);
825  }
826 
827  //search just in stairs environment
828  Eigen::Vector2f xAxes;
829  xAxes(0)=1;
830  xAxes(1)=0;
831  Eigen::Vector2f dir2f;
832  dir2f(0)=dir(0);
833  dir2f(1)=dir(1);
834  float angleXToStairs=acos((dir2f.dot(xAxes))/(dir2f.norm()*xAxes.norm()));
835 
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");
841  pass.setFilterLimits(0.2, passThroughZMax_);
842  pass.filter(*processCloud_v1);
843 
844  pass.setInputCloud(processCloud_v1);
845  pass.setFilterFieldName("y");
846  pass.setFilterLimits(base(1)-fabs(sin(angleXToStairs)*maxDistBetweenStairsPoints_)-maxClusterXYDimension_/2, base(1)+fabs(sin(angleXToStairs)*maxDistBetweenStairsPoints_)+maxClusterXYDimension_/2);
847  pass.filter(*processCloud_v2);
848 
849  pass.setInputCloud(processCloud_v2);
850  pass.setFilterFieldName("x");
851  pass.setFilterLimits(base(0)-fabs(cos(angleXToStairs)*maxDistBetweenStairsPoints_)-maxClusterXYDimension_/2, base(0)+fabs(cos(angleXToStairs)*maxDistBetweenStairsPoints_)+maxClusterXYDimension_/2);
852  pass.filter(*searchCloud);
853 
855 
856  planeCloud->header.frame_id=worldFrame_;
857  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
858  pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
859  // Create the segmentation object
860  pcl::SACSegmentation<pcl::PointXYZ> seg;
861  seg.setModelType (pcl::SACMODEL_PERPENDICULAR_PLANE);
862  seg.setMethodType (pcl::SAC_RANSAC);
863  seg.setDistanceThreshold (planeSegDistTresh_);
864  seg.setAxis(searchAxes);
865  seg.setEpsAngle(planeSegAngleEps_);
866 
867  seg.setInputCloud (searchCloud);
868  seg.segment (*inliers, *coefficients);
869 
870  if (inliers->indices.size () == 0)
871  {
872  PCL_ERROR ("Could not estimate more planar models for the given dataset.");
873  }
874 
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);
881  planeCloud->header.frame_id=worldFrame_;
882 
883  //check if plane contains stairs points
884  Eigen::Vector3f normal;
885  normal(0)=coefficients->values[0];
886  normal(1)=coefficients->values[1];
887  normal(2)=coefficients->values[2];
888 
889  Eigen::Vector3f point;
890  point(0)=0;
891  point(1)=0;
892  point(2)=-(coefficients->values[3]/coefficients->values[2]);
893 
894  Eigen::Vector3f normal_0;
895  normal_0= normal/normal.squaredNorm();
896 
897  float d_hesse= point.dot(normal_0);
898 
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;
905  // std::cout<<"hesse distance: "<<fabs(stairs_point.dot(normal_0)-d_hesse) <<std::endl;
906  if(fabs(stairs_point.dot(normal_0)-d_hesse) > hesseTresh_){
907  isPossiblePlane=false;
908  break;
909  }
910  }
911 
912  if(isPossiblePlane){
913  ROS_INFO("staris plane found");
915  }else{
916  planeCloud->resize(0);
917  }
918 }
919 
920 float HectorStairDetection::maxDistBetweenPoints(pcl::PointCloud<pcl::PointXYZI>::Ptr input_cloud){
921  float max_dist=0;
922  float temp_dist=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){
927  max_dist=temp_dist;
928  }
929  }
930  }
931  return max_dist;
932 }
933 
934 float HectorStairDetection::minHightDistBetweenPoints(pcl::PointCloud<pcl::PointXYZI>::Ptr input_cloud){
935  float min_dist=FLT_MAX;
936  float temp_dist=0;
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){
941  min_dist=temp_dist;
942  }
943  }
944  }
945  return min_dist;
946 }
947 
948 }
949 
950 
void getStairsPositionAndOrientation(Eigen::Vector3f &base, Eigen::Vector3f point, std::string frameID, Eigen::Vector3f &direction, geometry_msgs::PoseStamped &position_and_orientaion)
Chain d2()
void publish(const boost::shared_ptr< M > &message) const
void transformTFToEigen(const tf::Transform &t, Eigen::Affine3d &e)
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())
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)
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
TFSIMD_FORCE_INLINE const tfScalar & getW() const
void getPreprocessedCloud(pcl::PointCloud< pcl::PointXYZ >::Ptr &input_cloud, pcl::PointCloud< pcl::PointNormal >::Ptr &output_cloud)
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
float maxDistBetweenPoints(pcl::PointCloud< pcl::PointXYZI >::Ptr input_cloud)
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)
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
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)
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)
#define ROS_ERROR(...)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
std::string frame_id_
void toPCL(const ros::Time &stamp, pcl::uint64_t &pcl_stamp)
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)
#define ROS_DEBUG(...)


hector_stair_detection
Author(s):
autogenerated on Mon Jun 10 2019 13:36:41