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_conversions/pcl_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 const double PI = 3.1415926;
00024
00025 const float scanPeriod = 0.1;
00026
00027 const int skipFrameNum = 1;
00028 bool systemInited = false;
00029
00030 double timeCornerPointsSharp = 0;
00031 double timeCornerPointsLessSharp = 0;
00032 double timeSurfPointsFlat = 0;
00033 double timeSurfPointsLessFlat = 0;
00034 double timeLaserCloudFullRes = 0;
00035 double timeImuTrans = 0;
00036
00037 bool newCornerPointsSharp = false;
00038 bool newCornerPointsLessSharp = false;
00039 bool newSurfPointsFlat = false;
00040 bool newSurfPointsLessFlat = false;
00041 bool newLaserCloudFullRes = false;
00042 bool newImuTrans = false;
00043
00044 pcl::PointCloud<pcl::PointXYZI>::Ptr cornerPointsSharp(new pcl::PointCloud<pcl::PointXYZI>());
00045 pcl::PointCloud<pcl::PointXYZI>::Ptr cornerPointsLessSharp(new pcl::PointCloud<pcl::PointXYZI>());
00046 pcl::PointCloud<pcl::PointXYZI>::Ptr surfPointsFlat(new pcl::PointCloud<pcl::PointXYZI>());
00047 pcl::PointCloud<pcl::PointXYZI>::Ptr surfPointsLessFlat(new pcl::PointCloud<pcl::PointXYZI>());
00048 pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudCornerLast(new pcl::PointCloud<pcl::PointXYZI>());
00049 pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudSurfLast(new pcl::PointCloud<pcl::PointXYZI>());
00050 pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudOri(new pcl::PointCloud<pcl::PointXYZI>());
00051
00052
00053
00054
00055 pcl::PointCloud<pcl::PointXYZI>::Ptr coeffSel(new pcl::PointCloud<pcl::PointXYZI>());
00056 pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudFullRes(new pcl::PointCloud<pcl::PointXYZI>());
00057 pcl::PointCloud<pcl::PointXYZ>::Ptr imuTrans(new pcl::PointCloud<pcl::PointXYZ>());
00058 pcl::KdTreeFLANN<pcl::PointXYZI>::Ptr kdtreeCornerLast(new pcl::KdTreeFLANN<pcl::PointXYZI>());
00059 pcl::KdTreeFLANN<pcl::PointXYZI>::Ptr kdtreeSurfLast(new pcl::KdTreeFLANN<pcl::PointXYZI>());
00060
00061 int laserCloudCornerLastNum;
00062 int laserCloudSurfLastNum;
00063
00064 int pointSelCornerInd[40000];
00065 float pointSearchCornerInd1[40000];
00066 float pointSearchCornerInd2[40000];
00067
00068 int pointSelSurfInd[40000];
00069 float pointSearchSurfInd1[40000];
00070 float pointSearchSurfInd2[40000];
00071 float pointSearchSurfInd3[40000];
00072
00073 float transform[6] = {0};
00074 float transformSum[6] = {0};
00075
00076 float imuRollStart = 0, imuPitchStart = 0, imuYawStart = 0;
00077 float imuRollLast = 0, imuPitchLast = 0, imuYawLast = 0;
00078 float imuShiftFromStartX = 0, imuShiftFromStartY = 0, imuShiftFromStartZ = 0;
00079 float imuVeloFromStartX = 0, imuVeloFromStartY = 0, imuVeloFromStartZ = 0;
00080
00081 void TransformToStart(pcl::PointXYZI *pi, pcl::PointXYZI *po)
00082 {
00083 float s = 10 * (pi->intensity - int(pi->intensity));
00084
00085 float rx = s * transform[0];
00086 float ry = s * transform[1];
00087 float rz = s * transform[2];
00088 float tx = s * transform[3];
00089 float ty = s * transform[4];
00090 float tz = s * transform[5];
00091
00092 float x1 = cos(rz) * (pi->x - tx) + sin(rz) * (pi->y - ty);
00093 float y1 = -sin(rz) * (pi->x - tx) + cos(rz) * (pi->y - ty);
00094 float z1 = (pi->z - tz);
00095
00096 float x2 = x1;
00097 float y2 = cos(rx) * y1 + sin(rx) * z1;
00098 float z2 = -sin(rx) * y1 + cos(rx) * z1;
00099
00100 po->x = cos(ry) * x2 - sin(ry) * z2;
00101 po->y = y2;
00102 po->z = sin(ry) * x2 + cos(ry) * z2;
00103 po->intensity = pi->intensity;
00104 }
00105
00106 void TransformToEnd(pcl::PointXYZI *pi, pcl::PointXYZI *po)
00107 {
00108 float s = 10 * (pi->intensity - int(pi->intensity));
00109
00110 float rx = s * transform[0];
00111 float ry = s * transform[1];
00112 float rz = s * transform[2];
00113 float tx = s * transform[3];
00114 float ty = s * transform[4];
00115 float tz = s * transform[5];
00116
00117 float x1 = cos(rz) * (pi->x - tx) + sin(rz) * (pi->y - ty);
00118 float y1 = -sin(rz) * (pi->x - tx) + cos(rz) * (pi->y - ty);
00119 float z1 = (pi->z - tz);
00120
00121 float x2 = x1;
00122 float y2 = cos(rx) * y1 + sin(rx) * z1;
00123 float z2 = -sin(rx) * y1 + cos(rx) * z1;
00124
00125 float x3 = cos(ry) * x2 - sin(ry) * z2;
00126 float y3 = y2;
00127 float z3 = sin(ry) * x2 + cos(ry) * z2;
00128
00129 rx = transform[0];
00130 ry = transform[1];
00131 rz = transform[2];
00132 tx = transform[3];
00133 ty = transform[4];
00134 tz = transform[5];
00135
00136 float x4 = cos(ry) * x3 + sin(ry) * z3;
00137 float y4 = y3;
00138 float z4 = -sin(ry) * x3 + cos(ry) * z3;
00139
00140 float x5 = x4;
00141 float y5 = cos(rx) * y4 - sin(rx) * z4;
00142 float z5 = sin(rx) * y4 + cos(rx) * z4;
00143
00144 float x6 = cos(rz) * x5 - sin(rz) * y5 + tx;
00145 float y6 = sin(rz) * x5 + cos(rz) * y5 + ty;
00146 float z6 = z5 + tz;
00147
00148 float x7 = cos(imuRollStart) * (x6 - imuShiftFromStartX)
00149 - sin(imuRollStart) * (y6 - imuShiftFromStartY);
00150 float y7 = sin(imuRollStart) * (x6 - imuShiftFromStartX)
00151 + cos(imuRollStart) * (y6 - imuShiftFromStartY);
00152 float z7 = z6 - imuShiftFromStartZ;
00153
00154 float x8 = x7;
00155 float y8 = cos(imuPitchStart) * y7 - sin(imuPitchStart) * z7;
00156 float z8 = sin(imuPitchStart) * y7 + cos(imuPitchStart) * z7;
00157
00158 float x9 = cos(imuYawStart) * x8 + sin(imuYawStart) * z8;
00159 float y9 = y8;
00160 float z9 = -sin(imuYawStart) * x8 + cos(imuYawStart) * z8;
00161
00162 float x10 = cos(imuYawLast) * x9 - sin(imuYawLast) * z9;
00163 float y10 = y9;
00164 float z10 = sin(imuYawLast) * x9 + cos(imuYawLast) * z9;
00165
00166 float x11 = x10;
00167 float y11 = cos(imuPitchLast) * y10 + sin(imuPitchLast) * z10;
00168 float z11 = -sin(imuPitchLast) * y10 + cos(imuPitchLast) * z10;
00169
00170 po->x = cos(imuRollLast) * x11 + sin(imuRollLast) * y11;
00171 po->y = -sin(imuRollLast) * x11 + cos(imuRollLast) * y11;
00172 po->z = z11;
00173 po->intensity = int(pi->intensity);
00174 }
00175
00176 void PluginIMURotation(float bcx, float bcy, float bcz, float blx, float bly, float blz,
00177 float alx, float aly, float alz, float &acx, float &acy, float &acz)
00178 {
00179 float sbcx = sin(bcx);
00180 float cbcx = cos(bcx);
00181 float sbcy = sin(bcy);
00182 float cbcy = cos(bcy);
00183 float sbcz = sin(bcz);
00184 float cbcz = cos(bcz);
00185
00186 float sblx = sin(blx);
00187 float cblx = cos(blx);
00188 float sbly = sin(bly);
00189 float cbly = cos(bly);
00190 float sblz = sin(blz);
00191 float cblz = cos(blz);
00192
00193 float salx = sin(alx);
00194 float calx = cos(alx);
00195 float saly = sin(aly);
00196 float caly = cos(aly);
00197 float salz = sin(alz);
00198 float calz = cos(alz);
00199
00200 float srx = -sbcx*(salx*sblx + calx*caly*cblx*cbly + calx*cblx*saly*sbly)
00201 - cbcx*cbcz*(calx*saly*(cbly*sblz - cblz*sblx*sbly)
00202 - calx*caly*(sbly*sblz + cbly*cblz*sblx) + cblx*cblz*salx)
00203 - cbcx*sbcz*(calx*caly*(cblz*sbly - cbly*sblx*sblz)
00204 - calx*saly*(cbly*cblz + sblx*sbly*sblz) + cblx*salx*sblz);
00205 acx = -asin(srx);
00206
00207 float srycrx = (cbcy*sbcz - cbcz*sbcx*sbcy)*(calx*saly*(cbly*sblz - cblz*sblx*sbly)
00208 - calx*caly*(sbly*sblz + cbly*cblz*sblx) + cblx*cblz*salx)
00209 - (cbcy*cbcz + sbcx*sbcy*sbcz)*(calx*caly*(cblz*sbly - cbly*sblx*sblz)
00210 - calx*saly*(cbly*cblz + sblx*sbly*sblz) + cblx*salx*sblz)
00211 + cbcx*sbcy*(salx*sblx + calx*caly*cblx*cbly + calx*cblx*saly*sbly);
00212 float crycrx = (cbcz*sbcy - cbcy*sbcx*sbcz)*(calx*caly*(cblz*sbly - cbly*sblx*sblz)
00213 - calx*saly*(cbly*cblz + sblx*sbly*sblz) + cblx*salx*sblz)
00214 - (sbcy*sbcz + cbcy*cbcz*sbcx)*(calx*saly*(cbly*sblz - cblz*sblx*sbly)
00215 - calx*caly*(sbly*sblz + cbly*cblz*sblx) + cblx*cblz*salx)
00216 + cbcx*cbcy*(salx*sblx + calx*caly*cblx*cbly + calx*cblx*saly*sbly);
00217 acy = atan2(srycrx / cos(acx), crycrx / cos(acx));
00218
00219 float srzcrx = sbcx*(cblx*cbly*(calz*saly - caly*salx*salz)
00220 - cblx*sbly*(caly*calz + salx*saly*salz) + calx*salz*sblx)
00221 - cbcx*cbcz*((caly*calz + salx*saly*salz)*(cbly*sblz - cblz*sblx*sbly)
00222 + (calz*saly - caly*salx*salz)*(sbly*sblz + cbly*cblz*sblx)
00223 - calx*cblx*cblz*salz) + cbcx*sbcz*((caly*calz + salx*saly*salz)*(cbly*cblz
00224 + sblx*sbly*sblz) + (calz*saly - caly*salx*salz)*(cblz*sbly - cbly*sblx*sblz)
00225 + calx*cblx*salz*sblz);
00226 float crzcrx = sbcx*(cblx*sbly*(caly*salz - calz*salx*saly)
00227 - cblx*cbly*(saly*salz + caly*calz*salx) + calx*calz*sblx)
00228 + cbcx*cbcz*((saly*salz + caly*calz*salx)*(sbly*sblz + cbly*cblz*sblx)
00229 + (caly*salz - calz*salx*saly)*(cbly*sblz - cblz*sblx*sbly)
00230 + calx*calz*cblx*cblz) - cbcx*sbcz*((saly*salz + caly*calz*salx)*(cblz*sbly
00231 - cbly*sblx*sblz) + (caly*salz - calz*salx*saly)*(cbly*cblz + sblx*sbly*sblz)
00232 - calx*calz*cblx*sblz);
00233 acz = atan2(srzcrx / cos(acx), crzcrx / cos(acx));
00234 }
00235
00236 void AccumulateRotation(float cx, float cy, float cz, float lx, float ly, float lz,
00237 float &ox, float &oy, float &oz)
00238 {
00239 float srx = cos(lx)*cos(cx)*sin(ly)*sin(cz) - cos(cx)*cos(cz)*sin(lx) - cos(lx)*cos(ly)*sin(cx);
00240 ox = -asin(srx);
00241
00242 float srycrx = sin(lx)*(cos(cy)*sin(cz) - cos(cz)*sin(cx)*sin(cy)) + cos(lx)*sin(ly)*(cos(cy)*cos(cz)
00243 + sin(cx)*sin(cy)*sin(cz)) + cos(lx)*cos(ly)*cos(cx)*sin(cy);
00244 float crycrx = cos(lx)*cos(ly)*cos(cx)*cos(cy) - cos(lx)*sin(ly)*(cos(cz)*sin(cy)
00245 - cos(cy)*sin(cx)*sin(cz)) - sin(lx)*(sin(cy)*sin(cz) + cos(cy)*cos(cz)*sin(cx));
00246 oy = atan2(srycrx / cos(ox), crycrx / cos(ox));
00247
00248 float srzcrx = sin(cx)*(cos(lz)*sin(ly) - cos(ly)*sin(lx)*sin(lz)) + cos(cx)*sin(cz)*(cos(ly)*cos(lz)
00249 + sin(lx)*sin(ly)*sin(lz)) + cos(lx)*cos(cx)*cos(cz)*sin(lz);
00250 float crzcrx = cos(lx)*cos(lz)*cos(cx)*cos(cz) - cos(cx)*sin(cz)*(cos(ly)*sin(lz)
00251 - cos(lz)*sin(lx)*sin(ly)) - sin(cx)*(sin(ly)*sin(lz) + cos(ly)*cos(lz)*sin(lx));
00252 oz = atan2(srzcrx / cos(ox), crzcrx / cos(ox));
00253 }
00254
00255 void laserCloudSharpHandler(const sensor_msgs::PointCloud2ConstPtr& cornerPointsSharp2)
00256 {
00257 timeCornerPointsSharp = cornerPointsSharp2->header.stamp.toSec();
00258
00259 cornerPointsSharp->clear();
00260 pcl::fromROSMsg(*cornerPointsSharp2, *cornerPointsSharp);
00261
00262 newCornerPointsSharp = true;
00263 }
00264
00265 void laserCloudLessSharpHandler(const sensor_msgs::PointCloud2ConstPtr& cornerPointsLessSharp2)
00266 {
00267 timeCornerPointsLessSharp = cornerPointsLessSharp2->header.stamp.toSec();
00268
00269 cornerPointsLessSharp->clear();
00270 pcl::fromROSMsg(*cornerPointsLessSharp2, *cornerPointsLessSharp);
00271
00272 newCornerPointsLessSharp = true;
00273 }
00274
00275 void laserCloudFlatHandler(const sensor_msgs::PointCloud2ConstPtr& surfPointsFlat2)
00276 {
00277 timeSurfPointsFlat = surfPointsFlat2->header.stamp.toSec();
00278
00279 surfPointsFlat->clear();
00280 pcl::fromROSMsg(*surfPointsFlat2, *surfPointsFlat);
00281
00282 newSurfPointsFlat = true;
00283 }
00284
00285 void laserCloudLessFlatHandler(const sensor_msgs::PointCloud2ConstPtr& surfPointsLessFlat2)
00286 {
00287 timeSurfPointsLessFlat = surfPointsLessFlat2->header.stamp.toSec();
00288
00289 surfPointsLessFlat->clear();
00290 pcl::fromROSMsg(*surfPointsLessFlat2, *surfPointsLessFlat);
00291
00292 newSurfPointsLessFlat = true;
00293 }
00294
00295 void laserCloudFullResHandler(const sensor_msgs::PointCloud2ConstPtr& laserCloudFullRes2)
00296 {
00297 timeLaserCloudFullRes = laserCloudFullRes2->header.stamp.toSec();
00298
00299 laserCloudFullRes->clear();
00300 pcl::fromROSMsg(*laserCloudFullRes2, *laserCloudFullRes);
00301
00302 newLaserCloudFullRes = true;
00303 }
00304
00305 void imuTransHandler(const sensor_msgs::PointCloud2ConstPtr& imuTrans2)
00306 {
00307 timeImuTrans = imuTrans2->header.stamp.toSec();
00308
00309 imuTrans->clear();
00310 pcl::fromROSMsg(*imuTrans2, *imuTrans);
00311
00312 imuPitchStart = imuTrans->points[0].x;
00313 imuYawStart = imuTrans->points[0].y;
00314 imuRollStart = imuTrans->points[0].z;
00315
00316 imuPitchLast = imuTrans->points[1].x;
00317 imuYawLast = imuTrans->points[1].y;
00318 imuRollLast = imuTrans->points[1].z;
00319
00320 imuShiftFromStartX = imuTrans->points[2].x;
00321 imuShiftFromStartY = imuTrans->points[2].y;
00322 imuShiftFromStartZ = imuTrans->points[2].z;
00323
00324 imuVeloFromStartX = imuTrans->points[3].x;
00325 imuVeloFromStartY = imuTrans->points[3].y;
00326 imuVeloFromStartZ = imuTrans->points[3].z;
00327
00328 newImuTrans = true;
00329 }
00330
00331 int main(int argc, char** argv)
00332 {
00333 ros::init(argc, argv, "laserOdometry");
00334 ros::NodeHandle nh;
00335
00336 ros::Subscriber subCornerPointsSharp = nh.subscribe<sensor_msgs::PointCloud2>
00337 ("/laser_cloud_sharp", 2, laserCloudSharpHandler);
00338
00339 ros::Subscriber subCornerPointsLessSharp = nh.subscribe<sensor_msgs::PointCloud2>
00340 ("/laser_cloud_less_sharp", 2, laserCloudLessSharpHandler);
00341
00342 ros::Subscriber subSurfPointsFlat = nh.subscribe<sensor_msgs::PointCloud2>
00343 ("/laser_cloud_flat", 2, laserCloudFlatHandler);
00344
00345 ros::Subscriber subSurfPointsLessFlat = nh.subscribe<sensor_msgs::PointCloud2>
00346 ("/laser_cloud_less_flat", 2, laserCloudLessFlatHandler);
00347
00348 ros::Subscriber subLaserCloudFullRes = nh.subscribe<sensor_msgs::PointCloud2>
00349 ("/velodyne_cloud_2", 2, laserCloudFullResHandler);
00350
00351 ros::Subscriber subImuTrans = nh.subscribe<sensor_msgs::PointCloud2>
00352 ("/imu_trans", 5, imuTransHandler);
00353
00354 ros::Publisher pubLaserCloudCornerLast = nh.advertise<sensor_msgs::PointCloud2>
00355 ("/laser_cloud_corner_last", 2);
00356
00357 ros::Publisher pubLaserCloudSurfLast = nh.advertise<sensor_msgs::PointCloud2>
00358 ("/laser_cloud_surf_last", 2);
00359
00360 ros::Publisher pubLaserCloudFullRes = nh.advertise<sensor_msgs::PointCloud2>
00361 ("/velodyne_cloud_3", 2);
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 ros::Publisher pubLaserOdometry = nh.advertise<nav_msgs::Odometry> ("/laser_odom_to_init", 5);
00372 nav_msgs::Odometry laserOdometry;
00373 laserOdometry.header.frame_id = "/camera_init";
00374 laserOdometry.child_frame_id = "/laser_odom";
00375
00376 tf::TransformBroadcaster tfBroadcaster;
00377 tf::StampedTransform laserOdometryTrans;
00378 laserOdometryTrans.frame_id_ = "/camera_init";
00379 laserOdometryTrans.child_frame_id_ = "/laser_odom";
00380
00381 std::vector<int> pointSearchInd;
00382 std::vector<float> pointSearchSqDis;
00383
00384 pcl::PointXYZI pointOri, pointSel, tripod1, tripod2, tripod3, pointProj, coeff;
00385
00386 bool isDegenerate = false;
00387 cv::Mat matP(6, 6, CV_32F, cv::Scalar::all(0));
00388
00389 int frameCount = skipFrameNum;
00390 ros::Rate rate(100);
00391 bool status = ros::ok();
00392 while (status) {
00393 ros::spinOnce();
00394
00395 if (newCornerPointsSharp && newCornerPointsLessSharp && newSurfPointsFlat &&
00396 newSurfPointsLessFlat && newLaserCloudFullRes && newImuTrans &&
00397 fabs(timeCornerPointsSharp - timeSurfPointsLessFlat) < 0.005 &&
00398 fabs(timeCornerPointsLessSharp - timeSurfPointsLessFlat) < 0.005 &&
00399 fabs(timeSurfPointsFlat - timeSurfPointsLessFlat) < 0.005 &&
00400 fabs(timeLaserCloudFullRes - timeSurfPointsLessFlat) < 0.005 &&
00401 fabs(timeImuTrans - timeSurfPointsLessFlat) < 0.005) {
00402 newCornerPointsSharp = false;
00403 newCornerPointsLessSharp = false;
00404 newSurfPointsFlat = false;
00405 newSurfPointsLessFlat = false;
00406 newLaserCloudFullRes = false;
00407 newImuTrans = false;
00408
00409 if (!systemInited) {
00410 pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudTemp = cornerPointsLessSharp;
00411 cornerPointsLessSharp = laserCloudCornerLast;
00412 laserCloudCornerLast = laserCloudTemp;
00413
00414 laserCloudTemp = surfPointsLessFlat;
00415 surfPointsLessFlat = laserCloudSurfLast;
00416 laserCloudSurfLast = laserCloudTemp;
00417
00418 kdtreeCornerLast->setInputCloud(laserCloudCornerLast);
00419 kdtreeSurfLast->setInputCloud(laserCloudSurfLast);
00420
00421 sensor_msgs::PointCloud2 laserCloudCornerLast2;
00422 pcl::toROSMsg(*laserCloudCornerLast, laserCloudCornerLast2);
00423 laserCloudCornerLast2.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);
00424 laserCloudCornerLast2.header.frame_id = "/camera";
00425 pubLaserCloudCornerLast.publish(laserCloudCornerLast2);
00426
00427 sensor_msgs::PointCloud2 laserCloudSurfLast2;
00428 pcl::toROSMsg(*laserCloudSurfLast, laserCloudSurfLast2);
00429 laserCloudSurfLast2.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);
00430 laserCloudSurfLast2.header.frame_id = "/camera";
00431 pubLaserCloudSurfLast.publish(laserCloudSurfLast2);
00432
00433 transformSum[0] += imuPitchStart;
00434
00435 transformSum[2] += imuRollStart;
00436
00437 systemInited = true;
00438 continue;
00439 }
00440
00441 laserCloudOri->clear();
00442
00443
00444
00445
00446 coeffSel->clear();
00447
00448 transform[3] -= imuVeloFromStartX * scanPeriod;
00449 transform[4] -= imuVeloFromStartY * scanPeriod;
00450 transform[5] -= imuVeloFromStartZ * scanPeriod;
00451
00452 if (laserCloudCornerLastNum > 10 && laserCloudSurfLastNum > 100) {
00453 int cornerPointsSharpNum = cornerPointsSharp->points.size();
00454 int surfPointsFlatNum = surfPointsFlat->points.size();
00455 for (int iterCount = 0; iterCount < 25; iterCount++) {
00456 for (int i = 0; i < cornerPointsSharpNum; i++) {
00457 TransformToStart(&cornerPointsSharp->points[i], &pointSel);
00458
00459 if (iterCount % 5 == 0) {
00460 kdtreeCornerLast->nearestKSearch(pointSel, 1, pointSearchInd, pointSearchSqDis);
00461
00462 int closestPointInd = -1, minPointInd2 = -1;
00463 if (pointSearchSqDis[0] < 25) {
00464 closestPointInd = pointSearchInd[0];
00465 int closestPointScan = int(laserCloudCornerLast->points[closestPointInd].intensity);
00466
00467 float pointSqDis, minPointSqDis2 = 25;
00468 for (int j = closestPointInd + 1; j < cornerPointsSharpNum; j++) {
00469 if (int(laserCloudCornerLast->points[j].intensity) > closestPointScan + 2.5) {
00470 break;
00471 }
00472
00473 pointSqDis = (laserCloudCornerLast->points[j].x - pointSel.x) *
00474 (laserCloudCornerLast->points[j].x - pointSel.x) +
00475 (laserCloudCornerLast->points[j].y - pointSel.y) *
00476 (laserCloudCornerLast->points[j].y - pointSel.y) +
00477 (laserCloudCornerLast->points[j].z - pointSel.z) *
00478 (laserCloudCornerLast->points[j].z - pointSel.z);
00479
00480 if (int(laserCloudCornerLast->points[j].intensity) > closestPointScan) {
00481 if (pointSqDis < minPointSqDis2) {
00482 minPointSqDis2 = pointSqDis;
00483 minPointInd2 = j;
00484 }
00485 }
00486 }
00487 for (int j = closestPointInd - 1; j >= 0; j--) {
00488 if (int(laserCloudCornerLast->points[j].intensity) < closestPointScan - 2.5) {
00489 break;
00490 }
00491
00492 pointSqDis = (laserCloudCornerLast->points[j].x - pointSel.x) *
00493 (laserCloudCornerLast->points[j].x - pointSel.x) +
00494 (laserCloudCornerLast->points[j].y - pointSel.y) *
00495 (laserCloudCornerLast->points[j].y - pointSel.y) +
00496 (laserCloudCornerLast->points[j].z - pointSel.z) *
00497 (laserCloudCornerLast->points[j].z - pointSel.z);
00498
00499 if (int(laserCloudCornerLast->points[j].intensity) < closestPointScan) {
00500 if (pointSqDis < minPointSqDis2) {
00501 minPointSqDis2 = pointSqDis;
00502 minPointInd2 = j;
00503 }
00504 }
00505 }
00506 }
00507
00508 pointSearchCornerInd1[i] = closestPointInd;
00509 pointSearchCornerInd2[i] = minPointInd2;
00510 }
00511
00512 if (pointSearchCornerInd2[i] >= 0) {
00513 tripod1 = laserCloudCornerLast->points[pointSearchCornerInd1[i]];
00514 tripod2 = laserCloudCornerLast->points[pointSearchCornerInd2[i]];
00515
00516 float x0 = pointSel.x;
00517 float y0 = pointSel.y;
00518 float z0 = pointSel.z;
00519 float x1 = tripod1.x;
00520 float y1 = tripod1.y;
00521 float z1 = tripod1.z;
00522 float x2 = tripod2.x;
00523 float y2 = tripod2.y;
00524 float z2 = tripod2.z;
00525
00526 float a012 = sqrt(((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))
00527 * ((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))
00528 + ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))
00529 * ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))
00530 + ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))
00531 * ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1)));
00532
00533 float l12 = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));
00534
00535 float la = ((y1 - y2)*((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))
00536 + (z1 - z2)*((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))) / a012 / l12;
00537
00538 float lb = -((x1 - x2)*((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))
00539 - (z1 - z2)*((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))) / a012 / l12;
00540
00541 float lc = -((x1 - x2)*((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))
00542 + (y1 - y2)*((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))) / a012 / l12;
00543
00544 float ld2 = a012 / l12;
00545
00546 pointProj = pointSel;
00547 pointProj.x -= la * ld2;
00548 pointProj.y -= lb * ld2;
00549 pointProj.z -= lc * ld2;
00550
00551 float s = 1;
00552 if (iterCount >= 5) {
00553 s = 1 - 1.8 * fabs(ld2);
00554 }
00555
00556 coeff.x = s * la;
00557 coeff.y = s * lb;
00558 coeff.z = s * lc;
00559 coeff.intensity = s * ld2;
00560
00561 if (s > 0.1 && ld2 != 0) {
00562 laserCloudOri->push_back(cornerPointsSharp->points[i]);
00563
00564
00565
00566 coeffSel->push_back(coeff);
00567 }
00568 }
00569 }
00570
00571 for (int i = 0; i < surfPointsFlatNum; i++) {
00572 TransformToStart(&surfPointsFlat->points[i], &pointSel);
00573
00574 if (iterCount % 5 == 0) {
00575 kdtreeSurfLast->nearestKSearch(pointSel, 1, pointSearchInd, pointSearchSqDis);
00576
00577 int closestPointInd = -1, minPointInd2 = -1, minPointInd3 = -1;
00578 if (pointSearchSqDis[0] < 25) {
00579 closestPointInd = pointSearchInd[0];
00580 int closestPointScan = int(laserCloudSurfLast->points[closestPointInd].intensity);
00581
00582 float pointSqDis, minPointSqDis2 = 25, minPointSqDis3 = 25;
00583 for (int j = closestPointInd + 1; j < surfPointsFlatNum; j++) {
00584 if (int(laserCloudSurfLast->points[j].intensity) > closestPointScan + 2.5) {
00585 break;
00586 }
00587
00588 pointSqDis = (laserCloudSurfLast->points[j].x - pointSel.x) *
00589 (laserCloudSurfLast->points[j].x - pointSel.x) +
00590 (laserCloudSurfLast->points[j].y - pointSel.y) *
00591 (laserCloudSurfLast->points[j].y - pointSel.y) +
00592 (laserCloudSurfLast->points[j].z - pointSel.z) *
00593 (laserCloudSurfLast->points[j].z - pointSel.z);
00594
00595 if (int(laserCloudSurfLast->points[j].intensity) <= closestPointScan) {
00596 if (pointSqDis < minPointSqDis2) {
00597 minPointSqDis2 = pointSqDis;
00598 minPointInd2 = j;
00599 }
00600 } else {
00601 if (pointSqDis < minPointSqDis3) {
00602 minPointSqDis3 = pointSqDis;
00603 minPointInd3 = j;
00604 }
00605 }
00606 }
00607 for (int j = closestPointInd - 1; j >= 0; j--) {
00608 if (int(laserCloudSurfLast->points[j].intensity) < closestPointScan - 2.5) {
00609 break;
00610 }
00611
00612 pointSqDis = (laserCloudSurfLast->points[j].x - pointSel.x) *
00613 (laserCloudSurfLast->points[j].x - pointSel.x) +
00614 (laserCloudSurfLast->points[j].y - pointSel.y) *
00615 (laserCloudSurfLast->points[j].y - pointSel.y) +
00616 (laserCloudSurfLast->points[j].z - pointSel.z) *
00617 (laserCloudSurfLast->points[j].z - pointSel.z);
00618
00619 if (int(laserCloudSurfLast->points[j].intensity) >= closestPointScan) {
00620 if (pointSqDis < minPointSqDis2) {
00621 minPointSqDis2 = pointSqDis;
00622 minPointInd2 = j;
00623 }
00624 } else {
00625 if (pointSqDis < minPointSqDis3) {
00626 minPointSqDis3 = pointSqDis;
00627 minPointInd3 = j;
00628 }
00629 }
00630 }
00631 }
00632
00633 pointSearchSurfInd1[i] = closestPointInd;
00634 pointSearchSurfInd2[i] = minPointInd2;
00635 pointSearchSurfInd3[i] = minPointInd3;
00636 }
00637
00638 if (pointSearchSurfInd2[i] >= 0 && pointSearchSurfInd3[i] >= 0) {
00639 tripod1 = laserCloudSurfLast->points[pointSearchSurfInd1[i]];
00640 tripod2 = laserCloudSurfLast->points[pointSearchSurfInd2[i]];
00641 tripod3 = laserCloudSurfLast->points[pointSearchSurfInd3[i]];
00642
00643 float pa = (tripod2.y - tripod1.y) * (tripod3.z - tripod1.z)
00644 - (tripod3.y - tripod1.y) * (tripod2.z - tripod1.z);
00645 float pb = (tripod2.z - tripod1.z) * (tripod3.x - tripod1.x)
00646 - (tripod3.z - tripod1.z) * (tripod2.x - tripod1.x);
00647 float pc = (tripod2.x - tripod1.x) * (tripod3.y - tripod1.y)
00648 - (tripod3.x - tripod1.x) * (tripod2.y - tripod1.y);
00649 float pd = -(pa * tripod1.x + pb * tripod1.y + pc * tripod1.z);
00650
00651 float ps = sqrt(pa * pa + pb * pb + pc * pc);
00652 pa /= ps;
00653 pb /= ps;
00654 pc /= ps;
00655 pd /= ps;
00656
00657 float pd2 = pa * pointSel.x + pb * pointSel.y + pc * pointSel.z + pd;
00658
00659 pointProj = pointSel;
00660 pointProj.x -= pa * pd2;
00661 pointProj.y -= pb * pd2;
00662 pointProj.z -= pc * pd2;
00663
00664 float s = 1;
00665 if (iterCount >= 5) {
00666 s = 1 - 1.8 * fabs(pd2) / sqrt(sqrt(pointSel.x * pointSel.x
00667 + pointSel.y * pointSel.y + pointSel.z * pointSel.z));
00668 }
00669
00670 coeff.x = s * pa;
00671 coeff.y = s * pb;
00672 coeff.z = s * pc;
00673 coeff.intensity = s * pd2;
00674
00675 if (s > 0.1 && pd2 != 0) {
00676 laserCloudOri->push_back(surfPointsFlat->points[i]);
00677
00678
00679
00680
00681 coeffSel->push_back(coeff);
00682 }
00683 }
00684 }
00685
00686 int pointSelNum = laserCloudOri->points.size();
00687 if (pointSelNum < 10) {
00688 continue;
00689 }
00690
00691 cv::Mat matA(pointSelNum, 6, CV_32F, cv::Scalar::all(0));
00692 cv::Mat matAt(6, pointSelNum, CV_32F, cv::Scalar::all(0));
00693 cv::Mat matAtA(6, 6, CV_32F, cv::Scalar::all(0));
00694 cv::Mat matB(pointSelNum, 1, CV_32F, cv::Scalar::all(0));
00695 cv::Mat matAtB(6, 1, CV_32F, cv::Scalar::all(0));
00696 cv::Mat matX(6, 1, CV_32F, cv::Scalar::all(0));
00697 for (int i = 0; i < pointSelNum; i++) {
00698 pointOri = laserCloudOri->points[i];
00699 coeff = coeffSel->points[i];
00700
00701 float s = 1;
00702
00703 float srx = sin(s * transform[0]);
00704 float crx = cos(s * transform[0]);
00705 float sry = sin(s * transform[1]);
00706 float cry = cos(s * transform[1]);
00707 float srz = sin(s * transform[2]);
00708 float crz = cos(s * transform[2]);
00709 float tx = s * transform[3];
00710 float ty = s * transform[4];
00711 float tz = s * transform[5];
00712
00713 float arx = (-s*crx*sry*srz*pointOri.x + s*crx*crz*sry*pointOri.y + s*srx*sry*pointOri.z
00714 + s*tx*crx*sry*srz - s*ty*crx*crz*sry - s*tz*srx*sry) * coeff.x
00715 + (s*srx*srz*pointOri.x - s*crz*srx*pointOri.y + s*crx*pointOri.z
00716 + s*ty*crz*srx - s*tz*crx - s*tx*srx*srz) * coeff.y
00717 + (s*crx*cry*srz*pointOri.x - s*crx*cry*crz*pointOri.y - s*cry*srx*pointOri.z
00718 + s*tz*cry*srx + s*ty*crx*cry*crz - s*tx*crx*cry*srz) * coeff.z;
00719
00720 float ary = ((-s*crz*sry - s*cry*srx*srz)*pointOri.x
00721 + (s*cry*crz*srx - s*sry*srz)*pointOri.y - s*crx*cry*pointOri.z
00722 + tx*(s*crz*sry + s*cry*srx*srz) + ty*(s*sry*srz - s*cry*crz*srx)
00723 + s*tz*crx*cry) * coeff.x
00724 + ((s*cry*crz - s*srx*sry*srz)*pointOri.x
00725 + (s*cry*srz + s*crz*srx*sry)*pointOri.y - s*crx*sry*pointOri.z
00726 + s*tz*crx*sry - ty*(s*cry*srz + s*crz*srx*sry)
00727 - tx*(s*cry*crz - s*srx*sry*srz)) * coeff.z;
00728
00729 float arz = ((-s*cry*srz - s*crz*srx*sry)*pointOri.x + (s*cry*crz - s*srx*sry*srz)*pointOri.y
00730 + tx*(s*cry*srz + s*crz*srx*sry) - ty*(s*cry*crz - s*srx*sry*srz)) * coeff.x
00731 + (-s*crx*crz*pointOri.x - s*crx*srz*pointOri.y
00732 + s*ty*crx*srz + s*tx*crx*crz) * coeff.y
00733 + ((s*cry*crz*srx - s*sry*srz)*pointOri.x + (s*crz*sry + s*cry*srx*srz)*pointOri.y
00734 + tx*(s*sry*srz - s*cry*crz*srx) - ty*(s*crz*sry + s*cry*srx*srz)) * coeff.z;
00735
00736 float atx = -s*(cry*crz - srx*sry*srz) * coeff.x + s*crx*srz * coeff.y
00737 - s*(crz*sry + cry*srx*srz) * coeff.z;
00738
00739 float aty = -s*(cry*srz + crz*srx*sry) * coeff.x - s*crx*crz * coeff.y
00740 - s*(sry*srz - cry*crz*srx) * coeff.z;
00741
00742 float atz = s*crx*sry * coeff.x - s*srx * coeff.y - s*crx*cry * coeff.z;
00743
00744 float d2 = coeff.intensity;
00745
00746 matA.at<float>(i, 0) = arx;
00747 matA.at<float>(i, 1) = ary;
00748 matA.at<float>(i, 2) = arz;
00749 matA.at<float>(i, 3) = atx;
00750 matA.at<float>(i, 4) = aty;
00751 matA.at<float>(i, 5) = atz;
00752 matB.at<float>(i, 0) = -0.05 * d2;
00753 }
00754 cv::transpose(matA, matAt);
00755 matAtA = matAt * matA;
00756 matAtB = matAt * matB;
00757 cv::solve(matAtA, matAtB, matX, cv::DECOMP_QR);
00758
00759 if (iterCount == 0) {
00760 cv::Mat matE(1, 6, CV_32F, cv::Scalar::all(0));
00761 cv::Mat matV(6, 6, CV_32F, cv::Scalar::all(0));
00762 cv::Mat matV2(6, 6, CV_32F, cv::Scalar::all(0));
00763
00764 cv::eigen(matAtA, matE, matV);
00765 matV.copyTo(matV2);
00766
00767 isDegenerate = false;
00768 float eignThre[6] = {10, 10, 10, 10, 10, 10};
00769 for (int i = 5; i >= 0; i--) {
00770 if (matE.at<float>(0, i) < eignThre[i]) {
00771 for (int j = 0; j < 6; j++) {
00772 matV2.at<float>(i, j) = 0;
00773 }
00774 isDegenerate = true;
00775 } else {
00776 break;
00777 }
00778 }
00779 matP = matV.inv() * matV2;
00780 }
00781
00782 if (isDegenerate) {
00783 cv::Mat matX2(6, 1, CV_32F, cv::Scalar::all(0));
00784 matX.copyTo(matX2);
00785 matX = matP * matX2;
00786
00787
00788 }
00789
00790 transform[0] += matX.at<float>(0, 0);
00791 transform[1] += matX.at<float>(1, 0);
00792 transform[2] += matX.at<float>(2, 0);
00793 transform[3] += matX.at<float>(3, 0);
00794 transform[4] += matX.at<float>(4, 0);
00795 transform[5] += matX.at<float>(5, 0);
00796
00797 float deltaR = sqrt(matX.at<float>(0, 0) * 180 / PI * matX.at<float>(0, 0) * 180 / PI
00798 + matX.at<float>(1, 0) * 180 / PI * matX.at<float>(1, 0) * 180 / PI
00799 + matX.at<float>(2, 0) * 180 / PI * matX.at<float>(2, 0) * 180 / PI);
00800 float deltaT = sqrt(matX.at<float>(3, 0) * 100 * matX.at<float>(3, 0) * 100
00801 + matX.at<float>(4, 0) * 100 * matX.at<float>(4, 0) * 100
00802 + matX.at<float>(5, 0) * 100 * matX.at<float>(5, 0) * 100);
00803
00804 if (deltaR < 0.1 && deltaT < 0.1) {
00805 break;
00806 }
00807
00808
00809 }
00810 }
00811
00812 float rx, ry, rz, tx, ty, tz;
00813 AccumulateRotation(transformSum[0], transformSum[1], transformSum[2],
00814 -transform[0], -transform[1] * 1.05, -transform[2], rx, ry, rz);
00815
00816 float x1 = cos(rz) * (transform[3] - imuShiftFromStartX)
00817 - sin(rz) * (transform[4] - imuShiftFromStartY);
00818 float y1 = sin(rz) * (transform[3] - imuShiftFromStartX)
00819 + cos(rz) * (transform[4] - imuShiftFromStartY);
00820 float z1 = transform[5] * 1.05 - imuShiftFromStartZ;
00821
00822 float x2 = x1;
00823 float y2 = cos(rx) * y1 - sin(rx) * z1;
00824 float z2 = sin(rx) * y1 + cos(rx) * z1;
00825
00826 tx = transformSum[3] - (cos(ry) * x2 + sin(ry) * z2);
00827 ty = transformSum[4] - y2;
00828 tz = transformSum[5] - (-sin(ry) * x2 + cos(ry) * z2);
00829
00830 PluginIMURotation(rx, ry, rz, imuPitchStart, imuYawStart, imuRollStart,
00831 imuPitchLast, imuYawLast, imuRollLast, rx, ry, rz);
00832
00833 transformSum[0] = rx;
00834 transformSum[1] = ry;
00835 transformSum[2] = rz;
00836 transformSum[3] = tx;
00837 transformSum[4] = ty;
00838 transformSum[5] = tz;
00839
00840 geometry_msgs::Quaternion geoQuat = tf::createQuaternionMsgFromRollPitchYaw(rz, -rx, -ry);
00841
00842 laserOdometry.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);
00843 laserOdometry.pose.pose.orientation.x = -geoQuat.y;
00844 laserOdometry.pose.pose.orientation.y = -geoQuat.z;
00845 laserOdometry.pose.pose.orientation.z = geoQuat.x;
00846 laserOdometry.pose.pose.orientation.w = geoQuat.w;
00847 laserOdometry.pose.pose.position.x = tx;
00848 laserOdometry.pose.pose.position.y = ty;
00849 laserOdometry.pose.pose.position.z = tz;
00850 pubLaserOdometry.publish(laserOdometry);
00851
00852 laserOdometryTrans.stamp_ = ros::Time().fromSec(timeSurfPointsLessFlat);
00853 laserOdometryTrans.setRotation(tf::Quaternion(-geoQuat.y, -geoQuat.z, geoQuat.x, geoQuat.w));
00854 laserOdometryTrans.setOrigin(tf::Vector3(tx, ty, tz));
00855 tfBroadcaster.sendTransform(laserOdometryTrans);
00856
00857 int cornerPointsLessSharpNum = cornerPointsLessSharp->points.size();
00858 for (int i = 0; i < cornerPointsLessSharpNum; i++) {
00859 TransformToEnd(&cornerPointsLessSharp->points[i], &cornerPointsLessSharp->points[i]);
00860 }
00861
00862 int surfPointsLessFlatNum = surfPointsLessFlat->points.size();
00863 for (int i = 0; i < surfPointsLessFlatNum; i++) {
00864 TransformToEnd(&surfPointsLessFlat->points[i], &surfPointsLessFlat->points[i]);
00865 }
00866
00867 frameCount++;
00868 if (frameCount >= skipFrameNum + 1) {
00869 int laserCloudFullResNum = laserCloudFullRes->points.size();
00870 for (int i = 0; i < laserCloudFullResNum; i++) {
00871 TransformToEnd(&laserCloudFullRes->points[i], &laserCloudFullRes->points[i]);
00872 }
00873 }
00874
00875 pcl::PointCloud<pcl::PointXYZI>::Ptr laserCloudTemp = cornerPointsLessSharp;
00876 cornerPointsLessSharp = laserCloudCornerLast;
00877 laserCloudCornerLast = laserCloudTemp;
00878
00879 laserCloudTemp = surfPointsLessFlat;
00880 surfPointsLessFlat = laserCloudSurfLast;
00881 laserCloudSurfLast = laserCloudTemp;
00882
00883 laserCloudCornerLastNum = laserCloudCornerLast->points.size();
00884 laserCloudSurfLastNum = laserCloudSurfLast->points.size();
00885 if (laserCloudCornerLastNum > 10 && laserCloudSurfLastNum > 100) {
00886 kdtreeCornerLast->setInputCloud(laserCloudCornerLast);
00887 kdtreeSurfLast->setInputCloud(laserCloudSurfLast);
00888 }
00889
00890 if (frameCount >= skipFrameNum + 1) {
00891 frameCount = 0;
00892
00893 sensor_msgs::PointCloud2 laserCloudCornerLast2;
00894 pcl::toROSMsg(*laserCloudCornerLast, laserCloudCornerLast2);
00895 laserCloudCornerLast2.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);
00896 laserCloudCornerLast2.header.frame_id = "/camera";
00897 pubLaserCloudCornerLast.publish(laserCloudCornerLast2);
00898
00899 sensor_msgs::PointCloud2 laserCloudSurfLast2;
00900 pcl::toROSMsg(*laserCloudSurfLast, laserCloudSurfLast2);
00901 laserCloudSurfLast2.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);
00902 laserCloudSurfLast2.header.frame_id = "/camera";
00903 pubLaserCloudSurfLast.publish(laserCloudSurfLast2);
00904
00905 sensor_msgs::PointCloud2 laserCloudFullRes3;
00906 pcl::toROSMsg(*laserCloudFullRes, laserCloudFullRes3);
00907 laserCloudFullRes3.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);
00908 laserCloudFullRes3.header.frame_id = "/camera";
00909 pubLaserCloudFullRes.publish(laserCloudFullRes3);
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 }
00936
00937 status = ros::ok();
00938 rate.sleep();
00939 }
00940
00941 return 0;
00942 }