42 #include <pcl/common/transforms.h>
45 #include <xmmintrin.h>
49 #include <immintrin.h>
66 template<
typename Scalar>
69 const Eigen::Matrix<Scalar, 4, 4>&
tf;
74 Transformer (
const Eigen::Matrix<Scalar, 4, 4>& transform) :
tf (transform) { };
79 void so3 (
const float* src,
float* tgt)
const
81 const Scalar p[3] = { src[0], src[1], src[2] };
82 tgt[0] =
static_cast<float> (
tf (0, 0) * p[0] +
tf (0, 1) * p[1] +
tf (0, 2) * p[2]);
83 tgt[1] =
static_cast<float> (
tf (1, 0) * p[0] +
tf (1, 1) * p[1] +
tf (1, 2) * p[2]);
84 tgt[2] =
static_cast<float> (
tf (2, 0) * p[0] +
tf (2, 1) * p[1] +
tf (2, 2) * p[2]);
91 void se3 (
const float* src,
float* tgt)
const
93 const Scalar p[3] = { src[0], src[1], src[2] };
94 tgt[0] =
static_cast<float> (
tf (0, 0) * p[0] +
tf (0, 1) * p[1] +
tf (0, 2) * p[2] +
tf (0, 3));
95 tgt[1] =
static_cast<float> (
tf (1, 0) * p[0] +
tf (1, 1) * p[1] +
tf (1, 2) * p[2] +
tf (1, 3));
96 tgt[2] =
static_cast<float> (
tf (2, 0) * p[0] +
tf (2, 1) * p[1] +
tf (2, 2) * p[2] +
tf (2, 3));
101 #if defined(__SSE2__)
105 struct Transformer<float>
112 for (std::size_t i = 0; i < 4; ++i)
113 c[i] = _mm_load_ps (
tf.col (i).data ());
116 void so3 (
const float* src,
float* tgt)
const
118 __m128 p0 = _mm_mul_ps (_mm_load_ps1 (&src[0]), c[0]);
119 __m128 p1 = _mm_mul_ps (_mm_load_ps1 (&src[1]), c[1]);
120 __m128 p2 = _mm_mul_ps (_mm_load_ps1 (&src[2]), c[2]);
121 _mm_store_ps (tgt, _mm_add_ps(p0, _mm_add_ps(p1, p2)));
124 void se3 (
const float* src,
float* tgt)
const
126 __m128 p0 = _mm_mul_ps (_mm_load_ps1 (&src[0]), c[0]);
127 __m128 p1 = _mm_mul_ps (_mm_load_ps1 (&src[1]), c[1]);
128 __m128 p2 = _mm_mul_ps (_mm_load_ps1 (&src[2]), c[2]);
129 _mm_store_ps (tgt, _mm_add_ps(p0, _mm_add_ps(p1, _mm_add_ps(p2, c[3]))));
133 #if !defined(__AVX__)
137 struct Transformer<double>
144 for (std::size_t i = 0; i < 4; ++i)
146 c[i][0] = _mm_load_pd (
tf.col (i).data () + 0);
147 c[i][1] = _mm_load_pd (
tf.col (i).data () + 2);
151 void so3 (
const float* src,
float* tgt)
const
153 __m128d xx = _mm_cvtps_pd (_mm_load_ps1 (&src[0]));
154 __m128d p0 = _mm_mul_pd (xx, c[0][0]);
155 __m128d p1 = _mm_mul_pd (xx, c[0][1]);
157 for (std::size_t i = 1; i < 3; ++i)
159 __m128d vv = _mm_cvtps_pd (_mm_load_ps1 (&src[i]));
160 p0 = _mm_add_pd (_mm_mul_pd (vv, c[i][0]), p0);
161 p1 = _mm_add_pd (_mm_mul_pd (vv, c[i][1]), p1);
164 _mm_store_ps (tgt, _mm_movelh_ps (_mm_cvtpd_ps (p0), _mm_cvtpd_ps (p1)));
167 void se3 (
const float* src,
float* tgt)
const
169 __m128d p0 = c[3][0];
170 __m128d p1 = c[3][1];
172 for (std::size_t i = 0; i < 3; ++i)
174 __m128d vv = _mm_cvtps_pd (_mm_load_ps1 (&src[i]));
175 p0 = _mm_add_pd (_mm_mul_pd (vv, c[i][0]), p0);
176 p1 = _mm_add_pd (_mm_mul_pd (vv, c[i][1]), p1);
179 _mm_store_ps (tgt, _mm_movelh_ps (_mm_cvtpd_ps (p0), _mm_cvtpd_ps (p1)));
187 struct Transformer<double>
193 for (std::size_t i = 0; i < 4; ++i)
194 c[i] = _mm256_load_pd (
tf.col (i).data ());
197 void so3 (
const float* src,
float* tgt)
const
199 __m256d p0 = _mm256_mul_pd (_mm256_cvtps_pd (_mm_load_ps1 (&src[0])), c[0]);
200 __m256d p1 = _mm256_mul_pd (_mm256_cvtps_pd (_mm_load_ps1 (&src[1])), c[1]);
201 __m256d p2 = _mm256_mul_pd (_mm256_cvtps_pd (_mm_load_ps1 (&src[2])), c[2]);
202 _mm_store_ps (tgt, _mm256_cvtpd_ps (_mm256_add_pd(p0, _mm256_add_pd(p1, p2))));
205 void se3 (
const float* src,
float* tgt)
const
207 __m256d p0 = _mm256_mul_pd (_mm256_cvtps_pd (_mm_load_ps1 (&src[0])), c[0]);
208 __m256d p1 = _mm256_mul_pd (_mm256_cvtps_pd (_mm_load_ps1 (&src[1])), c[1]);
209 __m256d p2 = _mm256_mul_pd (_mm256_cvtps_pd (_mm_load_ps1 (&src[2])), c[2]);
210 _mm_store_ps (tgt, _mm256_cvtpd_ps (_mm256_add_pd(p0, _mm256_add_pd(p1, _mm256_add_pd(p2, c[3])))));
220 template <
typename Po
intT,
typename Scalar>
void
223 const Eigen::Matrix<Scalar, 4, 4> &transform,
224 bool copy_all_fields)
226 if (&cloud_in != &cloud_out)
243 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
250 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
252 if (!std::isfinite (cloud_in[i].x) ||
253 !std::isfinite (cloud_in[i].y) ||
254 !std::isfinite (cloud_in[i].z))
256 tf.
se3 (cloud_in[i].data, cloud_out[i].data);
262 template <
typename Po
intT,
typename Scalar>
void
266 const Eigen::Matrix<Scalar, 4, 4> &transform,
267 bool copy_all_fields)
269 std::size_t npts = indices.size ();
273 cloud_out.
width =
static_cast<int> (npts);
283 for (std::size_t i = 0; i < npts; ++i)
287 cloud_out[i] = cloud_in[indices[i]];
288 tf.
se3 (cloud_in[indices[i]].data, cloud_out[i].data);
295 for (std::size_t i = 0; i < npts; ++i)
298 cloud_out[i] = cloud_in[indices[i]];
299 if (!std::isfinite (cloud_in[indices[i]].x) ||
300 !std::isfinite (cloud_in[indices[i]].y) ||
301 !std::isfinite (cloud_in[indices[i]].z))
303 tf.
se3 (cloud_in[indices[i]].data, cloud_out[i].data);
312 const Eigen::Affine2f &transform,
313 bool copy_all_fields)
315 if (&cloud_in != &cloud_out)
329 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
331 cloud_out[i].getVector2fMap () = transform * cloud_in[i].getVector2fMap();
336 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
338 if (!std::isfinite(cloud_in[i].x) || !std::isfinite(cloud_in[i].y))
342 cloud_out[i].getVector2fMap () = transform * cloud_in[i].getVector2fMap();
348 template <
typename Po
intT,
typename Scalar>
void
351 const Eigen::Matrix<Scalar, 4, 4> &transform,
352 bool copy_all_fields)
354 if (&cloud_in != &cloud_out)
372 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
374 tf.
se3 (cloud_in[i].data, cloud_out[i].data);
375 tf.
so3 (cloud_in[i].data_n, cloud_out[i].data_n);
381 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
383 if (!std::isfinite (cloud_in[i].x) ||
384 !std::isfinite (cloud_in[i].y) ||
385 !std::isfinite (cloud_in[i].z))
387 tf.
se3 (cloud_in[i].data, cloud_out[i].data);
388 tf.
so3 (cloud_in[i].data_n, cloud_out[i].data_n);
394 template <
typename Po
intT,
typename Scalar>
void
398 const Eigen::Matrix<Scalar, 4, 4> &transform,
399 bool copy_all_fields)
401 std::size_t npts = indices.size ();
405 cloud_out.
width =
static_cast<int> (npts);
415 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
419 cloud_out[i] = cloud_in[indices[i]];
420 tf.
se3 (cloud_in[indices[i]].data, cloud_out[i].data);
421 tf.
so3 (cloud_in[indices[i]].data_n, cloud_out[i].data_n);
427 for (std::size_t i = 0; i < cloud_out.
size (); ++i)
431 cloud_out[i] = cloud_in[indices[i]];
433 if (!std::isfinite (cloud_in[indices[i]].x) ||
434 !std::isfinite (cloud_in[indices[i]].y) ||
435 !std::isfinite (cloud_in[indices[i]].z))
438 tf.
se3 (cloud_in[indices[i]].data, cloud_out[i].data);
439 tf.
so3 (cloud_in[indices[i]].data_n, cloud_out[i].data_n);
445 template <
typename Po
intT,
typename Scalar>
inline void
448 const Eigen::Matrix<Scalar, 3, 1> &offset,
449 const Eigen::Quaternion<Scalar> &rotation,
450 bool copy_all_fields)
452 Eigen::Translation<Scalar, 3> translation (offset);
454 Eigen::Transform<Scalar, 3, Eigen::Affine> t (translation * rotation);
459 template <
typename Po
intT,
typename Scalar>
inline void
462 const Eigen::Matrix<Scalar, 3, 1> &offset,
463 const Eigen::Quaternion<Scalar> &rotation,
464 bool copy_all_fields)
466 Eigen::Translation<Scalar, 3> translation (offset);
468 Eigen::Transform<Scalar, 3, Eigen::Affine> t (translation * rotation);
473 template <
typename Po
intT,
typename Scalar>
inline PointT
478 tf.
se3 (point.data, ret.data);
483 template <
typename Po
intT,
typename Scalar>
inline PointT
488 tf.
se3 (point.data, ret.data);
489 tf.
so3 (point.data_n, ret.data_n);
494 template <
typename Po
intT,
typename Scalar>
double
496 Eigen::Transform<Scalar, 3, Eigen::Affine> &transform)
498 EIGEN_ALIGN16 Eigen::Matrix<Scalar, 3, 3> covariance_matrix;
499 Eigen::Matrix<Scalar, 4, 1> centroid;
503 EIGEN_ALIGN16 Eigen::Matrix<Scalar, 3, 3> eigen_vects;
504 Eigen::Matrix<Scalar, 3, 1> eigen_vals;
505 pcl::eigen33 (covariance_matrix, eigen_vects, eigen_vals);
507 double rel1 = eigen_vals.coeff (0) / eigen_vals.coeff (1);
508 double rel2 = eigen_vals.coeff (1) / eigen_vals.coeff (2);
510 transform.translation () = centroid.template head<3> ();
511 transform.linear () = eigen_vects;
513 return (std::min (rel1, rel2));
PointCloud represents the base class in PCL for storing collections of 3D points.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
void resize(std::size_t count)
Resizes the container to contain count elements.
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
std::uint32_t width
The point cloud width (if organized as an image-structure).
pcl::PCLHeader header
The point cloud header.
std::uint32_t height
The point cloud height (if organized as an image-structure).
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
void reserve(std::size_t n)
iterator begin() noexcept
void assign(index_t count, const PointT &value)
Replaces the points with count copies of value
void transformPointCloudWithNormals(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Matrix< Scalar, 4, 4 > &transform, bool copy_all_fields)
Transform a point cloud and rotate its normals using an Eigen transform.
PointT transformPointWithNormal(const PointT &point, const Eigen::Transform< Scalar, 3, Eigen::Affine > &transform)
Transform a point with members x,y,z,normal_x,normal_y,normal_z.
unsigned int computeMeanAndCovarianceMatrix(const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix, Eigen::Matrix< Scalar, 4, 1 > ¢roid)
Compute the normalized 3x3 covariance matrix and the centroid of a given set of points in a single lo...
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Matrix< Scalar, 4, 4 > &transform, bool copy_all_fields)
Apply a rigid transform defined by a 4x4 matrix.
void eigen33(const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
determines the eigenvector and eigenvalue of the smallest eigenvalue of the symmetric positive semi d...
void transformPoint(const Eigen::Matrix< Scalar, 3, 1 > &point_in, Eigen::Matrix< Scalar, 3, 1 > &point_out, const Eigen::Transform< Scalar, 3, Eigen::Affine > &transformation)
Transform a point using an affine matrix.
double getPrincipalTransformation(const pcl::PointCloud< PointT > &cloud, Eigen::Transform< Scalar, 3, Eigen::Affine > &transform)
Calculates the principal (PCA-based) alignment of the point cloud.
IndicesAllocator<> Indices
Type used for indices in PCL.
A point structure representing Euclidean xyz coordinates, and the RGB color.