laserOdometry.cpp
Go to the documentation of this file.
00001 #include <math.h>
00002 #include <time.h>
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <ros/ros.h>
00006 
00007 #include <nav_msgs/Odometry.h>
00008 #include <sensor_msgs/Imu.h>
00009 #include <sensor_msgs/PointCloud2.h>
00010 
00011 #include <tf/transform_datatypes.h>
00012 #include <tf/transform_broadcaster.h>
00013 
00014 #include <opencv/cv.h>
00015 #include <opencv2/highgui/highgui.hpp>
00016 
00017 #include <pcl/ros/conversions.h>
00018 #include <pcl/point_cloud.h>
00019 #include <pcl/point_types.h>
00020 #include <pcl/filters/voxel_grid.h>
00021 #include <pcl/kdtree/kdtree_flann.h>
00022 
00023 
00024 const double PI = 3.1415926;
00025 const double rad2deg = 180 / PI;
00026 const double deg2rad = PI / 180;
00027 
00028 bool systemInited = false;
00029 
00030 double initTime;
00031 double timeLasted;
00032 double timeLastedRec;
00033 double startTimeCur;
00034 double startTimeLast;
00035 
00036 double timeLaserCloudExtreCur = 0;
00037 double timeLaserCloudLast = 0;
00038 
00039 bool newLaserCloudExtreCur = false;
00040 bool newLaserCloudLast = false;
00041 
00042 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreCur(new pcl::PointCloud<pcl::PointXYZHSV>());
00043 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreLast(new pcl::PointCloud<pcl::PointXYZHSV>());
00044 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreOri(new pcl::PointCloud<pcl::PointXYZHSV>());
00045 //pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreSel(new pcl::PointCloud<pcl::PointXYZHSV>());
00046 //pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreUnsel(new pcl::PointCloud<pcl::PointXYZHSV>());
00047 //pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreProj(new pcl::PointCloud<pcl::PointXYZHSV>());
00048 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudLast(new pcl::PointCloud<pcl::PointXYZHSV>());
00049 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudCornerLast(new pcl::PointCloud<pcl::PointXYZHSV>());
00050 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudSurfLast(new pcl::PointCloud<pcl::PointXYZHSV>());
00051 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudCornerLLast(new pcl::PointCloud<pcl::PointXYZHSV>());
00052 pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudSurfLLast(new pcl::PointCloud<pcl::PointXYZHSV>());
00053 //pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudSel(new pcl::PointCloud<pcl::PointXYZHSV>());
00054 pcl::PointCloud<pcl::PointXYZHSV>::Ptr coeffSel(new pcl::PointCloud<pcl::PointXYZHSV>());
00055 pcl::KdTreeFLANN<pcl::PointXYZHSV>::Ptr kdtreeCornerLast(new pcl::KdTreeFLANN<pcl::PointXYZHSV>());
00056 pcl::KdTreeFLANN<pcl::PointXYZHSV>::Ptr kdtreeSurfLast(new pcl::KdTreeFLANN<pcl::PointXYZHSV>());
00057 pcl::KdTreeFLANN<pcl::PointXYZHSV>::Ptr kdtreeCornerLLast(new pcl::KdTreeFLANN<pcl::PointXYZHSV>());
00058 pcl::KdTreeFLANN<pcl::PointXYZHSV>::Ptr kdtreeSurfLLast(new pcl::KdTreeFLANN<pcl::PointXYZHSV>());
00059 
00060 float transform[6] = {0};
00061 float transformRec[6] = {0};
00062 float transformSum[6] = {0};
00063 
00064 float imuRollStartCur = 0, imuPitchStartCur = 0, imuYawStartCur = 0;
00065 float imuRollCur = 0, imuPitchCur = 0, imuYawCur = 0;
00066 float imuShiftFromStartXCur = 0, imuShiftFromStartYCur = 0, imuShiftFromStartZCur = 0;
00067 float imuVeloFromStartXCur = 0, imuVeloFromStartYCur = 0, imuVeloFromStartZCur = 0;
00068 
00069 float imuRollStartLast = 0, imuPitchStartLast = 0, imuYawStartLast = 0;
00070 float imuRollLast = 0, imuPitchLast = 0, imuYawLast = 0;
00071 float imuShiftFromStartXLast = 0, imuShiftFromStartYLast = 0, imuShiftFromStartZLast = 0;
00072 float imuVeloFromStartXLast = 0, imuVeloFromStartYLast = 0, imuVeloFromStartZLast = 0;
00073 
00074 bool imuInited = false;
00075 
00076 void TransformReset()
00077 {
00078   for (int i = 0; i < 6; i++) {
00079     transformRec[i] = transform[i];
00080     transform[i] = 0;
00081   }
00082 
00083   transformRec[3] -= imuVeloFromStartXLast * (startTimeCur - startTimeLast);
00084   transformRec[4] -= imuVeloFromStartYLast * (startTimeCur - startTimeLast);
00085   transformRec[5] -= imuVeloFromStartZLast * (startTimeCur - startTimeLast);
00086 }
00087 
00088 void TransformToStart(pcl::PointXYZHSV *pi, pcl::PointXYZHSV *po, double startTime, double endTime)
00089 {
00090   float s = (pi->h - startTime) / (endTime - startTime);
00091 
00092   float rx = s * transform[0];
00093   float ry = s * transform[1];
00094   float rz = s * transform[2];
00095   float tx = s * transform[3];
00096   float ty = s * transform[4];
00097   float tz = s * transform[5];
00098 
00099   float x1 = cos(rz) * (pi->x - tx) + sin(rz) * (pi->y - ty);
00100   float y1 = -sin(rz) * (pi->x - tx) + cos(rz) * (pi->y - ty);
00101   float z1 = (pi->z - tz);
00102 
00103   float x2 = x1;
00104   float y2 = cos(rx) * y1 + sin(rx) * z1;
00105   float z2 = -sin(rx) * y1 + cos(rx) * z1;
00106 
00107   po->x = cos(ry) * x2 - sin(ry) * z2;
00108   po->y = y2;
00109   po->z = sin(ry) * x2 + cos(ry) * z2;
00110   po->h = pi->h;
00111   po->s = pi->s;
00112   po->v = pi->v;
00113 }
00114 
00115 void TransformToEnd(pcl::PointXYZHSV *pi, pcl::PointXYZHSV *po, double startTime, double endTime)
00116 {
00117   float s = (pi->h - startTime) / (endTime - startTime);
00118 
00119   float rx = s * transform[0];
00120   float ry = s * transform[1];
00121   float rz = s * transform[2];
00122   float tx = s * transform[3];
00123   float ty = s * transform[4];
00124   float tz = s * transform[5];
00125 
00126   float x1 = cos(rz) * (pi->x - tx) + sin(rz) * (pi->y - ty);
00127   float y1 = -sin(rz) * (pi->x - tx) + cos(rz) * (pi->y - ty);
00128   float z1 = (pi->z - tz);
00129 
00130   float x2 = x1;
00131   float y2 = cos(rx) * y1 + sin(rx) * z1;
00132   float z2 = -sin(rx) * y1 + cos(rx) * z1;
00133 
00134   float x3 = cos(ry) * x2 - sin(ry) * z2;
00135   float y3 = y2;
00136   float z3 = sin(ry) * x2 + cos(ry) * z2;
00137 
00138   rx = transform[0];
00139   ry = transform[1];
00140   rz = transform[2];
00141   tx = transform[3];
00142   ty = transform[4];
00143   tz = transform[5];
00144 
00145   float x4 = cos(ry) * x3 + sin(ry) * z3;
00146   float y4 = y3;
00147   float z4 = -sin(ry) * x3 + cos(ry) * z3;
00148 
00149   float x5 = x4;
00150   float y5 = cos(rx) * y4 - sin(rx) * z4;
00151   float z5 = sin(rx) * y4 + cos(rx) * z4;
00152 
00153   float x6 = cos(rz) * x5 - sin(rz) * y5 + tx;
00154   float y6 = sin(rz) * x5 + cos(rz) * y5 + ty;
00155   float z6 = z5 + tz;
00156 
00157   float x7 = cos(imuRollStartLast) * (x6 - imuShiftFromStartXLast) 
00158            - sin(imuRollStartLast) * (y6 - imuShiftFromStartYLast);
00159   float y7 = sin(imuRollStartLast) * (x6 - imuShiftFromStartXLast) 
00160            + cos(imuRollStartLast) * (y6 - imuShiftFromStartYLast);
00161   float z7 = z6 - imuShiftFromStartZLast;
00162 
00163   float x8 = x7;
00164   float y8 = cos(imuPitchStartLast) * y7 - sin(imuPitchStartLast) * z7;
00165   float z8 = sin(imuPitchStartLast) * y7 + cos(imuPitchStartLast) * z7;
00166 
00167   float x9 = cos(imuYawStartLast) * x8 + sin(imuYawStartLast) * z8;
00168   float y9 = y8;
00169   float z9 = -sin(imuYawStartLast) * x8 + cos(imuYawStartLast) * z8;
00170 
00171   float x10 = cos(imuYawLast) * x9 - sin(imuYawLast) * z9;
00172   float y10 = y9;
00173   float z10 = sin(imuYawLast) * x9 + cos(imuYawLast) * z9;
00174 
00175   float x11 = x10;
00176   float y11 = cos(imuPitchLast) * y10 + sin(imuPitchLast) * z10;
00177   float z11 = -sin(imuPitchLast) * y10 + cos(imuPitchLast) * z10;
00178 
00179   po->x = cos(imuRollLast) * x11 + sin(imuRollLast) * y11;
00180   po->y = -sin(imuRollLast) * x11 + cos(imuRollLast) * y11;
00181   po->z = z11;
00182   po->h = pi->h;
00183   po->s = pi->s;
00184   po->v = pi->v;
00185 }
00186 
00187 void laserCloudExtreCurHandler(const sensor_msgs::PointCloud2ConstPtr& laserCloudExtreCur2)
00188 {
00189   if (!systemInited) {
00190     initTime = laserCloudExtreCur2->header.stamp.toSec();
00191     systemInited = true;
00192   }
00193   timeLaserCloudExtreCur = laserCloudExtreCur2->header.stamp.toSec();
00194   timeLasted = timeLaserCloudExtreCur - initTime;
00195 
00196   pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudExtreCur3(new pcl::PointCloud<pcl::PointXYZHSV>());
00197   pcl::fromROSMsg(*laserCloudExtreCur2, *laserCloudExtreCur3);
00198   int laserCloudExtreCur3Size = laserCloudExtreCur3->points.size();
00199 
00200   laserCloudExtreCur->clear();
00201   for (int i = 0; i < laserCloudExtreCur3Size; i++) {
00202     if (fabs(laserCloudExtreCur3->points[i].v - 10) < 0.005) {
00203       imuPitchStartCur = laserCloudExtreCur3->points[i].x;
00204       imuYawStartCur = laserCloudExtreCur3->points[i].y;
00205       imuRollStartCur = laserCloudExtreCur3->points[i].z;
00206     } else if (fabs(laserCloudExtreCur3->points[i].v - 11) < 0.005) {
00207       imuPitchCur = laserCloudExtreCur3->points[i].x;
00208       imuYawCur = laserCloudExtreCur3->points[i].y;
00209       imuRollCur = laserCloudExtreCur3->points[i].z;
00210     } else if (fabs(laserCloudExtreCur3->points[i].v - 12) < 0.005) {
00211       imuShiftFromStartXCur = laserCloudExtreCur3->points[i].x;
00212       imuShiftFromStartYCur = laserCloudExtreCur3->points[i].y;
00213       imuShiftFromStartZCur = laserCloudExtreCur3->points[i].z;
00214     } else if (fabs(laserCloudExtreCur3->points[i].v - 13) < 0.005) {
00215       imuVeloFromStartXCur = laserCloudExtreCur3->points[i].x;
00216       imuVeloFromStartYCur = laserCloudExtreCur3->points[i].y;
00217       imuVeloFromStartZCur = laserCloudExtreCur3->points[i].z;
00218     } else {
00219       laserCloudExtreCur->push_back(laserCloudExtreCur3->points[i]);
00220     }
00221   }
00222   laserCloudExtreCur3->clear();
00223 
00224   if (!imuInited) {
00225     transformSum[0] += imuPitchStartCur;
00226     //transformSum[1] += imuYawStartCur;
00227     transformSum[2] += imuRollStartCur;
00228 
00229     imuInited = true;
00230   }
00231 
00232   if (timeLasted > 4.0) {
00233     newLaserCloudExtreCur = true;
00234   }
00235 }
00236 
00237 void laserCloudLastHandler(const sensor_msgs::PointCloud2ConstPtr& laserCloudLast2)
00238 {
00239   if (laserCloudLast2->header.stamp.toSec() > timeLaserCloudLast + 0.005) {
00240     timeLaserCloudLast = laserCloudLast2->header.stamp.toSec();
00241     startTimeLast = startTimeCur;
00242     startTimeCur = timeLaserCloudLast - initTime;
00243 
00244     pcl::PointCloud<pcl::PointXYZHSV>::Ptr laserCloudPointer = laserCloudCornerLLast;
00245     laserCloudCornerLLast = laserCloudCornerLast;
00246     laserCloudCornerLast = laserCloudPointer;
00247 
00248     laserCloudPointer = laserCloudSurfLLast;
00249     laserCloudSurfLLast = laserCloudSurfLast;
00250     laserCloudSurfLast = laserCloudPointer;
00251 
00252     laserCloudLast->clear();
00253     pcl::fromROSMsg(*laserCloudLast2, *laserCloudLast);
00254     int laserCloudLastSize = laserCloudLast->points.size();
00255 
00256     laserCloudExtreLast->clear();
00257     laserCloudCornerLast->clear();
00258     laserCloudSurfLast->clear();
00259     for (int i = 0; i < laserCloudLastSize; i++) {
00260       if (fabs(laserCloudLast->points[i].v - 2) < 0.005 || fabs(laserCloudLast->points[i].v + 1) < 0.005) {
00261         laserCloudExtreLast->push_back(laserCloudLast->points[i]);
00262       } 
00263       if (fabs(laserCloudLast->points[i].v - 2) < 0.005 || fabs(laserCloudLast->points[i].v - 1) < 0.005) {
00264         laserCloudCornerLast->push_back(laserCloudLast->points[i]);
00265       } 
00266       if (fabs(laserCloudLast->points[i].v) < 0.005 || fabs(laserCloudLast->points[i].v + 1) < 0.005) {
00267         laserCloudSurfLast->push_back(laserCloudLast->points[i]);
00268       }
00269       if (fabs(laserCloudLast->points[i].v - 10) < 0.005) {
00270         imuPitchStartLast = laserCloudLast->points[i].x;
00271         imuYawStartLast = laserCloudLast->points[i].y;
00272         imuRollStartLast = laserCloudLast->points[i].z;
00273       }
00274       if (fabs(laserCloudLast->points[i].v - 11) < 0.005) {
00275         imuPitchLast = laserCloudLast->points[i].x;
00276         imuYawLast = laserCloudLast->points[i].y;
00277         imuRollLast = laserCloudLast->points[i].z;
00278       }
00279       if (fabs(laserCloudLast->points[i].v - 12) < 0.005) {
00280         imuShiftFromStartXLast = laserCloudLast->points[i].x;
00281         imuShiftFromStartYLast = laserCloudLast->points[i].y;
00282         imuShiftFromStartZLast = laserCloudLast->points[i].z;
00283       }
00284       if (fabs(laserCloudLast->points[i].v - 13) < 0.005) {
00285         imuVeloFromStartXLast = laserCloudLast->points[i].x;
00286         imuVeloFromStartYLast = laserCloudLast->points[i].y;
00287         imuVeloFromStartZLast = laserCloudLast->points[i].z;
00288       }
00289     }
00290 
00291     pcl::KdTreeFLANN<pcl::PointXYZHSV>::Ptr kdtreePointer = kdtreeCornerLLast;
00292     kdtreeCornerLLast = kdtreeCornerLast;
00293     kdtreeCornerLast = kdtreePointer;
00294     kdtreeCornerLast->setInputCloud(laserCloudCornerLast);
00295 
00296     kdtreePointer = kdtreeSurfLLast;
00297     kdtreeSurfLLast = kdtreeSurfLast;
00298     kdtreeSurfLast = kdtreePointer;
00299     kdtreeSurfLast->setInputCloud(laserCloudSurfLast);
00300 
00301     if (timeLasted > 4.0) {
00302       newLaserCloudLast = true;
00303     }
00304   }
00305 }
00306 
00307 int main(int argc, char** argv)
00308 {
00309   ros::init(argc, argv, "laserOdometry");
00310   ros::NodeHandle nh;
00311 
00312   ros::Subscriber subLaserCloudExtreCur = nh.subscribe<sensor_msgs::PointCloud2> 
00313                                           ("/laser_cloud_extre_cur", 2, laserCloudExtreCurHandler);
00314 
00315   ros::Subscriber subLaserCloudLast = nh.subscribe<sensor_msgs::PointCloud2> 
00316                                       ("/laser_cloud_last", 2, laserCloudLastHandler);
00317 
00318   ros::Publisher pubLaserCloudLast2 = nh.advertise<sensor_msgs::PointCloud2> ("/laser_cloud_last_2", 2);
00319 
00320   //ros::Publisher pub1 = nh.advertise<sensor_msgs::PointCloud2> ("/pc1", 1);
00321 
00322   //ros::Publisher pub2 = nh.advertise<sensor_msgs::PointCloud2> ("/pc2", 1);
00323 
00324   //ros::Publisher pub3 = nh.advertise<sensor_msgs::PointCloud2> ("/pc3", 1);
00325 
00326   //ros::Publisher pub4 = nh.advertise<sensor_msgs::PointCloud2> ("/pc4", 1);
00327 
00328   //ros::Publisher pub5 = nh.advertise<sensor_msgs::PointCloud2> ("/pc5", 1);
00329 
00330   //ros::Publisher pub6 = nh.advertise<sensor_msgs::PointCloud2> ("/pc6", 1);
00331 
00332   ros::Publisher pubLaserOdometry = nh.advertise<nav_msgs::Odometry> ("/cam_to_init", 5);
00333   nav_msgs::Odometry laserOdometry;
00334   laserOdometry.header.frame_id = "/camera_init";
00335   laserOdometry.child_frame_id = "/camera";
00336 
00337   tf::TransformBroadcaster tfBroadcaster;
00338   tf::StampedTransform laserOdometryTrans;
00339   laserOdometryTrans.frame_id_ = "/camera_init";
00340   laserOdometryTrans.child_frame_id_ = "/camera";
00341 
00342   std::vector<int> pointSearchInd;
00343   std::vector<float> pointSearchSqDis;
00344   std::vector<int> pointSelInd;
00345 
00346   pcl::PointXYZHSV extreOri, extreSel, extreProj, tripod1, tripod2, tripod3, coeff;
00347 
00348   bool status = ros::ok();
00349   while (status) {
00350     ros::spinOnce();
00351 
00352     bool sweepEnd = false;
00353     bool newLaserPoints = false;
00354     bool sufficientPoints = false;
00355     double startTime, endTime;
00356     pcl::PointCloud<pcl::PointXYZHSV>::Ptr extrePointsPtr, laserCloudCornerPtr, laserCloudSurfPtr;
00357     pcl::KdTreeFLANN<pcl::PointXYZHSV>::Ptr kdtreeCornerPtr, kdtreeSurfPtr;
00358     if (newLaserCloudExtreCur && newLaserCloudLast) {
00359 
00360       startTime = startTimeLast;
00361       endTime = startTimeCur;
00362 
00363       extrePointsPtr = laserCloudExtreLast;
00364       laserCloudCornerPtr = laserCloudCornerLLast;
00365       laserCloudSurfPtr = laserCloudSurfLLast;
00366       kdtreeCornerPtr = kdtreeCornerLLast;
00367       kdtreeSurfPtr = kdtreeSurfLLast;
00368 
00369       laserOdometry.header.stamp = ros::Time().fromSec(timeLaserCloudLast);
00370       laserOdometryTrans.stamp_ = ros::Time().fromSec(timeLaserCloudLast);
00371 
00372       sweepEnd = true;
00373       newLaserPoints = true;
00374 
00375       if (laserCloudSurfLLast->points.size() >= 100) {
00376         sufficientPoints = true;
00377       }
00378 
00379     } else if (newLaserCloudExtreCur) {
00380 
00381       startTime = startTimeCur;
00382       endTime = timeLasted;
00383 
00384       extrePointsPtr = laserCloudExtreCur;
00385       laserCloudCornerPtr = laserCloudCornerLast;
00386       laserCloudSurfPtr = laserCloudSurfLast;
00387       kdtreeCornerPtr = kdtreeCornerLast;
00388       kdtreeSurfPtr = kdtreeSurfLast;
00389 
00390       laserOdometry.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00391       laserOdometryTrans.stamp_ = ros::Time().fromSec(timeLaserCloudExtreCur);
00392 
00393       float s = (timeLasted - timeLastedRec) / (startTimeCur - startTimeLast);
00394       for (int i = 0; i < 6; i++) {
00395         transform[i] += s * transformRec[i];        
00396       }
00397       timeLastedRec = timeLasted;
00398 
00399       newLaserPoints = true;
00400 
00401       if (laserCloudSurfLast->points.size() >= 100) {
00402         sufficientPoints = true;
00403       }
00404     }
00405 
00406     if (newLaserPoints && sufficientPoints) {
00407       newLaserCloudExtreCur = false;
00408       newLaserCloudLast = false;
00409 
00410       int extrePointNum = extrePointsPtr->points.size();
00411       int laserCloudCornerNum = laserCloudCornerPtr->points.size();
00412       int laserCloudSurfNum = laserCloudSurfPtr->points.size();
00413 
00414       float st = 1;
00415       if (!sweepEnd) {
00416         st = (timeLasted - startTime) / (startTimeCur - startTimeLast);
00417       }
00418       int iterNum = st * 50;
00419 
00420       int pointSelSkipNum = 2;
00421       for (int iterCount = 0; iterCount < iterNum; iterCount++) {
00422 
00423         laserCloudExtreOri->clear();
00424         //laserCloudExtreSel->clear();
00425         //laserCloudExtreUnsel->clear();
00426         //laserCloudExtreProj->clear();
00427         //laserCloudSel->clear();
00428         coeffSel->clear();
00429 
00430         bool isPointSel = false;
00431         if (iterCount % (pointSelSkipNum + 1) == 0) {
00432           isPointSel = true;
00433           pointSelInd.clear();
00434         }
00435 
00436         for (int i = 0; i < extrePointNum; i++) {
00437           extreOri = extrePointsPtr->points[i];
00438           TransformToStart(&extreOri, &extreSel, startTime, endTime);
00439 
00440           if (isPointSel) {
00441             pointSelInd.push_back(-1);
00442             pointSelInd.push_back(-1);
00443             pointSelInd.push_back(-1);
00444           }
00445 
00446           if (fabs(extreOri.v + 1) < 0.05) {
00447 
00448             int closestPointInd = -1, minPointInd2 = -1, minPointInd3 = -1;
00449             if (isPointSel) {
00450               kdtreeSurfPtr->nearestKSearch(extreSel, 1, pointSearchInd, pointSearchSqDis);
00451               if (pointSearchSqDis[0] > 1.0) {
00452                 continue;
00453               }
00454 
00455               closestPointInd = pointSearchInd[0];
00456               float closestPointTime = laserCloudSurfPtr->points[closestPointInd].h;
00457 
00458               float pointSqDis, minPointSqDis2 = 1, minPointSqDis3 = 1;
00459               for (int j = closestPointInd + 1; j < laserCloudSurfNum; j++) {
00460                 if (laserCloudSurfPtr->points[j].h > closestPointTime + 0.07) {
00461                   break;
00462                 }
00463 
00464                 pointSqDis = (laserCloudSurfPtr->points[j].x - extreSel.x) * 
00465                              (laserCloudSurfPtr->points[j].x - extreSel.x) + 
00466                              (laserCloudSurfPtr->points[j].y - extreSel.y) * 
00467                              (laserCloudSurfPtr->points[j].y - extreSel.y) + 
00468                              (laserCloudSurfPtr->points[j].z - extreSel.z) * 
00469                              (laserCloudSurfPtr->points[j].z - extreSel.z);
00470 
00471                 if (laserCloudSurfPtr->points[j].h < closestPointTime + 0.005) {
00472                    if (pointSqDis < minPointSqDis2) {
00473                      minPointSqDis2 = pointSqDis;
00474                      minPointInd2 = j;
00475                    }
00476                 } else {
00477                    if (pointSqDis < minPointSqDis3) {
00478                      minPointSqDis3 = pointSqDis;
00479                      minPointInd3 = j;
00480                    }
00481                 }
00482               }
00483               for (int j = closestPointInd - 1; j >= 0; j--) {
00484                 if (laserCloudSurfPtr->points[j].h < closestPointTime - 0.07) {
00485                   break;
00486                 }
00487 
00488                 pointSqDis = (laserCloudSurfPtr->points[j].x - extreSel.x) * 
00489                              (laserCloudSurfPtr->points[j].x - extreSel.x) + 
00490                              (laserCloudSurfPtr->points[j].y - extreSel.y) * 
00491                              (laserCloudSurfPtr->points[j].y - extreSel.y) + 
00492                              (laserCloudSurfPtr->points[j].z - extreSel.z) * 
00493                              (laserCloudSurfPtr->points[j].z - extreSel.z);
00494 
00495                 if (laserCloudSurfPtr->points[j].h > closestPointTime - 0.005) {
00496                    if (pointSqDis < minPointSqDis2) {
00497                      minPointSqDis2 = pointSqDis;
00498                      minPointInd2 = j;
00499                    }
00500                 } else {
00501                    if (pointSqDis < minPointSqDis3) {
00502                      minPointSqDis3 = pointSqDis;
00503                      minPointInd3 = j;
00504                    }
00505                 }
00506               }
00507             } else {
00508               if (pointSelInd[3 * i] >= 0) {
00509                 closestPointInd = pointSelInd[3 * i];
00510                 minPointInd2 = pointSelInd[3 * i + 1];
00511                 minPointInd3 = pointSelInd[3 * i + 2];
00512 
00513                 float distX = extreSel.x - laserCloudSurfPtr->points[closestPointInd].x;
00514                 float distY = extreSel.y - laserCloudSurfPtr->points[closestPointInd].y;
00515                 float distZ = extreSel.z - laserCloudSurfPtr->points[closestPointInd].z;
00516                 if (distX * distX + distY * distY + distZ * distZ > 1.0) {
00517                   continue;
00518                 }
00519               } else {
00520                 continue;
00521               }
00522             }
00523 
00524             if (minPointInd2 >= 0 && minPointInd3 >= 0) {
00525               tripod1 = laserCloudSurfPtr->points[closestPointInd];
00526               tripod2 = laserCloudSurfPtr->points[minPointInd2];
00527               tripod3 = laserCloudSurfPtr->points[minPointInd3];
00528 
00529               float pa = (tripod2.y - tripod1.y) * (tripod3.z - tripod1.z) 
00530                        - (tripod3.y - tripod1.y) * (tripod2.z - tripod1.z);
00531               float pb = (tripod2.z - tripod1.z) * (tripod3.x - tripod1.x) 
00532                        - (tripod3.z - tripod1.z) * (tripod2.x - tripod1.x);
00533               float pc = (tripod2.x - tripod1.x) * (tripod3.y - tripod1.y) 
00534                        - (tripod3.x - tripod1.x) * (tripod2.y - tripod1.y);
00535               float pd = -(pa * tripod1.x + pb * tripod1.y + pc * tripod1.z);
00536 
00537               float ps = sqrt(pa * pa + pb * pb + pc * pc);
00538               pa /= ps;
00539               pb /= ps;
00540               pc /= ps;
00541               pd /= ps;
00542 
00543               float pd2 = pa * extreSel.x + pb * extreSel.y + pc * extreSel.z + pd;
00544 
00545               extreProj = extreSel;
00546               extreProj.x -= pa * pd2;
00547               extreProj.y -= pb * pd2;
00548               extreProj.z -= pc * pd2;
00549 
00550               float s = 1;
00551               if (iterCount >= 30) {
00552                 s = 1 - 8 * fabs(pd2) / sqrt(sqrt(extreSel.x * extreSel.x
00553                   + extreSel.y * extreSel.y + extreSel.z * extreSel.z));
00554               }
00555 
00556               coeff.x = s * pa;
00557               coeff.y = s * pb;
00558               coeff.z = s * pc;
00559               coeff.h = s * pd2;
00560 
00561               if (s > 0.2 || iterNum < 30) {
00562                 laserCloudExtreOri->push_back(extreOri);
00563                 //laserCloudExtreSel->push_back(extreSel);
00564                 //laserCloudExtreProj->push_back(extreProj);
00565                 //laserCloudSel->push_back(tripod1);
00566                 //laserCloudSel->push_back(tripod2);
00567                 //laserCloudSel->push_back(tripod3);
00568                 coeffSel->push_back(coeff);
00569 
00570                 if (isPointSel) {
00571                   pointSelInd[3 * i] = closestPointInd;
00572                   pointSelInd[3 * i + 1] = minPointInd2;
00573                   pointSelInd[3 * i + 2] = minPointInd3;
00574                 }
00575               } else {
00576                 //laserCloudExtreUnsel->push_back(extreSel);
00577               }
00578             }
00579           } else if (fabs(extreOri.v - 2) < 0.05) {
00580 
00581             int closestPointInd = -1, minPointInd2 = -1;
00582             if (isPointSel) {
00583               kdtreeCornerPtr->nearestKSearch(extreSel, 1, pointSearchInd, pointSearchSqDis);
00584               if (pointSearchSqDis[0] > 1.0) {
00585                 continue;
00586               }
00587 
00588               closestPointInd = pointSearchInd[0];
00589               float closestPointTime = laserCloudCornerPtr->points[closestPointInd].h;
00590 
00591               float pointSqDis, minPointSqDis2 = 1;
00592               for (int j = closestPointInd + 1; j < laserCloudCornerNum; j++) {
00593                 if (laserCloudCornerPtr->points[j].h > closestPointTime + 0.07) {
00594                   break;
00595                 }
00596 
00597                 pointSqDis = (laserCloudCornerPtr->points[j].x - extreSel.x) * 
00598                              (laserCloudCornerPtr->points[j].x - extreSel.x) + 
00599                              (laserCloudCornerPtr->points[j].y - extreSel.y) * 
00600                              (laserCloudCornerPtr->points[j].y - extreSel.y) + 
00601                              (laserCloudCornerPtr->points[j].z - extreSel.z) * 
00602                              (laserCloudCornerPtr->points[j].z - extreSel.z);
00603 
00604                 if (laserCloudCornerPtr->points[j].h > closestPointTime + 0.005) {
00605                    if (pointSqDis < minPointSqDis2) {
00606                      minPointSqDis2 = pointSqDis;
00607                      minPointInd2 = j;
00608                    }
00609                 }
00610               }
00611               for (int j = closestPointInd - 1; j >= 0; j--) {
00612                 if (laserCloudCornerPtr->points[j].h < closestPointTime - 0.07) {
00613                   break;
00614                 }
00615 
00616                 pointSqDis = (laserCloudCornerPtr->points[j].x - extreSel.x) * 
00617                              (laserCloudCornerPtr->points[j].x - extreSel.x) + 
00618                              (laserCloudCornerPtr->points[j].y - extreSel.y) * 
00619                              (laserCloudCornerPtr->points[j].y - extreSel.y) + 
00620                              (laserCloudCornerPtr->points[j].z - extreSel.z) * 
00621                              (laserCloudCornerPtr->points[j].z - extreSel.z);
00622 
00623                 if (laserCloudCornerPtr->points[j].h < closestPointTime - 0.005) {
00624                    if (pointSqDis < minPointSqDis2) {
00625                      minPointSqDis2 = pointSqDis;
00626                      minPointInd2 = j;
00627                    }
00628                 }
00629               }
00630             } else {
00631               if (pointSelInd[3 * i] >= 0) {
00632                 closestPointInd = pointSelInd[3 * i];
00633                 minPointInd2 = pointSelInd[3 * i + 1];
00634 
00635                 float distX = extreSel.x - laserCloudCornerPtr->points[closestPointInd].x;
00636                 float distY = extreSel.y - laserCloudCornerPtr->points[closestPointInd].y;
00637                 float distZ = extreSel.z - laserCloudCornerPtr->points[closestPointInd].z;
00638                 if (distX * distX + distY * distY + distZ * distZ > 1.0) {
00639                   continue;
00640                 }
00641               } else {
00642                 continue;
00643               }
00644             }
00645 
00646             if (minPointInd2 >= 0) {
00647               tripod1 = laserCloudCornerPtr->points[closestPointInd];
00648               tripod2 = laserCloudCornerPtr->points[minPointInd2];
00649 
00650               float x0 = extreSel.x;
00651               float y0 = extreSel.y;
00652               float z0 = extreSel.z;
00653               float x1 = tripod1.x;
00654               float y1 = tripod1.y;
00655               float z1 = tripod1.z;
00656               float x2 = tripod2.x;
00657               float y2 = tripod2.y;
00658               float z2 = tripod2.z;
00659 
00660               float a012 = sqrt(((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))
00661                         * ((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1)) 
00662                         + ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))
00663                         * ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1)) 
00664                         + ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))
00665                         * ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1)));
00666 
00667               float l12 = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));
00668 
00669               float la = ((y1 - y2)*((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1)) 
00670                        + (z1 - z2)*((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))) / a012 / l12;
00671 
00672               float lb = -((x1 - x2)*((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1)) 
00673                        - (z1 - z2)*((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))) / a012 / l12;
00674 
00675               float lc = -((x1 - x2)*((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1)) 
00676                        + (y1 - y2)*((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))) / a012 / l12;
00677 
00678               float ld2 = a012 / l12;
00679 
00680               extreProj = extreSel;
00681               extreProj.x -= la * ld2;
00682               extreProj.y -= lb * ld2;
00683               extreProj.z -= lc * ld2;
00684 
00685               float s = 2 * (1 - 8 * fabs(ld2));
00686 
00687               coeff.x = s * la;
00688               coeff.y = s * lb;
00689               coeff.z = s * lc;
00690               coeff.h = s * ld2;
00691 
00692               if (s > 0.4) {
00693                 laserCloudExtreOri->push_back(extreOri);
00694                 //laserCloudExtreSel->push_back(extreSel);
00695                 //laserCloudExtreProj->push_back(extreProj);
00696                 //laserCloudSel->push_back(tripod1);
00697                 //laserCloudSel->push_back(tripod2);
00698                 coeffSel->push_back(coeff);
00699 
00700                 if (isPointSel) {
00701                   pointSelInd[3 * i] = closestPointInd;
00702                   pointSelInd[3 * i + 1] = minPointInd2;
00703                 }
00704               } else {
00705                 //laserCloudExtreUnsel->push_back(extreSel);
00706               }
00707             }
00708           }
00709         }
00710         int extrePointSelNum = laserCloudExtreOri->points.size();
00711 
00712         if (extrePointSelNum < 10) {
00713           continue;
00714         }
00715 
00716         cv::Mat matA(extrePointSelNum, 6, CV_32F, cv::Scalar::all(0));
00717         cv::Mat matAt(6, extrePointSelNum, CV_32F, cv::Scalar::all(0));
00718         cv::Mat matAtA(6, 6, CV_32F, cv::Scalar::all(0));
00719         cv::Mat matB(extrePointSelNum, 1, CV_32F, cv::Scalar::all(0));
00720         cv::Mat matAtB(6, 1, CV_32F, cv::Scalar::all(0));
00721         cv::Mat matX(6, 1, CV_32F, cv::Scalar::all(0));
00722         for (int i = 0; i < extrePointSelNum; i++) {
00723           extreOri = laserCloudExtreOri->points[i];
00724           coeff = coeffSel->points[i];
00725 
00726           float s = (extreOri.h - startTime) / (endTime - startTime);
00727 
00728           float srx = sin(s * transform[0]);
00729           float crx = cos(s * transform[0]);
00730           float sry = sin(s * transform[1]);
00731           float cry = cos(s * transform[1]);
00732           float srz = sin(s * transform[2]);
00733           float crz = cos(s * transform[2]);
00734           float tx = s * transform[3];
00735           float ty = s * transform[4];
00736           float tz = s * transform[5];
00737 
00738           float arx = (-s*crx*sry*srz*extreOri.x + s*crx*crz*sry*extreOri.y + s*srx*sry*extreOri.z 
00739                     + s*tx*crx*sry*srz - s*ty*crx*crz*sry - s*tz*srx*sry) * coeff.x
00740                     + (s*srx*srz*extreOri.x - s*crz*srx*extreOri.y + s*crx*extreOri.z
00741                     + s*ty*crz*srx - s*tz*crx - s*tx*srx*srz) * coeff.y
00742                     + (s*crx*cry*srz*extreOri.x - s*crx*cry*crz*extreOri.y - s*cry*srx*extreOri.z
00743                     + s*tz*cry*srx + s*ty*crx*cry*crz - s*tx*crx*cry*srz) * coeff.z;
00744 
00745           float ary = ((-s*crz*sry - s*cry*srx*srz)*extreOri.x 
00746                     + (s*cry*crz*srx - s*sry*srz)*extreOri.y - s*crx*cry*extreOri.z 
00747                     + tx*(s*crz*sry + s*cry*srx*srz) + ty*(s*sry*srz - s*cry*crz*srx) 
00748                     + s*tz*crx*cry) * coeff.x
00749                     + ((s*cry*crz - s*srx*sry*srz)*extreOri.x 
00750                     + (s*cry*srz + s*crz*srx*sry)*extreOri.y - s*crx*sry*extreOri.z
00751                     + s*tz*crx*sry - ty*(s*cry*srz + s*crz*srx*sry) 
00752                     - tx*(s*cry*crz - s*srx*sry*srz)) * coeff.z;
00753 
00754           float arz = ((-s*cry*srz - s*crz*srx*sry)*extreOri.x + (s*cry*crz - s*srx*sry*srz)*extreOri.y
00755                     + tx*(s*cry*srz + s*crz*srx*sry) - ty*(s*cry*crz - s*srx*sry*srz)) * coeff.x
00756                     + (-s*crx*crz*extreOri.x - s*crx*srz*extreOri.y
00757                     + s*ty*crx*srz + s*tx*crx*crz) * coeff.y
00758                     + ((s*cry*crz*srx - s*sry*srz)*extreOri.x + (s*crz*sry + s*cry*srx*srz)*extreOri.y
00759                     + tx*(s*sry*srz - s*cry*crz*srx) - ty*(s*crz*sry + s*cry*srx*srz)) * coeff.z;
00760 
00761           float atx = -s*(cry*crz - srx*sry*srz) * coeff.x + s*crx*srz * coeff.y 
00762                     - s*(crz*sry + cry*srx*srz) * coeff.z;
00763   
00764           float aty = -s*(cry*srz + crz*srx*sry) * coeff.x - s*crx*crz * coeff.y 
00765                     - s*(sry*srz - cry*crz*srx) * coeff.z;
00766   
00767           float atz = s*crx*sry * coeff.x - s*srx * coeff.y - s*crx*cry * coeff.z;
00768   
00769           float d2 = coeff.h;
00770 
00771           matA.at<float>(i, 0) = arx;
00772           matA.at<float>(i, 1) = ary;
00773           matA.at<float>(i, 2) = arz;
00774           matA.at<float>(i, 3) = atx;
00775           matA.at<float>(i, 4) = aty;
00776           matA.at<float>(i, 5) = atz;
00777           matB.at<float>(i, 0) = -0.015 * st * d2;
00778         }
00779         cv::transpose(matA, matAt);
00780         matAtA = matAt * matA; //+ 0.1 * cv::Mat::eye(6, 6, CV_32F);
00781         matAtB = matAt * matB;
00782         cv::solve(matAtA, matAtB, matX, cv::DECOMP_QR);
00783         //cv::solve(matA, matB, matX, cv::DECOMP_SVD);
00784 
00785         if (fabs(matX.at<float>(0, 0)) < 0.005 &&
00786             fabs(matX.at<float>(1, 0)) < 0.005 &&
00787             fabs(matX.at<float>(2, 0)) < 0.005 &&
00788             fabs(matX.at<float>(3, 0)) < 0.01 &&
00789             fabs(matX.at<float>(4, 0)) < 0.01 &&
00790             fabs(matX.at<float>(5, 0)) < 0.01) {
00791 
00792           //transform[0] += 0.7 * matX.at<float>(0, 0);
00793           //transform[1] += 0.7 * matX.at<float>(1, 0);
00794           //transform[2] += 0.7 * matX.at<float>(2, 0);
00795           transform[0] += 0.1 * matX.at<float>(0, 0);
00796           transform[1] += 0.1 * matX.at<float>(1, 0);
00797           transform[2] += 0.1 * matX.at<float>(2, 0);
00798           transform[3] += matX.at<float>(3, 0);
00799           transform[4] += matX.at<float>(4, 0);
00800           transform[5] += matX.at<float>(5, 0);
00801         } else {
00802           //ROS_INFO ("Odometry update out of bound");
00803         }
00804       }
00805 
00806       /*sensor_msgs::PointCloud2 pc12;
00807       pcl::toROSMsg(*laserCloudCornerPtr, pc12);
00808       pc12.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00809       pc12.header.frame_id = "/camera";
00810       pub1.publish(pc12);
00811 
00812       sensor_msgs::PointCloud2 pc22;
00813       pcl::toROSMsg(*laserCloudSurfPtr, pc22);
00814       pc22.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00815       pc22.header.frame_id = "/camera";
00816       pub2.publish(pc22);
00817 
00818       sensor_msgs::PointCloud2 pc32;
00819       pcl::toROSMsg(*laserCloudExtreSel, pc32);
00820       pc32.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00821       pc32.header.frame_id = "/camera";
00822       pub3.publish(pc32);
00823 
00824       sensor_msgs::PointCloud2 pc42;
00825       pcl::toROSMsg(*laserCloudExtreUnsel, pc42);
00826       pc42.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00827       pc42.header.frame_id = "/camera";
00828       pub4.publish(pc42);
00829 
00830       sensor_msgs::PointCloud2 pc52;
00831       pcl::toROSMsg(*laserCloudExtreProj, pc52);
00832       pc52.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00833       pc52.header.frame_id = "/camera";
00834       pub5.publish(pc52);
00835 
00836       sensor_msgs::PointCloud2 pc62;
00837       pcl::toROSMsg(*laserCloudSel, pc62);
00838       pc62.header.stamp = ros::Time().fromSec(timeLaserCloudExtreCur);
00839       pc62.header.frame_id = "/camera";
00840       pub6.publish(pc62);*/
00841     }
00842 
00843     if (newLaserPoints) {
00844       float rx, ry, rz, tx, ty, tz;
00845       if (sweepEnd) {
00846         rx = transformSum[0] - transform[0];
00847         ry = transformSum[1] - transform[1] * 1.05;
00848         rz = transformSum[2] - transform[2];
00849 
00850         float x1 = cos(rz) * (transform[3] - imuShiftFromStartXLast) 
00851                  - sin(rz) * (transform[4] - imuShiftFromStartYLast);
00852         float y1 = sin(rz) * (transform[3] - imuShiftFromStartXLast) 
00853                  + cos(rz) * (transform[4] - imuShiftFromStartYLast);
00854         float z1 = transform[5] * 1.05 - imuShiftFromStartZLast;
00855 
00856         float x2 = x1;
00857         float y2 = cos(rx) * y1 - sin(rx) * z1;
00858         float z2 = sin(rx) * y1 + cos(rx) * z1;
00859 
00860         tx = transformSum[3] - (cos(ry) * x2 + sin(ry) * z2);
00861         ty = transformSum[4] - y2;
00862         tz = transformSum[5] - (-sin(ry) * x2 + cos(ry) * z2);
00863 
00864         rx += imuPitchLast - imuPitchStartLast;
00865         ry += imuYawLast - imuYawStartLast;
00866         rz += imuRollLast - imuRollStartLast;
00867 
00868         int laserCloudCornerLastNum = laserCloudCornerLast->points.size();
00869         for (int i = 0; i < laserCloudCornerLastNum; i++) {
00870           TransformToEnd(&laserCloudCornerLast->points[i], &laserCloudCornerLast->points[i], 
00871                          startTimeLast, startTimeCur);
00872         }
00873 
00874         int laserCloudSurfLastNum = laserCloudSurfLast->points.size();
00875         for (int i = 0; i < laserCloudSurfLastNum; i++) {
00876           TransformToEnd(&laserCloudSurfLast->points[i], &laserCloudSurfLast->points[i], 
00877                          startTimeLast, startTimeCur);
00878         }
00879 
00880         TransformReset();
00881 
00882         transformSum[0] = rx;
00883         transformSum[1] = ry;
00884         transformSum[2] = rz;
00885         transformSum[3] = tx;
00886         transformSum[4] = ty;
00887         transformSum[5] = tz;
00888 
00889         sensor_msgs::PointCloud2 laserCloudLast2;
00890         pcl::toROSMsg(*laserCloudCornerLast + *laserCloudSurfLast, laserCloudLast2);
00891         laserCloudLast2.header.stamp = ros::Time().fromSec(timeLaserCloudLast);
00892         laserCloudLast2.header.frame_id = "/camera";
00893         pubLaserCloudLast2.publish(laserCloudLast2);
00894 
00895       } else {
00896         rx = transformSum[0] - transform[0];
00897         ry = transformSum[1] - transform[1] * 1.05;
00898         rz = transformSum[2] - transform[2];
00899 
00900         float x1 = cos(rz) * (transform[3] - imuShiftFromStartXCur) 
00901                  - sin(rz) * (transform[4] - imuShiftFromStartYCur);
00902         float y1 = sin(rz) * (transform[3] - imuShiftFromStartXCur) 
00903                  + cos(rz) * (transform[4] - imuShiftFromStartYCur);
00904         float z1 = transform[5] * 1.05 - imuShiftFromStartZCur;
00905 
00906         float x2 = x1;
00907         float y2 = cos(rx) * y1 - sin(rx) * z1;
00908         float z2 = sin(rx) * y1 + cos(rx) * z1;
00909 
00910         tx = transformSum[3] - (cos(ry) * x2 + sin(ry) * z2);
00911         ty = transformSum[4] - y2;
00912         tz = transformSum[5] - (-sin(ry) * x2 + cos(ry) * z2);
00913 
00914         rx += imuPitchCur - imuPitchStartCur;
00915         ry += imuYawCur - imuYawStartCur;
00916         rz += imuRollCur - imuRollStartCur;
00917       }
00918 
00919       geometry_msgs::Quaternion geoQuat = tf::createQuaternionMsgFromRollPitchYaw(rz, -rx, -ry);
00920 
00921       laserOdometry.pose.pose.orientation.x = -geoQuat.y;
00922       laserOdometry.pose.pose.orientation.y = -geoQuat.z;
00923       laserOdometry.pose.pose.orientation.z = geoQuat.x;
00924       laserOdometry.pose.pose.orientation.w = geoQuat.w;
00925       laserOdometry.pose.pose.position.x = tx;
00926       laserOdometry.pose.pose.position.y = ty;
00927       laserOdometry.pose.pose.position.z = tz;
00928       pubLaserOdometry.publish(laserOdometry);
00929 
00930       laserOdometryTrans.setRotation(tf::Quaternion(-geoQuat.y, -geoQuat.z, geoQuat.x, geoQuat.w));
00931       laserOdometryTrans.setOrigin(tf::Vector3(tx, ty, tz));
00932       tfBroadcaster.sendTransform(laserOdometryTrans);
00933 
00934       //ROS_INFO ("%f %f %f %f %f %f", transformSum[0], transformSum[1], transformSum[2], 
00935       //                               transformSum[3], transformSum[4], transformSum[5]);
00936     }
00937 
00938     status = ros::ok();
00939     cvWaitKey(10);
00940   }
00941 
00942   return 0;
00943 }


loam_back_and_forth
Author(s): Ji Zhang
autogenerated on Tue Jan 7 2014 11:20:25