2012年7月29日日曜日

OpenNIを利用したアプリ:跳ねるボール

はじめに

OpenNIとXtion Pro Liveを使って、こんなアプリを作りました。
  1. Xtion Pro Liveから取り込んだデプスデータから3次元点群(ポイントクラウド)を作成する。
  2. Point Cloud Library(PCL)を用いて、各点の法線ベクトルを算出する。
  3. 仮想ボールを投入し、環境内の障害物と衝突する様子をシミュレーションする。
法線ベクトルの導出は、一度だけ行います。その後のフレームでは同じデータを使います。描画はOpenGLで行います。

開発環境

  1. Mac OS X 10.7.4
  2. プロセッサ:3.06 GHz Intel Core 2 Duo
  3. メモリ:4GB
  4. Xcode4.3.3

主要ライブラリ

  1. boost-1.50.0
  2. pcl-1.6.0
  3. 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行目でこれを見ています(このあたりの実装はもっと上手いやり方があるかもしれません)。

0 件のコメント:

コメントを投稿