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
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;
00070 fclose(f);
00071 }
00072
00076 double getSystemTime() {
00077
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
00243 ros::Subscriber subCloud = nh.subscribe (cloudTopic, qSize, cloudCallback);
00244
00245
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();
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
00274 ros::spinOnce ();
00275 ros::Duration (0.001).sleep ();
00276 visualizer.spinOnce(10);
00277
00278
00279 if (!cloudPtr)
00280 continue;
00281
00282 if (cloudPtr == oldCloudPtr)
00283 continue;
00284
00285
00286 mCloud.lock ();
00287
00288 pcl::fromROSMsg (*cloudPtr, *cloud);
00289
00290
00291 pcl::transformPointCloud(*cloud, *cloudSwap, transformMatrix);
00292
00293
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
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
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 std::vector<pcl::PointXYZ> robotPositions;
00338 detectRobots(cloudSwap, robotPositions, cloud);
00339 *cloudDisplay = *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
00350
00351
00352
00353
00354
00355
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 }