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 = 15;
00020 double syncCloudTime[keepSyncCloudNum] = {0};
00021 pcl::PointCloud<pcl::PointXYZ>::Ptr syncCloudArray[keepSyncCloudNum];
00022 int syncCloudInd = -1;
00023 int cloudRegInd = 0;
00024
00025 int cloudCount = -1;
00026 const int cloudSkipNum = 5;
00027
00028 pcl::PointCloud<pcl::PointXYZ>::Ptr surroundCloud(new pcl::PointCloud<pcl::PointXYZ>());
00029 pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>());
00030 pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud2(new pcl::PointCloud<pcl::PointXYZ>());
00031
00032 double timeRec = 0;
00033 double rxRec = 0, ryRec = 0, rzRec = 0;
00034 double txRec = 0, tyRec = 0, tzRec = 0;
00035
00036 int showCount = -1;
00037 const int showSkipNum = 9;
00038
00039 ros::Publisher *surroundCloudPubPointer = NULL;
00040
00041 void voDataHandler(const nav_msgs::Odometry::ConstPtr& voData)
00042 {
00043 showCount = (showCount + 1) % (showSkipNum + 1);
00044 if (showCount != 0) {
00045 return;
00046 }
00047
00048 double time = voData->header.stamp.toSec();
00049
00050 double rx, ry, rz;
00051 geometry_msgs::Quaternion geoQuat = voData->pose.pose.orientation;
00052 tf::Matrix3x3(tf::Quaternion(geoQuat.z, -geoQuat.x, -geoQuat.y, geoQuat.w)).getRPY(rz, rx, ry);
00053
00054 double tx = voData->pose.pose.position.x;
00055 double ty = voData->pose.pose.position.y;
00056 double tz = voData->pose.pose.position.z;
00057
00058 if (time - timeRec < 0.5 && syncCloudInd >= 0) {
00059 pcl::PointXYZ point;
00060 tempCloud->clear();
00061 int surroundCloudNum = surroundCloud->points.size();
00062 for (int i = 0; i < surroundCloudNum; i++) {
00063 point = surroundCloud->points[i];
00064
00065 double xDiff = point.x - tx;
00066 double yDiff = point.y - ty;
00067 double zDiff = point.z - tz;
00068
00069 double pointDis = sqrt(xDiff * xDiff + yDiff * yDiff + zDiff * zDiff);
00070 if (pointDis < 50) {
00071 tempCloud->push_back(point);
00072 }
00073 }
00074
00075 while (syncCloudTime[cloudRegInd] <= time && cloudRegInd != (syncCloudInd + 1) % keepSyncCloudNum) {
00076 double scaleLast = (time - syncCloudTime[cloudRegInd]) / (time - timeRec);
00077 double scaleCur = (syncCloudTime[cloudRegInd] - timeRec) / (time - timeRec);
00078 if (scaleLast > 1) {
00079 scaleLast = 1;
00080 } else if (scaleLast < 0) {
00081 scaleLast = 0;
00082 }
00083 if (scaleCur > 1) {
00084 scaleCur = 1;
00085 } else if (scaleCur < 0) {
00086 scaleCur = 0;
00087 }
00088
00089 double rx2 = rx * scaleCur + rxRec * scaleLast;
00090 double ry2;
00091 if (ry - ryRec > PI) {
00092 ry2 = ry * scaleCur + (ryRec + 2 * PI) * scaleLast;
00093 } else if (ry - ryRec < -PI) {
00094 ry2 = ry * scaleCur + (ryRec - 2 * PI) * scaleLast;
00095 } else {
00096 ry2 = ry * scaleCur + ryRec * scaleLast;
00097 }
00098 double rz2 = rz * scaleCur + rzRec * scaleLast;
00099
00100 double tx2 = tx * scaleCur + txRec * scaleLast;
00101 double ty2 = ty * scaleCur + tyRec * scaleLast;
00102 double tz2 = tz * scaleCur + tzRec * scaleLast;
00103
00104 double cosrx2 = cos(rx2);
00105 double sinrx2 = sin(rx2);
00106 double cosry2 = cos(ry2);
00107 double sinry2 = sin(ry2);
00108 double cosrz2 = cos(rz2);
00109 double sinrz2 = sin(rz2);
00110
00111 pcl::PointCloud<pcl::PointXYZ>::Ptr syncCloudPointer = syncCloudArray[cloudRegInd];
00112 int syncCloudNum = syncCloudPointer->points.size();
00113 for (int i = 0; i < syncCloudNum; i++) {
00114 point = syncCloudPointer->points[i];
00115 double pointDis = sqrt(point.x * point.x + point.y * point.y + point.z * point.z);
00116 if (pointDis > 0.3 && pointDis < 5) {
00117 double x1 = cosrz2 * point.x - sinrz2 * point.y;
00118 double y1 = sinrz2 * point.x + cosrz2 * point.y;
00119 double z1 = point.z;
00120
00121 double x2 = x1;
00122 double y2 = cosrx2 * y1 + sinrx2 * z1;
00123 double z2 = -sinrx2 * y1 + cosrx2 * z1;
00124
00125 point.x = cosry2 * x2 - sinry2 * z2 + tx2;
00126 point.y = y2 + ty2;
00127 point.z = sinry2 * x2 + cosry2 * z2 + tz2;
00128
00129 tempCloud->push_back(point);
00130 }
00131 }
00132
00133 cloudRegInd = (cloudRegInd + 1) % keepSyncCloudNum;
00134 }
00135
00136 surroundCloud->clear();
00137 pcl::VoxelGrid<pcl::PointXYZ> downSizeFilter;
00138 downSizeFilter.setInputCloud(tempCloud);
00139 downSizeFilter.setLeafSize(0.2, 0.2, 0.2);
00140 downSizeFilter.filter(*surroundCloud);
00141 surroundCloudNum = surroundCloud->points.size();
00142
00143 surroundCloud->header.frame_id = "/camera_init";
00144 surroundCloud->header.stamp = voData->header.stamp;
00145 sensor_msgs::PointCloud2 surroundCloud2;
00146 pcl::toROSMsg(*surroundCloud, surroundCloud2);
00147 surroundCloudPubPointer->publish(surroundCloud2);
00148 }
00149
00150 rxRec = rx; ryRec = ry; rzRec = rz;
00151 txRec = tx; tyRec = ty; tzRec = tz;
00152
00153 timeRec = time;
00154 }
00155
00156 void syncCloudHandler(const sensor_msgs::Image::ConstPtr& syncCloud2)
00157 {
00158 cloudCount = (cloudCount + 1) % (cloudSkipNum + 1);
00159 if (cloudCount != 0) {
00160 return;
00161 }
00162
00163 double time = syncCloud2->header.stamp.toSec();
00164
00165 syncCloudInd = (syncCloudInd + 1) % keepSyncCloudNum;
00166 syncCloudTime[syncCloudInd] = time;
00167
00168 tempCloud2->clear();
00169 pcl::PointXYZ point;
00170 const float* syncCloud2Pointer = reinterpret_cast<const float*>(&syncCloud2->data[0]);
00171 for (int i = 0; i < imagePixelNum; i++) {
00172 float val = syncCloud2Pointer[i];
00173
00174 int xd = i % imageWidth;
00175 int yd = int(i / imageWidth);
00176
00177 float ud = (kDepth[2] - xd) / kDepth[0];
00178 float vd = (kDepth[5] - yd) / kDepth[4];
00179
00180 point.z = val;
00181 point.x = ud * val;
00182 point.y = vd * val;
00183
00184 if (point.z > 0.3 && point.z < 7) {
00185 tempCloud2->push_back(point);
00186 }
00187 }
00188
00189 pcl::PointCloud<pcl::PointXYZ>::Ptr syncCloudPointer = syncCloudArray[syncCloudInd];
00190 syncCloudPointer->clear();
00191
00192 pcl::VoxelGrid<pcl::PointXYZ> downSizeFilter;
00193 downSizeFilter.setInputCloud(tempCloud2);
00194 downSizeFilter.setLeafSize(0.1, 0.1, 0.1);
00195 downSizeFilter.filter(*syncCloudPointer);
00196 }
00197
00198 int main(int argc, char** argv)
00199 {
00200 ros::init(argc, argv, "registerPointCloud");
00201 ros::NodeHandle nh;
00202
00203 for (int i = 0; i < keepSyncCloudNum; i++) {
00204 pcl::PointCloud<pcl::PointXYZ>::Ptr syncCloudTemp(new pcl::PointCloud<pcl::PointXYZ>());
00205 syncCloudArray[i] = syncCloudTemp;
00206 }
00207
00208 ros::Subscriber voDataSub = nh.subscribe<nav_msgs::Odometry> ("/cam2_to_init", 5, voDataHandler);
00209
00210 ros::Subscriber syncCloudSub = nh.subscribe<sensor_msgs::Image>
00211 ("/camera/depth_registered/image", 1, syncCloudHandler);
00212
00213 ros::Publisher surroundCloudPub = nh.advertise<sensor_msgs::PointCloud2> ("/surround_cloud", 1);
00214 surroundCloudPubPointer = &surroundCloudPub;
00215
00216 ros::spin();
00217
00218 return 0;
00219 }