00001 #include <string> 00002 #include <vector> 00003 00004 #include "Eigen/Eigen" 00005 #include "pcl/common/common.h" 00006 #include "pcl/filters/crop_box.h" 00007 #include "pcl_conversions/pcl_conversions.h" 00008 #include "ros/ros.h" 00009 #include "sensor_msgs/PointCloud2.h" 00010 #include "surface_perception/segmentation.h" 00011 #include "surface_perception/surface_objects.h" 00012 #include "surface_perception/typedefs.h" 00013 #include "surface_perception/visualization.h" 00014 #include "tf/transform_listener.h" 00015 #include "tf_conversions/tf_eigen.h" 00016 00017 using surface_perception::SurfaceObjects; 00018 using surface_perception::SurfaceViz; 00019 00020 class Demo { 00021 public: 00022 Demo(const SurfaceViz& viz, const std::string& target_frame, 00023 const ros::Publisher& input_pub); 00024 void Callback(const sensor_msgs::PointCloud2ConstPtr& cloud); 00025 00026 private: 00027 SurfaceViz viz_; 00028 ros::Publisher input_pub_; 00029 std::string target_frame_; 00030 tf::TransformListener tf_listener_; 00031 }; 00032 00033 Demo::Demo(const SurfaceViz& viz, const std::string& target_frame, 00034 const ros::Publisher& input_pub) 00035 : viz_(viz), 00036 input_pub_(input_pub), 00037 target_frame_(target_frame), 00038 tf_listener_() {} 00039 00040 void Demo::Callback(const sensor_msgs::PointCloud2ConstPtr& cloud) { 00041 PointCloudC::Ptr pcl_cloud_raw(new PointCloudC); 00042 pcl::fromROSMsg(*cloud, *pcl_cloud_raw); 00043 PointCloudC::Ptr pcl_cloud(new PointCloudC); 00044 00045 if (cloud->header.frame_id != target_frame_) { 00046 tf_listener_.waitForTransform(target_frame_, cloud->header.frame_id, 00047 ros::Time(0), ros::Duration(1)); 00048 tf::StampedTransform transform; 00049 tf_listener_.lookupTransform(target_frame_, cloud->header.frame_id, 00050 ros::Time(0), transform); 00051 Eigen::Affine3d affine; 00052 tf::transformTFToEigen(transform, affine); 00053 pcl::transformPointCloud(*pcl_cloud_raw, *pcl_cloud, affine); 00054 pcl_cloud->header.frame_id = target_frame_; 00055 } else { 00056 pcl_cloud = pcl_cloud_raw; 00057 } 00058 00059 std::vector<int> indices; 00060 pcl::removeNaNFromPointCloud(*pcl_cloud, *pcl_cloud, indices); 00061 00062 pcl::PointIndices::Ptr point_indices(new pcl::PointIndices); 00063 PointCloudC::Ptr cropped_cloud(new PointCloudC); 00064 sensor_msgs::PointCloud2 msg_out; 00065 00066 pcl::CropBox<PointC> crop; 00067 crop.setInputCloud(pcl_cloud); 00068 00069 double max_x, max_y, max_z, min_x, min_y, min_z; 00070 ros::param::param("crop_min_x", min_x, 0.0); 00071 ros::param::param("crop_min_y", min_y, -0.5); 00072 ros::param::param("crop_min_z", min_z, 0.05); 00073 ros::param::param("crop_max_x", max_x, 1.3); 00074 ros::param::param("crop_max_y", max_y, 0.5); 00075 ros::param::param("crop_max_z", max_z, 2.0); 00076 00077 Eigen::Vector4f min; 00078 min << min_x, min_y, min_z, 1; 00079 crop.setMin(min); 00080 Eigen::Vector4f max; 00081 max << max_x, max_y, max_z, 1; 00082 crop.setMax(max); 00083 crop.filter(point_indices->indices); 00084 crop.filter(*cropped_cloud); 00085 00086 pcl::toROSMsg(*cropped_cloud, msg_out); 00087 input_pub_.publish(msg_out); 00088 00089 double horizontal_tolerance_degrees; 00090 ros::param::param("horizontal_tolerance_degrees", 00091 horizontal_tolerance_degrees, 10.0); 00092 double margin_above_surface; 00093 ros::param::param("margin_above_surface", margin_above_surface, 0.025); 00094 double max_point_distance; 00095 ros::param::param("max_point_distance", max_point_distance, 0.015); 00096 double cluster_distance; 00097 ros::param::param("cluster_distance", cluster_distance, 0.01); 00098 int min_cluster_size; 00099 ros::param::param("min_cluster_size", min_cluster_size, 100); 00100 int max_cluster_size; 00101 ros::param::param("max_cluster_size", max_cluster_size, 5000); 00102 int min_surface_size; 00103 ros::param::param("min_surface_size", min_surface_size, 5000); 00104 int min_surface_exploration_iteration; 00105 ros::param::param("min_surface_exploration_iteration", 00106 min_surface_exploration_iteration, 1000); 00107 00108 surface_perception::Segmentation seg; 00109 seg.set_input_cloud(pcl_cloud); 00110 seg.set_indices(point_indices); 00111 seg.set_horizontal_tolerance_degrees(horizontal_tolerance_degrees); 00112 seg.set_margin_above_surface(margin_above_surface); 00113 seg.set_max_point_distance(max_point_distance); 00114 seg.set_cluster_distance(cluster_distance); 00115 seg.set_min_cluster_size(min_cluster_size); 00116 seg.set_max_cluster_size(max_cluster_size); 00117 seg.set_min_surface_size(min_surface_size); 00118 seg.set_min_surface_exploration_iteration(min_surface_exploration_iteration); 00119 00120 std::vector<SurfaceObjects> surface_objects; 00121 bool success = seg.Segment(&surface_objects); 00122 00123 if (!success || surface_objects.size() == 0) { 00124 ROS_ERROR("Failed to segment scene!"); 00125 } else { 00126 size_t object_count = 0; 00127 for (size_t i = 0; i < surface_objects.size(); i++) { 00128 object_count += surface_objects[i].objects.size(); 00129 } 00130 ROS_INFO("Found %ld surfaces with %ld objects", surface_objects.size(), 00131 object_count); 00132 } 00133 00134 viz_.Hide(); 00135 viz_.set_surface_objects(surface_objects); 00136 viz_.Show(); 00137 } 00138 00139 int main(int argc, char** argv) { 00140 ros::init(argc, argv, "surface_perception_demo"); 00141 ros::NodeHandle nh; 00142 00143 ros::Publisher marker_pub = 00144 nh.advertise<visualization_msgs::Marker>("surface_objects", 100); 00145 ros::Publisher cropped_input_pub = nh.advertise<sensor_msgs::PointCloud2>( 00146 "demo_cropped_input_cloud", 1, true); 00147 00148 std::string target_frame("base_link"); 00149 if (argc > 1) { 00150 target_frame = argv[1]; 00151 } 00152 00153 SurfaceViz viz(marker_pub); 00154 Demo demo(viz, target_frame, cropped_input_pub); 00155 ros::Subscriber pc_sub = nh.subscribe<sensor_msgs::PointCloud2>( 00156 "cloud_in", 1, &Demo::Callback, &demo); 00157 ros::spin(); 00158 }