processDepthmap.cpp
Go to the documentation of this file.
00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <ros/ros.h>
00005 
00006 #include <nav_msgs/Odometry.h>
00007 
00008 #include <tf/transform_datatypes.h>
00009 #include <tf/transform_listener.h>
00010 #include <tf/transform_broadcaster.h>
00011 
00012 #include "cameraParameters.h"
00013 #include "pointDefinition.h"
00014 
00015 const double PI = 3.1415926;
00016 
00017 const int imagePixelNum = imageHeight * imageWidth;
00018 
00019 const int keepSyncCloudNum = 5;
00020 double syncCloudTime[keepSyncCloudNum] = {0};
00021 pcl::PointCloud<pcl::PointXYZI>::Ptr syncCloudArray[keepSyncCloudNum];
00022 int syncCloudInd = -1;
00023 int cloudRegInd = 0;
00024 
00025 pcl::PointCloud<pcl::PointXYZI>::Ptr depthCloud(new pcl::PointCloud<pcl::PointXYZI>());
00026 pcl::PointCloud<pcl::PointXYZI>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZI>());
00027 pcl::PointCloud<pcl::PointXYZI>::Ptr tempCloud2(new pcl::PointCloud<pcl::PointXYZI>());
00028 pcl::PointCloud<pcl::PointXYZI>::Ptr tempCloud3(new pcl::PointCloud<pcl::PointXYZI>());
00029 
00030 double timeRec = 0;
00031 double rxRec = 0, ryRec = 0, rzRec = 0;
00032 double txRec = 0, tyRec = 0, tzRec = 0;
00033 
00034 bool systemInited = false;
00035 double initTime;
00036 
00037 int cloudCount = -1;
00038 const int cloudSkipNum = 5;
00039 const int cloudDSRate = 5;
00040 
00041 ros::Publisher *depthCloudPubPointer = NULL;
00042 
00043 void voDataHandler(const nav_msgs::Odometry::ConstPtr& voData)
00044 {
00045   double time = voData->header.stamp.toSec();
00046 
00047   double roll, pitch, yaw;
00048   geometry_msgs::Quaternion geoQuat = voData->pose.pose.orientation;
00049   tf::Matrix3x3(tf::Quaternion(geoQuat.z, -geoQuat.x, -geoQuat.y, geoQuat.w)).getRPY(roll, pitch, yaw);
00050 
00051   double rx = voData->twist.twist.angular.x - rxRec;
00052   double ry = voData->twist.twist.angular.y - ryRec;
00053   double rz = voData->twist.twist.angular.z - rzRec;
00054 
00055   if (ry < -PI) {
00056     ry += 2 * PI;
00057   } else if (ry > PI) {
00058     ry -= 2 * PI;
00059   }
00060 
00061   double tx = voData->pose.pose.position.x - txRec;
00062   double ty = voData->pose.pose.position.y - tyRec;
00063   double tz = voData->pose.pose.position.z - tzRec;
00064 
00065   rxRec = voData->twist.twist.angular.x;
00066   ryRec = voData->twist.twist.angular.y;
00067   rzRec = voData->twist.twist.angular.z;
00068 
00069   txRec = voData->pose.pose.position.x;
00070   tyRec = voData->pose.pose.position.y;
00071   tzRec = voData->pose.pose.position.z;
00072 
00073   double x1 = cos(yaw) * tx + sin(yaw) * tz;
00074   double y1 = ty;
00075   double z1 = -sin(yaw) * tx + cos(yaw) * tz;
00076 
00077   double x2 = x1;
00078   double y2 = cos(pitch) * y1 - sin(pitch) * z1;
00079   double z2 = sin(pitch) * y1 + cos(pitch) * z1;
00080 
00081   tx = cos(roll) * x2 + sin(roll) * y2;
00082   ty = -sin(roll) * x2 + cos(roll) * y2;
00083   tz = z2;
00084 
00085   double cosrx = cos(rx);
00086   double sinrx = sin(rx);
00087   double cosry = cos(ry);
00088   double sinry = sin(ry);
00089   double cosrz = cos(rz);
00090   double sinrz = sin(rz);
00091 
00092   if (time - timeRec < 0.5 && syncCloudInd >= 0) {
00093     pcl::PointXYZI point;
00094     tempCloud->clear();
00095     double x1, y1, z1, x2, y2, z2;
00096     int depthCloudNum = depthCloud->points.size();
00097     for (int i = 0; i < depthCloudNum; i++) {
00098       point = depthCloud->points[i];
00099 
00100       x1 = cosry * point.x - sinry * point.z;
00101       y1 = point.y;
00102       z1 = sinry * point.x + cosry * point.z;
00103 
00104       x2 = x1;
00105       y2 = cosrx * y1 + sinrx * z1;
00106       z2 = -sinrx * y1 + cosrx * z1;
00107 
00108       point.x = cosrz * x2 + sinrz * y2 - tx;
00109       point.y = -sinrz * x2 + cosrz * y2 - ty;
00110       point.z = z2 - tz;
00111 
00112       double pointDis = sqrt(point.x * point.x + point.y * point.y + point.z * point.z);
00113       double timeDis = time - initTime - point.intensity;
00114       if (fabs(point.x / point.z) < 2 && fabs(point.y / point.z) < 1 && point.z > 0.3 && pointDis < 15 &&  
00115           timeDis <= 5.0) {
00116         tempCloud->push_back(point);
00117       }
00118     }
00119 
00120     while (syncCloudTime[cloudRegInd] <= time && cloudRegInd != (syncCloudInd + 1) % keepSyncCloudNum) {
00121       double scale = (time - syncCloudTime[cloudRegInd]) / (time - timeRec);
00122       if (scale > 1) {
00123         scale = 1;
00124       } else if (scale < 0) {
00125         scale = 0;
00126       }
00127 
00128       double rx2 = rx * scale;
00129       double ry2 = ry * scale;
00130       double rz2 = rz * scale;
00131 
00132       double tx2 = tx * scale;
00133       double ty2 = ty * scale;
00134       double tz2 = tz * scale;
00135 
00136       double cosrx2 = cos(rx2);
00137       double sinrx2 = sin(rx2);
00138       double cosry2 = cos(ry2);
00139       double sinry2 = sin(ry2);
00140       double cosrz2 = cos(rz2);
00141       double sinrz2 = sin(rz2);
00142 
00143       pcl::PointCloud<pcl::PointXYZI>::Ptr syncCloudPointer = syncCloudArray[cloudRegInd];
00144       int syncCloudNum = syncCloudPointer->points.size();
00145       for (int i = 0; i < syncCloudNum; i++) {
00146         point = syncCloudPointer->points[i];
00147 
00148         x1 = cosry2 * point.x - sinry2 * point.z;
00149         y1 = point.y;
00150         z1 = sinry2 * point.x + cosry2 * point.z;
00151 
00152         x2 = x1;
00153         y2 = cosrx2 * y1 + sinrx2 * z1;
00154         z2 = -sinrx2 * y1 + cosrx2 * z1;
00155 
00156         point.x = cosrz2 * x2 + sinrz2 * y2 - tx2;
00157         point.y = -sinrz2 * x2 + cosrz2 * y2 - ty2;
00158         point.z = z2 - tz2;
00159 
00160         double pointDis = sqrt(point.x * point.x + point.y * point.y + point.z * point.z);
00161         if (fabs(point.x / point.z) < 2 && fabs(point.y / point.z) < 1.5 && point.z > 0.3 && 
00162             pointDis < 15) {
00163           tempCloud->push_back(point);
00164         }
00165       }
00166       cloudRegInd = (cloudRegInd + 1) % keepSyncCloudNum;
00167     }
00168 
00169     depthCloud->clear();
00170     pcl::VoxelGrid<pcl::PointXYZI> downSizeFilter;
00171     downSizeFilter.setInputCloud(tempCloud);
00172     downSizeFilter.setLeafSize(0.05, 0.05, 0.05);
00173     downSizeFilter.filter(*depthCloud);
00174     depthCloudNum = depthCloud->points.size();
00175 
00176     tempCloud->clear();
00177     for (int i = 0; i < depthCloudNum; i++) {
00178       point = depthCloud->points[i];
00179 
00180       if (fabs(point.x / point.z) < 1 && fabs(point.y / point.z) < 0.6) {
00181         point.intensity = depthCloud->points[i].z;
00182         point.x *= 10 / depthCloud->points[i].z;
00183         point.y *= 10 / depthCloud->points[i].z;
00184         point.z = 10;
00185 
00186         tempCloud->push_back(point);
00187       }
00188     }
00189 
00190     tempCloud2->clear();
00191     downSizeFilter.setInputCloud(tempCloud);
00192     downSizeFilter.setLeafSize(0.1, 0.1, 0.1);
00193     downSizeFilter.filter(*tempCloud2);
00194     int tempCloud2Num = tempCloud2->points.size();
00195 
00196     for (int i = 0; i < tempCloud2Num; i++) {
00197       tempCloud2->points[i].z = tempCloud2->points[i].intensity;
00198       tempCloud2->points[i].x *= tempCloud2->points[i].z / 10;
00199       tempCloud2->points[i].y *= tempCloud2->points[i].z / 10;
00200       tempCloud2->points[i].intensity = 10;
00201     }
00202 
00203     sensor_msgs::PointCloud2 depthCloud2;
00204     pcl::toROSMsg(*tempCloud2, depthCloud2);
00205     depthCloud2.header.frame_id = "camera2";
00206     depthCloud2.header.stamp = voData->header.stamp;
00207     depthCloudPubPointer->publish(depthCloud2);
00208   }
00209 
00210   timeRec = time;
00211 }
00212 
00213 void syncCloudHandler(const sensor_msgs::Image::ConstPtr& syncCloud2)
00214 {
00215   cloudCount = (cloudCount + 1) % (cloudSkipNum + 1);
00216   if (cloudCount != 0) {
00217     return;
00218   }
00219 
00220   if (!systemInited) {
00221     initTime = syncCloud2->header.stamp.toSec();
00222     systemInited = true;
00223   }
00224 
00225   double time = syncCloud2->header.stamp.toSec();
00226   double timeLasted = time - initTime;
00227 
00228   syncCloudInd = (syncCloudInd + 1) % keepSyncCloudNum;
00229   syncCloudTime[syncCloudInd] = time;
00230 
00231   tempCloud3->clear();
00232   pcl::PointXYZI point;
00233   double halfDSRate = cloudDSRate / 2.0 - 0.5;
00234   const float* syncCloud2Pointer = reinterpret_cast<const float*>(&syncCloud2->data[0]);
00235   for (double i = halfDSRate; i < imageHeight; i += cloudDSRate) {
00236     for (double j = halfDSRate; j < imageWidth; j += cloudDSRate) {
00237       int pixelCount = 0;
00238       float val, valSum = 0;
00239       int is = int(i - halfDSRate), ie = int(i + halfDSRate);
00240       int js = int(j - halfDSRate), je = int(j + halfDSRate);
00241       for (int ii = is; ii <= ie; ii++) {
00242         for (int jj = js; jj <= je; jj++) {
00243           val = syncCloud2Pointer[ii * imageWidth + jj];
00244           if (val > 0.3 && val < 7) {
00245             valSum += val;
00246             pixelCount++;
00247           }
00248         }
00249       }
00250 
00251       if (pixelCount > 0) {
00252         double ud = (kDepth[2] - j) / kDepth[0];
00253         double vd = (kDepth[5] - i) / kDepth[4];
00254 
00255         val = valSum / pixelCount;
00256 
00257         point.z = val;
00258         point.x = ud * val;
00259         point.y = vd * val;
00260         point.intensity = timeLasted;
00261 
00262         tempCloud3->push_back(point);
00263       }
00264     }
00265   }
00266 
00267   pcl::PointCloud<pcl::PointXYZI>::Ptr syncCloudPointer = syncCloudArray[syncCloudInd];
00268   syncCloudPointer->clear();
00269 
00270   pcl::VoxelGrid<pcl::PointXYZI> downSizeFilter;
00271   downSizeFilter.setInputCloud(tempCloud3);
00272   downSizeFilter.setLeafSize(0.1, 0.1, 0.1);
00273   downSizeFilter.filter(*syncCloudPointer);
00274 }
00275 
00276 int main(int argc, char** argv)
00277 {
00278   ros::init(argc, argv, "processDepthmap");
00279   ros::NodeHandle nh;
00280 
00281   for (int i = 0; i < keepSyncCloudNum; i++) {
00282     pcl::PointCloud<pcl::PointXYZI>::Ptr syncCloudTemp(new pcl::PointCloud<pcl::PointXYZI>());
00283     syncCloudArray[i] = syncCloudTemp;
00284   }
00285 
00286   ros::Subscriber voDataSub = nh.subscribe<nav_msgs::Odometry> ("/cam_to_init", 5, voDataHandler);
00287 
00288   ros::Subscriber syncCloudSub = nh.subscribe<sensor_msgs::Image>
00289                                  ("/camera/depth_registered/image", 1, syncCloudHandler);
00290 
00291   ros::Publisher depthCloudPub = nh.advertise<sensor_msgs::PointCloud2> ("/depth_cloud", 5);
00292   depthCloudPubPointer = &depthCloudPub;
00293 
00294   ros::spin();
00295 
00296   return 0;
00297 }


demo_rgbd
Author(s): Ji Zhang
autogenerated on Tue Mar 3 2015 18:01:08