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 
00039 
00040 
00041 #include <boost/unordered_map.hpp>
00042 
00044 template <typename PointSource, typename PointTarget> void
00045 pcl::IterativeClosestPoint<PointSource, PointTarget>::computeTransformation (PointCloudSource &output, const Eigen::Matrix4f &guess)
00046 {
00047   
00048   std::vector<int> nn_indices (1);
00049   std::vector<float> nn_dists (1);
00050 
00051   
00052   PointCloudTarget input_corresp;
00053   input_corresp.points.resize (indices_->size ());
00054 
00055   nr_iterations_ = 0;
00056   converged_ = false;
00057   double dist_threshold = corr_dist_threshold_ * corr_dist_threshold_;
00058 
00059   
00060   if (guess != Eigen::Matrix4f::Identity ())
00061   {
00062     
00063     final_transformation_ = guess;
00064     
00065     transformPointCloud (output, output, guess);
00066   }
00067 
00068   
00069   std::vector<float> previous_correspondence_distances (indices_->size ());
00070   correspondence_distances_.resize (indices_->size ());
00071 
00072   while (!converged_)           
00073   {
00074     
00075     previous_transformation_ = transformation_;
00076     
00077     previous_correspondence_distances = correspondence_distances_;
00078 
00079     int cnt = 0;
00080     std::vector<int> source_indices (indices_->size ());
00081     std::vector<int> target_indices (indices_->size ());
00082 
00083     
00084     for (size_t idx = 0; idx < indices_->size (); ++idx)
00085     {
00086       if (!this->searchForNeighbors (output, (*indices_)[idx], nn_indices, nn_dists))
00087       {
00088         PCL_ERROR ("[pcl::%s::computeTransformation] Unable to find a nearest neighbor in the target dataset for point %d in the source!\n", getClassName ().c_str (), (*indices_)[idx]);
00089         return;
00090       }
00091 
00092       
00093       if (nn_dists[0] < dist_threshold)
00094       {
00095         source_indices[cnt] = (*indices_)[idx];
00096         target_indices[cnt] = nn_indices[0];
00097         cnt++;
00098       }
00099 
00100       
00101       correspondence_distances_[(*indices_)[idx]] = std::min (nn_dists[0], static_cast<float> (dist_threshold));
00102     }
00103     if (cnt < min_number_correspondences_)
00104     {
00105       PCL_ERROR ("[pcl::%s::computeTransformation] Not enough correspondences found. Relax your threshold parameters.\n", getClassName ().c_str ());
00106       converged_ = false;
00107       return;
00108     }
00109 
00110     
00111     source_indices.resize (cnt); target_indices.resize (cnt);
00112 
00113     std::vector<int> source_indices_good;
00114     std::vector<int> target_indices_good;
00115     {
00116       
00117       
00118       typedef typename SampleConsensusModelRegistration<PointSource>::Ptr SampleConsensusModelRegistrationPtr;
00119       SampleConsensusModelRegistrationPtr model;
00120       model.reset (new SampleConsensusModelRegistration<PointSource> (output.makeShared (), source_indices));
00121       
00122       model->setInputTarget (target_, target_indices);
00123       
00124       RandomSampleConsensus<PointSource> sac (model, inlier_threshold_);
00125       sac.setMaxIterations (ransac_iterations_);
00126 
00127       
00128       if (!sac.computeModel ())
00129       {
00130         source_indices_good = source_indices;
00131         target_indices_good = target_indices;
00132       }
00133       else
00134       {
00135         std::vector<int> inliers;
00136         
00137         sac.getInliers (inliers);
00138         source_indices_good.resize (inliers.size ());
00139         target_indices_good.resize (inliers.size ());
00140 
00141         boost::unordered_map<int, int> source_to_target;
00142         for (unsigned int i = 0; i < source_indices.size(); ++i)
00143           source_to_target[source_indices[i]] = target_indices[i];
00144 
00145         
00146         std::copy(inliers.begin(), inliers.end(), source_indices_good.begin());
00147         for (size_t i = 0; i < inliers.size (); ++i)
00148           target_indices_good[i] = source_to_target[inliers[i]];
00149       }
00150     }
00151 
00152     
00153     cnt = static_cast<int> (source_indices_good.size ());
00154     if (cnt < min_number_correspondences_)
00155     {
00156       PCL_ERROR ("[pcl::%s::computeTransformation] Not enough correspondences found. Relax your threshold parameters.\n", getClassName ().c_str ());
00157       converged_ = false;
00158       return;
00159     }
00160 
00161     PCL_DEBUG ("[pcl::%s::computeTransformation] Number of correspondences %d [%f%%] out of %zu points [100.0%%], RANSAC rejected: %zu [%f%%].\n", 
00162         getClassName ().c_str (), 
00163         cnt, 
00164         (static_cast<float> (cnt) * 100.0f) / static_cast<float> (indices_->size ()), 
00165         indices_->size (), 
00166         source_indices.size () - cnt, 
00167         static_cast<float> (source_indices.size () - cnt) * 100.0f / static_cast<float> (source_indices.size ()));
00168   
00169     
00170     
00171     transformation_estimation_->estimateRigidTransformation (output, source_indices_good, *target_, target_indices_good, transformation_);
00172 
00173     
00174     transformPointCloud (output, output, transformation_);
00175 
00176     
00177     final_transformation_ = transformation_ * final_transformation_;
00178 
00179     nr_iterations_++;
00180 
00181     
00182     if (update_visualizer_ != 0)
00183       update_visualizer_(output, source_indices_good, *target_, target_indices_good );
00184 
00185     
00186     
00187     
00188     
00189     
00190     
00191     
00192 
00193     if (nr_iterations_ >= max_iterations_ ||
00194         (transformation_ - previous_transformation_).array ().abs ().sum () < transformation_epsilon_ ||
00195         fabs (this->getFitnessScore (correspondence_distances_, previous_correspondence_distances)) <= euclidean_fitness_epsilon_
00196        )
00197     {
00198       converged_ = true;
00199       PCL_DEBUG ("[pcl::%s::computeTransformation] Convergence reached. Number of iterations: %d out of %d. Transformation difference: %f\n",
00200                  getClassName ().c_str (), nr_iterations_, max_iterations_, (transformation_ - previous_transformation_).array ().abs ().sum ());
00201 
00202       PCL_DEBUG ("nr_iterations_ (%d) >= max_iterations_ (%d)\n", nr_iterations_, max_iterations_);
00203       PCL_DEBUG ("(transformation_ - previous_transformation_).array ().abs ().sum () (%f) < transformation_epsilon_ (%f)\n",
00204                  (transformation_ - previous_transformation_).array ().abs ().sum (), transformation_epsilon_);
00205       PCL_DEBUG ("fabs (getFitnessScore (correspondence_distances_, previous_correspondence_distances)) (%f) <= euclidean_fitness_epsilon_ (%f)\n",
00206                  fabs (this->getFitnessScore (correspondence_distances_, previous_correspondence_distances)),
00207                  euclidean_fitness_epsilon_);
00208 
00209     }
00210   }
00211 }
00212