detect.cc
Go to the documentation of this file.
00001 
00017 #include <ros/ros.h>
00018 #include <image_transport/image_transport.h>
00019 #include <image_geometry/pinhole_camera_model.h>
00020 
00021 #include <boost/thread/mutex.hpp>
00022 #include <boost/lexical_cast.hpp>
00023 
00024 #include <pcl/point_types.h>
00025 #include <pcl_visualization/pcl_visualizer.h>
00026 #include <pcl/registration/transforms.h>
00027 #include <pcl/filters/extract_indices.h>
00028 #include <pcl/segmentation/extract_clusters.h>
00029 #include <terminal_tools/parse.h>
00030 
00031 #include <Eigen/Core>
00032 
00033 #include <color_table/common.h>
00034 #include <ground_truth/field_provider.h>
00035 
00036 /* Display modes */
00037 #define FULL 1
00038 #define RELEVANT 2
00039 
00040 using namespace color_table;
00041 
00042 namespace {
00043   sensor_msgs::PointCloud2ConstPtr cloudPtr, oldCloudPtr;
00044   boost::mutex mCloud;
00045   pcl_visualization::PointCloudColorHandler<pcl::PointXYZRGB>::Ptr colorHandler;
00046   pcl_visualization::PointCloudGeometryHandler<pcl::PointXYZRGB>::Ptr geometryHandler;
00047 
00048   std::string calibFile;
00049   std::string colorTableFile;
00050   std::string logFile;
00051   Eigen::Affine3f transformMatrix;
00052 
00053   int qSize;
00054   std::string cloudTopic;
00055   int mode;
00056 
00057   unsigned int numRobotsDisplayed = 0;
00058   unsigned int numBallsDisplayed = 0;
00059 
00060   ColorTable colorTable;
00061 } 
00062 
00066 void loadColorTable() {
00067   FILE* f = fopen(colorTableFile.c_str(), "rb");
00068   size_t size = fread(colorTable, 128*128*128, 1, f);
00069   size = size; // remove warning
00070   fclose(f);
00071 }
00072 
00076 double getSystemTime() {
00077   // set time
00078   struct timezone tz;
00079   timeval timeT;
00080   gettimeofday(&timeT, &tz);
00081   return timeT.tv_sec + (timeT.tv_usec / 1000000.0);
00082 }
00083 
00088 inline std::string getUniqueName(const std::string &baseName, int uniqueId) {
00089   return baseName + boost::lexical_cast<std::string>(uniqueId);
00090 }
00091 
00098 void detectBall(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudIn, std::vector<pcl::PointXYZ> &ballPositions, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudOut) {
00099 
00100   pcl::PointIndices inliers;
00101 
00102   ballPositions.clear();
00103 
00104   for (unsigned int i = 0; i < cloudIn->points.size(); i++) {
00105     pcl::PointXYZRGB *pt = &cloudIn->points[i];
00106     int rgb = *reinterpret_cast<int*>(&pt->rgb);
00107     int r = ((rgb >> 16) & 0xff);
00108     int g = ((rgb >> 8) & 0xff);
00109     int b = (rgb & 0xff);
00110     if (colorTable[r/2][g/2][b/2] == ORANGE && fabs(pt->x) < 3.5 && fabs(pt->y) < 2.25 && fabs(pt->z) < 0.15 ) {
00111       inliers.indices.push_back(i);
00112     }
00113   }
00114 
00115   pcl::ExtractIndices<pcl::PointXYZRGB> extract;
00116   extract.setInputCloud(cloudIn);
00117   extract.setIndices(boost::make_shared<pcl::PointIndices>(inliers));
00118   extract.setNegative(false);
00119   extract.filter(*cloudOut);
00120 
00121   if (cloudOut->points.size() == 0)
00122     return;
00123 
00124   pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> cluster;
00125   cluster.setClusterTolerance(0.1);
00126   cluster.setMinClusterSize(5);
00127   cluster.setInputCloud(cloudOut);
00128   std::vector<pcl::PointIndices> clusters;
00129   cluster.extract(clusters);
00130 
00131   for (unsigned int i = 0; i < clusters.size(); i++) {
00132     pcl::PointIndices clusterIndex = clusters[i];
00133 
00134     pcl::PointXYZ point(0,0,0);
00135     for (unsigned int j = 0; j < clusterIndex.indices.size(); j++) {
00136       point.x += cloudOut->points[clusterIndex.indices[j]].x;
00137       point.y += cloudOut->points[clusterIndex.indices[j]].y;
00138     }
00139     point.z = 0;
00140     point.x /= clusterIndex.indices.size();
00141     point.y /= clusterIndex.indices.size();
00142     ballPositions.push_back(point);
00143   }
00144 
00145 }
00146 
00153 void detectRobots(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudIn, std::vector<pcl::PointXYZ> &robotPositions, pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudOut) {
00154 
00155   pcl::PointIndices inliers;
00156 
00157   robotPositions.clear();
00158 
00159   for (unsigned int i = 0; i < cloudIn->points.size(); i++) {
00160     pcl::PointXYZRGB *pt = &cloudIn->points[i];
00161     if (pt->z > 0.25 && pt->y < 2 && pt->y > -2 && pt->x < 2.75 && pt->x > -2.75) {
00162       inliers.indices.push_back(i);
00163     }
00164   }
00165 
00166   pcl::ExtractIndices<pcl::PointXYZRGB> extract;
00167   extract.setInputCloud(cloudIn);
00168   extract.setIndices(boost::make_shared<pcl::PointIndices>(inliers));
00169   extract.setNegative(false);
00170   extract.filter(*cloudOut);
00171 
00172   if (cloudOut->points.size() == 0)
00173     return;
00174 
00175   pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> cluster;
00176   cluster.setClusterTolerance(0.1);
00177   cluster.setMinClusterSize(200);
00178   cluster.setInputCloud(cloudOut);
00179   std::vector<pcl::PointIndices> clusters;
00180   cluster.extract(clusters);
00181 
00182   for (unsigned int i = 0; i < clusters.size(); i++) {
00183     pcl::PointIndices clusterIndex = clusters[i];
00184 
00185     pcl::PointXYZ point(0,0,0);
00186     bool highPoint = false;
00187     for (unsigned int j = 0; j < clusterIndex.indices.size(); j++) {
00188       if (cloudOut->points[clusterIndex.indices[j]].z > 0.7) {
00189         highPoint = true;
00190       }
00191       point.x += cloudOut->points[clusterIndex.indices[j]].x;
00192       point.y += cloudOut->points[clusterIndex.indices[j]].y;
00193     }
00194     if (highPoint)
00195       continue;
00196     point.z = 0;
00197     point.x /= clusterIndex.indices.size();
00198     point.y /= clusterIndex.indices.size();
00199     robotPositions.push_back(point);
00200   }
00201 
00202 }
00203 
00207 void cloudCallback (const sensor_msgs::PointCloud2ConstPtr& cloudPtrFromMsg) {
00208   mCloud.lock();
00209   cloudPtr = cloudPtrFromMsg;
00210   mCloud.unlock();
00211 }
00212 
00216 void getParameters(ros::NodeHandle &nh, int argc, char ** argv) {
00217 
00218   qSize = 1;
00219   cloudTopic = "input";
00220   calibFile = "data/calib.txt";
00221   colorTableFile = "data/default.col";
00222   mode = 1;
00223 
00224   terminal_tools::parse_argument (argc, argv, "-qsize", qSize);
00225   terminal_tools::parse_argument (argc, argv, "-calibFile", calibFile);
00226   terminal_tools::parse_argument (argc, argv, "-logFile", logFile);
00227   terminal_tools::parse_argument (argc, argv, "-colorTableFile", colorTableFile);
00228   terminal_tools::parse_argument (argc, argv, "-mode", mode);
00229 
00230   ROS_INFO("Calib File: %s", calibFile.c_str());
00231   ROS_INFO("Log File: %s", logFile.c_str());
00232   ROS_INFO("ColorTable File: %s", colorTableFile.c_str());
00233 }
00234 
00235 int main (int argc, char** argv) {
00236 
00237   ros::init (argc, argv, "pointcloud_online_viewer");
00238   ros::NodeHandle nh;
00239 
00240   getParameters(nh, argc, argv);
00241 
00242   // Create a ROS subscriber for the point cloud
00243   ros::Subscriber subCloud = nh.subscribe (cloudTopic, qSize, cloudCallback);
00244 
00245   // Get transformation that needs to be applied to each input cloud to get the cloud in the correct reference frame
00246   std::ifstream fin(calibFile.c_str());
00247   if (!fin) {
00248     ROS_ERROR("Unable to open calibration file!!");
00249     return -1;
00250   }
00251   for (int i = 0; i < 4; i++) {
00252     for (int j = 0; j < 4; j++) {
00253       fin >> transformMatrix(i,j);
00254     }
00255   }
00256   fin.close();
00257 
00258   pcl_visualization::PCLVisualizer visualizer(argc, argv, "PointCloud");
00259   visualizer.addCoordinateSystem(); // Good for reference
00260   ground_truth::FieldProvider field;
00261   field.get3dField(visualizer);
00262 
00263   pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
00264   pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudSwap(new pcl::PointCloud<pcl::PointXYZRGB>);
00265   pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudDisplay;
00266   
00267   loadColorTable();
00268 
00269   std::ofstream log(logFile.c_str());
00270 
00271   while (nh.ok ()) {
00272 
00273     // Spin
00274     ros::spinOnce ();
00275     ros::Duration (0.001).sleep ();
00276     visualizer.spinOnce(10);
00277 
00278     // If no cloud received yet, continue
00279     if (!cloudPtr)
00280       continue;
00281 
00282     if (cloudPtr == oldCloudPtr)
00283       continue;
00284 
00285     // Convert to PointCloud<T>
00286     mCloud.lock ();
00287 
00288     pcl::fromROSMsg (*cloudPtr, *cloud);
00289 
00290     // Apply transformation to get the correct reference frame
00291     pcl::transformPointCloud(*cloud, *cloudSwap, transformMatrix);
00292 
00293     // Apply filter to extract only those points which are on the field
00294 
00295     if (mode == FULL) {
00296 
00297       pcl::PointIndices inliers;
00298       for (unsigned int i = 0; i < cloudSwap->points.size(); i++) {
00299         pcl::PointXYZRGB *pt = &cloudSwap->points[i];
00300         if (pcl_isfinite(pt->x)) {
00301           inliers.indices.push_back(i);
00302         }
00303       }
00304       pcl::ExtractIndices<pcl::PointXYZRGB> extract;
00305       extract.setInputCloud(cloudSwap);
00306       extract.setIndices(boost::make_shared<pcl::PointIndices>(inliers));
00307       extract.setNegative(false);
00308       extract.filter(*cloud);
00309       
00310       cloudDisplay.reset(new pcl::PointCloud<pcl::PointXYZRGB>);
00311       *cloudDisplay = *cloud;
00312     } else {
00313 
00314       cloudDisplay.reset(new pcl::PointCloud<pcl::PointXYZRGB>);
00315       // Ball
00316       std::vector<pcl::PointXYZ> ballPositions;
00317       detectBall(cloudSwap, ballPositions, cloud);
00318       for (unsigned int i = 0; i < numBallsDisplayed; i++) {
00319         visualizer.removeShape(getUniqueName("ball", i));
00320       }
00321       for (unsigned int i = 0; i < ballPositions.size(); i++) {
00322         visualizer.addSphere(ballPositions[i], 0.05, 1.0, 0.4, 0.0, getUniqueName("ball", i));
00323       }
00324       numBallsDisplayed = ballPositions.size();
00325 
00326       /* 
00327       //Sample log file code
00328       log << std::fixed << getSystemTime() << ",";
00329       if (ballPositions.size() == 0) {
00330         log << "-7," << "-7,";
00331       } else if (ballPositions.size() == 1) {
00332         log << ballPositions[0].x << "," << ballPositions[0].y << ",";
00333       }
00334       */
00335 
00336       // Robots
00337       std::vector<pcl::PointXYZ> robotPositions;
00338       detectRobots(cloudSwap, robotPositions, cloud);
00339       *cloudDisplay = *cloud;                           // Display the cloud
00340       for (unsigned int i = 0; i < numRobotsDisplayed; i++) {
00341         visualizer.removeShape(getUniqueName("robot", i));
00342       }
00343       for (unsigned int i = 0; i < robotPositions.size(); i++) {
00344         visualizer.addSphere(robotPositions[i], 0.1, 1.0, 1.0, 1.0, getUniqueName("robot", i));
00345       }
00346       numRobotsDisplayed = robotPositions.size();
00347 
00348       /*
00349       //Sample log file code
00350       if (robotPositions.size() == 0) {
00351         log << "-7," << "-7,";
00352       } else if (robotPositions.size() == 1) {
00353         log << robotPositions[0].x << "," << robotPositions[0].y << ",";
00354       }
00355       log << std::endl;
00356       */
00357 
00358     }
00359 
00360     visualizer.removePointCloud();
00361     colorHandler.reset (new pcl_visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> (*cloudDisplay));
00362     geometryHandler.reset (new pcl_visualization::PointCloudGeometryHandlerXYZ<pcl::PointXYZRGB> (*cloudDisplay));
00363     visualizer.addPointCloud<pcl::PointXYZRGB>(*cloudDisplay, *colorHandler, *geometryHandler);
00364 
00365     oldCloudPtr = cloudPtr;
00366 
00367     mCloud.unlock ();
00368   }
00369   log.close();
00370   return (0);
00371 }


ground_truth
Author(s): Piyush Khandelwal
autogenerated on Mon Jan 6 2014 11:54:38