@@ -66,8 +66,9 @@ string input_topic;
6666string output_topic;
6767string coefficients_topic;
6868
69+ int argmin = -1 ;
6970Eigen::Matrix4d icp_transform;
70- string template_cuboid_filename ;
71+ vector<Eigen::Matrix4d> icp_transforms ;
7172sensor_msgs::PointCloud2 bbox_msg;
7273sensor_msgs::PointCloud2 output_msg;
7374sensor_msgs::PointCloud2 template_msg;
@@ -78,6 +79,11 @@ double dimensions[3];
7879double icp_fitness_score;
7980pcl::PCLPointCloud2::Ptr input_pcl (new pcl::PCLPointCloud2);
8081
82+ // Template paths
83+ string template_path;
84+ string template_filenames[] = {" " , " screwdriver_ascii_tf.pcd" , " eraser_ascii_tf.pcd" ,
85+ " clamp_ascii_tf.pcd" , " marker_ascii_tf.pcd" };
86+
8187// Flags
8288bool DEBUG = false ;
8389bool ICP_SUCCESS = false ;
@@ -141,26 +147,23 @@ void publish_bounding_box(Eigen::Matrix4d H)
141147 pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud (new pcl::PointCloud<pcl::PointXYZ>);
142148 pcl::transformPointCloud (box_cloud, *transformed_cloud, H.cast <float >());
143149
144- if (FIRST)
145- {
146- FIRST = false ;
147- cout << " Bounding Box Points:" << endl;
148- for (int i = 0 ; i < transformed_cloud->size (); i++)
149- {
150- cout << " X: " << transformed_cloud->points [i].x << " | "
151- << " Y: " << transformed_cloud->points [i].y << " | "
152- << " Z: " << transformed_cloud->points [i].z << endl;
153- }
154- }
150+ // cout << "Bounding Box Points:" << endl;
151+ // for (int i = 0; i < transformed_cloud->size(); i++)
152+ // {
153+ // cout << "X: " << transformed_cloud->points[i].x << " | "
154+ // << "Y: " << transformed_cloud->points[i].y << " | "
155+ // << "Z: " << transformed_cloud->points[i].z << endl;
156+ // }
155157
156158 // Convert to ROS data type and publish
157159 pcl::toROSMsg (*transformed_cloud, bbox_msg);
158160 bbox_msg.header .frame_id = " camera_depth_optical_frame" ;
159161 bbox_pub.publish (bbox_msg);
160162}
161163
162- void icp_registration (pcl::PointCloud<pcl::PointXYZ>::Ptr input_pcl, pcl::PointCloud<pcl::PointXYZ>::Ptr template_pcl)
164+ double icp_registration (pcl::PointCloud<pcl::PointXYZ>::Ptr input_pcl, pcl::PointCloud<pcl::PointXYZ>::Ptr template_pcl)
163165{
166+ int max_iter = 0 ;
164167 while (1 )
165168 {
166169 // Point cloud containers
@@ -176,21 +179,22 @@ void icp_registration(pcl::PointCloud<pcl::PointXYZ>::Ptr input_pcl, pcl::PointC
176179 icp.setEuclideanFitnessEpsilon (icp_fitness_score);
177180 icp.setRANSACOutlierRejectionThreshold (1.5 );
178181 icp.align (*output_cloud);
179- icp_transform = icp.getFinalTransformation ().cast <double >().inverse ();
182+ Eigen::Matrix4d icp_transform_local = icp.getFinalTransformation ().cast <double >().inverse ();
183+ icp_transforms.push_back (icp_transform_local);
180184
181185 cerr << " ICP Score Before: " << icp.getFitnessScore () << endl;
186+ max_iter++;
182187
183- if (icp.hasConverged () && icp.getFitnessScore () < icp_fitness_score)
188+ if (( icp.hasConverged () && icp.getFitnessScore () < icp_fitness_score) || (max_iter > 10 ) )
184189 {
185190 // Display ICP results
186191 cerr << " \n ICP Score: " << icp.getFitnessScore () << endl;
187- cerr << " ICP Transform:\n " << icp_transform << endl;
192+ cerr << " ICP Transform:\n " << icp_transform_local << endl;
188193
189194 // Convert to ROS data type
190195 pcl::toROSMsg (*output_cloud, output_msg);
191196 pcl::toROSMsg (*template_pcl, template_msg);
192- ICP_SUCCESS = true ;
193- return ;
197+ return icp.getFitnessScore ();
194198 }
195199 }
196200}
@@ -202,7 +206,7 @@ void pcl_callback(const sensor_msgs::PointCloud2ConstPtr& input)
202206 if (DEBUG) cerr << " PointCloud before filtering: " << input_pcl->width << " " << input_pcl->height << " data points." << endl;
203207
204208 // Publish template point cloud
205- if (ICP_SUCCESS)
209+ if (ICP_SUCCESS and argmin != - 1 )
206210 {
207211 icp_pub.publish (output_msg);
208212 template_msg.header .frame_id = " camera_depth_optical_frame" ;
@@ -274,7 +278,7 @@ bool service_callback(object_detection::ObjectDetection::Request &req,
274278 pcl::PassThrough<pcl::PCLPointCloud2> pass_z2;
275279 pass_z2.setInputCloud (plane_cloud_ptr);
276280 pass_z2.setFilterFieldName (" z" );
277- pass_z2.setFilterLimits (0.0 , 0.7 );
281+ pass_z2.setFilterLimits (0.0 , 0.75 );
278282 pass_z2.filter (*cloud_filtered_ptr_z2);
279283 if (DEBUG) cerr << " PointCloud after filtering: " << cloud_filtered_ptr_z2->width << " " << cloud_filtered_ptr->height << " data points." << endl;
280284
@@ -298,10 +302,15 @@ bool service_callback(object_detection::ObjectDetection::Request &req,
298302 ec.extract (object_cluster_indices);
299303
300304 // Display number of objects detceted
305+ cerr << " \n Requested Object: " << template_filenames[req.object_id ] << endl;
301306 cerr << " Objects Detected: " << object_cluster_indices.size () << endl;
302- int obj_id = 1 ;
303307
304- // What is this?
308+ // Find the best registered object
309+ int obj_id = req.object_id ;
310+ vector<double > icp_scores;
311+ icp_transforms.clear ();
312+ ICP_SUCCESS = false ;
313+
305314 for (vector<pcl::PointIndices>::const_iterator it = object_cluster_indices.begin (); it != object_cluster_indices.end (); ++it)
306315 {
307316 // Create a pcl object to hold the extracted cluster
@@ -323,7 +332,7 @@ bool service_callback(object_detection::ObjectDetection::Request &req,
323332 pcl_pub.publish (output);
324333
325334 // Read template point cloud
326- string template_filename = " /home/heethesh/ROS-Workspaces/dash_ws/src/perception/object_detection/templates/eraser_ascii_tf.pcd " ;
335+ string template_filename = template_path + template_filenames[req. object_id ] ;
327336 pcl::PointCloud<pcl::PointXYZ>::Ptr template_pcl (new pcl::PointCloud<pcl::PointXYZ>);
328337 if (pcl::io::loadPCDFile<pcl::PointXYZ>(template_filename, *template_pcl) == -1 )
329338 {
@@ -333,9 +342,35 @@ bool service_callback(object_detection::ObjectDetection::Request &req,
333342 }
334343
335344 // Register using ICP and broadcast TF
336- icp_registration (object_cluster_pcl, template_pcl);
345+ double score = icp_registration (object_cluster_pcl, template_pcl);
346+ icp_scores.push_back (score);
347+ }
348+
349+ // Find the object with best ICP score
350+ double min_score = 1000 ;
351+ argmin = -1 ;
352+ for (int i = 0 ; i < icp_scores.size (); i++)
353+ {
354+ if (icp_scores[i] < min_score)
355+ {
356+ argmin = i;
357+ min_score = icp_scores[i];
358+ }
359+ }
360+
361+ cerr << " \n Lowest Object Index: " << argmin << " with Score: " << min_score << endl;
362+ icp_transform = icp_transforms[argmin];
363+
364+ if (min_score < icp_fitness_score) {
365+ cerr << " ICP Registration Success!\n " << endl;
366+ ICP_SUCCESS = true ;
337367 res.success = true ;
338368 return true ;
369+ } else {
370+ cerr << " ICP Registration Failed to Converge within Threshold!\n " << endl;
371+ ICP_SUCCESS = false ;
372+ res.success = false ;
373+ return false ;
339374 }
340375}
341376
@@ -352,6 +387,7 @@ int main(int argc, char** argv)
352387 nh.getParam (" input" , input_topic);
353388 nh.getParam (" output" , output_topic);
354389 nh.getParam (" icp_fitness_score" , icp_fitness_score);
390+ nh.getParam (" template_path" , template_path);
355391
356392 // Params defaults
357393 nh.param <bool >(" invert" , invert, true );
@@ -366,7 +402,8 @@ int main(int argc, char** argv)
366402 cout << " Distance Threshold: " << distance_threshold << endl;
367403 cout << " Input Topic: " << input_topic << endl;
368404 cout << " Output Topic: " << output_topic << endl;
369- cerr << " ICP Fitness Score:" << icp_fitness_score << endl;
405+ cerr << " ICP Fitness Score: " << icp_fitness_score << endl;
406+ cerr << " ICP Template Folder: " << template_path << endl;
370407
371408 // Create a ROS subscriber for the input point cloud
372409 ros::Subscriber sub = nh.subscribe (input_topic, 1 , pcl_callback);
0 commit comments