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