00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010, Willow Garage, Inc. 00006 * Copyright (c) 2012-, Open Perception, Inc. 00007 * 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 00014 * * Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * * Redistributions in binary form must reproduce the above 00017 * copyright notice, this list of conditions and the following 00018 * disclaimer in the documentation and/or other materials provided 00019 * with the distribution. 00020 * * Neither the name of the copyright holder(s) nor the names of its 00021 * contributors may be used to endorse or promote products derived 00022 * from this software without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00025 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00026 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00027 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00028 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00029 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00030 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00031 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00032 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00033 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00034 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00035 * POSSIBILITY OF SUCH DAMAGE. 00036 * 00037 * 00038 */ 00039 #ifndef PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_DQ_HPP_ 00040 #define PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_DQ_HPP_ 00041 00042 #include <pcl/common/eigen.h> 00043 00044 /////////////////////////////////////////////////////////////////////////////////////////// 00045 template <typename PointSource, typename PointTarget, typename Scalar> inline void 00046 pcl::registration::TransformationEstimationDualQuaternion<PointSource, PointTarget, Scalar>::estimateRigidTransformation ( 00047 const pcl::PointCloud<PointSource> &cloud_src, 00048 const pcl::PointCloud<PointTarget> &cloud_tgt, 00049 Matrix4 &transformation_matrix) const 00050 { 00051 size_t nr_points = cloud_src.points.size (); 00052 if (cloud_tgt.points.size () != nr_points) 00053 { 00054 PCL_ERROR ("[pcl::TransformationEstimationDualQuaternion::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", nr_points, cloud_tgt.points.size ()); 00055 return; 00056 } 00057 00058 ConstCloudIterator<PointSource> source_it (cloud_src); 00059 ConstCloudIterator<PointTarget> target_it (cloud_tgt); 00060 estimateRigidTransformation (source_it, target_it, transformation_matrix); 00061 } 00062 00063 /////////////////////////////////////////////////////////////////////////////////////////// 00064 template <typename PointSource, typename PointTarget, typename Scalar> void 00065 pcl::registration::TransformationEstimationDualQuaternion<PointSource, PointTarget, Scalar>::estimateRigidTransformation ( 00066 const pcl::PointCloud<PointSource> &cloud_src, 00067 const std::vector<int> &indices_src, 00068 const pcl::PointCloud<PointTarget> &cloud_tgt, 00069 Matrix4 &transformation_matrix) const 00070 { 00071 if (indices_src.size () != cloud_tgt.points.size ()) 00072 { 00073 PCL_ERROR ("[pcl::TransformationDQ::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", indices_src.size (), cloud_tgt.points.size ()); 00074 return; 00075 } 00076 00077 ConstCloudIterator<PointSource> source_it (cloud_src, indices_src); 00078 ConstCloudIterator<PointTarget> target_it (cloud_tgt); 00079 estimateRigidTransformation (source_it, target_it, transformation_matrix); 00080 } 00081 00082 /////////////////////////////////////////////////////////////////////////////////////////// 00083 template <typename PointSource, typename PointTarget, typename Scalar> inline void 00084 pcl::registration::TransformationEstimationDualQuaternion<PointSource, PointTarget, Scalar>::estimateRigidTransformation ( 00085 const pcl::PointCloud<PointSource> &cloud_src, 00086 const std::vector<int> &indices_src, 00087 const pcl::PointCloud<PointTarget> &cloud_tgt, 00088 const std::vector<int> &indices_tgt, 00089 Matrix4 &transformation_matrix) const 00090 { 00091 if (indices_src.size () != indices_tgt.size ()) 00092 { 00093 PCL_ERROR ("[pcl::TransformationEstimationDualQuaternion::estimateRigidTransformation] Number or points in source (%zu) differs than target (%zu)!\n", indices_src.size (), indices_tgt.size ()); 00094 return; 00095 } 00096 00097 ConstCloudIterator<PointSource> source_it (cloud_src, indices_src); 00098 ConstCloudIterator<PointTarget> target_it (cloud_tgt, indices_tgt); 00099 estimateRigidTransformation (source_it, target_it, transformation_matrix); 00100 } 00101 00102 /////////////////////////////////////////////////////////////////////////////////////////// 00103 template <typename PointSource, typename PointTarget, typename Scalar> void 00104 pcl::registration::TransformationEstimationDualQuaternion<PointSource, PointTarget, Scalar>::estimateRigidTransformation ( 00105 const pcl::PointCloud<PointSource> &cloud_src, 00106 const pcl::PointCloud<PointTarget> &cloud_tgt, 00107 const pcl::Correspondences &correspondences, 00108 Matrix4 &transformation_matrix) const 00109 { 00110 ConstCloudIterator<PointSource> source_it (cloud_src, correspondences, true); 00111 ConstCloudIterator<PointTarget> target_it (cloud_tgt, correspondences, false); 00112 estimateRigidTransformation (source_it, target_it, transformation_matrix); 00113 } 00114 00115 /////////////////////////////////////////////////////////////////////////////////////////// 00116 template <typename PointSource, typename PointTarget, typename Scalar> inline void 00117 pcl::registration::TransformationEstimationDualQuaternion<PointSource, PointTarget, Scalar>::estimateRigidTransformation ( 00118 ConstCloudIterator<PointSource>& source_it, 00119 ConstCloudIterator<PointTarget>& target_it, 00120 Matrix4 &transformation_matrix) const 00121 { 00122 const int npts = static_cast<int> (source_it.size ()); 00123 00124 transformation_matrix.setIdentity (); 00125 00126 // dual quaternion optimization 00127 Eigen::Matrix<double, 4, 4> C1 = Eigen::Matrix<double, 4, 4>::Zero (); 00128 Eigen::Matrix<double, 4, 4> C2 = Eigen::Matrix<double, 4, 4>::Zero (); 00129 double* c1 = C1.data (); 00130 double* c2 = C2.data (); 00131 00132 for (int i = 0; i < npts; ++i) 00133 { 00134 const PointSource& a = *source_it; 00135 const PointTarget& b = *target_it; 00136 const double axbx = a.x * b.x; 00137 const double ayby = a.y * b.y; 00138 const double azbz = a.z * b.z; 00139 const double axby = a.x * b.y; 00140 const double aybx = a.y * b.x; 00141 const double axbz = a.x * b.z; 00142 const double azbx = a.z * b.x; 00143 const double aybz = a.y * b.z; 00144 const double azby = a.z * b.y; 00145 c1[0] += axbx - azbz - ayby; 00146 c1[5] += ayby - azbz - axbx; 00147 c1[10] += azbz - axbx - ayby; 00148 c1[15] += axbx + ayby + azbz; 00149 c1[1] += axby + aybx; 00150 c1[2] += axbz + azbx; 00151 c1[3] += aybz - azby; 00152 c1[6] += azby + aybz; 00153 c1[7] += azbx - axbz; 00154 c1[11] += axby - aybx; 00155 00156 c2[1] += a.z + b.z; 00157 c2[2] -= a.y + b.y; 00158 c2[3] += a.x - b.x; 00159 c2[6] += a.x + b.x; 00160 c2[7] += a.y - b.y; 00161 c2[11] += a.z - b.z; 00162 source_it++; 00163 target_it++; 00164 } 00165 00166 c1[4] = c1[1]; 00167 c1[8] = c1[2]; 00168 c1[9] = c1[6]; 00169 c1[12] = c1[3]; 00170 c1[13] = c1[7]; 00171 c1[14] = c1[11]; 00172 c2[4] = -c2[1]; 00173 c2[8] = -c2[2]; 00174 c2[12] = -c2[3]; 00175 c2[9] = -c2[6]; 00176 c2[13] = -c2[7]; 00177 c2[14] = -c2[11]; 00178 00179 C1 *= -2.0; 00180 C2 *= 2.0; 00181 00182 const Eigen::Matrix<double, 4, 4> A = (0.25 / double (npts)) * C2.transpose () * C2 - C1; 00183 00184 const Eigen::EigenSolver<Eigen::Matrix<double, 4, 4> > es (A); 00185 00186 ptrdiff_t i; 00187 es.eigenvalues ().real ().maxCoeff (&i); 00188 const Eigen::Matrix<double, 4, 1> qmat = es.eigenvectors ().col (i).real (); 00189 const Eigen::Matrix<double, 4, 1> smat = - (0.5 / double (npts)) * C2 * qmat; 00190 00191 const Eigen::Quaternion<double> q (qmat (3), qmat (0), qmat (1), qmat (2)); 00192 const Eigen::Quaternion<double> s (smat (3), smat (0), smat (1), smat (2)); 00193 00194 const Eigen::Quaternion<double> t = s * q.conjugate (); 00195 00196 const Eigen::Matrix<double, 3, 3> R (q.toRotationMatrix ()); 00197 00198 for (int i = 0; i < 3; ++i) 00199 for (int j = 0; j < 3; ++j) 00200 transformation_matrix (i, j) = R (i, j); 00201 00202 transformation_matrix (0, 3) = - t.x (); 00203 transformation_matrix (1, 3) = - t.y (); 00204 transformation_matrix (2, 3) = - t.z (); 00205 } 00206 00207 #endif /* PCL_REGISTRATION_TRANSFORMATION_ESTIMATION_DQ_HPP_ */
Except where otherwise noted, the PointClouds.org web pages are licensed under Creative Commons Attribution 3.0.
Pages generated on Wed Mar 25 00:25:10 2015