Bladeren bron

gtsam 异常

zx 1 jaar geleden
bovenliggende
commit
2bc747bc1c
7 gewijzigde bestanden met toevoegingen van 114 en 126 verwijderingen
  1. 5 27
      Log/mat_pre.txt
  2. 1 1
      config/horizon.yaml
  3. 3 0
      src/IMU_Processing.hpp
  4. 29 2
      src/keyFramesManager.cpp
  5. 9 3
      src/keyFramesManager.h
  6. 63 93
      src/laserMapping.cpp
  7. 4 0
      src/preprocess.h

+ 5 - 27
Log/mat_pre.txt

@@ -1,27 +1,5 @@
-            0.199676 0 0 0     -7.12899      2.49997 -2.99513e-05 0 0 0 0.05512 0.02226 -0.0297  1.86156e-06  -0.00122469 -0.000970106   0.00464148 -0.000870643  0.000336383 0 0 0  0.123513 -0.104763  -9.80766 
-            0.299528    0.336845 -0.00665055   -0.295737  -7.09647   2.55902 0.0524542  3.47004e-06  1.16491e-06 -4.40443e-06  0.0551203  0.0222606 -0.0296995    0.003329 -0.00623542  0.00461199  0.00464139 -0.00087063 0.000336437 -1.63869e-07 -3.04352e-07  -2.6525e-07  0.123513 -0.104763  -9.80766 
-            0.399378  0.275098 -0.167176 -0.532669    -7.0657    2.57988 -0.0133141  0.000129849 -0.000176921  2.48062e-05    0.05512  0.0222605 -0.0296992  0.153697 0.0969923 -0.328103   0.00485513 -0.000299866   0.00115769 -2.36462e-05 -1.68018e-05  5.03149e-05  0.123535 -0.104747  -9.80766 
-            0.499218   0.336702 -0.0982113  -0.642529   -7.02973    2.58575 -0.0447578 -0.00164777   -0.103213  0.00128784  0.0551173  0.0221916 -0.0296558  0.238531 0.0776154 -0.323048   0.00464595 -0.000178481    0.0015198   -0.0183762  0.000307649 -0.000443912 0.141191 -0.10519 -9.80742 
-            0.599858  0.727053 -0.290012 -0.514673   -7.01705    2.50224 -0.0540624    -0.30817   0.0428974 -0.00431915  0.0550099  0.0223068 -0.0295188  0.186883 -0.237426 -0.244952   0.00434637 -6.00997e-05   0.00101622 0.00789977  0.0545194 -0.0265759  0.115723 -0.157509  -9.80705 
-            0.699698  0.821333  -0.48661 -0.506166  -7.01611   2.44584 -0.025839  -0.514034     0.2944 -0.0107318  0.0550353  0.0225474 -0.0294227   0.100327  -0.364238 -0.0676286    0.0046987 -0.000305849  0.000964423 0.0539036 0.0898803 -0.140683  0.072383 -0.193225  -9.80683 
-            0.799555  0.179839 -0.654088 -0.843384   -7.00834    2.46609 -0.0561265 -0.00585028    0.317101 -0.00321389  0.054968 0.0227545 -0.029145 0.0731343 -0.184008 -0.136804    0.005125 0.000170583  0.00206204   0.0569284 0.000105008  -0.0700647 0.0694308 -0.105304  -9.80819 
-            0.899395 -0.413014 -0.677849  -1.23473 -7.01386  2.51487 -0.02519  0.627766  0.456992 0.0113526  0.0547431  0.0221508 -0.0287935 0.000468793   0.0568207   0.0242281   0.00501508 -0.000225516   0.00325559 0.0837415 -0.112653 -0.215365   0.0456643 3.76025e-05    -9.80889 
-            0.999233 -0.868656 -0.654661  -1.69459   -7.01519    2.57462 0.00595212   1.10572  0.457918 0.0235214  0.0544943  0.0218165 -0.0284686 -0.0252153   0.277333   0.141917   0.00492007 -0.000339005   0.00463237 0.0855349 -0.197372 -0.304898 0.0454622 0.0798594  -9.80857 
-             1.09987 -0.895258   -0.6992  -2.12407  -7.02518   2.59858 0.0199077   1.04851  0.513059 0.0195701  0.0545246  0.0217829 -0.0285018 -0.0774682   0.310114   0.165343   0.00520115 -0.000397136   0.00589476 0.0948447 -0.187301 -0.300185  0.036274 0.0705249  -9.80868 
-             1.19971  -0.39553 -0.674439  -2.34025  -7.02838   2.58246 0.0139767 0.694164 0.465877 0.012825  0.0546043  0.0214558 -0.0280562 -0.0826777   0.191166   0.117179   0.00472213 -0.000332907   0.00647379 0.0855197 -0.124594 -0.235881  0.0437599 0.00898636    -9.8089 
-             1.29954  0.356995 -0.638708  -2.32782    -7.0347    2.48961 0.00270136 -0.0360141   0.431105 -0.0113497  0.0541054  0.0208304 -0.0261424 -0.101337  -0.15252 0.0689334   0.0046055 -0.00030355   0.0064453   0.0781804 0.000178774   -0.179852 0.0464816 -0.112786  -9.80824 
-             1.39937  0.945425 -0.561155  -2.24354  -7.04067   2.35883 0.0135846  -0.701543   0.371995 -0.0373174  0.0532895  0.0208194 -0.0242511 -0.107959 -0.521441  0.102573    0.0048609 -0.000323258   0.00618378 0.0685054  0.110563 -0.188173  0.050397 -0.219133  -9.80642 
-              1.4992   1.34959 -0.583753  -2.15574   -7.05118     2.2307 0.00103485   -1.0765  0.354104 -0.055243  0.0527496  0.0204922 -0.0235595  -0.12736 -0.792619 0.0491135   0.00477245 -0.000202705   0.00590221  0.064066  0.174852 -0.141027 0.0512368 -0.281847  -9.80482 
-             1.59984   1.77905 -0.493213  -2.07316    -7.05991      2.0485 -0.00614024   -1.52715   0.302596 -0.0781575   0.052144  0.0204112 -0.0233576 -0.133152  -1.15687 0.0247036   0.00482783 -0.000298327   0.00567747 0.0545094  0.252348 -0.117412 0.0538524 -0.356779  -9.80236 
-             1.69968   2.1478 -0.40358 -1.94986    -7.06528      1.8237 -0.00310582  -1.95347  0.229352 -0.102992  0.0516771   0.020393 -0.0234588 -0.117885  -1.55511 0.0364771   0.00497196 -0.000353102      0.00535 0.0415202  0.327184 -0.117756 0.0576744 -0.430084   -9.7994 
-             1.79954    2.5306 -0.325873  -1.77716     -7.06901      1.56694 -0.000177004  -2.30754  0.160989 -0.124618  0.0514094  0.0204045 -0.0238531 -0.100705  -1.94835 0.0410749   0.00487764 -0.000395217   0.00488792 0.0293135  0.390714 -0.116334 0.0604377  -0.49209  -9.79646 
-             1.89937   2.82571 -0.247509   -1.6494   -7.06675    1.24251 -0.0134631  -2.74017 0.0694491  -0.15088  0.0512294  0.0205238 -0.0245816  -0.0681355    -2.43965 -0.00421502    0.0051952 -0.000367838   0.00458821  0.0126915   0.468444 -0.0919446 0.0637467 -0.564301  -9.79255 
-             1.99921   3.24665 -0.121813  -1.46523   -7.05152   0.825076 -0.0107051   -3.25249 -0.0745023  -0.192667  0.0511295  0.0205115 -0.0254485  0.0112016   -3.07896 0.00937973   0.00538094 -0.000346597   0.00420724 -0.0129646   0.564856  -0.101007 0.0703687 -0.661153  -9.78644 
-             2.09987   3.60124 0.0275236   -1.2092    -7.03294    0.361838 -0.00206466  -3.66757 -0.188536 -0.223536  0.0510647  0.0204835 -0.0258848 0.0758616  -3.68648 0.0398377   0.00549642 -0.000469309   0.00361663 -0.0331205   0.644845  -0.117489 0.0734017 -0.743384  -9.78051 
-             2.19971      3.5942 -0.00626557   -0.887192   -7.01749 -0.0680569 -0.0183523  -3.84933 -0.236371 -0.237355  0.0509829  0.0205859 -0.0263398    0.10295   -4.03479 -0.0137531    0.0059501 -0.000320784   0.00278836 -0.0413044   0.674793 -0.0933499 0.0746029 -0.764626  -9.77887 
-             2.29957    3.40602 -0.0453024  -0.487438   -7.00838  -0.437141 -0.0288895  -3.74783  -0.21963 -0.242017  0.0510242  0.0207375 -0.0258005  0.0962766   -4.09254 -0.0345151   0.00615671 -0.000331516   0.00174594 -0.0384806   0.653321 -0.0795553 0.0767396 -0.739744  -9.78077 
-              2.3994     2.9524 -0.0630898  -0.160849   -7.00422  -0.765998 -0.0347945  -3.51511 -0.173944 -0.246022  0.0510597  0.0208449 -0.0243484  0.0719388   -3.99826 -0.0319839   0.00669746 -0.000455641  0.000894066 -0.0311949   0.609963 -0.0726976  0.079623 -0.697327  -9.78386 
-             2.49924   2.50266 -0.198557   0.11789   -7.01689   -1.08369 -0.0444925    -3.3039 -0.0886779  -0.215586  0.0509862  0.0209393 -0.0230114 -0.0116216   -3.89056 -0.0420773   0.00726524 -0.000364049  9.82998e-05 -0.0167659   0.569311 -0.0618797 0.0739072 -0.654661  -9.78685 
-             2.59987   2.32222 -0.238719  0.290352   -7.03438   -1.43138 -0.0397285    -3.1684 -0.0298815  -0.187814  0.0508696  0.0207372 -0.0224468  -0.0804996    -3.89194 -0.00902005   0.00734269 -0.000417549 -0.000397109 -0.00645932    0.546273  -0.0694175 0.0677312  -0.63658  -9.78809 
-             2.69971  1.99622 -0.18965 0.526424   -7.04793   -1.78663 -0.0284917     -3.0626 -0.00925562   -0.184438  0.0507373  0.0206414 -0.0222508 -0.108687  -3.91947 0.0325656   0.00783515 -0.000608023 -0.000950144 -0.00286584    0.528928  -0.0801345 0.0661514 -0.625277  -9.78883 
-             2.79954  1.73958 -0.13882 0.714661   -7.05012   -2.13982 0.00158323   -2.93395 -0.0264739  -0.208612   0.050549  0.0206507 -0.0221289 -0.0828248   -3.92997    0.11911   0.00808385 -0.000703514  -0.00132922 -0.00698287    0.510041   -0.104944 0.0712518 -0.616826  -9.78933 
+            0.299528 0 0 0  4.46143e-05 -0.000145041 -0.000149158 0 0 0 0.05512 0.02226 -0.0297  0.000109393 -0.000516061 -0.000849742   0.00464148 -0.000870643  0.000336383 0 0 0  0.123513 -0.104763  -9.80766 
+            0.399378  0.00480656  -0.0828206 -0.00422964 -0.00772205  0.00732081   -0.019306  1.06891e-06 -7.16561e-07 -3.60446e-07  0.0551199  0.0222601 -0.0297002  -0.00518483 -0.000803933  -0.00589671   0.00464145 -0.000870633  0.000336385  1.35589e-07 -1.46321e-07   3.6324e-07  0.123512 -0.104763  -9.80766 
+            0.499218 -0.00988241  -0.0716865  -0.0136613 2.17469e+09 -1.5577e+09 2.76741e+09 -7.84114e-05 -8.69432e-05 -9.41052e-07  0.0551198  0.0222602 -0.0297003 -0.499552  0.334559  -1.62961   0.00469042 -0.000894243  0.000375273 -1.49671e-05  1.38694e-05 -1.20493e-05  0.123527 -0.104777  -9.80766 
+            0.599858  155.826  38.0769 -71.7041 -1.01648e+23  4.55403e+23   2.3476e+20 -7.84114e-05 -8.69432e-05 -9.41052e-07  0.0551198  0.0222602 -0.0297003 -0.584485  0.718245  -3.51523   0.00469042 -0.000894243  0.000375273 -1.49671e-05  1.38694e-05 -1.20493e-05  0.123527 -0.104777  -9.80766 
+            0.699698 -158.632  11.9836  -16.246 -2.98024e+53 -4.43846e+53  -1.9931e+53 -7.84114e-05 -8.69432e-05 -9.41052e-07  0.0551198  0.0222602 -0.0297003 -0.681893   1.14418   -5.3637   0.00469042 -0.000894243  0.000375273 -1.49671e-05  1.38694e-05 -1.20493e-05  0.123527 -0.104777  -9.80766 

+ 1 - 1
config/horizon.yaml

@@ -77,7 +77,7 @@ recontructKdTree: true
 
 # Export settings
 ndtLoopMatch: true  # false -- icp
-locate_mode: true
+locate_mode: false
 locate:
     init_pos: [-7.129,2.5,0]
     init_rpy: [0,0,0.00]

+ 3 - 0
src/IMU_Processing.hpp

@@ -1,3 +1,5 @@
+#ifndef __IMU_Processing_HPP__
+#define __IMU_Processing_HPP__
 #include <cmath>
 #include <math.h>
 #include <deque>
@@ -405,3 +407,4 @@ void ImuProcess::Process(const MeasureGroup &meas,  esekfom::esekf<state_ikfom,
   
   //std::cout<<"[ IMU Process ]: Time: "<<t3 - t1<<std::endl;
 }
+#endif

+ 29 - 2
src/keyFramesManager.cpp

@@ -15,6 +15,21 @@ keyFrame::keyFrame(PointTypePose pose, PointCloudXYZI::Ptr cloud) {
   pose_changed_=true;
 
 }
+
+keyFrame::keyFrame(const keyFrame& frame){
+  cloud_=frame.cloud_;
+  cloud_world_=frame.cloud_world_;
+  pose_=frame.pose_;
+  pose_changed_=frame.pose_changed_;
+}
+keyFrame& keyFrame::operator=(const keyFrame& frame){
+  cloud_=frame.cloud_;
+  cloud_world_=frame.cloud_world_;
+  pose_=frame.pose_;
+  pose_changed_=frame.pose_changed_;
+  return *this;
+}
+
 keyFrame::~keyFrame() {}
 
 void keyFrame::ResetPose(PointTypePose pose){
@@ -23,14 +38,21 @@ void keyFrame::ResetPose(PointTypePose pose){
 }
 
 
-PointCloudXYZI::Ptr keyFrame::world_cloud(){
+PointCloudXYZI::Ptr keyFrame::world_cloud(Eigen::Isometry3d lidar_2_imu){
   if(pose_changed_==false){
     return cloud_world_;
   }
   int cloudSize = cloud_->size();
   cloud_world_->resize(cloudSize);
 
-  Eigen::Affine3f transCur = pcl::getTransformation(pose_.x, pose_.y, pose_.z, pose_.roll, pose_.pitch, pose_.yaw);
+  Eigen::Affine3f T_w_b_ = pcl::getTransformation(pose_.x, pose_.y, pose_.z, pose_.roll, pose_.pitch, pose_.yaw);
+
+  Eigen::Isometry3d T_w_b ;          //   world2body
+  T_w_b.matrix() = T_w_b_.matrix().cast<double>();
+
+  Eigen::Isometry3d  T_w_lidar  =  T_w_b * lidar_2_imu  ;           //  T_w_lidar  转换矩阵
+
+  Eigen::Isometry3d transCur = T_w_lidar;
 
   int numberOfCores=4;
 #pragma omp parallel for num_threads(numberOfCores)
@@ -46,6 +68,11 @@ PointCloudXYZI::Ptr keyFrame::world_cloud(){
   return cloud_world_;
 }
 
+//----------------------------------------------------------------------------------------------------
+
+keyFramesManager::keyFramesManager(){}
+keyFramesManager::~keyFramesManager(){}
+
 pcl::PointCloud<PointTypePose>::Ptr keyFramesManager::GetPoses(){
   pcl::PointCloud<PointTypePose>::Ptr ret(new pcl::PointCloud<PointTypePose>);
   ret->resize(frames_.size());

+ 9 - 3
src/keyFramesManager.h

@@ -4,17 +4,20 @@
 
 #ifndef FAST_LIO_SAM_KEYFRAMESMANAGER_H
 #define FAST_LIO_SAM_KEYFRAMESMANAGER_H
-#include "common_lib.h"
 #include "preprocess.h"
+typedef pcl::PointXYZINormal PointType;
+typedef pcl::PointCloud<PointType> PointCloudXYZI;
 class keyFrame{
 public:
     keyFrame(PointCloudXYZI::Ptr cloud);
     keyFrame(PointTypePose pose,PointCloudXYZI::Ptr cloud);
+    keyFrame(const keyFrame& frame);
+    keyFrame& operator=(const keyFrame& frame);
     ~keyFrame();
     void ResetPose(PointTypePose pose);
     PointTypePose Pose(){return pose_;}
     PointCloudXYZI::Ptr cloud(){return cloud_;}
-    PointCloudXYZI::Ptr world_cloud();
+    PointCloudXYZI::Ptr world_cloud(Eigen::Isometry3d lidar_2_imu );
 protected:
     PointTypePose pose_;
     PointCloudXYZI::Ptr cloud_;
@@ -26,8 +29,11 @@ class keyFramesManager {
 public:
     keyFramesManager();
     ~keyFramesManager();
-
+    int size(){return frames_.size();}
+    keyFrame& back(){return frames_.back();}
+    void push_back(const keyFrame& frame){frames_.push_back(frame);}
     pcl::PointCloud<PointTypePose>::Ptr GetPoses();
+    keyFrame& operator[](int id){ return frames_[id];}
 
     std::vector<keyFrame> frames_;
 

+ 63 - 93
src/laserMapping.cpp

@@ -166,11 +166,9 @@ shared_ptr<Preprocess> p_pre(new Preprocess());
 shared_ptr<ImuProcess> p_imu(new ImuProcess());
 
 /*back end*/
-vector<pcl::PointCloud<PointType>::Ptr> cornerCloudKeyFrames; // 历史所有关键帧的角点集合(降采样)
-vector<pcl::PointCloud<PointType>::Ptr> surfCloudKeyFrames;   // 历史所有关键帧的平面点集合(降采样)
-
+keyFramesManager keyFrames_;
 pcl::PointCloud<PointType>::Ptr cloudKeyPoses3D(new pcl::PointCloud<PointType>());         // 历史关键帧位姿(位置)
-pcl::PointCloud<PointTypePose>::Ptr cloudKeyPoses6D(new pcl::PointCloud<PointTypePose>()); // 历史关键帧位姿
+
 pcl::PointCloud<PointType>::Ptr copy_cloudKeyPoses3D(new pcl::PointCloud<PointType>());
 pcl::PointCloud<PointTypePose>::Ptr copy_cloudKeyPoses6D(new pcl::PointCloud<PointTypePose>());
 
@@ -512,7 +510,7 @@ bool saveFrame()
         return true;
 
     // 前一帧位姿
-    Eigen::Affine3f transStart = pclPointToAffine3f(cloudKeyPoses6D->back());
+    Eigen::Affine3f transStart = pclPointToAffine3f(keyFrames_.back().Pose());
     // 当前帧位姿
     Eigen::Affine3f transFinal = trans2Affine3f(transformTobeMapped);
     // Eigen::Affine3f transFinal = pcl::getTransformation(transformTobeMapped[3], transformTobeMapped[4], transformTobeMapped[5],
@@ -544,17 +542,26 @@ void addOdomFactor()
         gtSAMgraph.add(gtsam::PriorFactor<gtsam::Pose3>(0, trans2gtsamPose(transformTobeMapped), priorNoise));
         // 变量节点设置初始值
         initialEstimate.insert(0, trans2gtsamPose(transformTobeMapped));
+        gtsam::Pose3 init=trans2gtsamPose(transformTobeMapped);
+        printf("  add 0  init 0 :%f %f %f %f %f %f\n",init.x(),init.y(),init.z(),
+               init.rotation().roll(),init.rotation().pitch(),init.rotation().yaw());
     }
     else
     {
         // 添加激光里程计因子
         gtsam::noiseModel::Diagonal::shared_ptr odometryNoise = gtsam::noiseModel::Diagonal::Variances((gtsam::Vector(6) << 1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4).finished());
-        gtsam::Pose3 poseFrom = pclPointTogtsamPose3(cloudKeyPoses6D->points.back()); /// pre
+
+        gtsam::Pose3 poseFrom = pclPointTogtsamPose3(keyFrames_.back().Pose()); /// pre
         gtsam::Pose3 poseTo = trans2gtsamPose(transformTobeMapped);                   // cur
         // 参数:前一帧id,当前帧id,前一帧与当前帧的位姿变换(作为观测值),噪声协方差
         gtSAMgraph.add(gtsam::BetweenFactor<gtsam::Pose3>(cloudKeyPoses3D->size() - 1, cloudKeyPoses3D->size(), poseFrom.between(poseTo), odometryNoise));
         // 变量节点设置初始值
         initialEstimate.insert(cloudKeyPoses3D->size(), poseTo);
+      printf(" add between :%d to  %d  init %d:%f %f %f %f %f %f\n",
+             cloudKeyPoses3D->size()-1,cloudKeyPoses3D->size(),cloudKeyPoses3D->size(),
+             poseTo.x(),poseTo.y(),poseTo.z(),
+             poseTo.rotation().roll(),poseTo.rotation().pitch(),poseTo.rotation().yaw());
+
     }
 }
 
@@ -593,7 +600,7 @@ void loopFindNearKeyframes(pcl::PointCloud<PointType>::Ptr &nearKeyframes, const
   // 提取key索引的关键帧前后相邻若干帧的关键帧特征点集合
   nearKeyframes->clear();
   int cloudSize = copy_cloudKeyPoses6D->size();
-  auto surfcloud_keyframes_size = surfCloudKeyFrames.size() ;
+  auto surfcloud_keyframes_size = keyFrames_.size() ;
   for (int i = -searchNum; i <= searchNum; ++i)
   {
     int keyNear = key + i;
@@ -603,9 +610,10 @@ void loopFindNearKeyframes(pcl::PointCloud<PointType>::Ptr &nearKeyframes, const
     if (keyNear < 0 || keyNear >= surfcloud_keyframes_size)
       continue;
 
-    // *nearKeyframes += *transformPointCloud(cornerCloudKeyFrames[keyNear], &copy_cloudKeyPoses6D->points[keyNear]);
     // 注意:cloudKeyPoses6D 存储的是 T_w_b , 而点云是lidar系下的,构建icp的submap时,需要通过外参数T_b_lidar 转换 , 参考pointBodyToWorld 的转换
-    *nearKeyframes += *transformPointCloud(surfCloudKeyFrames[keyNear], &copy_cloudKeyPoses6D->points[keyNear]); //  fast-lio 没有进行特征提取,默认点云就是surf
+    Eigen::Isometry3d T_b_lidar(state_point.offset_R_L_I  );       //  获取  body2lidar  外参
+    T_b_lidar.pretranslate(state_point.offset_T_L_I);
+    *nearKeyframes += *keyFrames_[keyNear].world_cloud(T_b_lidar);
   }
 
   if (nearKeyframes->empty())
@@ -628,12 +636,12 @@ void performLoopClosure() {
 
   mtx.lock();
   *copy_cloudKeyPoses3D = *cloudKeyPoses3D;
-  *copy_cloudKeyPoses6D = *cloudKeyPoses6D;
+  *copy_cloudKeyPoses6D = *keyFrames_.GetPoses();
   mtx.unlock();
 
   // 当前关键帧索引,候选闭环匹配帧索引
   static int LastKeyFrameSize=0;//;
-  if(LastKeyFrameSize>=surfCloudKeyFrames.size())   //没有更新的keyframe 无需检测
+  if(LastKeyFrameSize>=keyFrames_.size())   //没有更新的keyframe 无需检测
     return ;
 
   int loopKeyCur;
@@ -647,7 +655,7 @@ void performLoopClosure() {
     return;
 
   auto detectResult = scManager.detectLoopClosureID(); // first: nn index, second: yaw diff
-  LastKeyFrameSize=surfCloudKeyFrames.size();
+  LastKeyFrameSize=keyFrames_.size();
   int SCclosestHistoryFrameID = detectResult.first;
   if( SCclosestHistoryFrameID != -1 ) {
 
@@ -680,12 +688,7 @@ void performLoopClosure() {
   float noiseScore;
   Eigen::Affine3f correctionLidarFrame;
   float x, y, z, roll, pitch, yaw;
-  /*PointTypePose current = copy_cloudKeyPoses6D->points[loopKeyCur];
-  PointTypePose target = copy_cloudKeyPoses6D->points[loopKeyPre];
-  gtsam::Pose3 poseSrc(gtsam::Rot3::RzRyRx(double(current.roll), double(current.pitch), double(current.yaw)),
-                       gtsam::Point3(double(current.x), double(current.y), double(current.z)));
-  gtsam::Pose3 poseTar(gtsam::Rot3::RzRyRx(double(target.roll), double(target.pitch), double(target.yaw)),
-                       gtsam::Point3(double(target.x), double(target.y), double(target.z)));*/
+
   // ICP Settings
 if(ndt_loop==false) {
   pcl::IterativeClosestPoint<PointType, PointType> icp;
@@ -782,12 +785,17 @@ void saveKeyFramesAndFactor()
     // 激光里程计因子(from fast-lio),  输入的是frame_relative pose  帧间位姿(body 系下)
     addOdomFactor();
   scManager.makeAndSaveScancontextAndKeys(*feats_undistort);
+
   performLoopClosure();   //闭环检测
+
   visualizeLoopClosure();//展示闭环边
+
     // 闭环因子 (rs-loop-detect)  基于欧氏距离的检测
     addLoopFactor();
+
     // 执行优化
     isam->update(gtSAMgraph, initialEstimate);
+
     isam->update();
     if (aLoopIsClosed == true) // 有回环因子,多update几次
     {
@@ -800,6 +808,7 @@ void saveKeyFramesAndFactor()
     }
     // update之后要清空一下保存的因子图,注:历史数据不会清掉,ISAM保存起来了
     gtSAMgraph.resize(0);
+
     initialEstimate.clear();
 
     PointType thisPose3D;
@@ -810,7 +819,6 @@ void saveKeyFramesAndFactor()
     isamCurrentEstimate = isam->calculateBestEstimate();
     // 当前帧位姿结果
     latestEstimate = isamCurrentEstimate.at<gtsam::Pose3>(isamCurrentEstimate.size() - 1);
-
     // cloudKeyPoses3D加入当前帧位置
     thisPose3D.x = latestEstimate.translation().x();
     thisPose3D.y = latestEstimate.translation().y();
@@ -829,7 +837,7 @@ void saveKeyFramesAndFactor()
     thisPose6D.pitch = latestEstimate.rotation().pitch();
     thisPose6D.yaw = latestEstimate.rotation().yaw();
     thisPose6D.time = lidar_end_time;
-    cloudKeyPoses6D->push_back(thisPose6D);
+
 
     // 位姿协方差
     poseCovariance = isam->marginalCovariance(isamCurrentEstimate.size() - 1);
@@ -846,32 +854,14 @@ void saveKeyFramesAndFactor()
     // if(aLoopIsClosed == true )
   ikfom_.change_x(state_updated);  //  对cur_pose 进行isam2优化后的修正
 
-    // TODO:  P的修正有待考察,按照yanliangwang的做法,修改了p,会跑飞
-    // esekfom::esekf<state_ikfom, 12, input_ikfom>::cov P_updated = kf.get_P(); // 获取当前的状态估计的协方差矩阵
-    // P_updated.setIdentity();
-    // P_updated(6, 6) = P_updated(7, 7) = P_updated(8, 8) = 0.00001;
-    // P_updated(9, 9) = P_updated(10, 10) = P_updated(11, 11) = 0.00001;
-    // P_updated(15, 15) = P_updated(16, 16) = P_updated(17, 17) = 0.0001;
-    // P_updated(18, 18) = P_updated(19, 19) = P_updated(20, 20) = 0.001;
-    // P_updated(21, 21) = P_updated(22, 22) = 0.00001;
-    // kf.change_P(P_updated);
-
     // 当前帧激光角点、平面点,降采样集合
     // pcl::PointCloud<PointType>::Ptr thisCornerKeyFrame(new pcl::PointCloud<PointType>());
     pcl::PointCloud<PointType>::Ptr thisSurfKeyFrame(new pcl::PointCloud<PointType>());
     // pcl::copyPointCloud(*feats_undistort,  *thisCornerKeyFrame);
     pcl::copyPointCloud(*feats_undistort, *thisSurfKeyFrame); // 存储关键帧,没有降采样的点云
-
-    // 保存特征点降采样集合
-    // cornerCloudKeyFrames.push_back(thisCornerKeyFrame);
-    surfCloudKeyFrames.push_back(thisSurfKeyFrame);
-
-    //sc关键帧保存降采样的点云
-  /*pcl::PointCloud<PointType>::Ptr cloud_temp(new pcl::PointCloud<PointType>());
-  downSizeFilterICP.setInputCloud(thisSurfKeyFrame);
-  downSizeFilterICP.filter(*cloud_temp);*/
-
-
+    keyFrames_.push_back(keyFrame(thisPose6D,thisSurfKeyFrame));
+    printf(" keyFrames add %d pose: %f %f %f %f %f %f\n",keyFrames_.size(),thisPose6D.x,thisPose6D.y,thisPose6D.z,
+           thisPose6D.roll,thisPose6D.pitch,thisPose6D.yaw);
     updatePath(thisPose6D); //  可视化update后的path
 }
 
@@ -906,8 +896,9 @@ void recontructIKdTree(){
             if (pointDistance(subMapKeyPosesDS->points[i], cloudKeyPoses3D->back()) > globalMapVisualizationSearchRadius)
                     continue;
             int thisKeyInd = (int)subMapKeyPosesDS->points[i].intensity;
-            // *globalMapKeyFrames += *transformPointCloud(cornerCloudKeyFrames[thisKeyInd],  &cloudKeyPoses6D->points[thisKeyInd]);
-            *subMapKeyFrames += *transformPointCloud(surfCloudKeyFrames[thisKeyInd], &cloudKeyPoses6D->points[thisKeyInd]); //  fast_lio only use  surfCloud
+          Eigen::Isometry3d T_b_lidar(state_point.offset_R_L_I  );       //  获取  body2lidar  外参
+          T_b_lidar.pretranslate(state_point.offset_T_L_I);
+          *subMapKeyFrames += *keyFrames_[thisKeyInd].world_cloud(T_b_lidar);
         }
         // 降采样,发布
         pcl::VoxelGrid<PointType> downSizeFilterGlobalMapKeyFrames;                                                                                   // for global map visualization
@@ -947,15 +938,17 @@ void correctPoses()
             cloudKeyPoses3D->points[i].y = isamCurrentEstimate.at<gtsam::Pose3>(i).translation().y();
             cloudKeyPoses3D->points[i].z = isamCurrentEstimate.at<gtsam::Pose3>(i).translation().z();
 
-            cloudKeyPoses6D->points[i].x = cloudKeyPoses3D->points[i].x;
-            cloudKeyPoses6D->points[i].y = cloudKeyPoses3D->points[i].y;
-            cloudKeyPoses6D->points[i].z = cloudKeyPoses3D->points[i].z;
-            cloudKeyPoses6D->points[i].roll = isamCurrentEstimate.at<gtsam::Pose3>(i).rotation().roll();
-            cloudKeyPoses6D->points[i].pitch = isamCurrentEstimate.at<gtsam::Pose3>(i).rotation().pitch();
-            cloudKeyPoses6D->points[i].yaw = isamCurrentEstimate.at<gtsam::Pose3>(i).rotation().yaw();
+            PointTypePose new_pose;
+            new_pose.x = cloudKeyPoses3D->points[i].x;
+            new_pose.y = cloudKeyPoses3D->points[i].y;
+            new_pose.z = cloudKeyPoses3D->points[i].z;
+            new_pose.roll = isamCurrentEstimate.at<gtsam::Pose3>(i).rotation().roll();
+            new_pose.pitch = isamCurrentEstimate.at<gtsam::Pose3>(i).rotation().pitch();
+            new_pose.yaw = isamCurrentEstimate.at<gtsam::Pose3>(i).rotation().yaw();
+            keyFrames_[i].ResetPose(new_pose);
 
             // 更新里程计轨迹
-            updatePath(cloudKeyPoses6D->points[i]);
+            updatePath(keyFrames_[i].Pose());
         }
         // 清空局部map, reconstruct  ikdtree submap
         recontructIKdTree();
@@ -1643,9 +1636,9 @@ bool savePoseService(fast_lio_sam::save_poseRequest& req, fast_lio_sam::save_pos
     CreateFile(file_pose_without_optimized, savePoseDirectory + "/without_optimized_pose.txt");
 
     //  save optimize data
-    for(int i = 0; i  < cloudKeyPoses6D->size(); i++){  
-        pose_optimized.t =  Eigen::Vector3d(cloudKeyPoses6D->points[i].x, cloudKeyPoses6D->points[i].y, cloudKeyPoses6D->points[i].z  );
-        pose_optimized.R = Exp(double(cloudKeyPoses6D->points[i].roll), double(cloudKeyPoses6D->points[i].pitch), double(cloudKeyPoses6D->points[i].yaw) );
+    for(int i = 0; i  < keyFrames_.size(); i++){
+        pose_optimized.t =  Eigen::Vector3d(keyFrames_[i].Pose().x, keyFrames_[i].Pose().y,keyFrames_[i].Pose().z  );
+        pose_optimized.R = Exp(double(keyFrames_[i].Pose().roll), double(keyFrames_[i].Pose().pitch), double(keyFrames_[i].Pose().yaw) );
         WriteText(file_pose_optimized, pose_optimized);
     }
     cout << "Sucess global optimized  poses to pose files ..." << endl;
@@ -1682,19 +1675,18 @@ bool saveMapService(fast_lio_sam::save_mapRequest& req, fast_lio_sam::save_mapRe
     //   unused = system((std::string("mkdir -p ") + saveMapDirectory).c_str());
       // 保存历史关键帧位姿
       pcl::io::savePCDFileBinary(saveMapDirectory + "/trajectory.pcd", *cloudKeyPoses3D);                    // 关键帧位置
-      pcl::io::savePCDFileBinary(saveMapDirectory + "/transformations.pcd", *cloudKeyPoses6D);      // 关键帧位姿
+      pcl::io::savePCDFileBinary(saveMapDirectory + "/transformations.pcd", *(keyFrames_.GetPoses()));      // 关键帧位姿
       // 提取历史关键帧点集合
 
       pcl::PointCloud<PointType>::Ptr globalSurfCloud(new pcl::PointCloud<PointType>());
       pcl::PointCloud<PointType>::Ptr globalSurfCloudDS(new pcl::PointCloud<PointType>());
       pcl::PointCloud<PointType>::Ptr globalMapCloud(new pcl::PointCloud<PointType>());
 
-      // 注意:拼接地图时,keyframe是lidar系,而fastlio更新后的存到的cloudKeyPoses6D 关键帧位姿是body系下的,需要把
-      //cloudKeyPoses6D  转换为T_world_lidar 。 T_world_lidar = T_world_body * T_body_lidar , T_body_lidar 是外参
-      for (int i = 0; i < (int)cloudKeyPoses6D->size(); i++) {
-            //   *globalCornerCloud += *transformPointCloud(cornerCloudKeyFrames[i],  &cloudKeyPoses6D->points[i]);
-            *globalSurfCloud   += *transformPointCloud(surfCloudKeyFrames[i],    &cloudKeyPoses6D->points[i]);
-            cout << "\r" << std::flush << "Processing feature cloud " << i << " of " << cloudKeyPoses6D->size() << " ...";
+      for (int i = 0; i < (int)keyFrames_.size(); i++) {
+        Eigen::Isometry3d T_b_lidar(state_point.offset_R_L_I  );       //  获取  body2lidar  外参
+        T_b_lidar.pretranslate(state_point.offset_T_L_I);
+        *globalSurfCloud += *keyFrames_[i].world_cloud(T_b_lidar);
+        cout << "\r" << std::flush << "Processing feature cloud " << i << " of " << keyFrames_.size() << " ...";
       }
 
       if(req.resolution != 0)
@@ -1788,8 +1780,9 @@ void publishGlobalMap()
         if (pointDistance(globalMapKeyPosesDS->points[i], cloudKeyPoses3D->back()) > globalMapVisualizationSearchRadius)
                 continue;
         int thisKeyInd = (int)globalMapKeyPosesDS->points[i].intensity;
-        // *globalMapKeyFrames += *transformPointCloud(cornerCloudKeyFrames[thisKeyInd],  &cloudKeyPoses6D->points[thisKeyInd]);
-        *globalMapKeyFrames += *transformPointCloud(surfCloudKeyFrames[thisKeyInd], &cloudKeyPoses6D->points[thisKeyInd]); //  fast_lio only use  surfCloud
+      Eigen::Isometry3d T_b_lidar(state_point.offset_R_L_I  );       //  获取  body2lidar  外参
+      T_b_lidar.pretranslate(state_point.offset_T_L_I);
+      *globalMapKeyFrames += *keyFrames_[thisKeyInd].world_cloud(T_b_lidar);
     }
     // 降采样,发布
     pcl::VoxelGrid<PointType> downSizeFilterGlobalMapKeyFrames;                                                                                   // for global map visualization
@@ -2061,6 +2054,7 @@ int main(int argc, char **argv) {
   gtsam::ISAM2Params parameters;
   parameters.relinearizeThreshold = 0.01;
   parameters.relinearizeSkip = 1;
+  parameters.factorization=gtsam::ISAM2Params::QR;
   isam = new gtsam::ISAM2(parameters);
 
   path.header.stamp = ros::Time::now();
@@ -2205,7 +2199,6 @@ int main(int argc, char **argv) {
         ikf_lock_.unlock();
         continue;
       }
-
       double t0, t1, t2, t3, t4, t5, match_start, solve_start, svd_time;
 
       match_time = 0;
@@ -2228,38 +2221,16 @@ int main(int argc, char **argv) {
         continue;
       }
 
+
       // 检查当前lidar数据时间,与最早lidar数据时间是否足够,两帧间隔0.1s
       flg_EKF_inited = (Measures.lidar_beg_time - first_lidar_time) < INIT_TIME ? false : true;
 
       /*** Segment the map in lidar FOV ***/
       if (locate_mode == false)
         lasermap_fov_segment(); // 根据lidar在W系下的位置,重新确定局部地图的包围盒角点,移除远端的点
-      else {
-        /*** downsample the feature points in a scan ***/
-        double ndt_beg = omp_get_wtime();
-        downSizeFilterSurf.setInputCloud(feats_undistort);
-        downSizeFilterSurf.filter(*feats_down_body);
-
-        pcl::NormalDistributionsTransform<PointType, PointType> ndt;
-        ndt.setTransformationEpsilon(0.001);
-        // Setting maximum step size for More-Thuente line search.
-        ndt.setStepSize(0.1);
-        //Setting Resolution of NDT grid structure (VoxelGridCovariance).
-        ndt.setResolution(0.5);
-        // Setting max number of registration iterations.
-        ndt.setMaximumIterations(50);
-        // Setting point cloud to be aligned.
-        ndt.setInputSource(feats_down_body);
-        // Setting point cloud to be aligned to.
-        ndt.setInputTarget(featsFromMap);
-        pcl::PointCloud<PointType>::Ptr unused_result(new pcl::PointCloud<PointType>());
-        ndt.align(*unused_result, Eigen::Matrix4f::Identity());
-        double ndt_end = omp_get_wtime();
-
-        printf(" ndt time :%f , size(%d  %d)\n", ndt_end - ndt_beg, feats_down_body->size(), featsFromMap->size());
-
-      }
 
+      downSizeFilterSurf.setInputCloud(feats_undistort);
+      downSizeFilterSurf.filter(*feats_down_body);
       t1 = omp_get_wtime();
       feats_down_size = feats_down_body->points.size(); //当前帧降采样后点数
 
@@ -2276,6 +2247,7 @@ int main(int argc, char **argv) {
             ikdtree.Build(feats_down_world->points);
           }
           ikf_lock_.unlock();
+
           continue;
         }
       }
@@ -2315,11 +2287,7 @@ int main(int argc, char **argv) {
       bool matched = ikfom_.update_iterated_dyn_share_modified(LASER_POINT_COV, solve_H_time);//预测、更新
       state_point = ikfom_.get_x();
       last_state_point = state_point;
-      /*if (matched==false && locate_mode==true) {
-        printf(" ikfom state update failed ...continue...\n");
-        ikfom_.change_x(last_state_point);//恢复到前一帧的数据
-        state_point = last_state_point;
-      }*/
+
 
       euler_cur = SO3ToEuler(state_point.rot);
       pos_lid = state_point.pos + state_point.rot * state_point.offset_T_L_I; // world系下lidar坐标
@@ -2329,6 +2297,7 @@ int main(int argc, char **argv) {
       geoQuat.w = state_point.rot.coeffs()[3];
       double t_update_end = omp_get_wtime();
       getCurPose(state_point); //   更新transformTobeMapped
+
       // Publish points
       if (scan_pub_en) {
         publish_frame_world(pubLaserCloudFull);        //   发布world系下的点云
@@ -2350,6 +2319,7 @@ int main(int argc, char **argv) {
         saveKeyFramesAndFactor();
         // 更新因子图中所有变量节点的位姿,也就是所有历史关键帧的位姿,更新里程计轨迹, 重构ikdtree
         correctPoses();
+
       }
       double tloop = omp_get_wtime();
       /*printf(" match time:%fs,kdtree points:%d  save KeyFrame loop time:%fs\n", t_update_end - t_update_start,

+ 4 - 0
src/preprocess.h

@@ -1,3 +1,6 @@
+#ifndef __IMU_Processing__HH
+#define __IMU_Processing__HH
+
 #include <ros/ros.h>
 #include <pcl_conversions/pcl_conversions.h>
 #include <sensor_msgs/PointCloud2.h>
@@ -164,3 +167,4 @@ class Preprocess
   double smallp_intersect, smallp_ratio;
   double vx, vy, vz;
 };
+#endif