1+ #include < cmath>
2+ #include < tuple>
3+ #include < mutex>
4+ #include < chrono>
5+ #include < thread>
6+ #include < unordered_map>
7+ #include < queue>
8+ #include < Eigen/Dense>
9+
10+ #include < scancontext/Scancontext.h>
11+ #include < open3d/geometry/PointCloud.h>
12+ #include < open3d/pipelines/registration/Registration.h>
13+ #include < open3d/pipelines/registration/PoseGraph.h>
14+ #include < open3d/pipelines/registration/GlobalOptimization.h>
15+ #include < open3d/pipelines/registration/GlobalOptimizationMethod.h>
16+ #include < open3d/utility/Logging.h>
17+ #include < open3d/io/PoseGraphIO.h>
18+ #include < open3d/pipelines/registration/Feature.h>
19+
20+ #include < open3d/visualization/visualizer/Visualizer.h>
21+
22+ #include < kitti_tools.h>
23+ #include < io_tools.h>
24+
25+ #include < gtsam/inference/Symbol.h>
26+ #include < gtsam/nonlinear/Values.h>
27+ #include < gtsam/nonlinear/Marginals.h>
28+ #include < gtsam/geometry/Rot3.h>
29+ #include < gtsam/geometry/Pose3.h>
30+ #include < gtsam/slam/PriorFactor.h>
31+ #include < gtsam/slam/BetweenFactor.h>
32+ #include < gtsam/nonlinear/NonlinearFactorGraph.h>
33+ #include < gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
34+ #include < gtsam/nonlinear/ISAM2.h>
35+
36+ gtsam::Pose3 Eigen2GTSAM (const Eigen::Isometry3d &poseEigen);
37+ gtsam::Pose3 Eigen2GTSAM (const Eigen::Matrix4d &poseEigen);
38+
39+ std::tuple<double ,double > PoseDif (Eigen::Isometry3d &srcPose, Eigen::Isometry3d &tgtPose);
40+ std::tuple<double ,double > PoseDif (Eigen::Matrix4d &srcPose, Eigen::Matrix4d &tgtPose);
41+
42+ open3d::pipelines::registration::RegistrationResult Registration (const open3d::geometry::PointCloud &srcPointCloud, const open3d::geometry::PointCloud &tgtPointCloud, const Eigen::Matrix4d &initialPose, const double icp_corr_dist);
43+ open3d::pipelines::registration::RegistrationResult Registration (const open3d::geometry::PointCloud &srcPointCloud, const open3d::geometry::PointCloud &tgtPointCloud, const Eigen::Matrix4d &initialPose, const double icp_coarse_dist, const double icp_refine_dist);
44+
45+ open3d::geometry::PointCloud ReadPointCloudO3D (const std::string filename);
46+
47+ class BackEndOption {
48+ public:
49+ bool verborse = false ;
50+ bool vis = false ;
51+ double voxel = 0.4 ;
52+ double o3d_voxel = 0.2 ;
53+ double keyframeMeterGap = 2 ;
54+ double keyframeRadGap = 0.2 ;
55+ double LCkeyframeMeterGap = 20 ;
56+ double LCkeyframeRadGap = 2.0 ;
57+ int LCSubmapSize = 25 ;
58+
59+ double scDistThres = 0.2 ;
60+ double scMaximumRadius = 80 ;
61+ double loopOverlapThre = 0.8 ; // the overlapping area (# of inlier correspondences / # of points in target). Higher is better.
62+ double loopInlierRMSEThre = 0.3 ;
63+ double icp_corase_dist = 0.4 * 15 ;
64+ double icp_refine_dist = 0.4 * 1.5 ;
65+ int icp_max_iter = 30 ;
66+
67+ double relinearizeThreshold = 0.01 ;
68+ int relinearizeSkip = 1 ;
69+ gtsam::ISAM2Params::Factorization factorization = gtsam::ISAM2Params::QR;
70+ gtsam::Vector6 priorNoiseVector6;
71+ gtsam::Vector6 odomNoiseVector6;
72+ gtsam::Vector6 robustNoiseVector6;
73+
74+ double MRmaxCorrDist = 0.6 ;
75+ double MREdgePruneThre = 0.25 ;
76+ int MRmaxIter = 100 ;
77+
78+ public:
79+ BackEndOption (){
80+ priorNoiseVector6 << 1e-12 , 1e-12 , 1e-12 , 1e-12 , 1e-12 , 1e-12 ;
81+ odomNoiseVector6 << 1e-6 , 1e-6 , 1e-6 , 1e-4 , 1e-4 , 1e-4 ;
82+ robustNoiseVector6 << 0.5 , 0.5 , 0.5 , 0.5 , 0.5 , 0.5 ;
83+ }
84+ };
85+
86+ class BackEndOptimizer {
87+ public:
88+ BackEndOptimizer (const BackEndOption &option);
89+ void LoadPose (const std::string dirname);
90+ void LoadDataFilename (const std::string dirname);
91+ Eigen::Isometry3d getPose (const int i);
92+ Eigen::Isometry3d getrelPose (const int i, const int j);
93+ open3d::geometry::PointCloud LoadPCD (const int idx) const ;
94+ open3d::geometry::PointCloud LoadPCD (const int idx, double voxel_) const ;
95+ open3d::geometry::PointCloud MergeLoadPCD (const int ref_idx, const int start_idx, const int end_idx);
96+ void AddLoopClosure (const std::tuple<int ,int ,open3d::geometry::PointCloud> &item);
97+ bool IsLoopBufEmpty ();
98+ void AddPriorFactor (const int i, const gtsam::Pose3 &pose);
99+ void AddOdomFactor (const int i, const int j, const gtsam::Pose3 &relPose, const gtsam::Pose3 &currPose);
100+ void AddBetweenFactor (const gtsam::BetweenFactor<gtsam::Pose3> &factor);
101+ std::tuple<int ,int ,open3d::geometry::PointCloud> PopLoopClosure ();
102+ void SCManage (const int i = 0 ); // for initialization
103+ void SCManage (const int i, const int j); // for odometry
104+ void LoopClosureRegThread (void );
105+ bool CheckStopLoopClosure (void );
106+ void StopLoopClosure (void );
107+ void UpdateISAM ();
108+ void UpdatePosesFromEstimates (const gtsam::Values &Estimates);
109+ void UpdatePosesFromInitialEstimates ();
110+ void UpdatePosesFromPG ();
111+ void LoopClosureRun (const std::string pose_dir, const std::string file_dir);
112+ void PerformLoopClosure (const int j, open3d::geometry::PointCloud &PointCloud);
113+ void MultiRegistration (bool OdomRefinement=false );
114+ void writePoseGraph (const std::string &filename) const ;
115+ void writePoses (const std::string &filename);
116+
117+ private:
118+ bool verborse;
119+ bool vis;
120+ const double voxel;
121+ const double o3d_voxel;
122+ const double keyframeMeterGap;
123+ const double keyframeRadGap;
124+ const double scDistThres;
125+ const double scMaximumRadius;
126+
127+ const double loopOverlapThre;
128+ const double loopInlierRMSEThre;
129+ const int LCSubmapSize;
130+ const double LCkeyframeMeterGap;
131+ const double LCkeyframeRadGap;
132+
133+ const double icp_corase_dist;
134+ const double icp_refine_dist;
135+ const int icp_max_iter;
136+
137+ const double MRmaxCorrDist;
138+ const double MREdgePruneThre;
139+ const int MRmaxIter;
140+
141+ double translationAccumulated;
142+ double rotationAccumulated;
143+ double LCtranslationAccumulated;
144+ double LCrotationAccumulated;
145+
146+ bool IsLoopClosureStop;
147+
148+ std::vector<Eigen::Isometry3d> RawFramePoses;
149+ std::vector<std::string> PointCloudFiles;
150+ SC2::SCManager SCManager;
151+ open3d::pipelines::registration::PoseGraph PoseGraph;
152+
153+ // SCManager
154+ std::vector<Eigen::Isometry3d> FramePoses;
155+ std::vector<int > KeyFrameQuery;
156+ std::queue<std::tuple<int , int , open3d::geometry::PointCloud>> LoopClosureBuf;
157+ std::unordered_map<int , int > LoopQueryMap;
158+
159+
160+ // GTSAM
161+ Eigen::Isometry3d OdomPose;
162+ gtsam::ISAM2* isam;
163+ gtsam::Values initialEstimate;
164+ gtsam::NonlinearFactorGraph FactorGraph;
165+ gtsam::noiseModel::Diagonal::shared_ptr priorNoise;
166+ gtsam::noiseModel::Diagonal::shared_ptr odomNoise;
167+ gtsam::noiseModel::Base::shared_ptr robustLoopNoise;
168+
169+ std::mutex LoopClosureMutex;
170+ std::mutex LoopBufMutex;
171+ std::mutex FactorGraphMutex;
172+ std::mutex FramePoseMutex;
173+
174+
175+ };
0 commit comments