ラベル OpenNI の投稿を表示しています。 すべての投稿を表示
ラベル OpenNI の投稿を表示しています。 すべての投稿を表示

2012年10月29日月曜日

OpenNI Application "Bouncing Ball 3"

in Japanese

Introduction

In the previous page, I showed the application that is using the OpenNI and the Open Dynamics Engine libraries with the Xtion Pro Live. Recently I have introduced the SceneAnalyzer node, which is supported by the OpenNI library, to the application. In this page, I provide you with an explanation on the new application. (Here is my first introduction to the ODE.)

Demo

I start by showing a demo movie.

Developement Environment

  1. Mac OS X 10.8.2
  2. Processor:3.06 GHz Intel Core 2 Duo
  3. Memory:4GB
  4. Xcode4.5.1

Primary Libraries

  1. boost-1.51.0
  2. pcl-1.6.0
  3. OpenNI-Bin-Dev-MacOSX-v1.5.4.0
  4. ode-0.12

My Source Code

Here is my source code. I do not confirm the behavior of the application on environments other than mine.

Compile Options

Header Search Path:
Path Purpose
/usr/include/ni/ to include the OpenNI headers
/opt/local/include/ to include the Boost and the ODE headers
/usr/local/include/pcl-1.6/ to include the PCL headers
/opt/local/include/eigen3/ to include the Eigen headers on which the PCL depends
/opt/local/include/vtk-5.10/ to include the VTK headers on which PCL dependes

Library Search Path:
Path Purpose
/opt/local/lib to link the Boost library
/usr/local/lib to link the PCL library

Other Linker Flags:
-lboost_thread-mt -lboost_filesystem-mt -lboost_unit_test_framework-mt -lboost_chrono-mt -lboost_program_options-mt -lboost_system-mt /usr/lib/libOpenNI.dylib -framework OpenGL -framework GLUT -lpcl_filters -lpcl_kdtree -lpcl_segmentation -lpcl_surface -lpcl_search -lpcl_features -lpcl_common -lode -lpcl_io


Usage

An execution file name is InteractiveObjects. Running it with an argument --help, it writes the following usage statements on the standard output. As shown above, the default window size is 320x240. I encountered the following error when running it with arguments --width 640 --height 480: The 21th-22th lines are output from the OpenNI library. I may be mistaken, but I think that the SceneAnalyzer node does not support the resolution 640x480.
Running it without any arguments (i.e. default size), it opens a viewer and begins to display frames captured by the Xtion Pro Live. Typing "m" on the keyboard under the situation where the application focuses on the viewer, a triangular mesh is constructed from a point cloud. The point cloud is calculated from the depth data in the frame at the moment when typing "m." The triangular mesh is used to create the background objects which consist of a floor, a wall, and so on. Then typing "r" brings virtual rigid bodies (balls and cylinders) into the captured scenes. The cylinders are fastened on to the floor. In the viewer, you can see that the balls collide with the cylinders, the background objects, and the other balls. Typing "o" enables an object detection, and the viewer begins to draw the collision between the detected object (human body) and the balls. To quit the application, type "q."

Brief Overview Of Source Code

I will show you different code from the previous one.

Transforming Depth into Point Cloud

In the method Device::create_cloud, a depth data captured by the Xtion Pro Live is transformed into three point clouds:
  1. a point cloud which is used to draw RGB images (cloud_)
  2. a point cloud which is used to calculate a triangular mesh which describes the background objects (background_cloud_)
  3. a point cloud which is used to calculate a triangular mesh which describes the objects detected by the SceneAnalyzer node (object_cloud_)
The 11th-13th lines and the 39th-44th lines in the code shown below are related to the SceneAnalyzer node. The point cloud object_cloud_ is captured per frame, while background_cloud_ is captured at the moment when typing "m" and it is fixed until typing "m" again.

Rigid Bodies

I use the ODE library to describe the rigid bodies. The ODE objects in the application are defined as follows: The prefix character "d" indicates the class provided by the ODE library. The object which moves based on the rigid body dynamics is represented by the dBody object. The object which requires the collision detection is represented by the dGeom object. In the application, a ball moves under the rigid body dynamics and collides with each other and other objects. Therefore, it is defined as the 5th-9th lines, where dSphere is the derived class from dGeom.
On the other hand, a cylinder is fastened on to the floor, so it does not move, but only collides with the balls. For that reason, as shown in the 18th line, I defined it as the object of the class dCylinder which is the derived class from dGeom.

Additional details (e.g. the transformation of a point cloud to a triangular mesh, registration of a mesh to the ODE, a collision detection, and so on) are seen in the previous page or my source code.

2012年10月27日土曜日

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

in English

はじめに

以前こんなアプリを作りました。今回はこれにOpenNIのSceneAnalyzerを組み合わせてみたので紹介します。

動画

こんな感じです。

開発環境

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

主要ライブラリ

  1. boost-1.51.0
  2. pcl-1.6.0
  3. OpenNI-Bin-Dev-MacOSX-v1.5.4.0
  4. ode-0.12

ソース

こちらです。自分のマシーンでしか動作確認していません。

コンパイルオプション

Header Search Path:
パス 目的
/usr/include/ni/ OpenNIヘッダー
/opt/local/include/ boost/odeヘッダー
/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ライブラリ

Other Linker Flags:
-lboost_thread-mt -lboost_filesystem-mt -lboost_unit_test_framework-mt -lboost_chrono-mt -lboost_program_options-mt -lboost_system-mt /usr/lib/libOpenNI.dylib -framework OpenGL -framework GLUT -lpcl_filters -lpcl_kdtree -lpcl_segmentation -lpcl_surface -lpcl_search -lpcl_features -lpcl_common -lode -lpcl_io


使い方

実行ファイ名は、InteractiveObjectsです。引数--helpをつけて実行すると以下を出力します。 OpenNIのSceneAnalyzerは640x480をサポートしていないようです。以下のようにSegmentation faultが発生しました。 21,22行目はOpenNIのライブラリが出力した文字列です。私の実装の仕方が悪いのかもしれません。今回は320x240で動作させます。
引数なしで実行すると、Viewerが起動しXtion Pro Liveの映像が流れます。 窓にフォーカスがある状態で、キーボードから「m」を打つと、そのときのフレーム内にあるポイントクラウドから三角メッシュを導出します。これが床や壁などを表現する背景オブジェクトとなります。 続いて「r」を打つと、環境内に剛体(ボールと円柱)が出現します。そして、ボールが背景と円柱に衝突する様子が、実時間で描画されます。剛体の投入は何度でもできます。円柱は背景に固定されています。 「o」を打つと映像内に侵入する人物と剛体の間の衝突が描画されます。 「q」を打つと終了します。

ソースの概要

以前と異なる部分だけ紹介します。

ポイントクラウドへの変換

Device::create_cloudで行います。以下3つのポイントクラウドを生成します。
  1. カラー画像描画のためのポイントクラウド(cloud_
  2. 背景の三角メッシュを算出するためのポイントクラウド(background_cloud_
  3. 人物の三角メッシュを算出するためのポイントクラウド(object_cloud_
object_cloud_を生成するため、OpenNIのSceneAnalyzerを導入しました。それに関連するコードが11行目から13行目、39行目から44行目にあります。SceneAnalyzerが捉えた物体はフレーム単位で三角メッシュに変換され、ODEに登録されます。一方、背景となる三角メッシュは「m」が押された瞬間のフレームから作られ、それ以降は固定されます。

剛体オブジェクト

前回に引き続き、剛体を記述するためにODEを使用しました。ODEオブジェクトを定義している部分を以下に示します。dで始まるクラスは全てODEが提供するクラスです。 ODEでは、剛体運動する物体をdBodyのオブジェクトで記述します。また、衝突検出を必要とする物体を、dGeomのオブジェクトで表現します。今回導入したボールは衝突しながら剛体運動を行います。上記の7、8行目がそれを表しています。ここで、dSpheredGeomの子クラスです。
一方、円柱は背景に固定しているので、ボールと衝突するだけでそれ自身は剛体運動を行いません。従って、dGeomの子クラスdCylinderで定義しました(18行目)。

その他、ポイントクラウドから三角メッシュへの変換、三角メッシュのODEへの登録、衝突の検出などは以前のページ、あるいはソースをご覧ください。

2012年10月12日金曜日

OpenNI Application "Bouncing Ball2"

in Japanese

Introduction

In the previous page, I implemented an application with the use of the OpenNI library. The application includes the simple simulation by the Newtonian dynamics. Recently, I have replaced the simulation with the Open Dynamics Engine(ODE). In this page, I give you an explanation on the new application. (Here is my first introduction to the ODE.)

Demo

I start with a demo movie.
Unfortunately, the image quality has degraded after uploading to this blog.

Development Environment

  1. Mac OS X 10.8.2
  2. Processor:3.06 GHz Intel Core 2 Duo
  3. Memory:4GB
  4. Xcode4.5.1

Primary Libraries

  1. boost-1.51.0
  2. pcl-1.6.0
  3. OpenNI-Bin-Dev-MacOSX-v1.5.4.0
  4. ode-0.12

My Source Code

Here is my source code. I do not confirm the behavior of the application on other environments.

Compile Options

Header Search Path:
Path Purpose
/usr/include/ni/ to include the OpenNI headers
/opt/local/include/ to include the Boost and ODE headers
/usr/local/include/pcl-1.6/ to include the PCL headers
/opt/local/include/eigen3/ to include the Eigen header on which the PCL depends
/opt/local/include/vtk-5.10/ to include the VTK headers on which the PCL depends

Library Search Path:
Path Purpose
/opt/local/lib to link the Boost libraries
/usr/local/lib to link with the PCL libraries

Other Linker Flags:
-lboost_thread-mt -lboost_filesystem-mt -lboost_unit_test_framework-mt -lboost_chrono-mt -lboost_program_options-mt -lboost_system-mt /usr/lib/libOpenNI.dylib -framework OpenGL -framework GLUT -lpcl_filters -lpcl_kdtree -lpcl_segmentation -lpcl_surface -lpcl_search -lpcl_features -lpcl_common -lode -lpcl_io


Usage

An execution file name is BouncingBallWithOde. Running it with an argument --help, it writes the following usage statements on the standard output. Running it without any arguments, it opens a viewer and begins to display frames captured by the Xtion Pro Live. Typing "m" on the keyboard under the situation where the application focuses on the viewer, a triangular mesh is constructed from a point cloud. The point cloud is calculated from the depth data in the frame at the moment when typing "m". Typing "b" generates virtual balls in the captured scenes, and the interactions between the balls and the objects in the environment are drawn in real time. You can generate balls as many times as needed. Though an error occurs in the 29th line, no major disruptions are observed. To quit the application, type "q."

Brief Overview of Source code

View Point of OpenGL

The view point of the OpenGL is as follow: A unit of length in the application is mm. You might need some changes to the arguments in the 6th line according to the environment captured by your depth sensor.

Transforming Depth into Point Cloud

A depth data is transformed into a point cloud in the method Device::create_cloud. In this application, two point clouds are generated, one (cloud_) is for displaying the color frames and another (cloud_xyz_) is for calculating a triangular mesh. RGB values are set in the 25,26th lines. The depth data is transformed into the point cloud in the 29th-30th lines. The point cloud used to calculate the triangular mesh is generated in the 33th line.

Drawing Color Image

The point cloud cloud_ is passed to the method Viewer::display_point_cloud as follows: The arguments buf and size indicate the pointer to the head address of cloud_ and the size of cloud_, respectively.

Calculation of Triangular Mesh

In the method Device::convert_to_polyton_mesh, the triangular mesh is constructed from the point cloud cloud_xyz_ by the use of the PCL library. (Here is my first introduction to the PCL library.) You might need to change parameters in the 27th-36th lines according to your environment.

Making Balls

A ball treated in the application is an ODE object. It consists of a dBody object and a dGeom one. The former manages the rigid body dynamics and the latter manages the collision detection. dSphere is the derived class from the base class dGeom. In the method PhysicalSimulator::create_balls(), balls are registered to the ODE framework. world_ in the 20th line and space_ in the 41th line are the dWorld and the dSpace objects, respectively. In the ODE framework, the object which moves based on the rigid body dynamics has to be registered to the dWorld object. The object which collides with other objects has to be registered to the dSpace object.

Registration of Triangular Mesh

The triangular mesh is registered to the ODE framework in the method PhysicalSimulator::register_triangular_mesh. triangular_mesh_ is the dGeomID object.

Collision Detection

The ODE library supports the method dCollide which handles the collision detection. The collision detection is carried out per frame. In the loop, the various properties are set to the collision points. The variable bounce in the 14th line corresponds to the reflection coefficient.

2012年10月8日月曜日

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

in English

はじめに

以前こんなアプリを作りました。このアプリのシミュレーション部分をOpen Dynamics Engine(ODE)に置き換えてみたので紹介します。

動画

こんな感じ(アップロードしたら画質が悪くなった)。

開発環境

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

主要ライブラリ

  1. boost-1.51.0
  2. pcl-1.6.0
  3. OpenNI-Bin-Dev-MacOSX-v1.5.4.0
  4. ode-0.12

ソース

こちらです。自分のマシーンでしか動作確認していません。

コンパイルオプション

Header Search Path:
パス 目的
/usr/include/ni/ OpenNIヘッダー
/opt/local/include/ boost/odeヘッダー
/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ライブラリ

Other Linker Flags:
-lboost_thread-mt -lboost_filesystem-mt -lboost_unit_test_framework-mt -lboost_chrono-mt -lboost_program_options-mt -lboost_system-mt /usr/lib/libOpenNI.dylib -framework OpenGL -framework GLUT -lpcl_filters -lpcl_kdtree -lpcl_segmentation -lpcl_surface -lpcl_search -lpcl_features -lpcl_common -lode -lpcl_io


使い方

実行ファイ名は、BouncingBallWithOdeです。引数--helpをつけて実行すると以下を出力します。 引数なしで実行すると、Viewerが起動しXtion Pro Liveの映像が映し出されます。 窓にフォーカスがある状態で、キーボードから「m」を打つと、その瞬間のポイントクラウドから三角メッシュを導出する計算が始まります。 19、20行目に警告が出ていますが大丈夫です。【追記:下記に示した関数gp.setMaximumNearestNeighborsの引数を10から100にしたところ、警告はなくなりました。】続いて「b」を打つと、環境内にボールが投入されます。ボールと背景との相互作用がリアルタイムで描画されます。ボールの投入は何度でもできます。 33行目にエラーが出ていますが大丈夫です。「q」を打つと終了します。

ソースの概要

OpenGLの視点

以下のように設定しています。本アプリの長さの単位は全てmmです。 6行目の引数は使用する環境に合わせる必要があります。

ポイントクラウドへの変換

Device::create_cloudで行います。カラー画像描画のためのポイントクラウド(cloud_)と三角メッシュ算出用のポイントクラウド(cloud_xyz_)の2種類を生成しています。 25,26行目でRGB値を設定しています。29,30行目でデプスから3次元座標への変換を行っています。33行目で三角メッシュ用のポイントクラウドを取得しています。

カラー画像の描画

カラー画像用のポイントクラウド(cloud_)は、OpenGLのglInterleavedArraysに以下(5行目)のように渡されます。bufcloud_の先頭ポインタ、sizecloud_のサイズです。

三角メッシュの計算

三角メッシュ用のポイントクラウド(cloud_xyz_)はDevice::convert_to_polyton_meshで処理されます。 PCLライブラリを使用しています。27から36行目にかけてのパラメータは環境に合わせる必要があるかもしれません。 【追記:上記に示した関数gp.setMaximumNearestNeighborsの引数を10から100にしたところ、警告はなくなりました。】

ボールの投入

ボールはODEのオブジェクトです。これは、剛体力学の計算に関与するdBodyと衝突計算に関与するdGeomから構成されます。 dSpheredGeomの子クラスです。 そして、ボールはPhysicalSimulator::create_balls()で環境内に投入されます。 20行目のworld_dWorldのオブジェクトです。41行目のspace_dSpaceのオブジェクトです。ODEでは、剛体力学の計算を必要とするオブジェクトはdWorldに、衝突計算を行うオブジェクトはdSpaceに登録しなければなりません。

三角メッシュの登録

先に計算した三角メッシュは、PhysicalSimulator::register_triangular_mesh内でODEに登録されます。 triangular_mesh_dGeomIDのオブジェクトです。

衝突の検出

毎フレーブごとに、ODEにより衝突検出が行われます。 3行目のdCollideが衝突を検出するODEの関数です。ループ内では衝突点の属性を設定します。14行目のbounceは反発係数に相当します。

2012年8月25日土曜日

OpenNI MultiViewer

Introduction

Recently, I bought a second Xtion Pro Live. In this page I describe a multi-viewer which captures images simultaneously from two devices. The viewer derives a 3D point cloud from a depth image, and displays it with corresponding colors obtained from an RGB image using the OpenGL.

Development Environment

  1. iMac
  2. Mac OS X 10.8.1
  3. Processor:3.06GHz Intel Core 2 Duo
  4. Memory:4GB
  5. Xcode4.4.1

Primary Libraries

  1. Boost
  2. OpenNI
  3. OpenGL

Source Code

Here is my source code. I confirmed that it works well on my machine.

Compile Options

Header Search Path:
Path Purpose
/usr/include/ni/ to include the OpenNI headers
/opt/local/include/ to include the Boost headers

Library Search Path:
Path Purpose
/opt/local/lib to link with the Boost libraries

To use the OpenGL, I also set "-framework OpenGL" and "-framework GLUT." More detailed information is in my source code.

Usage

An executable file name is "OpenNiMultiViewer." Running it with an argument --help, it prints the following statements. After connecting two devices with the computer, running it without any arguments, it opens two viewers for images captured by devices. To quit the application, type an escape key under the situation where the application focuses on viewers.

Addition

  1. To change the number of devices, you have to extend my code.
  2. My application paints white color in the region where the device is unable to take the depth.
  3. The Xtion Pro Live uses infrared ray to take the depth. If there is more than one device, the number of regions where the devices are unable to take the depth increases because of interference between infrared rays.

OpenNIのMultiViewer

はじめに

Xtion Pro Liveの2台目を購入しました。2台同時に描画できるMutiViewerを実装したので紹介します。デプス画像から3次元点群を導出し、各点にRGB画像から取得した色を付けて描画します。

開発環境

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

主要ライブラリ

  1. Boost
  2. OpenNI
  3. OpenGL

ソース

こちらです。自分のマシーンでしか動作確認してません。

コンパイルオプション

Header Search Path:
パス 目的
/usr/include/ni/ OpenNIヘッダー
/opt/local/include/ Boostヘッダー

Library Search Path:
パス 目的
/opt/local/lib Boostライブラリ

その他、OpenGLを使用するため、-framework OpenGLなどを設定しています。詳細はソースをご覧ください。

使い方

実行ファイ名は、OpenNiMultiViewerです。引数--helpを付けて実行すると以下を出力します。 Xtion Pro Liveを2台接続し引数なしで実行すると、窓が2つ開き映像が映し出されます。--width/--heightの値はデフォルト値でしか動作確認していません。 窓にフォーカスがある状態で、キーボードから「ecs」を打つと終了します。

補足

  1. Xtion Pro Liveの台数を可変にするには手直しが必要です。
  2. 深さを取得できない領域は白抜きになります。
  3. Xtion Pro Liveは赤外線を使用します。2台以上あるとお互いの赤外線が干渉するため、深さを取得できない領域が多くなります。

2012年8月5日日曜日

OpenNI Application "Bouncing Ball"

Introduction

I implemented an application which
  1. generates a point cloud from a depth data captured by the Xtion Pro Live,
  2. calculates a normal vector for each point in the point cloud using the Point Cloud Library(PCL),
  3. introduces virtual balls into an environment on the viewer,
  4. and simulates collisions between the balls and the objects in the environment.
The application does not retrieve normal vectors from each frame, but from a certain frame just one time. The simulation is executed in real time under those normal vectors. I used the OpenGL library to draw frames.

Development Environment

  1. Mac OS X 10.7.4
  2. Processor:3.06 GHz Intel Core 2 Duo
  3. Memory:4GB
  4. Xcode4.3.3

Primary Libraries

  1. Boost-1.50.0
  2. PCL-1.6.0
  3. OpenNI-Bin-Dev-MacOSX-v1.5.4.0
  4. Sensor-Bin-MacOSX-v5.1.2.1

Source Codes

Here is my source codes. I confirmed that the application works well on my machine.

Compile Options

Header Search Path:
Path Purpose
/usr/include/ni/ to include the OpenNI headers
/opt/local/include/ to include the Boost headers
/usr/local/include/pcl-1.6/ to include the PCL headers
/opt/local/include/eigen3/ to include the Eigen headers on which the PCL depends
/opt/local/include/vtk-5.10/ to include the VTK headers on which the PCL depends

Library Search Path:
Path Purpose
/opt/local/lib to link with the Boost libraries
/usr/local/lib to link with the PCL libraries

In addition, to use the OpenGL, I set "-framework OpenGL." More detailed information is in my source codes.

Usage

The executable file name is OpenNiViewer. Running it without any arguments, it prints the following statements. Running it with setting the path to a file "SamplesConfig.xml" to --config, it opens a viewer for a video captured by the Xtion Pro Live. The file "SamplesConfig.xml" is enclosed in my source codes. I don't verify the behavior of the application with values other than default ones for --width and --height. Typing "p" on the keyboard under the situation where the application focuses on the viewer, the derivation of normal vectors begins. After seeing "Normals has been extracted" on the standard output, typing "i" yields virtual balls in the captured scenes, and the interactions between the balls and the objects in the environment are drawn in real time. To quit the application, type the escape key.

Brief Overview of Source Codes

View Point of OpenGL

The view point of the OpenGL is as follows: A unit of length in the application is mm. You need to change the argument in the 8th line according to your environment.

Transforming Depth into Point Cloud

A depth data is transformed into a point cloud in the method OpenNiDevice::create_cloud. I generate two point clouds, one (cloud_) is for displaying the color video and another (cloud_xyz_) is for calculating normal vectors. RGB values are set in the 26th, 27th, and 28th lines. The depth data is transformed into the point cloud in the 33th line. The point cloud for calculating normal vectors is created in the 34th line.

Drawing Color Image

The point cloud used for the color video, cloud_, is passed to the OpenGL method glInterleavedArrays as

Derivation of Normal Vectors

The cloud used for deriving normal vectors (cloud_xyz_) is processed in the method OpenNiDevice::calculate_normals. The method initialize in the 6th line is as follows: The region of the local nearest search is set in the 9th line. This argument varies depending on your environment. The plane is calculated using points inside the region. The normal vector of the plane is what we want. The normal vectors is derived with each typing "p" on the keyboard. If you change position of the Xtion Pro Live, you have to type "p" again.

Configuration of Balls

The virtual balls is registered in the method OpenNiViewer::register_balls. The radius of the ball is set in the 25th line. The initial position, the initial velocity, and the acceleration are set in the 31th, 32th, and 33th lines, respectively. These values also vary depending on your environment.

Configuration of Walls

A wall is placed at the front of the viewer to avoid the balls disappearing from view.

Search of Normal Vectors

For each frame, the normal vectors located adjacent to the balls are detected by means of the kd-tree. kdtree_ in the 8th line is the object of the class pcl::KdTreeFLANN<pcl::PointXYZ>. Because the object returns nan if it fails to detect neighbors, the returned value is checked in the 12th line.

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