solver: writing...
parent
69135ebe48
commit
acc6f39660
|
@ -54,6 +54,8 @@ target_link_libraries(main
|
||||||
g3log
|
g3log
|
||||||
common
|
common
|
||||||
oh_my_loam
|
oh_my_loam
|
||||||
|
# helper
|
||||||
|
# solver
|
||||||
extractor
|
extractor
|
||||||
visualizer
|
visualizer
|
||||||
# odometry
|
# odometry
|
||||||
|
|
|
@ -64,8 +64,6 @@ struct PointXYZT {
|
||||||
y = p.y;
|
y = p.y;
|
||||||
z = p.z;
|
z = p.z;
|
||||||
time = p.time;
|
time = p.time;
|
||||||
curvature = p.curvature;
|
|
||||||
type = p.type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
add_subdirectory(extractor)
|
add_subdirectory(extractor)
|
||||||
add_subdirectory(visualizer)
|
add_subdirectory(visualizer)
|
||||||
# add_subdirectory(odometry)
|
# add_subdirectory(odometry)
|
||||||
|
add_subdirectory(helper)
|
||||||
|
add_subdirectory(solver)
|
||||||
|
|
||||||
aux_source_directory(. SRC_FILES)
|
aux_source_directory(. SRC_FILES)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
aux_source_directory(. SRC_FILES)
|
||||||
|
|
||||||
|
add_library(helper SHARED ${SRC_FILES})
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
namespace oh_my_loam {
|
||||||
|
|
||||||
|
float GetTime(const TPoint& pt) { return pt.time - GetScanId(pt); }
|
||||||
|
|
||||||
|
int GetScanId(const TPoint& pt) { return static_cast<int>(pt.time); }
|
||||||
|
|
||||||
|
double PointLinePair::DistPointToLine() const { return 0.0; }
|
||||||
|
|
||||||
|
double PointPlanePair::DistPointToPlane() const { return 0.0; }
|
||||||
|
|
||||||
|
} // oh_my_loam
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
namespace oh_my_loam {
|
||||||
|
|
||||||
|
float GetTime(const TPoint& pt);
|
||||||
|
|
||||||
|
int GetScanId(const TPoint& pt);
|
||||||
|
|
||||||
|
struct PointLinePair {
|
||||||
|
TPoint pt;
|
||||||
|
struct Line {
|
||||||
|
TPoint pt1, pt2;
|
||||||
|
Line() = default;
|
||||||
|
Line(const TPoint& pt1, const TPoint& pt2) : pt1(pt1), pt2(pt2) {}
|
||||||
|
};
|
||||||
|
Line line;
|
||||||
|
PointLinePair(const TPoint& pt, const Line& line) : pt(pt), line(line) {}
|
||||||
|
double DistPointToLine() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointPlanePair {
|
||||||
|
TPoint pt;
|
||||||
|
struct Plane {
|
||||||
|
TPoint pt1, pt2, pt3;
|
||||||
|
Plane() = default;
|
||||||
|
Plane(const TPoint& pt1, const TPoint& pt2, const TPoint& pt3)
|
||||||
|
: pt1(pt1), pt2(pt2), pt3(pt3) {}
|
||||||
|
};
|
||||||
|
Plane plane;
|
||||||
|
PointPlanePair(const TPoint& pt, const Plane& plane) : pt(pt), plane(plane) {}
|
||||||
|
double DistPointToPlane() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // oh_my_loam
|
|
@ -2,8 +2,15 @@
|
||||||
|
|
||||||
namespace oh_my_loam {
|
namespace oh_my_loam {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int kNearbyScanNum = 2;
|
||||||
|
double kDistSquareThresh = 25;
|
||||||
|
}
|
||||||
|
|
||||||
bool Odometry::Init(const YAML::Node& config) {
|
bool Odometry::Init(const YAML::Node& config) {
|
||||||
config_ = config;
|
config_ = config;
|
||||||
|
kdtree_surf_pts.reset(new pcl::KdTreeFLANN<TPoint>);
|
||||||
|
kdtree_corn_pts.reset(new pcl::KdTreeFLANN<TPoint>);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,40 +20,115 @@ void Odometry::Process(const FeaturePoints& feature) {
|
||||||
UpdatePre(feature);
|
UpdatePre(feature);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AssociateCornPoints();
|
std::vector<PointLinePair> pl_pairs;
|
||||||
AssociateSurfPoints();
|
std::vector<PointPlanePair> pp_pairs;
|
||||||
|
AssociateCornPoints(*feature.sharp_corner_pts, corn_pts_pre_, pl_pairs,
|
||||||
|
kDistSquareThresh);
|
||||||
|
AssociateSurfPoints(*feature.flat_surf_pts, surf_pts_pre_, pp_pairs,
|
||||||
|
kDistSquareThresh);
|
||||||
|
|
||||||
UpdatePre(feature);
|
UpdatePre(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Odometry::AssociateCornPoints(
|
void Odometry::AssociateCornPoints(const TPointCloud& src,
|
||||||
const TPointCloud& sharp_corn_pts_curr,
|
const TPointCloud& tgt,
|
||||||
std::vector<PointLinePair>* const pairs) const {
|
std::vector<PointLinePair>* const pairs,
|
||||||
for (const pt : sharp_corn_pts_curr) {
|
double dist_thresh) const {
|
||||||
Point p1, p2;
|
kdtree_corn_pts_->setInputCloud(tgt);
|
||||||
|
for (const query_pt : src) {
|
||||||
pairs->emplace_back(pt, {p1, p2});
|
std::vector<int> indices;
|
||||||
|
std::vector<float> dists;
|
||||||
|
kdtree_corn_pts->nearestKSearch(query_pt, 1, indices, dists);
|
||||||
|
if (dists[0] >= dist_thresh) continue;
|
||||||
|
Point pt1 = tgt.points[indices[0]];
|
||||||
|
int pt2_idx = -1;
|
||||||
|
double min_dist_pt2_squre = dist_thresh * dist_thresh;
|
||||||
|
int query_pt_scan_id = GetScanId(query_pt);
|
||||||
|
for (int i = indices[0] + 1; i < tgt.size(); ++i) {
|
||||||
|
const auto pt = tgt.points[i];
|
||||||
|
int scan_id = GetScanId(pt);
|
||||||
|
if (scan_id <= query_pt_scan_id) continue;
|
||||||
|
if (scan_id > query_pt_scan_id + kNearbyScanNum) break;
|
||||||
|
double dist_squre = DistanceSqure(query_pt, pt);
|
||||||
|
if (dist_squre < min_dist_pt2_squre) {
|
||||||
|
pt2_idx = i;
|
||||||
|
min_dist_pt2_squre = dist_squre;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = indices[0] - 1; i >= 0; --i) {
|
||||||
|
const auto pt = tgt.points[i];
|
||||||
|
int scan_id = GetScanId(pt);
|
||||||
|
if (scan_id >= query_pt_scan_id) continue;
|
||||||
|
if (scan_id < query_pt_scan_id - kNearbyScanNum) break;
|
||||||
|
double dist_squre = DistanceSqure(query_pt, pt);
|
||||||
|
if (dist_squre < min_dist_pt2_squre) {
|
||||||
|
pt2_idx = i;
|
||||||
|
min_dist_pt2_squre = dist_squre;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pt2_idx >= 0) {
|
||||||
|
TPoint pt2 = tgt.points[pt2_idx];
|
||||||
|
pairs->emplace_back(query_pt, {pt1, pt2});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Odometry::AssociateSurfPoints(
|
void Odometry::AssociateSurfPoints(const TPointCloud& src,
|
||||||
const TPointCloud& flat_surf_pts_curr,
|
const TPointCloud& tgt,
|
||||||
std::vector<PointPlanePair>* const pairs) const {
|
std::vector<PointPlanePair>* const pairs,
|
||||||
for (const pt : flat_surf_pts_curr) {
|
double dist_thresh) const {
|
||||||
Point p1, p2, p3;
|
kdtree_surf_pts_->setInputCloud(tgt);
|
||||||
pairs->emplace_back(pt, {p1, p2, p3});
|
for (const query_pt : src) {
|
||||||
|
std::vector<int> indices;
|
||||||
|
std::vector<float> dists;
|
||||||
|
kdtree_corn_pts->nearestKSearch(query_pt, 1, indices, dists);
|
||||||
|
if (dists[0] >= dist_thresh) continue;
|
||||||
|
Point pt1 = tgt.points[indices[0]];
|
||||||
|
int pt2_idx = -1, pt3_idx = -1;
|
||||||
|
double min_dist_pt2_squre = dist_thresh * dist_thresh;
|
||||||
|
double min_dist_pt3_squre = dist_thresh * dist_thresh;
|
||||||
|
int query_pt_scan_id = GetScanId(query_pt);
|
||||||
|
for (int i = indices[0] + 1; i < tgt.size(); ++i) {
|
||||||
|
const auto pt = tgt.points[i];
|
||||||
|
int scan_id = GetScanId(pt);
|
||||||
|
if (scan_id > query_pt_scan_id + kNearbyScanNum) break;
|
||||||
|
double dist_squre = DistanceSqure(query_pt, pt);
|
||||||
|
if (scan_id == query_pt_scan_id && dist_squre < min_dist_pt2_squre) {
|
||||||
|
pt2_idx = i;
|
||||||
|
min_dist_pt2_squre = dist_squre;
|
||||||
|
}
|
||||||
|
if (scan_id > query_pt_scan_id && dist_squre < min_dist_pt2_squre) {
|
||||||
|
pt3_idx = i;
|
||||||
|
min_dist_pt3_squre = dist_squre;
|
||||||
|
}
|
||||||
|
if (pt2_idx == -1 && scan_id > query_pt_scan_id) break;
|
||||||
|
}
|
||||||
|
for (int i = indices[0] - 1; i >= 0; --i) {
|
||||||
|
const auto pt = tgt.points[i];
|
||||||
|
int scan_id = GetScanId(pt);
|
||||||
|
if (scan_id >= query_pt_scan_id) continue;
|
||||||
|
if (scan_id < query_pt_scan_id - kNearbyScanNum) break;
|
||||||
|
double dist_squre = DistanceSqure(query_pt, pt);
|
||||||
|
if (scan_id == query_pt_scan_id && dist_squre < min_dist_pt2_squre) {
|
||||||
|
pt2_idx = i;
|
||||||
|
min_dist_pt2_squre = dist_squre;
|
||||||
|
}
|
||||||
|
if (scan_id < query_pt_scan_id && dist_squre < min_dist_pt2_squre) {
|
||||||
|
pt3_idx = i;
|
||||||
|
min_dist_pt3_squre = dist_squre;
|
||||||
|
}
|
||||||
|
if (pt2_idx == -1 && scan_id < query_pt_scan_id) break;
|
||||||
|
}
|
||||||
|
if (pt2_idx >= 0 && pt3_idx >= 0) {
|
||||||
|
TPoint pt2 = tgt.points[pt2_idx], pt3 = tgt.points[pt3_idx];
|
||||||
|
pairs->emplace_back(query_pt, {pt1, pt2, pt3});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Odometry::UpdatePre(const FeaturePoints& feature) {
|
void Odometry::UpdatePre(const FeaturePoints& feature) {
|
||||||
surf_pts_pre_ = feature.less_flat_surf_pts;
|
surf_pts_pre_ = feature.less_flat_surf_pts;
|
||||||
corn_pts_pre_ = feature.less_sharp_corner_pts;
|
corn_pts_pre_ = feature.less_sharp_corner_pts;
|
||||||
kdtree_surf_pts_->setInputCloud(surf_pts_pre_);
|
|
||||||
kdtree_corn_pts_->setInputCloud(corn_pts_pre_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetTime(const TPoint& pt) { return pt.time - GetScanId(pt); }
|
|
||||||
|
|
||||||
int GetScanId(const TPoint& pt) { return static_cast<int>(pt.time); }
|
|
||||||
|
|
||||||
} // namespace oh_my_loam
|
} // namespace oh_my_loam
|
||||||
|
|
|
@ -5,35 +5,10 @@
|
||||||
#include <eigen3/Eigen/Dense>
|
#include <eigen3/Eigen/Dense>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "helper/helper.h"
|
||||||
|
|
||||||
namespace oh_my_loam {
|
namespace oh_my_loam {
|
||||||
|
|
||||||
float GetTime(const TPoint& pt);
|
|
||||||
int GetScanId(const TPoint& pt);
|
|
||||||
|
|
||||||
struct PointLinePair {
|
|
||||||
Point pt;
|
|
||||||
struct Line {
|
|
||||||
Point pt1, pt2;
|
|
||||||
Line(const Point& pt1, const Point& pt2) : pt1(pt1), pt2(pt2) {}
|
|
||||||
};
|
|
||||||
Line line;
|
|
||||||
PointLinePair(const Point& pt, const Line& line) : pt(pt), line(line) {}
|
|
||||||
double PointToLineDist() { return 0.0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PointPlanePair {
|
|
||||||
Point pt;
|
|
||||||
struct Plane {
|
|
||||||
Point pt1, pt2, pt3;
|
|
||||||
Plane(const Point& pt1, const Point& pt2, const Point& pt3)
|
|
||||||
: pt1(pt1), pt2(pt2), pt3(pt3) {}
|
|
||||||
};
|
|
||||||
Plane plane;
|
|
||||||
PointLinePair(const Point& pt, const Plane& plane) : pt(pt), plane(plane) {}
|
|
||||||
double PointToPlaneDist() { return 0.0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// frame to frame lidar odometry
|
// frame to frame lidar odometry
|
||||||
class Odometry {
|
class Odometry {
|
||||||
public:
|
public:
|
||||||
|
@ -45,21 +20,23 @@ class Odometry {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdatePre(const FeaturePoints& feature);
|
void UpdatePre(const FeaturePoints& feature);
|
||||||
void AssociateCornPoints(const TPointCloud& sharp_corn_pts_curr,
|
void AssociateCornPoints(const TPointCloud& src, const TPointCloud& tgt,
|
||||||
std::vector<PointLinePair>* const pairs) const;
|
std::vector<PointLinePair>* const pairs,
|
||||||
|
double dist_thresh) const;
|
||||||
|
|
||||||
void AssociateSurfPoints(const TPointCloud& flat_surf_pts_curr,
|
void AssociateSurfPoints(const TPointCloud& src, const TPointCloud& tgt,
|
||||||
std::vector<PointPlanePair>* const pairs) const;
|
std::vector<PointPlanePair>* const pairs,
|
||||||
|
double dist_thresh) const;
|
||||||
YAML::Node config_;
|
|
||||||
|
|
||||||
bool is_initialized = false;
|
|
||||||
|
|
||||||
TPointCloudPtr surf_pts_pre_;
|
TPointCloudPtr surf_pts_pre_;
|
||||||
TPointCloudPtr corn_pts_pre_;
|
TPointCloudPtr corn_pts_pre_;
|
||||||
|
|
||||||
pcl::KdTreeFLANN<TPoint>::Ptr kdtree_surf_pts(new pcl::KdTreeFLANN<TPoint>);
|
pcl::KdTreeFLANN<TPoint>::Ptr kdtree_surf_pts;
|
||||||
pcl::KdTreeFLANN<TPoint>::Ptr kdtree_corn_pts(new pcl::KdTreeFLANN<TPoint>);
|
pcl::KdTreeFLANN<TPoint>::Ptr kdtree_corn_pts;
|
||||||
|
|
||||||
|
bool is_initialized = false;
|
||||||
|
|
||||||
|
YAML::Node config_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace oh_my_loam
|
} // namespace oh_my_loam
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
aux_source_directory(. SRC_FILES)
|
||||||
|
|
||||||
|
add_library(solver SHARED ${SRC_FILES})
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include "solver.h"
|
||||||
|
|
||||||
|
namespace oh_my_loam {
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
} // oh_my_loam
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ceres/ceres.h"
|
||||||
|
|
||||||
|
namespace oh_my_loam {
|
||||||
|
|
||||||
|
class Solver {
|
||||||
|
public:
|
||||||
|
Solver() = default;
|
||||||
|
|
||||||
|
void SetInitialGuess(double* param_q, double* param_p);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<ceres::Problem> problem_;
|
||||||
|
ceres::LocalParameterization* parameterization_;
|
||||||
|
ceres::LossFunction* loss_function_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // oh_my_loam
|
Loading…
Reference in New Issue