19 #include <Eigen/Dense>
20 #include <unsupported/Eigen/MatrixFunctions>
24 namespace registration {
30 inline Eigen::Matrix3d GetRotationFromE1ToX(
const Eigen::Vector3d &x) {
31 const Eigen::Vector3d e1{1, 0, 0};
32 const Eigen::Vector3d v = e1.cross(x);
33 const double c = e1.dot(x);
36 return Eigen::Matrix3d::Identity();
40 const double factor = 1 / (1 + c);
41 return Eigen::Matrix3d::Identity() + sv + (sv * sv) * factor;
49 std::shared_ptr<ccPointCloud> InitializePointCloudForGeneralizedICP(
51 auto output = std::make_shared<ccPointCloud>(pcd);
52 if (output->HasCovariances()) {
56 if (output->hasNormals()) {
61 output->EstimateNormals(
65 output->covariances_.resize(output->size());
66 const Eigen::Matrix3d C = Eigen::Vector3d(epsilon, 1, 1).asDiagonal();
67 #pragma omp parallel for schedule(static)
68 for (
int i = 0; i < (int)output->size(); i++) {
69 const auto Rx = GetRotationFromE1ToX(output->getEigenNormal(i));
70 output->covariances_[i] = Rx * C * Rx.transpose();
84 for (
const auto &c : corres) {
89 const Eigen::Vector3d d = vs - vt;
90 const Eigen::Matrix3d M = Ct + Cs;
91 const Eigen::Matrix3d W = M.inverse().sqrt();
92 err += d.transpose() * W * d;
94 return std::sqrt(err / (
double)corres.size());
104 return Eigen::Matrix4d::Identity();
107 auto compute_jacobian_and_residual =
109 std::vector<Eigen::Vector6d, utility::Vector6d_allocator> &J_r,
110 std::vector<double> &r, std::vector<double> &w) {
111 const Eigen::Vector3d vs = source.
getEigenPoint(corres[i][0]);
112 const Eigen::Matrix3d &Cs = source.
covariances_[corres[i][0]];
113 const Eigen::Vector3d vt = target.
getEigenPoint(corres[i][1]);
114 const Eigen::Matrix3d &Ct = target.
covariances_[corres[i][1]];
115 const Eigen::Vector3d d = vs - vt;
116 const Eigen::Matrix3d M = Ct + Cs;
117 const Eigen::Matrix3d W = M.inverse().sqrt();
119 Eigen::Matrix<double, 3, 6> J;
121 J.block<3, 3>(0, 3) = Eigen::Matrix3d::Identity();
124 constexpr
int n_rows = 3;
128 for (
size_t i = 0; i < n_rows; ++i) {
129 r[i] = W.row(i).dot(d);
138 std::tie(JTJ, JTr, r2) =
139 utility::ComputeJTJandJTr<Eigen::Matrix6d, Eigen::Vector6d>(
140 compute_jacobian_and_residual, (
int)corres.size());
142 bool is_success =
false;
143 Eigen::Matrix4d extrinsic;
144 std::tie(is_success, extrinsic) =
147 return is_success ? extrinsic : Eigen::Matrix4d::Identity();
154 const Eigen::Matrix4d &init ,
160 *InitializePointCloudForGeneralizedICP(source, estimation.
epsilon_),
161 *InitializePointCloudForGeneralizedICP(target, estimation.
epsilon_),
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool HasCovariances() const
Returns 'true' if the point cloud contains per-point covariance matrix.
std::vector< Eigen::Matrix3d > covariances_
Covariance Matrix for each point.
Eigen::Vector3d getEigenPoint(size_t index) const
KDTree search parameters for pure KNN search.
Class that defines the convergence criteria of ICP.
Eigen::Matrix< double, 6, 1 > Vector6d
Eigen::Matrix< double, 6, 6 > Matrix6d
Extending Eigen namespace by adding frequently used matrix type.
RegistrationResult RegistrationGeneralizedICP(const ccPointCloud &source, const ccPointCloud &target, double max_correspondence_distance, const Eigen::Matrix4d &init, const TransformationEstimationForGeneralizedICP &estimation, const ICPConvergenceCriteria &criteria)
Function for Generalized ICP registration.
std::vector< Eigen::Vector2i > CorrespondenceSet
RegistrationResult RegistrationICP(const ccPointCloud &source, const ccPointCloud &target, double max_correspondence_distance, const Eigen::Matrix4d &init, const TransformationEstimation &estimation, const ICPConvergenceCriteria &criteria)
Functions for ICP registration.
static const double max_correspondence_distance
Eigen::Matrix3d SkewMatrix(const Eigen::Vector3d &vec)
Genretate a skew-symmetric matrix from a vector 3x1.
std::tuple< bool, Eigen::Matrix4d > SolveJacobianSystemAndObtainExtrinsicMatrix(const Eigen::Matrix6d &JTJ, const Eigen::Vector6d &JTr)
Generic file read and write utility for python interface.