PCLでICPアルゴリズムを使ってみる。

###目的
PCLのICPアルゴリズムで、2つの点群の移動量を求める。

###環境
コンパイルを簡略化するため、PCL_ROSを使って、MakeFileでコンパイルする。
[PCL_ROSをMakeFileでコンパイルする](http://qiita.com/nnn112358/items/cdb899d21655b8b6c21b)
-Ubuntu 1404 x64
-ROS indigo


###実装
pcl::IterativeClosestPointに、移動前の点群と移動後の点群を入力する。
移動量は4x4の変換Matrixで出力される。

main.cpp

```
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>

using namespace std;

void print4x4Matrix (const Eigen::Matrix4d & matrix)
{
  printf ("Rotation matrix :\n");
  printf ("    | %6.3f %6.3f %6.3f | \n", matrix (0, 0), matrix (0, 1), matrix (0, 2));
  printf ("R = | %6.3f %6.3f %6.3f | \n", matrix (1, 0), matrix (1, 1), matrix (1, 2));
  printf ("    | %6.3f %6.3f %6.3f | \n", matrix (2, 0), matrix (2, 1), matrix (2, 2));
  printf ("Translation vector :\n");
  printf ("t = < %6.3f, %6.3f, %6.3f >\n\n", matrix (0, 3), matrix (1, 3), matrix (2, 3));
}

int main (int argc, char** argv){

	//点群を宣言する。
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out (new pcl::PointCloud<pcl::PointXYZ>);

	//点群の移動量を設定
	double x_offset=0.7f;
	double y_offset=0.5f;
	
	//点群cloud_inにデータを入力
	cloud_in->width    = 5;
	cloud_in->height   = 1;
	cloud_in->is_dense = false;
	cloud_in->points.resize (cloud_in->width * cloud_in->height);

	for (size_t i = 0; i < cloud_in->points.size (); ++i)	{
		cloud_in->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
		cloud_in->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
		cloud_in->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
	}

	std::cout << "Saved " << cloud_in->points.size () << " data points to input:"<< std::endl;
	for (size_t i = 0; i < cloud_in->points.size (); ++i) std::cout << "    " <<
	cloud_in->points[i].x << " " <<
	cloud_in->points[i].y << " " <<
	cloud_in->points[i].z << std::endl;
	*cloud_out = *cloud_in;
	std::cout << "size:" << cloud_out->points.size() << std::endl;

	//点群を移動させcloud_outを作る。
	for (size_t i = 0; i < cloud_in->points.size (); ++i){
		cloud_out->points[i].x = cloud_in->points[i].x + x_offset;
		cloud_out->points[i].y = cloud_in->points[i].y + y_offset;

	}
	std::cout << "Transformed " << cloud_in->points.size () << " data points:"	<< std::endl;

	for (size_t i = 0; i < cloud_out->points.size (); ++i)
	std::cout << "    " <<
	cloud_out->points[i].x << " " <<
	cloud_out->points[i].y << " " <<
	cloud_out->points[i].z << std::endl;

	//cloud_inとcloud_outをICPアルゴズムにより変換matrixを求める。
	pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
	icp.setInputCloud(cloud_in);
	icp.setInputTarget(cloud_out);

	pcl::PointCloud<pcl::PointXYZ> Final;
	icp.align(Final);

	//変換matrixを表示する
 	Eigen::Matrix4d transformation_matrix = Eigen::Matrix4d::Identity ();
   	transformation_matrix = icp.getFinalTransformation ().cast<double>();
	print4x4Matrix (transformation_matrix);

	return (0);
}
```


```
$ ./pcl_sample 
Saved 5 data points to input:
    0.352222 -0.151883 -0.106395
    -0.397406 -0.473106 0.292602
    -0.731898 0.667105 0.441304
    -0.734766 0.854581 -0.0361733
    -0.4607 -0.277468 -0.916762
size:5
Transformed 5 data points:
    1.05222 0.348117 -0.106395
    0.302594 0.0268941 0.292602
    -0.0318983 1.1671 0.441304
    -0.0347655 1.35458 -0.0361733
    0.2393 0.222532 -0.916762
Rotation matrix :
    |  1.000 -0.000  0.000 | 
R = | -0.000  1.000  0.000 | 
    | -0.000  0.000  1.000 | 
Translation vector :
t = <  0.700,  0.500, -0.000 >
```

x成分移動量=0.7,y成分移動量=0.5,z成分移動量=0.0を与えていたが、
pcl::IterativeClosestPointで、誤差ない結果が得られた。

###参考
[tutorials:iterative_closest_point](http://pointclouds.org/documentation/tutorials/iterative_closest_point.php)