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::TransformationEstimationDQ<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::TransformationEstimationDQ::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::TransformationEstimationDQ<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::TransformationEstimationDQ<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::TransformationEstimationDQ::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::TransformationEstimationDQ<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::TransformationEstimationDQ<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<Scalar,4,4> C1 = Eigen::Matrix<Scalar,4,4>::Zero(); 00128 Eigen::Matrix<Scalar,4,4> C2 = Eigen::Matrix<Scalar,4,4>::Zero(); 00129 Scalar *c1 = C1.data(); 00130 Scalar *c2 = C2.data(); 00131 00132 for( int i=0; i<npts; i++ ) { 00133 const PointSource &a = *source_it; 00134 const PointTarget &b = *target_it; 00135 const Scalar axbx = a.x*b.x; 00136 const Scalar ayby = a.y*b.y; 00137 const Scalar azbz = a.z*b.z; 00138 const Scalar axby = a.x*b.y; 00139 const Scalar aybx = a.y*b.x; 00140 const Scalar axbz = a.x*b.z; 00141 const Scalar azbx = a.z*b.x; 00142 const Scalar aybz = a.y*b.z; 00143 const Scalar azby = a.z*b.y; 00144 c1[0] += axbx - azbz - ayby; 00145 c1[5] += ayby - azbz - axbx; 00146 c1[10]+= azbz - axbx - ayby; 00147 c1[15]+= axbx + ayby + azbz; 00148 c1[1] += axby + aybx; 00149 c1[2] += axbz + azbx; 00150 c1[3] += aybz - azby; 00151 c1[6] += azby + aybz; 00152 c1[7] += azbx - axbz; 00153 c1[11]+= axby - aybx; 00154 00155 c2[1] += a.z + b.z; 00156 c2[2] -= a.y + b.y; 00157 c2[3] += a.x - b.x; 00158 c2[6] += a.x + b.x; 00159 c2[7] += a.y - b.y; 00160 c2[11]+= a.z - b.z; 00161 source_it++; 00162 target_it++; 00163 } 00164 00165 c1[4] = c1[1]; 00166 c1[8] = c1[2]; 00167 c1[9] = c1[6]; 00168 c1[12]= c1[3]; 00169 c1[13]= c1[7]; 00170 c1[14]= c1[11]; 00171 c2[4] = -c2[1]; 00172 c2[8] = -c2[2]; 00173 c2[12]= -c2[3]; 00174 c2[9] = -c2[6]; 00175 c2[13]= -c2[7]; 00176 c2[14]= -c2[11]; 00177 00178 C1 *= -2.0f; 00179 C2 *= 2.0f; 00180 00181 const Eigen::Matrix<Scalar,4,4> A = (0.25f/float(npts))*C2.transpose()*C2 - C1; 00182 00183 const Eigen::EigenSolver< Eigen::Matrix<Scalar,4,4> > es(A); 00184 00185 ptrdiff_t i; 00186 es.eigenvalues().real().maxCoeff(&i); 00187 const Eigen::Matrix<Scalar,4,1> qmat = es.eigenvectors().col(i).real(); 00188 const Eigen::Matrix<Scalar,4,1> smat = -(0.5f/float(npts))*C2*qmat; 00189 00190 const Eigen::Quaternion<Scalar> q( qmat(3), qmat(0), qmat(1), qmat(2) ); 00191 const Eigen::Quaternion<Scalar> s( smat(3), smat(0), smat(1), smat(2) ); 00192 00193 const Eigen::Quaternion<Scalar> t = s*q.conjugate(); 00194 00195 const Eigen::Matrix<Scalar,3,3> R( q.toRotationMatrix() ); 00196 00197 for( int i=0; i<3; ++i ) 00198 for( int j=0; j<3; ++j) 00199 transformation_matrix(i,j) = R(i,j); 00200 00201 transformation_matrix(0,3) = -t.x(); 00202 transformation_matrix(1,3) = -t.y(); 00203 transformation_matrix(2,3) = -t.z(); 00204 } 00205 00206 #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