takminの書きっぱなし備忘録 @はてなブログ

主にコンピュータビジョンなど技術について、たまに自分自身のことや思いついたことなど

PCLビルドの泥沼にはまる

Point Cloud Library 1.6.0のインストールに馬鹿のようにはまりまくったので、同じようなトラブルに直面した人たちの手助けとするために、記録を残しておきます。
とは言ってもこのトラブル、おそらくPCLのバージョンが上がればあっという間に解決する問題なので、非常に賞味期間の短いネタになるだろうと思います。


作業環境:

最初はVS2012で挑戦したんですが、依存ライブラリも含めてまだ対応してないものが大半のため、あきらめました。


おおまかな経緯:

  1. PCLからXtion Pro Liveを使いたい。
  2. PCLのAll-in-Oneインストーラに含まれているOpenNIがインストールできず。
  3. OpenNIの最新版を入れたところ、無事センサは動いたが、PCLからはOpenNIが呼び出せず。
  4. PCLのソースからビルドすれば動くのではないかと期待をして、悪戦苦闘。なんとかビルドに成功する。
  5. しかし、結局PCLからOpenNIを呼び出せず。
  6. Xtion Pro Live付属のCDでOpenNIをインストールし、ビルドし直したところあっさり動く。
  7. しかし!!結局、PCLのAll-in-Oneインストーラ+Xtion Pro Live付属のOpenNIで問題なく動作することが判明。(イママデノクロウハナンダッタンヤ)


というわけで、ググって来た人たちのために、エラーメッセージも含めて躓いた点とどのように解決したかを詳細に書いていきます。

PCLのインストール(All-in-One)

以下のサイトから、PCLのAll-in-Oneインストーラ(32bit版)をダウンロード
http://pointclouds.org/downloads/windows.html

ダウンロードしたPCL_1.6.0_All-In-One_Installer.exeを実行したところ、OpenNIのインストール中に

There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor.

というエラーメッセージが出て、OpenNIのインストールに失敗。

そこで、PCLダウンロードサイト

  • OpenNI 1.5.4 (patched)
  • Sensor 5.1.0 (patched)

を再度ダウンロードして、インストールしたところ、インストール成功。


そこで、
<OpenNIインストールディレクトリ>\Samples\Bin\Release\SimpleViewer.net.exe

を実行したところ、

Device: PrimeSense/SensorV2/5.0.3.3: The device is not connected!

というエラーが出て、起動に失敗。


本当は、ここでASUSのサイトから、もしくはXtion付属のCD-ROMからOpenNIをインストールしていれば問題解決だったのに、それに気づかず大変な回り道をすることになる。。。


いったん、OpenNIとSensorをアンインストールし、OpenNIのサイトからOpenNI2.1(Beta)SDKをダウンロード。(それ以前の古いバージョンはダウンロードできなくなっている。)


OpenNI2.1をインストール後、SimpleViewerを起動したところ、無事ポイントクラウドデータ取得に成功!

PCLからXtionのデータ取り込み

Visual Studio 2010から新規プロジェクトを作成し、PCLを使用してXtionからデータを取り込みます。

Visual StudioからPCLを使用する方法については、以下のサイトが参考になります。

http://pointclouds.org/documentation/tutorials/using_pcl_pcl_config.php
http://derivecv.tumblr.com/post/12359379355


また、OpenNIからのPoint Cloudデータ取り込みは、以下のチュートリアルを参考にしました。
http://pointclouds.org/documentation/tutorials/openni_grabber.php


以下、コードです。(チュートリアルのコードそのまま)

#include 
#include 
#include 
#include 

class SimpleOpenNIViewer
{
public:
	SimpleOpenNIViewer () : viewer ("PCL OpenNI Viewer") {}

	void cloud_cb_ (const pcl::PointCloud::ConstPtr &cloud)
	{
		if (!viewer.wasStopped())
			viewer.showCloud (cloud);
	}

	void run ()
	{
		pcl::Grabber* interface = new pcl::OpenNIGrabber();

		boost::function::ConstPtr&)> f =
			boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);

		interface->registerCallback (f);

		interface->start ();

		while (!viewer.wasStopped())
		{
			boost::this_thread::sleep (boost::posix_time::seconds (1));
		}

		interface->stop ();
	}

	pcl::visualization::CloudViewer viewer;
};

int main ()
{
	SimpleOpenNIViewer v;
	v.run ();
	return 0;
}

さて、以上のようなコードを書いて、OpenNI2.1からのデータを取り込もうとしたところ、コンパイル

1>c:\program files (x86)\pcl 1.6.0\include\pcl-1.6\pcl\io\openni_camera\openni_device.h(47): fatal error C1083: include ファイルを開けません。'XnCppWrapper.h': No such file or directory

というエラーが出て撃沈。
OpenNI1.5.xではIncludeディレクトリに存在した'XnCppWrapper.h'が2.1では存在しないことが原因らしい。


ということで、今度はPCLをソースからビルドしてみようと試みました。(PCLのコード内でXnCppWrapper.hを参照しているのだから、PCLをソースからビルドしたって無駄に決まっているのに、そこまで頭が回っていなかった。)

PCLをソースからビルドする

PCLをソースからビルドする手順は、以下のチュートリアルを参考。
http://pointclouds.org/documentation/tutorials/compiling_pcl_windows.php


以下、すでに上記のチュートリアルを元に、CMakeによるPCLのソースからのビルド方法を理解しているものとして解説していきます。

CMakeによるソリューションファイル作成

PCLが様々なライブラリに依存しているのはご承知の通り。僕は最初、どうせならこれらの依存ライブラリもできるだけ最新版にしてやろうと、それぞれをソースからビルドしようとしましたが、PCLをCMakeから"Configure"した際、
以下のようなエラーが出てしまい、これがどうにも解決できないため断念しました。(BOOST_LIBRARYの設定等いろいろ試しましたが)

  Unable to find the requested Boost libraries.

  Boost version: 1.53.0

  Boost include path: C:/ProgramFolders/boost/include/boost-1_53

  The following Boost libraries could not be found:

          boost_system
          boost_filesystem
          boost_thread
          boost_date_time
          boost_iostreams

  No Boost libraries were found.  You may need to set BOOST_LIBRARYDIR to the
  directory containing Boost libraries or BOOST_ROOT to the location of
  Boost.
Call Stack (most recent call first):
  cmake/pcl_find_boost.cmake:27 (find_package)
  CMakeLists.txt:175 (include)


というわけで、依存ライブラリをソースからビルドするのは諦めて、
PCLのダウンロードページから、各依存ライブラリ(OpenNI除く)のインストーラをそれぞれダウンロードして実行しました。
http://pointclouds.org/downloads/windows.html


次に、PCL1.6.0のソースをダウンロードして解凍します。PCL-1.6.0-Source.tar.bz2というファイルがダウンロードされるはずです。
さて、このbz2ファイルを解凍する際、罠があります。


日本でメジャーなLhaplusLhacaなどの解凍ソフトを使用すると、誤ったフォルダ構成で解凍されてしまいました。
本来は、

こんな感じのファイル構成にならなくてはいけないところが、



こんな感じで解凍されてしまいます。

たとえば7zipであれば問題なく解凍できます。


もし、このような誤ったファイル構成のままCMakeでConfigureを行うと、以下のようなエラーに悩まされることになります。

CMake Error at cmake/pcl_targets.cmake:103 (add_library):
  Cannot find source file:

    include/pcl/sample_consensus/impl/sac_model_normal_parallel_plane.hpp

  Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
  .hxx .in .txx
Call Stack (most recent call first):
  sample_consensus/CMakeLists.txt:90 (PCL_ADD_LIBRARY)


さて、正しいファイル構成のもとCMakeから"Configure"->"Generate"と行うことで、無事Visual C++ 2010用のプロジェクトファイルができあがりました。

VS2010でのビルド

CMakeにより生成したPCL.slnを起動して、プロジェクトを立ち上げます。
本来であればReleaseモードとDebugモードでそれぞれビルドすれば、ライブラリが出来上がってめでたしめでたしのはずですが、実際には以下のようなエラーが大量に出ました。

(略)
14>------ ビルド開始: プロジェクト: pcl_example_scope_time, 構成: Release Win32 ------
12>c:\users\takmin\downloads\pcl-1.6.0-source\io\include\pcl\io\openni_camera\openni_device.h(47): fatal error C1083: include ファイルを開けません。'XnCppWrapper.h': No such file or directory
12>c:\users\takmin\downloads\pcl-1.6.0-source\io\include\pcl\io\openni_camera\openni_device.h(47): fatal error C1083: include ファイルを開けません。'XnCppWrapper.h': No such file or directory
(略)

このようなエラーはOpenNI2.1で出るので、前述のとおりXtion付属のOpenNI1.5.2をインストールし直して、問題は解決しました。
しかし、それでもこんなエラーが出ます。

5>------ ビルドのスキップ: プロジェクト: uninstall, 構成: Release Win32 ------
5>プロジェクトはこのソリューション構成に対してビルドするように選択されていません。 
4>     ライブラリ C:/Users/takmin/Work/Build/PCL1.6.0/lib/pcl_io_ply_release.lib とオブジェクト C:/Users/takmin/Work/Build/PCL1.6.0/lib/pcl_io_ply_release.exp を作成中
4>libboost_thread-vc100-mt-1_50.lib(thread.obj) : error LNK2001: 外部シンボル ""public: static class boost::chrono::time_point > > __cdecl boost::chrono::system_clock::now(void)" (?now@system_clock@chrono@boost@@SA?AV?$time_point@Vsystem_clock@chrono@boost@@V?$duration@_JV?$ratio@$00$0JIJGIA@@boost@@@23@@23@XZ)" は未解決です。
4>C:\Users\takmin\Work\Build\PCL1.6.0\bin\pcl_io_ply_release.dll : fatal error LNK1120: 外部参照 1 が未解決です。

これは、本来BoostのShared Libraryとリンクしなければいけないのを、Static Libraryに対してリンクしようとしているためでした。
BOOSTのShared Library(DLL)を使用するためには、CMakeファイルを編集する必要がありました。。

具体的には、
PCL-1.6.0-Source\cmake\pcl_find_boost.cmake


の3行目を
if(NOT PCL_SHARED_LIBS OR WIN32)
から
if(NOT PCL_SHARED_LIBS)


6行目を
endif(NOT PCL_SHARED_LIBS OR WIN32)
から
endif(NOT PCL_SHARED_LIBS)


に修正して、再度CMakeのConfigure&Generateを行います。


これにより上記のリンクエラーはなくなりますが、それでもまだ以下のエラーが残りました。

3>------ ビルド開始: プロジェクト: pcl_octree_viewer, 構成: Release Win32 ------
(中略)
3>..\..\..\..\Downloads\PCL-1.6.0-Source\tools\octree_viewer.cpp(51): fatal error C1083: include ファイルを開けません。'omp.h': No such file or directory

これは、VS2010 ExpressがOpenMPをサポートしていないために生じるエラーです。
なんとかVS2010 ExpressでOpenMPを使うすべを探してググりまくりました。

http://www.atmarkit.co.jp/fdotnet/bookpreview/bunpouvcpp_1302/bunpouvcpp_1302_04.html
http://blender.jp/modules/newbb/viewtopic.php?viewmode=thread&topic_id=871&forum=4&post_id=6746


上記のサイトを参考に、Windows SDK for Windows8Visual Studio 2010 SP1をインストールしました。またVS2010 SP1用のパッチをWindows Updateから適用しました。


次に、プロジェクトのプロパティでOpenMPを有効にしました([構成プロパティ]の[C/C++]、[言語])が、やはりうまくいかず、自分のローカルディスク上でomp.hを検索したところ、

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\omp.h

に、見つかったため、これを

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\
へコピーしました。

ビルドすると、先ほどのエラーの代わりに

2>------ ビルド開始: プロジェクト: pcl_octree_viewer, 構成: Release Win32 ------
2>LINK : fatal error LNK1104: ファイル 'VCOMP.lib' を開くことができません。

というエラーが出たため、
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\lib\vcomp.lib
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\lib\vcompd.lib

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\
へコピーしました。
(VS11のデバッグライブラリをVS10にコピーして良いのだろうかという疑問は残りますが。。。)


なにはともあれ、これでなんとかビルドが通りました。


あとはライブラリとして必要なファイル一式をまとめる必要がありますが、これはINSTALLというプロジェクトをビルドすることで実行できます。


デフォルトでは

C:\Program Files (x86)\PCL

というフォルダの下に作成されます。


ただし、Windows7や8でこれを行う場合、管理者権限が必要になります。
Windows8で行う場合、エクスプローラの「ファイル」メニュー→「コマンドプロンプトを開く」→「コマンドプロンプトを管理者として開く」を選択します。

管理者用コマンドプロンプトから、PCL.slnを開いてINSTALLをビルドしたら完成です。

結論

WindowsからPCLをインストールする場合はできるだけAll-in-Oneパッケージを選ぼう!

どうしてもPCLをソースからビルドしたいなら、Ubuntu環境でするのが良いらしい