// this function gets called every time new pcl data comes in void cloudcb(const sensor_msgs::PointCloud2ConstPtr &scan) { ROS_INFO("Kinect point cloud receieved"); ros::Time start_time = ros::Time::now(); ros::Time tcur = ros::Time::now(); Eigen::Vector4f centroid; geometry_msgs::Point point; pcl::PassThrough<pcl::PointXYZ> pass; Eigen::VectorXf lims(6); sensor_msgs::PointCloud2::Ptr ros_cloud (new sensor_msgs::PointCloud2 ()), ros_cloud_filtered (new sensor_msgs::PointCloud2 ()); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ()), cloud_downsampled (new pcl::PointCloud<pcl::PointXYZ> ()), cloud_filtered (new pcl::PointCloud<pcl::PointXYZ> ()); // set a parameter telling the world that I am tracking the robot ros::param::set("/tracking_robot", true); ROS_DEBUG("finished declaring vars : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); ROS_DEBUG("About to transform cloud"); // New sensor message for holding the transformed data sensor_msgs::PointCloud2::Ptr scan_transformed (new sensor_msgs::PointCloud2()); try{ pcl_ros::transformPointCloud("/oriented_optimization_frame", tf, *scan, *scan_transformed); } catch(tf::TransformException ex) { ROS_ERROR("%s", ex.what()); } scan_transformed->header.frame_id = "/oriented_optimization_frame"; // Convert to pcl ROS_DEBUG("Convert cloud to pcd from rosmsg"); pcl::fromROSMsg(*scan_transformed, *cloud); ROS_DEBUG("cloud transformed and converted to pcl : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); // set time stamp and frame id ros::Time tstamp = ros::Time::now(); // run through pass-through filter to eliminate tarp and below robots. ROS_DEBUG("Pass-through filter"); pass_through(cloud, cloud_filtered, robot_limits); ROS_DEBUG("done with pass-through : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); // now let's publish that filtered cloud ROS_DEBUG("Converting and publishing cloud"); pcl::toROSMsg(*cloud_filtered, *ros_cloud_filtered); ros_cloud_filtered->header.frame_id = "/oriented_optimization_frame"; cloud_pub[0].publish(ros_cloud_filtered); ROS_DEBUG("published filtered cloud : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); // Let's do a downsampling before doing cluster extraction pcl::VoxelGrid<pcl::PointXYZ> vg; vg.setInputCloud (cloud_filtered); vg.setLeafSize (0.01f, 0.01f, 0.01f); vg.filter (*cloud_downsampled); ROS_DEBUG("finished downsampling : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); ROS_DEBUG("Begin extraction filtering"); // build a KdTree object for the search method of the extraction pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ()); tree->setInputCloud (cloud_downsampled); ROS_DEBUG("done with KdTree initialization : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); // create a vector for storing the indices of the clusters std::vector<pcl::PointIndices> cluster_indices; // setup extraction: pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; ec.setClusterTolerance (0.02); // cm ec.setMinClusterSize (50); ec.setMaxClusterSize (3000); ec.setSearchMethod (tree); ec.setInputCloud (cloud_downsampled); // now we can perform cluster extraction ec.extract (cluster_indices); ROS_DEBUG("finished extraction : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); // run through the indices, create new clouds, and then publish them int j=1; int number_clusters=0; geometry_msgs::PointStamped pt; puppeteer_msgs::Robots robots; std::vector<int> num; for (std::vector<pcl::PointIndices>::const_iterator it=cluster_indices.begin(); it!=cluster_indices.end (); ++it) { number_clusters = (int) cluster_indices.size(); ROS_DEBUG("Number of clusters found: %d",number_clusters); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>); for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++) { cloud_cluster->points.push_back(cloud_downsampled->points[*pit]); } cloud_cluster->width = cloud_cluster->points.size (); cloud_cluster->height = 1; cloud_cluster->is_dense = true; // convert to rosmsg and publish: ROS_DEBUG("Publishing extracted cloud"); pcl::toROSMsg(*cloud_cluster, *ros_cloud_filtered); ros_cloud_filtered->header.frame_id = "/oriented_optimization_frame"; if(j < MAX_CLUSTERS+1) cloud_pub[j].publish(ros_cloud_filtered); j++; // compute centroid and add to Robots: pcl::compute3DCentroid(*cloud_cluster, centroid); pt.point.x = centroid(0); pt.point.y = centroid(1); pt.point.z = centroid(2); pt.header.stamp = tstamp; pt.header.frame_id = "/oriented_optimization_frame"; robots.robots.push_back(pt); // add number of points in cluster to num: num.push_back(cloud_cluster->points.size()); } ROS_DEBUG("finished creating and publishing clusters : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); if (number_clusters > number_robots) { ROS_WARN("Number of clusters found is greater " "than the number of robots"); // pop minimum cluster count remove_least_likely(&robots, &num); } robots.header.stamp = tstamp; robots.header.frame_id = "/oriented_optimization_frame"; robots.number = number_clusters; robots_pub.publish(robots); ROS_DEBUG("removed extra clusters, and published : %f", (ros::Time::now()-tcur).toSec()); tcur = ros::Time::now(); ros::Duration d = ros::Time::now() - start_time; ROS_DEBUG("End of cloudcb; time elapsed = %f (%f Hz)", d.toSec(), 1/d.toSec()); }
// this function gets called every time new pcl data comes in void cloudcb(const sensor_msgs::PointCloud2ConstPtr &scan) { Eigen::Vector4f centroid; float xpos = 0.0; float ypos = 0.0; float zpos = 0.0; float D_sphere = 0.05; //meters float R_search = 2.0*D_sphere; puppeteer_msgs::PointPlus pointplus; geometry_msgs::Point point; pcl::PassThrough<pcl::PointXYZ> pass; Eigen::VectorXf lims(6); sensor_msgs::PointCloud2::Ptr robot_cloud (new sensor_msgs::PointCloud2 ()), robot_cloud_filtered (new sensor_msgs::PointCloud2 ()); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ()), cloud_filtered (new pcl::PointCloud<pcl::PointXYZ> ()); // set a parameter telling the world that I am tracking the robot ros::param::set("/tracking_robot", true); // New sensor message for holding the transformed data sensor_msgs::PointCloud2::Ptr scan_transformed (new sensor_msgs::PointCloud2()); try{ pcl_ros::transformPointCloud("/oriented_optimization_frame", tf, *scan, *scan_transformed); } catch(tf::TransformException ex) { ROS_ERROR("%s", ex.what()); } scan_transformed->header.frame_id = "/oriented_optimization_frame"; // Convert to pcl pcl::fromROSMsg(*scan_transformed, *cloud); // set time stamp and frame id pointplus.header.stamp = scan->header.stamp; pointplus.header.frame_id = "/oriented_optimization_frame"; // do we need to find the object? if (locate == true) { // lims << XMIN, XMAX, YMIN, YMAX, ZMIN, ZMAX; lims << frame_limits; pass_through(cloud, cloud_filtered, lims); pcl::compute3DCentroid(*cloud_filtered, centroid); xpos = centroid(0); ypos = centroid(1); zpos = centroid(2); // Publish cloud: pcl::toROSMsg(*cloud_filtered, *robot_cloud_filtered); robot_cloud_filtered->header.frame_id = "/oriented_optimization_frame"; cloud_pub[1].publish(robot_cloud_filtered); // are there enough points in the point cloud? if(cloud_filtered->points.size() > POINT_THRESHOLD) { locate = false; // We have re-found the object! // set values to publish pointplus.x = xpos; pointplus.y = ypos; pointplus.z = zpos; pointplus.error = false; pointplus_pub.publish(pointplus); } // otherwise we should publish a blank centroid // position with an error flag else { // set values to publish pointplus.x = 0.0; pointplus.y = 0.0; pointplus.z = 0.0; pointplus.error = true; pointplus_pub.publish(pointplus); } } // if "else", we are just going to calculate the centroid // of the input cloud else { lims << xpos_last-R_search, xpos_last+R_search, ypos_last-R_search, ypos_last+R_search, zpos_last-R_search, zpos_last+R_search; pass_through(cloud, cloud_filtered, lims); // are there enough points in the point cloud? if(cloud_filtered->points.size() < POINT_THRESHOLD) { locate = true; ROS_WARN("Lost Object at: x = %f y = %f z = %f\n", xpos_last,ypos_last,zpos_last); pointplus.x = 0.0; pointplus.y = 0.0; pointplus.z = 0.0; pointplus.error = true; pointplus_pub.publish(pointplus); return; } pcl::compute3DCentroid(*cloud_filtered, centroid); xpos = centroid(0); ypos = centroid(1); zpos = centroid(2); pcl::toROSMsg(*cloud_filtered, *robot_cloud); robot_cloud_filtered->header.frame_id = "/oriented_optimization_frame"; cloud_pub[0].publish(robot_cloud); tf::Transform transform; transform.setOrigin(tf::Vector3(xpos, ypos, zpos)); transform.setRotation(tf::Quaternion(0, 0, 0, 1)); static tf::TransformBroadcaster br; br.sendTransform(tf::StampedTransform (transform,ros::Time::now(), "/oriented_optimization_frame", "/robot_kinect_frame")); // set pointplus message values and publish pointplus.x = xpos; pointplus.y = ypos; pointplus.z = zpos; pointplus.error = false; pointplus_pub.publish(pointplus); } xpos_last = xpos; ypos_last = ypos; zpos_last = zpos; }