39 #ifndef PCL_REGISTRATION_IMPL_PPF_REGISTRATION_H_
40 #define PCL_REGISTRATION_IMPL_PPF_REGISTRATION_H_
52 feature_hash_map_->clear ();
53 unsigned int n =
static_cast<unsigned int> (
sqrt (static_cast<float> (feature_cloud->
points.size ())));
57 for (
size_t i = 0; i < n; ++i)
59 std::vector <float> alpha_m_row (n);
60 for (
size_t j = 0; j < n; ++j)
62 d1 =
static_cast<int> (floor (feature_cloud->
points[i*n+j].f1 / angle_discretization_step_));
63 d2 =
static_cast<int> (floor (feature_cloud->
points[i*n+j].f2 / angle_discretization_step_));
64 d3 =
static_cast<int> (floor (feature_cloud->
points[i*n+j].f3 / angle_discretization_step_));
65 d4 =
static_cast<int> (floor (feature_cloud->
points[i*n+j].f4 / distance_discretization_step_));
66 feature_hash_map_->insert (std::pair<
HashKeyStruct, std::pair<size_t, size_t> > (
HashKeyStruct (d1, d2, d3, d4), std::pair<size_t, size_t> (i, j)));
67 alpha_m_row [j] = feature_cloud->
points[i*n + j].alpha_m;
69 if (max_dist_ < feature_cloud->points[i*n + j].f4)
70 max_dist_ = feature_cloud->
points[i*n + j].f4;
75 internals_initialized_ =
true;
82 std::vector<std::pair<size_t, size_t> > &indices)
84 if (!internals_initialized_)
86 PCL_ERROR(
"[pcl::PPFRegistration::nearestNeighborSearch]: input feature cloud has not been set - skipping search!\n");
90 int d1 =
static_cast<int> (floor (f1 / angle_discretization_step_)),
91 d2 = static_cast<int> (floor (f2 / angle_discretization_step_)),
92 d3 = static_cast<int> (floor (f3 / angle_discretization_step_)),
93 d4 = static_cast<int> (floor (f4 / distance_discretization_step_));
97 std::pair <FeatureHashMapType::iterator, FeatureHashMapType::iterator> map_iterator_pair = feature_hash_map_->equal_range (key);
98 for (; map_iterator_pair.first != map_iterator_pair.second; ++ map_iterator_pair.first)
99 indices.push_back (std::pair<size_t, size_t> (map_iterator_pair.first->second.first,
100 map_iterator_pair.first->second.second));
105 template <
typename Po
intSource,
typename Po
intTarget>
void
111 scene_search_tree_->setInputCloud (target_);
116 template <
typename Po
intSource,
typename Po
intTarget>
void
121 PCL_ERROR(
"[pcl::PPFRegistration::computeTransformation] Search method not set - skipping computeTransformation!\n");
125 if (guess != Eigen::Matrix4f::Identity ())
127 PCL_ERROR(
"[pcl::PPFRegistration::computeTransformation] setting initial transform (guess) not implemented!\n");
130 PoseWithVotesList voted_poses;
131 std::vector <std::vector <unsigned int> > accumulator_array;
132 accumulator_array.resize (input_->points.size ());
133 for (
size_t i = 0; i < input_->points.size (); ++i)
135 std::vector <unsigned int> aux (static_cast<size_t> (floor(2*M_PI / search_method_->getAngleDiscretizationStep ()), 0));
136 accumulator_array[i] = aux;
138 PCL_INFO (
"Accumulator array size: %u x %u.\n", accumulator_array.size (), accumulator_array.back ().size ());
141 float f1, f2, f3, f4;
142 for (
size_t scene_reference_index = 0; scene_reference_index < target_->points.size (); scene_reference_index += scene_reference_point_sampling_rate_)
144 Eigen::Vector3f scene_reference_point = target_->points[scene_reference_index].getVector3fMap (),
145 scene_reference_normal = target_->points[scene_reference_index].getNormalVector3fMap ();
147 Eigen::AngleAxisf rotation_sg (acosf (scene_reference_normal.dot (Eigen::Vector3f::UnitX ())),
148 scene_reference_normal.cross (Eigen::Vector3f::UnitX ()). normalized());
149 Eigen::Affine3f transform_sg = Eigen::Translation3f ( rotation_sg* ((-1)*scene_reference_point)) * rotation_sg;
152 std::vector<int> indices;
153 std::vector<float> distances;
154 scene_search_tree_->radiusSearch (target_->points[scene_reference_index],
155 search_method_->getModelDiameter () /2,
158 for(
size_t i = 0; i < indices.size (); ++i)
162 size_t scene_point_index = indices[i];
163 if (scene_reference_index != scene_point_index)
166 target_->points[scene_reference_index].getNormalVector4fMap (),
167 target_->points[scene_point_index].getVector4fMap (),
168 target_->points[scene_point_index].getNormalVector4fMap (),
171 std::vector<std::pair<size_t, size_t> > nearest_indices;
172 search_method_->nearestNeighborSearch (f1, f2, f3, f4, nearest_indices);
175 Eigen::Vector3f scene_point = target_->points[scene_point_index].getVector3fMap ();
176 Eigen::AngleAxisf rotation_sg (acosf (scene_reference_normal.dot (Eigen::Vector3f::UnitX ())),
177 scene_reference_normal.cross (Eigen::Vector3f::UnitX ()).normalized ());
178 Eigen::Affine3f transform_sg = Eigen::Translation3f ( rotation_sg * ((-1) * scene_reference_point)) * rotation_sg;
181 Eigen::Vector3f scene_point_transformed = transform_sg * scene_point;
182 float alpha_s = atan2f ( -scene_point_transformed(2), scene_point_transformed(1));
183 if ( alpha_s != alpha_s)
188 if (sin (alpha_s) * scene_point_transformed(2) < 0.0f)
193 for (std::vector<std::pair<size_t, size_t> >::iterator v_it = nearest_indices.begin (); v_it != nearest_indices.end (); ++ v_it)
195 size_t model_reference_index = v_it->first,
196 model_point_index = v_it->second;
198 float alpha = search_method_->alpha_m_[model_reference_index][model_point_index] - alpha_s;
199 unsigned int alpha_discretized =
static_cast<unsigned int> (floor (alpha) + floor (M_PI / search_method_->getAngleDiscretizationStep ()));
200 accumulator_array[model_reference_index][alpha_discretized] ++;
203 else PCL_ERROR (
"[pcl::PPFRegistration::computeTransformation] Computing pair feature vector between points %zu and %zu went wrong.\n", scene_reference_index, scene_point_index);
207 size_t max_votes_i = 0, max_votes_j = 0;
208 unsigned int max_votes = 0;
210 for (
size_t i = 0; i < accumulator_array.size (); ++i)
211 for (
size_t j = 0; j < accumulator_array.back ().size (); ++j)
213 if (accumulator_array[i][j] > max_votes)
215 max_votes = accumulator_array[i][j];
220 accumulator_array[i][j] = 0;
223 Eigen::Vector3f model_reference_point = input_->points[max_votes_i].getVector3fMap (),
224 model_reference_normal = input_->points[max_votes_i].getNormalVector3fMap ();
225 Eigen::AngleAxisf rotation_mg (acosf (model_reference_normal.dot (Eigen::Vector3f::UnitX ())), model_reference_normal.cross (Eigen::Vector3f::UnitX ()).normalized ());
226 Eigen::Affine3f transform_mg = Eigen::Translation3f ( rotation_mg * ((-1) * model_reference_point)) * rotation_mg;
227 Eigen::Affine3f max_transform =
228 transform_sg.inverse () *
229 Eigen::AngleAxisf ((static_cast<float> (max_votes_j) - floorf (static_cast<float> (M_PI) / search_method_->getAngleDiscretizationStep ())) * search_method_->getAngleDiscretizationStep (), Eigen::Vector3f::UnitX ()) *
232 voted_poses.push_back (PoseWithVotes (max_transform, max_votes));
234 PCL_DEBUG (
"Done with the Hough Transform ...\n");
237 PoseWithVotesList results;
238 clusterPoses (voted_poses, results);
242 transformation_ = final_transformation_ = results.front ().pose.matrix ();
248 template <
typename Po
intSource,
typename Po
intTarget>
void
252 PCL_INFO (
"Clustering poses ...\n");
254 sort(poses.begin (), poses.end (), poseWithVotesCompareFunction);
256 std::vector<PoseWithVotesList> clusters;
257 std::vector<std::pair<size_t, unsigned int> > cluster_votes;
258 for (
size_t poses_i = 0; poses_i < poses.size(); ++ poses_i)
260 bool found_cluster =
false;
261 for (
size_t clusters_i = 0; clusters_i < clusters.size(); ++ clusters_i)
263 if (posesWithinErrorBounds (poses[poses_i].pose, clusters[clusters_i].front ().pose))
265 found_cluster =
true;
266 clusters[clusters_i].push_back (poses[poses_i]);
267 cluster_votes[clusters_i].second += poses[poses_i].votes;
272 if (found_cluster ==
false)
275 PoseWithVotesList new_cluster;
276 new_cluster.push_back (poses[poses_i]);
277 clusters.push_back (new_cluster);
278 cluster_votes.push_back (std::pair<size_t, unsigned int> (clusters.size () - 1, poses[poses_i].votes));
283 std::sort (cluster_votes.begin (), cluster_votes.end (), clusterVotesCompareFunction);
288 size_t max_clusters = (clusters.size () < 3) ? clusters.size () : 3;
289 for (
size_t cluster_i = 0; cluster_i < max_clusters; ++ cluster_i)
291 PCL_INFO (
"Winning cluster has #votes: %d and #poses voted: %d.\n", cluster_votes[cluster_i].second, clusters[cluster_votes[cluster_i].first].size ());
292 Eigen::Vector3f translation_average (0.0, 0.0, 0.0);
293 Eigen::Vector4f rotation_average (0.0, 0.0, 0.0, 0.0);
294 for (
typename PoseWithVotesList::iterator v_it = clusters[cluster_votes[cluster_i].first].begin (); v_it != clusters[cluster_votes[cluster_i].first].end (); ++ v_it)
296 translation_average += v_it->pose.translation ();
298 rotation_average += Eigen::Quaternionf (v_it->pose.rotation ()).coeffs ();
301 translation_average /=
static_cast<float> (clusters[cluster_votes[cluster_i].first].size ());
302 rotation_average /=
static_cast<float> (clusters[cluster_votes[cluster_i].first].size ());
304 Eigen::Affine3f transform_average;
305 transform_average.translation () = translation_average;
306 transform_average.linear () = Eigen::Quaternionf (rotation_average).normalized().toRotationMatrix ();
308 result.push_back (PoseWithVotes (transform_average, cluster_votes[cluster_i].second));
314 template <
typename Po
intSource,
typename Po
intTarget>
bool
316 Eigen::Affine3f &pose2)
318 float position_diff = (pose1.translation () - pose2.translation ()).norm ();
319 Eigen::AngleAxisf rotation_diff_mat (pose1.rotation ().inverse () * pose2.rotation ());
321 float rotation_diff_angle = fabsf (rotation_diff_mat.angle ());
323 if (position_diff < clustering_position_diff_threshold_ && rotation_diff_angle < clustering_rotation_diff_threshold_)
330 template <
typename Po
intSource,
typename Po
intTarget>
bool
339 template <
typename Po
intSource,
typename Po
intTarget>
bool
341 const std::pair<size_t, unsigned int> &b)
343 return (a.second > b.second);
348 #endif // PCL_REGISTRATION_IMPL_PPF_REGISTRATION_H_