|
1 | 1 | /* |
2 | | - ********************************************************* |
3 | | - * ******************************************************* |
4 | | - * *********** Iterative Closest Point (ICP) ************ |
5 | | - * ******************************************************* |
6 | | - * ************ written by Avinash on 04-02-2019 ********* |
7 | | - ********************************************************* |
8 | | - */ |
9 | | - |
| 2 | +Author: Avinash |
| 3 | +Version: 1.0.1 |
| 4 | +Date: Apr 03, 2019 |
| 5 | +*/ |
10 | 6 |
|
11 | 7 | #include <iostream> |
12 | 8 | #include <ros/ros.h> |
|
21 | 17 |
|
22 | 18 | using namespace std; |
23 | 19 |
|
24 | | -static ros::Publisher icp_transform_pub; |
25 | | -std::string template_cuboid_filename; |
| 20 | +// Globals |
| 21 | +ros::Publisher pcl_pub; |
| 22 | +Eigen::Matrix4d icp_transform; |
| 23 | +string template_cuboid_filename; |
26 | 24 |
|
| 25 | +// Flags |
| 26 | +bool DEBUG = false; |
| 27 | +bool ICP_SUCCESS = false; |
27 | 28 |
|
28 | | -void convert_icp_eigen_to_tf(Eigen::Matrix4f Tm) |
29 | | -{ |
| 29 | +void convert_icp_eigen_to_tf(Eigen::Matrix4d Tm) |
| 30 | +{ |
| 31 | + // Set translation |
30 | 32 | tf::Vector3 origin; |
31 | | - static tf::TransformBroadcaster br; |
32 | | - |
33 | | - origin.setValue(static_cast<double>(Tm(0,3)),static_cast<double>(Tm(1,3)),static_cast<double>(Tm(2,3))); |
34 | | - |
35 | | - cerr << origin << endl; |
36 | | - tf::Matrix3x3 tf3d; |
37 | | - tf3d.setValue(static_cast<double>(Tm(0,0)), static_cast<double>(Tm(0,1)), static_cast<double>(Tm(0,2)), |
38 | | - static_cast<double>(Tm(1,0)), static_cast<double>(Tm(1,1)), static_cast<double>(Tm(1,2)), |
39 | | - static_cast<double>(Tm(2,0)), static_cast<double>(Tm(2,1)), static_cast<double>(Tm(2,2))); |
40 | | - |
41 | | - tf::Quaternion tfqt; |
42 | | - tf3d.getRotation(tfqt); |
43 | | - |
| 33 | + origin.setValue(Tm(0, 3), Tm(1, 3), Tm(2, 3)); |
| 34 | + |
| 35 | + // Set rotation |
| 36 | + tf::Quaternion quaternion; |
| 37 | + tf::Matrix3x3 rotation_matrix; |
| 38 | + rotation_matrix.setValue(Tm(0, 0), Tm(0, 1), Tm(0, 2), |
| 39 | + Tm(1, 0), Tm(1, 1), Tm(1, 2), |
| 40 | + Tm(2, 0), Tm(2, 1), Tm(2, 2)); |
| 41 | + rotation_matrix.getRotation(quaternion); |
| 42 | + |
| 43 | + // Make tf transform message |
44 | 44 | tf::Transform transform; |
45 | 45 | transform.setOrigin(origin); |
46 | | - transform.setRotation(tfqt); |
| 46 | + transform.setRotation(quaternion); |
47 | 47 |
|
48 | | - br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "camera_depth_frame", "cuboid_frame")); |
| 48 | + // Broadcast the transforms |
| 49 | + tf::TransformBroadcaster br; |
| 50 | + while (true) br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "map", "cuboid_frame")); |
49 | 51 | } |
50 | 52 |
|
51 | | -void rawPCL_cb(const sensor_msgs::PointCloud2::ConstPtr& msg) |
| 53 | +void icp_callback(const sensor_msgs::PointCloud2::ConstPtr& msg) |
52 | 54 | { |
| 55 | + // Compute ICP only once |
| 56 | + if (ICP_SUCCESS) |
| 57 | + { |
| 58 | + return; |
| 59 | + } |
| 60 | + |
| 61 | + // Point cloud containers |
53 | 62 | pcl::PointCloud<pcl::PointXYZ>::Ptr template_cuboid(new pcl::PointCloud<pcl::PointXYZ>); |
54 | 63 | pcl::PointCloud<pcl::PointXYZ>::Ptr input_cuboid(new pcl::PointCloud<pcl::PointXYZ>); |
| 64 | + pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>); |
55 | 65 |
|
56 | | - pcl::PCLPointCloud2 pcl_pc2; |
57 | | - pcl_conversions::toPCL(*msg,pcl_pc2); |
58 | | - pcl::fromPCLPointCloud2(pcl_pc2,*input_cuboid); |
59 | | - |
60 | | - |
61 | | - if (pcl::io::loadPCDFile<pcl::PointXYZ> (template_cuboid_filename, *template_cuboid) == -1) //* load the file |
| 66 | + // Read input point cloud |
| 67 | + pcl::fromROSMsg(*msg, *input_cuboid); |
| 68 | + |
| 69 | + // Read template point cloud |
| 70 | + if (pcl::io::loadPCDFile<pcl::PointXYZ>(template_cuboid_filename, *template_cuboid) == -1) |
62 | 71 | { |
63 | | - PCL_ERROR ("Couldn't read file"); |
| 72 | + PCL_ERROR("Couldn't read the template PCL file"); |
64 | 73 | return; |
65 | 74 | } |
66 | 75 |
|
67 | | - pcl::IterativeClosestPoint <pcl::PointXYZ, pcl::PointXYZ> icp; |
| 76 | + // Run ICP |
| 77 | + pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; |
68 | 78 | icp.setInputSource(input_cuboid); |
69 | 79 | icp.setInputTarget(template_cuboid); |
70 | | - pcl::PointCloud <pcl::PointXYZ> Final; |
71 | | - icp.align(Final); |
72 | | - std::cerr << "has converged:" << icp.hasConverged() << " score: " << |
73 | | - icp.getFitnessScore() << std::endl; |
74 | | - std::cerr << icp.getFinalTransformation() << std::endl; |
75 | | - convert_icp_eigen_to_tf(icp.getFinalTransformation()); |
| 80 | + icp.align(*output_cloud); |
| 81 | + icp_transform = icp.getFinalTransformation().cast<double>(); |
| 82 | + |
| 83 | + // Convert ICP results and broadcast TF |
| 84 | + if (icp.hasConverged()) |
| 85 | + { |
| 86 | + cerr << "\nICP Score: " << icp.getFitnessScore() << endl; |
| 87 | + cerr << "ICP Transform:\n" << icp_transform << endl; |
| 88 | + |
| 89 | + ICP_SUCCESS = true; |
| 90 | + // convert_icp_eigen_to_tf(icp_transform); |
| 91 | + |
| 92 | + // Convert to ROS data type |
| 93 | + sensor_msgs::PointCloud2 output; |
| 94 | + pcl::toROSMsg(*output_cloud, output); |
| 95 | + pcl_pub.publish(output); |
| 96 | + } |
76 | 97 | } |
77 | 98 |
|
78 | 99 | int main(int argc, char **argv) |
79 | 100 | { |
| 101 | + // Init node |
80 | 102 | ros::init(argc, argv, "iterative_closest_point"); |
81 | 103 | ros::NodeHandle nh; |
82 | 104 |
|
| 105 | + // Handle params |
83 | 106 | nh.getParam("template_cuboid_path", template_cuboid_filename); |
84 | 107 | cerr << "\nTemplate filename: " << template_cuboid_filename; |
85 | 108 |
|
86 | | - ros::Subscriber raw_PCL_sub = nh.subscribe<sensor_msgs::PointCloud2>("/ground_plane_segmentation/points", 1, rawPCL_cb); |
| 109 | + // Subscribers |
| 110 | + ros::Subscriber pcl_sub = nh.subscribe<sensor_msgs::PointCloud2>("/ground_plane_segmentation/points", 1, icp_callback); |
87 | 111 |
|
| 112 | + // Publishers |
| 113 | + pcl_pub = nh.advertise<sensor_msgs::PointCloud2>("/icp/aligned_points", 1); |
| 114 | + |
88 | 115 | ros::spin(); |
89 | 116 | } |
0 commit comments