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

2013年1月30日水曜日

Xtion and OpenNI2 on Mac OSX

農作業の合間に、RDCS (多数の自律型ロボットを人の作業と組み合わせて運用/開発する統合環境)のOpenNI2対応を進めています。結構、工数かかります。
Raspberry Piの検証は、終わったので、画像処理や、空間認識サービスを提供しているMac (OSX 10.8.2)での検証をしました。

インストールは、至って簡単! 10分でできました。
OpenNI2のOSX版を
   ・ダウンロード  Here click!
   ・解凍し、解凍してできたディレクトリーに移動する。
   ・install.sh 実行
   ・環境変数の設定 (OPENNI2_REDIST,  OPENNI2_INCLUDE)
    install.sh 実行後にOpenNIDevEnvironmentファイルが生成される。
    その中の情報をそのまま使う。
   ・Samples/SimpleViewerに移動する。makeでビルド
   ・Bin に移動して、実行(下の画面)

開発環境としても、問題ありません。ダウンロード、確認まで10分ほど
ただし、OpenGL(freeglut), libusbは、事前にインストール必要です。Mac は既に、OpenGLが入っているので関係ないですね。
これからは、OPenNIを使っているserviceを、ガリガリとプログラム改修。

Raspberry Piの場合は、インストールパッケージの作成しなければなりません。
パッケージのbuildで、20から30分時間が必要なので、あまりにもすんなりに稼動確認ができたので、ビックリです。

お決まりの depth 画像
このデータを扱うと、すごく面白い事できます。
最近、飛んでいないラジコン飛行機が可哀想。
ラジコン飛行機は、空に絵を書く道具です。本当に、気持ちいいですよ!
でも、問題は、飛ばす所が減ってきた事。僕はなんとか確保していますが、、、
Raspberry Piの OpenNI2 で、Kinect を動かす事は、なんとか少しずつ進んでいます。
depthは取れます。僕は、depthが取れれば十分です。

ちなみに、Carmine1.90を発注してしまった。この円安の時に、、、 (-_-)

peace!

2013年1月28日月曜日

Xtion Pro and OpenNI2 on Raspberry Pi

OpenNI2のversion up が去年の12月にありました。
暫く移行を躊躇していました。しかし、そろそろ考えないとならないので検証しました。
Raspberry PiへのOpenNI2のインストール方法は、---> Here click!

      Xtion Pro-->  Raspberry Pi  > Arch Linux  >  OpenNI2  >  LXDE  >  AP

本日テストをして、その結果から、OpenNI2に移行する事に決めました。
写真は、Color stream と Depth steam テストのsnap shotです。
上のDepth画像と、下のVideo画像は、対象は違います。
Depth Stream  (snap shot)
Video Stream (snap shot)
LXDE上で、それぞれOpenCVを使ってストリームを表示しましたが、スムーズに表示できました。十分使える範囲だと思います。
これで、懸案の、OpenNI2への移行もなんとかなりそうです。
ただし、コンパイル&リンクの時間は、以前より長いかもしれません。

このような検証をする為に、LXDEの環境も作ってありますが、やはり使っているとフラストレーションが溜ります。
今回も、実行モジュールができるまでは、MacからSSH接続をして、画面表示の状態を確認するときだけLXDEで画面を見ます。

PCLの入力システムとしてのRaspberry Pi + Xtionは、なかなかの組合せです。
ただし、NITEは、考えてはなりませぬ。

今回のOpenNI2も、Kinectを公式にはサポートできない。
だんだんと、Raspberry PiでKinectを使う事が難しくなってきた。

いよいよ、Kinect 2台は、農場の監視カメラか。。。。。

peace!

2013年1月16日水曜日

An Installation of OpenNI2 on Raspberry Pi. To use a Xtion.


An Installation of OpenNI2.2 on Raspberry Pi ---> Please see a new post.


New Release OpenNI2 (2.1.0.4 branch:develop)
I've built new OpenNI2 driver and modules as following.
This installation time is an hour.

a Xion, a Webcam, and a Webcam on the Raspberry Pi

(1) Buliding Prerequisites
[root@rcmp-r03 ~]# pacman -Syu
[root@rcmp-r03 ~]# pacman -S gcc
[root@rcmp-r03 ~]# pacman -S make cmake pkg-config
[root@rcmp-r03 ~]# pacman -S libusb
[root@rcmp-r03 ~]# pacman -S python2
[root@rcmp-r03 ~]# pacman -S freeglut
[root@rcmp-r03 ~]# pacman -S doxygen
[root@rcmp-r03 ~]# pacman -S graphviz
or
pacman -S gcc make cmake pkg-config 
pacman -S libusb python2 freeglut doxygen graphviz 

(2) Download  & uncompress OpenNI2 source. (branch:develop 2.1.0.4)
(26 Jan, 2013 : Both the 'master' and 'develop' were up-to-date.
It's necessary to confirm the version of  branches.) 
Please download a source zip file form Here.
  Download > OpenNI 2.0 source code is available on GitHub > branch develop
Assuming an installation directory "~/OpenNI2-develop".

(3) Set  compiler options for the ARM1176JZF-S
ARM compiler option web-site. HERE 

[root@rcmp-r03 ~]# cd OpenNI2-develop/ThirdParty/PSCommon/BuildSystem
[root@rcmp-r03 BuildSystem]# vi Platform.Arm
[root@rcmp-r03 BuildSystem]# cat Platform.Arm

ifeq "$(CFG)" "Release"
    # Hardware specifying flags
    #CFLAGS += -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp #-mcpu=cortex-a8
  CFLAGS += -mtune=arm1176jzf-s -mfloat-abi=hard
    # Optimization level, minus currently buggy optimizing methods (which break bit-exact)
    #CFLAGS += -O3 -fno-tree-pre -fno-strict-aliasing
    # More optimization flags
   # CFLAGS += -ftree-vectorize -ffast-math -funsafe-math-optimizations -fsingle-precision-constant
endif

(4) Build
[root@rcmp-r03 OpenNI2-BuildSystem]# cd ../../..
[root@rcmp-r03 OpenNI2-develop]# make                             20-30 minites

(5) Packaging 
[root@rcmp-r03 OpenNI2-develop]# cd Redist
[root@rcmp-r03 Redist]# vi Redist.py
Line : 534
before
compilation_cmd = "make -j" + calc_jobs_number() + " CFG=" + configuration + " PLATFORM=" + platform + " > " + outfile + " 2>&1"
        if compilationMode == 'Rebuild':
after
compilation_cmd = "make -j1" + " CFG=" + configuration + " PLATFORM=" + platform + " > " + outfile + " 2>&1"
        if compilationMode == 'Rebuild':

[root@rcmp-r03 Redist]# ln -s /usr/bin/python2 /usr/bin/python
[root@rcmp-r03 Redist]# python ReleaseVersion.py arm      3 -5 minites
[root@rcmp-r03 Redist]# cd Final
[root@rcmp-r03 Final]# ls
OpenNI-Linux-Arm-2.1.0.tar.bz2

(6) Installation
[root@rcmp-r03 Final]# tar -jxvf OpenNI-Linux-Arm-2.1.0.tar.bz2
[root@rcmp-r03 Final]# cd OpenNI-2.1.0-arm
[root@rcmp-r03 Final]# sh install.sh


(7) Environment variable

[root@rcmp-r03 Final]# export OPENNI_DIR=/root/OpenNI2-develop
[root@rcmp-r03 Final]# export OPENNI2_INCLUDE=$OPENNI_DIR/Include
[root@rcmp-r03 Final]# export OPENNI2_REDIST=$OPENNI_DIR/Redist


(8) Testing
[root@rcmp-r03 Final]# cd Samples/Bin
[root@rcmp-r03 Bin]# SimpleRead
[00000000]        0
[00033369]        0
[00066738]        0
[00100107]        0
[00133477]        0
[00166846]        0
[00200215]        0
[00233584]        0
[00266954]        0
[00300323]        0
[00333692]        0

Success!

peace!

2012年10月3日水曜日

Performance testing Xtion on Raspberry Pi
Using a capturing server

Raspberry Pi is a good machine. But it don't have a capacity for 3D processing.  For this test, I use a Raspberry Pi as a capturing service (server).  And MacMini is 3D Processing service and viewing.
My test environment diagram is below.

Raspberry Piは、3D処理をするには性能がたりません。従って、Xtionを使ったcaputuring setverとして使い、空間認識などの処理をMacminiで処理します。そのテストをしました。
テストは、RDCS環境を使いまいた。RDCSは、分散コンピューティングをベースにしたロボットプラットフォームです。その機能を使ってテストをしました。
Micminiでpoint cloud処理をしています。さすがに瞬間的な処理です。


 Capturing Service        3D recognizing service
   Xtion
    Raspberry Pi                Mac MIni
----------------------------------------------------  Coordinator Layer
---------------------------------------------------- (Service Control)
             |                                |
----------------------------------------------------      Cooperative Layer
---------------------------------------------------- (Communication Control)

A performance testing was executed on RDCS.

RDCS is a robot platform based on a distributed computing model.
A lots of robot function (hardware, software) is connected by  "Cooperative Control" and "Coordinator".
"Cooperative Control" is a network communication control.  The control  connects computer , actuator, sensor and other robot device.
"Coordinator" offers robot required software. "Coordinator" integrates a lot robot software on RDCS.

This test flow is :

(1) 3D recognized service requests a data set ( image and depth ) to Capturing service.
(2) Capturing service on Raspberry Pi execute to capture image and depth.
(3) 3D recognized service receive a couple of capturing data.
(4) 3D processing and viewing

RESULT (sec)
(1)      0-1
(2)     8-10 (include the time which is Xtion initialize and terminate)
                   A Capture time is 1-2 sec.
(3)      0-1
(4)      0-1


This result means that a single robot don't have all function in it.
Therefore, it's able to develop a lightweight and low cost robot.
There are a lot of kinds wrok in farm. And my farm is large. Thus I need  a lot of robot. To do that,  I have to develop a low cost and multi-function robot.
My robots are structured by base robot and add-in function in order to realize a multi-function of robot.
And these robots have to been set up by commercialized product and builded  by component-based.

Now I'm developing a core component of robot  using 2 or 3 Raspberry Pi.
A core component of robot is structured by  6 components which are robot platform(RDCS), space recognition, obstacle detection, moving, fail-safe and recovery.
An effectivity of RDCS which I have developed was  confirmed by this testing.


この結果は、1台のロボットに全ての機能を集約しなくても良い事を示しています。
従って、軽量なかつ低価格のロボットを作る事ができます。
ロボットプラットフォーム、障害物検知、通信、移動、フェイルセーフと回復機能を持ったシンプルなロボットを、Raspberry Piを2、3個使って作れば良いと思います。その上に、アクチュエータなどのロボットのパーツを載せればよのではないでしょうか?
私の開発している、RDCSのアーキテクチャーの有効性を確認できました。




                                                     3D point cloud

Peace!

2012年9月28日金曜日

Performance testing Xtion on Raspberry Pi
Capturing RGB

Yesterday, I had done a performance testing.
A test program attached this post.
It's a processing time  from capturing  a  RBG data via OpenNI -Xtion  to writing a formated data.

A test path is below.
Xtion -> OpenNI (RGB, Depth) -> OpenCV (conversion format, writing) -> SD-card

(1)Capturer : 640x480, RGB24
(2)Pieces of writing format type are bmp, dib, jpd, jp2, png, pbm, pgm, ppm, ras, and tiff.

RESULT
(1) It's take 15-20 sec from capturing to writing SD-card.
        processing             time (sec)
     Initialize OpenNI            : 4 - 5
     Capture depth & RBG  : 0 - 1
     Merge                           : 3 - 4
     Convert & save            : 4 - 5
     Terminate                     : 4 - 5
     ( Processing time on MacMini (i5 2.5GHz 8G) is 2sec. )
   
(2) Processing time depends data format a little.
     Jpeg format is faster than png, 2-3 seconds.
(3) There aren't a difference  of processing time between clock speed 700MHz and 800MHz.

Next performance testing is a following process.
Capture (Raspberry Pi) ---  depth & RGB  (UDP) --> Receive (other machine).
This test use a function of Cooperative control of RDCS.

Peace!

/*****************************************************************************************
        Sample snapshot & save  program   (No Warranty)
******************************************************************************************/
OpenNI  1.5.4
Sensor  5.1.2.1
OpenCV 2.4
Xtion Pro Live

(1) Raspberry Pi  800MHz and 700MHz
Arch Linux arm 3.2.27-8-ARCH+
gcc (GCC) 4.7.1 20120721
It need a compiler option "-mcpu=arm1176jzf-s".

(2) Macmini
Darwin Kernel Version 12.2.0
llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658)

(3) Windows
No test.

//---------------------------------------------------------------------------
// Includes
//---------------------------------------------------------------------------
#include <XnOS.h>
#include <opencv2/opencv.hpp>
#include <XnCppWrapper.h>
#include <fstream>
#include <iostream>
#include <string>
#include <cstring>

#include <stdio.h>
//#include <stdlib.h>
#include <time.h>
#include <math.h>

using namespace std;
using namespace xn;
using namespace cv;
//---------------------------------------------------------------------------
// Defines
//---------------------------------------------------------------------------
#define SAMPLE_XML_PATH "../../Config/SamplesConfig.xml"

//#define PR1(A)
//#define PR2(A, B)
#define PR1(A) std::cout << A << endl;
#define PR2(A, B) std::cout << A << ":" << B << endl;
#define ER1(A) std::cout << A << endl;
#define ER2(A, B) std::cout << A << ":" << B << endl;

//---------------------------------------------------------------------------
// Globals
//---------------------------------------------------------------------------
XnStatus nRetVal = XN_STATUS_OK;

float* g_pDepthHist;
XnRGB24Pixel* g_pTexMap = NULL;
unsigned int g_nTexMapX = 0;
unsigned int g_nTexMapY = 0;
XnDepthPixel g_nZRes;

Context g_context;
xn::ScriptNode g_scriptNode;
xn::DepthGenerator g_depth;
xn::ImageGenerator g_image;
xn::DepthMetaData g_depthMD;
xn::ImageMetaData g_imageMD;


cv::Mat colorArr[3];
cv::Mat colorImage;

const XnRGB24Pixel* pImageRow;
const XnRGB24Pixel* pPixel;

void printTime(const char *msg) ;

//---------------------------------------------------------------------------
// Code
//---------------------------------------------------------------------------

/************************************************************************
*** Callback glutIdle
*************************************************************************/
void printTime(const char *msg) {
time_t timer;
struct tm *date;
char str[256];

timer = time(NULL);
date = localtime(&timer);
PR2(msg, asctime(date));
}
/************************************************************************
*** main
*************************************************************************/

int main(int argc, char* argv[])
{
XnStatus rc;
EnumerationErrors errors;
IplImage bgrIpl;
cv::Mat bgrImage;
int i, iFrame, iClean;
int iCnt = 0;

char framenumber[10];
std::stringstream ss;
std::string str_frame_number;



// -------------------------------------------------------------------------
// check argument.
// -------------------------------------------------------------------------
if (argc != 4) {
PR1("argument error. output file, format (jpg, png), count.");
return 1;
}
iFrame = atoi(argv[3]);
if (iFrame < 1 || iFrame > 100) {
ER1("frame 1-100.");
return 1;
}
if (!(strcmp(argv[2], "bmp") == 0 ||
strcmp(argv[2], "dib") == 0 ||
strcmp(argv[2], "jpg") == 0 ||
strcmp(argv[2], "jp2") == 0 ||
strcmp(argv[2], "png") == 0 ||
strcmp(argv[2], "pbm") == 0 ||
strcmp(argv[2], "pgm") == 0 ||
strcmp(argv[2], "ppm") == 0 ||
strcmp(argv[2], "ras") == 0 ||
strcmp(argv[2], "tiff") == 0
)) {
ER1("format error.");
return 1;
}

// -------------------------------------------------------------------------
// set up OpenNI camera.
// -------------------------------------------------------------------------
// read a device configuration file and initialyze
rc = g_context.InitFromXmlFile(SAMPLE_XML_PATH, g_scriptNode, &errors);
if (rc == XN_STATUS_NO_NODE_PRESENT){
XnChar strError[1024];
errors.ToString(strError, 1024);
ER1(strError);
return (rc);
}else if (rc != XN_STATUS_OK){
ER2("Open failed ", xnGetStatusString(rc));
return (rc);
}

// Searches for an existing created node of a specified type and returns a reference to it.
rc = g_context.FindExistingNode(XN_NODE_TYPE_DEPTH, g_depth);
if (rc != XN_STATUS_OK){
ER1("No depth node exists! Check your XML.");
return 1;
}

// Searches for an existing created node of a specified type and returns a reference to it.
rc = g_context.FindExistingNode(XN_NODE_TYPE_IMAGE, g_image);
if (rc != XN_STATUS_OK){
ER1("No image node exists! Check your XML.");
return 1;
}

PR1("first genelation*******************");
g_depth.GetMetaData(g_depthMD);
g_image.GetMetaData(g_imageMD);
PR1("***********************************");

// Hybrid mode isn't supported in this sample
if (g_imageMD.FullXRes() != g_depthMD.FullXRes() || g_imageMD.FullYRes() != g_depthMD.FullYRes()){
ER1 ("The device depth and image resolution must be equal!");
return 1;
}

// RGB is the only image format supported.
if (g_imageMD.PixelFormat() != XN_PIXEL_FORMAT_RGB24){
ER1("The device image format must be RGB24");
return 1;
}

// Texture map init
g_nTexMapX = (((unsigned short)(g_depthMD.FullXRes()-1) / 512) + 1) * 512;
g_nTexMapY = (((unsigned short)(g_depthMD.FullYRes()-1) / 512) + 1) * 512;
g_pTexMap = (XnRGB24Pixel*)malloc(g_nTexMapX * g_nTexMapY * sizeof(XnRGB24Pixel));

g_nZRes = g_depthMD.ZRes();
g_pDepthHist = (float*)malloc(g_nZRes * sizeof(float));

rc = g_context.WaitAnyUpdateAll();
if (rc != XN_STATUS_OK){
ER2("Read failed ", xnGetStatusString(rc));
return 1;
}
// -------------------------------------------------------------------------
// main routine.
// -------------------------------------------------------------------------

for (i = 0; i < iFrame; i++) {
printTime("start generation");
g_depth.GetMetaData(g_depthMD);
g_image.GetMetaData(g_imageMD);
printTime("end generation");
}

printTime("start output");
g_depth.GetAlternativeViewPointCap().SetViewPoint(g_image);
pImageRow = g_imageMD.RGB24Data();

colorArr[0] = cv::Mat(g_imageMD.YRes(), g_imageMD.XRes(),CV_8U);
colorArr[1] = cv::Mat(g_imageMD.YRes(), g_imageMD.XRes(),CV_8U);
colorArr[2] = cv::Mat(g_imageMD.YRes(), g_imageMD.XRes(),CV_8U);

printTime("create new matrix");
PR2("g_imageMD.YRes", g_imageMD.YRes());
for (int y = 0; y < g_imageMD.YRes(); y++){
pPixel = pImageRow;
uchar* Bptr = colorArr[0].ptr<uchar>(y);
uchar* Gptr = colorArr[1].ptr<uchar>(y);
uchar* Rptr = colorArr[2].ptr<uchar>(y);
for(int x=0; x < g_imageMD.XRes() ;++x , ++pPixel){
Bptr[x] = pPixel->nBlue;
Gptr[x] = pPixel->nGreen;
Rptr[x] = pPixel->nRed;
}
pImageRow += g_imageMD.XRes();
}
printTime("start merge");
cv::merge(colorArr, 3, colorImage);

printTime("start save");
sprintf(framenumber,"%s.%s",argv[1], argv[2]);
ss << framenumber;
ss >> str_frame_number;
std::string str_aux = str_frame_number;
bgrIpl = colorImage;
cvSaveImage(str_aux.c_str(), &bgrIpl);
printTime("end output");
//g_context.Shutdown();

return 0;
}