はじめに
OpenNIとXtion Pro Liveを使って、こんなアプリを作りました。- Xtion Pro Liveから取り込んだデプスデータから3次元点群(ポイントクラウド)を作成する。
- Point Cloud Library(PCL)を用いて、各点の法線ベクトルを算出する。
- 仮想ボールを投入し、環境内の障害物と衝突する様子をシミュレーションする。
開発環境
- Mac OS X 10.7.4
- プロセッサ:3.06 GHz Intel Core 2 Duo
- メモリ:4GB
- Xcode4.3.3
主要ライブラリ
- boost-1.50.0
- pcl-1.6.0
- OpenNI-Bin-Dev-MacOSX-v1.5.4.0
ソース
こちらです。自分のマシーンでしか動作確認していません。コンパイルオプション
Header Search Path:パス | 目的 |
---|---|
/usr/include/ni/ | OpenNIヘッダー |
/opt/local/include/ | boostヘッダー |
/usr/local/include/pcl-1.6/ | PCLヘッダー |
/opt/local/include/eigen3/ | eigenヘッダー(PCLがこれに依存している) |
/opt/local/include/vtk-5.10/ | vtkヘッダー(PCLがこれに依存している) |
Library Search Path:
パス | 目的 |
---|---|
/opt/local/lib | boostライブラリ |
/usr/local/lib | PCLライブラリ |
その他、OpenGLを使用するため、
-framework OpenGL
などを設定しています。詳細はソースをご覧ください。
使い方
実行ファイ名は、OpenNiViewer
です。引数なしで実行すると以下を出力します。
--config
にSamplesConfig.xmlを指定し実行すると、窓が開き、Xtion Pro Liveの映像が映し出されます。SamplesConfig.xmlはソースに同封しました。--width/--height
の値はデフォルト値でしか動作確認していません。
窓にフォーカスがある状態で、キーボードから「p」を打つと、法線ベクトルの計算が始まります。
"Normals is now being extracted."は計算中、"Normals has been extracted."は計算終了を表します。続いて、「i」を打つと、環境内にボールが投入されます。ボールと障害物の相互作用がリアルタイムで描画されます。
「esc」を打つと終了します。
ソースの概要
OpenGLの視点
以下のように設定しています。本アプリの長さの単位は全てmmです。 8行目の引数は使用する環境に合わせる必要があります。ポイントクラウドへの変換
OpenNiDevice::create_cloudで行います。カラー画像描画のためのポイントクラウド(cloud_
)と法線ベクトル算出用のポイントクラウド(cloud_xyz_
)の2種類を生成しています。
26,27,28行目でRGB値を設定しています。33行目でデプスから3次元座標への変換を行っています。34行目で法線用のデータを設定しています。
カラー画像の描画
カラー画像用のポイントクラウド(cloud_
)は、OpenGLのglInterleavedArrays
に以下(5行目)のように渡されます。
法線ベクトルの計算
法線算出用ポイントクラウド(cloud_xyz_
)はOpenNiDevice::calculate_normalsで処理されます。
6行目のinitializeの内容は以下の通りです。
9行目で近傍探索の範囲を指定しています。この引数は環境に合わせて変える必要があります。この範囲内にある点から平面を導出し、その法線ベクトルを求めます。
法線ベクトルの計算は「p」を打つと一度だけ行います。Xtion Pro Liveを動かした場合は、再度「p」を打つ必要があります。ボールの配置
ボールはOpenNiViewer::register_ballsで配置しています。 25行目でボールの半径を指定します。31行目で初期位置を、32行目で初期速度を、33行目で加速度を設定します。 これらも環境に合わせて変える必要があります。壁の配置
画面手前に壁を設定しています。環境に合わせてパラメータを変える必要があります。法線ベクトルの検索
毎フレーブごとに、ボール近傍にある法線ベクトルを検索する必要があります。この検索には、kd-treeを使います。 8行目のkdtree_
はpcl::KdTreeFLANN<pcl::PointXYZ>
のオブジェクトです。このクラスは、近傍点の探索に失敗するとnan
を返します。なので、12行目でこれを見ています(このあたりの実装はもっと上手いやり方があるかもしれません)。