1 #ifndef Csc3dCartographyProcessor_h
2 #define Csc3dCartographyProcessor_h
6 #include <pcl/point_types.h>
7 #include <pcl/point_cloud.h>
19 float pitchRad = 0.0f;
28 double deltaPitch = 0.0;
29 double deltaYaw = 0.0;
30 double deltaRoll = 0.0;
66 double timestamp = 0.0;
67 optional<OdometryDeltaSidecar> odometryDelta = nullopt;
70 string toJsonString()
const;
96 float voxelLeafSize = 5.0f;
106 float finalVoxelLeafSize = 2.0f;
116 double maxEdgeRmse = 30.0;
125 float maxAngleDeg = 45.0f;
127 bool odometryOnlyMode =
false;
129 double maxTranslationCorrection = 20.0f;
131 bool useOdometryInitialGuess =
true;
132 bool fallbackToOdometryWhenGicpRejected =
false;
134 bool enableYawMultistart =
true;
136 float odometryYawClampDeg = 8.0f;
137 float odometryTranslationScale = 0.7f;
139 bool accumulateStaticBootstrap =
true;
140 float staticBootstrapMaxTranslationCm = 2.0f;
141 float staticBootstrapMaxYawDeg = 1.0f;
143 std::vector<float> yawMultistartOffsetsDeg = {
162 int localMapWindowSize = 5;
171 int lumMaxIterations = 50;
180 int lumOverlapWindow = 10;
190 double gicpResolution = 10.0;
199 double spatialLoopDist = 500.0;
208 int temporalLoopGap = 50;
217 double loopClosureThreshold = 30.0;
227 float dynVoxelSize = 20.0f;
237 int minFrameObservations = 1;
246 int ransacMaxIterations = 200;
255 double ransacDistanceThreshold = 5.0;
265 int ransacMinInliers = 1000;
277 bool enableSpatialFilter =
true;
286 float maxAbsCoord = 1500.0f;
295 float maxRange = 1500.0f;
310 bool enableGroundLevelling =
false;
320 float groundMaxTiltDeg = 15.0f;
330 float groundMinUpDot = 0.95f;
392 const fs::path &inputFolderPath,
393 const fs::path &outputFilePath,
401 Eigen::Matrix4f estimateRelativeFrameTransform(
405 fs::path inputFolderPath;
406 fs::path outputFilePath;
408 std::string pcdPrefix =
"lidar_";
409 std::unique_ptr<CscLogger>
logger;
411 vector<FrameMetadata> frameMetadata;
412 vector<PointCloudT::Ptr> rawFrames;
413 vector<PointCloudT::Ptr> downsampledFrames;
414 vector<uint32_t> validFrameIds;
416 Eigen::Matrix3f groundLevellingR0 = Eigen::Matrix3f::Identity();
418 bool validateInputs()
const;
422 void computeInitialOdometry(vector<Eigen::Matrix4f> &poses);
424 void buildAndOptimizeElchGraph(
425 const vector<Eigen::Matrix4f> &initialPoses,
426 vector<Eigen::Matrix4f> &optimizedPoses);
428 PointCloudT::Ptr mergeAndFilter(
const vector<Eigen::Matrix4f> &poses);
430 void saveToPLY(
const PointCloudT::Ptr &cloud,
const fs::path &path);
432 bool readJsonSidecar(
const fs::path &jsonPath,
FrameMetadata &out)
const;
434 PointCloudT::Ptr applyVoxelGridFilter(PointCloudT::Ptr input,
float leafSize);
436 void computeGicpAlignment(
438 PointCloudT::Ptr target,
439 Eigen::Matrix4f &transformOut,
441 const Eigen::Matrix4f &initialGuess,
444 string getProgressBarText(
int current,
int total,
const std::string &prefix);
446 std::vector<bool> acceptedPoseMask;