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
00046
00047
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
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
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
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
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
00425
00426
00427
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
00564
00565
00566
00567
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
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
00695
00696
00697
00698 coeffSel->push_back(coeff);
00699
00700 if (isPointSel) {
00701 pointSelInd[3 * i] = closestPointInd;
00702 pointSelInd[3 * i + 1] = minPointInd2;
00703 }
00704 } else {
00705
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;
00781 matAtB = matAt * matB;
00782 cv::solve(matAtA, matAtB, matX, cv::DECOMP_QR);
00783
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
00793
00794
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
00803 }
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
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
00935
00936 }
00937
00938 status = ros::ok();
00939 cvWaitKey(10);
00940 }
00941
00942 return 0;
00943 }