00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <boost/unordered_map.hpp>
00039
00041 template <typename PointSource, typename PointTarget> void
00042 pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::estimateRigidTransformationLM (
00043 const PointCloudSource &cloud_src, const PointCloudTarget &cloud_tgt, Eigen::Matrix4f &transformation_matrix)
00044 {
00045 boost::mutex::scoped_lock lock (tmp_mutex_);
00046
00047 int n_unknowns = 6;
00048
00049 if (cloud_src.points.size () != cloud_tgt.points.size ())
00050 {
00051 PCL_ERROR ("[pcl::IterativeClosestPointNonLinear::estimateRigidTransformationLM] Number or points in source (%lu) differs than target (%lu)!\n", (unsigned long)cloud_src.points.size (), (unsigned long)cloud_tgt.points.size ());
00052 return;
00053 }
00054 if (cloud_src.points.size () < 4)
00055 {
00056 PCL_ERROR ("[pcl::IterativeClosestPointNonLinear::estimateRigidTransformationLM] Need at least 4 points to estimate a transform! Source and target have %lu points!\n", (unsigned long)cloud_src.points.size ());
00057 return;
00058 }
00059
00060 int m = cloud_src.points.size ();
00061 double *fvec = new double[m];
00062 int *iwa = new int[n_unknowns];
00063 int lwa = m * n_unknowns + 5 * n_unknowns + m;
00064 double *wa = new double[lwa];
00065
00066
00067 double *x = new double[n_unknowns];
00068
00069 x[0] = 0; x[1] = 0; x[2] = 0;
00070
00071 x[3] = 0; x[4] = 0; x[5] = 0;
00072
00073
00074 tmp_src_ = &cloud_src;
00075 tmp_tgt_ = &cloud_tgt;
00076
00077
00078 double tol = sqrt (dpmpar (1));
00079
00080
00081
00082 int info = lmdif1 (&pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::functionToOptimize, this, m, n_unknowns, x, fvec, tol, iwa, wa, lwa);
00083
00084
00085 PCL_DEBUG ("[pcl::%s::estimateRigidTransformationLM] LM solver finished with exit code %i, having a residual norm of %g. \n",
00086
00087 getClassName ().c_str (), info, enorm (m, fvec));
00088
00089
00090 delete [] wa; delete [] fvec;
00091
00092 transformation_matrix.setZero ();
00093
00094
00095
00096 Eigen::Quaternionf q (0, x[3], x[4], x[5]);
00097 q.w () = sqrt (1 - q.dot (q));
00098 transformation_matrix.topLeftCorner<3, 3> () = q.toRotationMatrix ();
00099
00100 Eigen::Vector4f t (x[0], x[1], x[2], 1.0);
00101 transformation_matrix.block <4, 1> (0, 3) = t;
00102
00103 tmp_src_ = tmp_tgt_ = NULL;
00104
00105 delete[] iwa;
00106 delete[] x;
00107 }
00108
00110 template <typename PointSource, typename PointTarget> void
00111 pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::estimateRigidTransformationLM (
00112 const PointCloudSource &cloud_src, const std::vector<int> &indices_src, const PointCloudTarget &cloud_tgt, const std::vector<int> &indices_tgt, Eigen::Matrix4f &transformation_matrix)
00113 {
00114 boost::mutex::scoped_lock lock (tmp_mutex_);
00115
00116 int n_unknowns = 6;
00117
00118 if (indices_src.size () != indices_tgt.size ())
00119 {
00120 PCL_ERROR ("[pcl::IterativeClosestPointNonLinear::estimateRigidTransformationLM] Number or points in source (%lu) differs than target (%lu)!\n", (unsigned long)indices_src.size (), (unsigned long)indices_tgt.size ());
00121 return;
00122 }
00123 if (indices_src.size () < 4)
00124 {
00125 PCL_ERROR ("[pcl::IterativeClosestPointNonLinear::estimateRigidTransformationLM] Need at least 4 points to estimate a transform! Source and target have %lu points!", (unsigned long)indices_src.size ());
00126 return;
00127 }
00128
00129 int m = indices_src.size ();
00130 double *fvec = new double[m];
00131 int *iwa = new int[n_unknowns];
00132 int lwa = m * n_unknowns + 5 * n_unknowns + m;
00133 double *wa = new double[lwa];
00134
00135
00136 double *x = new double[n_unknowns];
00137
00138 x[0] = 0; x[1] = 0; x[2] = 0;
00139
00140 x[3] = 0; x[4] = 0; x[5] = 0;
00141
00142
00143 tmp_src_ = &cloud_src;
00144 tmp_tgt_ = &cloud_tgt;
00145 tmp_idx_src_ = &indices_src;
00146 tmp_idx_tgt_ = &indices_tgt;
00147
00148
00149 double tol = sqrt (dpmpar (1));
00150
00151
00152 int info = lmdif1 (&pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::functionToOptimizeIndices, this, m, n_unknowns, x, fvec, tol, iwa, wa, lwa);
00153
00154
00155 PCL_DEBUG ("[pcl::%s::estimateRigidTransformationLM] LM solver finished with exit code %i, having a residual norm of %g. \n",
00156
00157 getClassName ().c_str (), info, enorm (m, fvec));
00158
00159
00160 delete [] wa; delete [] fvec;
00161
00162 transformation_matrix.setZero ();
00163
00164
00165
00166 Eigen::Quaternionf q (0, x[3], x[4], x[5]);
00167 q.w () = sqrt (1 - q.dot (q));
00168 transformation_matrix.topLeftCorner<3, 3> () = q.toRotationMatrix ();
00169
00170 Eigen::Vector4f t (x[0], x[1], x[2], 1.0);
00171 transformation_matrix.block <4, 1> (0, 3) = t;
00172
00173 tmp_src_ = tmp_tgt_ = NULL;
00174 tmp_idx_src_ = tmp_idx_tgt_ = NULL;
00175
00176 delete[] iwa;
00177 delete[] x;
00178 }
00179
00181 template <typename PointSource, typename PointTarget> inline int
00182 pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::functionToOptimize (void *p, int m, int n, const double *x, double *fvec, int iflag)
00183 {
00184 IterativeClosestPointNonLinear *model = (IterativeClosestPointNonLinear*)p;
00185
00186
00187 Eigen::Vector4f t (x[0], x[1], x[2], 1.0);
00188
00189 Eigen::Quaternionf q (0, x[3], x[4], x[5]);
00190 q.w () = sqrt (1 - q.dot (q));
00191
00192
00193
00194
00195 Eigen::Matrix4f transformation_matrix = Eigen::Matrix4f::Zero ();
00196 transformation_matrix.topLeftCorner<3, 3> () = q.toRotationMatrix ();
00197 transformation_matrix.block <4, 1> (0, 3) = t;
00198
00199 double sigma = model->getMaxCorrespondenceDistance ();
00200 for (int i = 0; i < m; ++i)
00201 {
00202
00203 Vector4fMapConst p_src = model->tmp_src_->points[i].getVector4fMap ();
00204
00205 Vector4fMapConst p_tgt = model->tmp_tgt_->points[i].getVector4fMap ();
00206
00207 Eigen::Vector4f pp = transformation_matrix * p_src;
00208
00209
00210
00211
00212 fvec[i] = model->distHuber (pp, p_tgt, sigma);
00213 }
00214 return (0);
00215 }
00216
00218 template <typename PointSource, typename PointTarget> inline double
00219 pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::computeMedian (double *fvec, int m)
00220 {
00221 double median;
00222
00223 std::vector<double> data (m);
00224 memcpy (&data[0], fvec, sizeof (double) * m);
00225
00226 std::sort (data.begin (), data.end ());
00227
00228 int mid = data.size () / 2;
00229 if (data.size () % 2 == 0)
00230 median = (data[mid-1] + data[mid]) / 2.0;
00231 else
00232 median = data[mid];
00233 return (median);
00234 }
00235
00237 template <typename PointSource, typename PointTarget> inline int
00238 pcl::IterativeClosestPointNonLinear<PointSource, PointTarget>::functionToOptimizeIndices (void *p, int m, int n, const double *x, double *fvec, int iflag)
00239 {
00240 IterativeClosestPointNonLinear *model = (IterativeClosestPointNonLinear*)p;
00241
00242
00243 Eigen::Vector4f t (x[0], x[1], x[2], 1.0);
00244
00245 Eigen::Quaternionf q (0, x[3], x[4], x[5]);
00246 q.w () = sqrt (1 - q.dot (q));
00247
00248
00249
00250
00251
00252 Eigen::Matrix4f transformation_matrix = Eigen::Matrix4f::Zero ();
00253 transformation_matrix.topLeftCorner<3, 3> () = q.toRotationMatrix ();
00254 transformation_matrix.block <4, 1> (0, 3) = t;
00255
00256
00257 for (int i = 0; i < m; ++i)
00258 {
00259
00260 Vector4fMapConst p_src = model->tmp_src_->points[(*model->tmp_idx_src_)[i]].getVector4fMap ();
00261
00262 Vector4fMapConst p_tgt = model->tmp_tgt_->points[(*model->tmp_idx_tgt_)[i]].getVector4fMap ();
00263
00264 Eigen::Vector4f pp = transformation_matrix * p_src;
00265
00266
00267
00268 fvec[i] = model->distL1 (pp, p_tgt);
00269
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 return (0);
00284 }
00285