39 #ifndef POINT_CLOUD_COMMON_TRANSFORMATION_ESTIMATION_SYMMETRIC_POINT_TO_PLANE_LLS_IMPL_H_
40 #define POINT_CLOUD_COMMON_TRANSFORMATION_ESTIMATION_SYMMETRIC_POINT_TO_PLANE_LLS_IMPL_H_
42 #include <pcl/cloud_iterator.h>
48 namespace registration {
50 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
53 const pcl::PointCloud<PointSource>& cloud_src,
const pcl::PointCloud<PointTarget>& cloud_tgt,
54 Matrix4& transformation_matrix)
const {
55 const auto nr_points = cloud_src.size();
56 if (cloud_tgt.size() != nr_points) {
58 "[pcl::TransformationEstimationSymmetricPointToPlaneLLS::"
59 "estimateRigidTransformation] Number or points in source (%zu) differs "
60 "from target (%zu)!\n",
61 static_cast<std::size_t
>(nr_points),
static_cast<std::size_t
>(cloud_tgt.size()));
65 ConstCloudIterator<PointSource> source_it(cloud_src);
66 ConstCloudIterator<PointTarget> target_it(cloud_tgt);
67 estimateRigidTransformation(source_it, target_it, transformation_matrix);
70 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
72 const pcl::PointCloud<PointSource>& cloud_src,
const std::vector<int>& indices_src,
73 const pcl::PointCloud<PointTarget>& cloud_tgt,
Matrix4& transformation_matrix)
const {
74 const auto nr_points = indices_src.size();
75 if (cloud_tgt.size() != nr_points) {
77 "[pcl::TransformationEstimationSymmetricPointToPlaneLLS::"
78 "estimateRigidTransformation] Number or points in source (%zu) differs "
79 "than target (%zu)!\n",
80 indices_src.size(),
static_cast<std::size_t
>(cloud_tgt.size()));
84 ConstCloudIterator<PointSource> source_it(cloud_src, indices_src);
85 ConstCloudIterator<PointTarget> target_it(cloud_tgt);
86 estimateRigidTransformation(source_it, target_it, transformation_matrix);
89 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
92 const pcl::PointCloud<PointSource>& cloud_src,
const std::vector<int>& indices_src,
93 const pcl::PointCloud<PointTarget>& cloud_tgt,
const std::vector<int>& indices_tgt,
94 Matrix4& transformation_matrix)
const {
95 const auto nr_points = indices_src.size();
96 if (indices_tgt.size() != nr_points) {
98 "[pcl::TransformationEstimationSymmetricPointToPlaneLLS::"
99 "estimateRigidTransformation] Number or points in source (%zu) differs "
100 "than target (%zu)!\n",
101 indices_src.size(), indices_tgt.size());
105 ConstCloudIterator<PointSource> source_it(cloud_src, indices_src);
106 ConstCloudIterator<PointTarget> target_it(cloud_tgt, indices_tgt);
107 estimateRigidTransformation(source_it, target_it, transformation_matrix);
110 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
113 const pcl::PointCloud<PointSource>& cloud_src,
const pcl::PointCloud<PointTarget>& cloud_tgt,
114 const pcl::Correspondences& correspondences,
Matrix4& transformation_matrix)
const {
115 ConstCloudIterator<PointSource> source_it(cloud_src, correspondences,
true);
116 ConstCloudIterator<PointTarget> target_it(cloud_tgt, correspondences,
false);
117 estimateRigidTransformation(source_it, target_it, transformation_matrix);
120 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
123 const Vector6& parameters,
Matrix4& transformation_matrix)
const {
125 const Eigen::AngleAxis<Scalar> rotation_z(parameters(2), Eigen::Matrix<Scalar, 3, 1>::UnitZ());
126 const Eigen::AngleAxis<Scalar> rotation_y(parameters(1), Eigen::Matrix<Scalar, 3, 1>::UnitY());
127 const Eigen::AngleAxis<Scalar> rotation_x(parameters(0), Eigen::Matrix<Scalar, 3, 1>::UnitX());
128 const Eigen::Translation<Scalar, 3> translation(parameters(3), parameters(4), parameters(5));
129 const Eigen::Transform<Scalar, 3, Eigen::Affine> transform =
130 rotation_z * rotation_y * rotation_x * translation * rotation_z * rotation_y * rotation_x;
131 transformation_matrix = transform.matrix();
134 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
137 ConstCloudIterator<PointSource>& source_it, ConstCloudIterator<PointTarget>& target_it,
138 Matrix4& transformation_matrix)
const {
139 using Matrix6 = Eigen::Matrix<Scalar, 6, 6>;
140 using Vector3 = Eigen::Matrix<Scalar, 3, 1>;
146 auto M = ATA.template selfadjointView<Eigen::Upper>();
151 for (; source_it.isValid() && target_it.isValid(); ++source_it, ++target_it) {
152 const Vector3 p(source_it->x, source_it->y, source_it->z);
153 const Vector3 q(target_it->x, target_it->y, target_it->z);
154 const Vector3 n1(source_it->getNormalVector3fMap().template cast<Scalar>());
155 const Vector3 n2(target_it->getNormalVector3fMap().template cast<Scalar>());
157 if (enforce_same_direction_normals_) {
158 if (n1.dot(n2) >= 0.)
166 if (!p.array().isFinite().all() || !q.array().isFinite().all() || !n.array().isFinite().all()) {
171 v << (p + q).cross(n), n;
174 ATb += v * (q - p).dot(n);
178 const Vector6 x = M.ldlt().solve(ATb);
181 constructTransformationMatrix(x, transformation_matrix);
184 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
187 bool enforce_same_direction_normals) {
188 enforce_same_direction_normals_ = enforce_same_direction_normals;
191 template <
typename Po
intSource,
typename Po
intTarget,
typename Scalar>
194 return enforce_same_direction_normals_;
199 #endif // POINT_CLOUD_COMMON_TRANSFORMATION_ESTIMATION_SYMMETRIC_POINT_TO_PLANE_LLS_IMPL_H_