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;
}

2012年9月24日月曜日

Xtion vs Kinect, which is the best Robot EYE


The purpose of introducing robots into farming is to improve productivity through reducing labor and other cost. My robots have  to work without the help of farmers.
Therefore my robots must have  self-control feature. I think the most important technology to acquire self-control is to recognize the space. This technology is base on  space 3D scanning and 3D recognition.
To develop the technology, I did a lot of experiments with  Xtion and Kinect. I decided to adopt Xtion from the results of the experiment.
(1) small and light
(2) bus power
(3) near mode
(4) cross platform (Arch Linux, Ubuntu, OSX, WindowsXp)
(5) cooperative with OpenCV and PCL
(6) commercial use free

私は、実際に業務で使えるロボットを開発したと考えています。
それは、人件費の削減を通じた生産性の向上をはたすものでなければなりません。
そのようなロボットを実現ためには、空間認識が最も重要な技術であると考えています。その為に、3Dスキャナーとして、XtionとKinectを実験してきましたが、ロボットに適しているのは、Xtionという結果を得ました。

Xtion and Kinect


2012年9月23日日曜日

Xtion on Raspberry Pi


Today, I  checked the performance of the parallel processing combined getting depth data from Xtion , moving 8 servos and getting 4 sensor's data on Raspberry PI.
I confirmed that it is necessary to adjust the performance.
To run  getting  depth data from Xtion  on another Raspberry Pi,  might be better.
It's easy to add a cpu like Raspberry Pi on my robot system. My robot system was designed as a distributed computing model.


Xtionからdepthデータを取得しながら、同時にサーボや、センサーを動かした。負荷が高まり、Xtionのデータ取りこぼしが発生した。やはり、複数台のRaspberry Piを使った方がよい。予想された事だけど、、、
下は、対応策の案。でも、私のシステムは問題なくCPUを増やせます。

improvement ideas
                              Cooperative Control      Xtion      Servo       Sensor
                                         (RDPS)
Raspberry Pi-A                 master                   -            x               x

Raspberry Pi-B                 agent                     x            -                -


Printer server (MZK-SP300N2) (?_?)

私が、開発に使っているのは、Mac Mini (2.5GHz i5, 8GB, OSX & WIndows7 64bit)と、Dell mini9 (atom N270, Ubuntu & Windows XP)です。その他にも、VAIOなどがあります。
今まで、特に印刷する事をしなかったのですが、やはりいろいろ複雑になってきたので、確認の為に、出力が必要になってきました。たまたま、家族がプリンターサーバー MZK-300N2経由でCANON IP4500を使っていたので、Macからもつなげる事にしました。
しかし、いつもの通り、一発ではつながりませんでした。Windowsの場合には、設定ソフトをインストールするとすぐに繋がります。
無線LAN接続ですから、まずDHCPサーバでアドレスを確認すると、自動でIPアドレスが割当てられています。そのアドレスにpingアクセスすると、アクセスできない。
マニュアルを見ると、DHPCに確認後xxx.xxx.xxx.252になると書いてある。しかし、ルータ側にアクセスしてクライアントモニターを見ると、末尾が252のクライアントない。
試しに、pingでxxx.xxx.xxx.252にアクセスするとok!. ?????????って感じ
webで、アクセスすると設定画面が出てくる。
ここで原因を追求すると、はまるので次のステップ。
Mac > システム環境設定 > プリントとスキャン > プリンターの追加
IPを選択して、アドレス、LPD, ドライバを選択。
出来たプリンターでテストプリント。
「でない!」、もう一度、xxx.xxx.xxx.252にアクセスして画面から再起動を選択。
暫くして、テストプリント。okでした。
覚え込ませないと、うごかないのかぁ?

なんで、DHCPサーバで割当てたIPでは、だめ???
マニュアルには、割当てられたIPで、okと書いてある。
なんで、再起動して覚え込ませる?
そんな事は、無いだろう?

これ以上は、考えない

補足
最近の傾向
Mac miniからの出力は、プリンターサーバにDHCPが割当てたxxx.xxx.xxx.13とマニュアルに記載されてるxxx.xxx.xxx.252の2つを使って、どちらかが駄目なら、もう片方を使う事にして一応運用ができている。
このような運用をしなければならないのは、ファーム側に問題があると思う。
が、時間を無駄にしたくないので、このプリンターサーバは、
「こんな、もんだ!」と割り切っている。

2012年9月21日金曜日

An Instllation of Raspberry Pi
Raspberry Pi インストール

I updated this installation manual.
Target image :  archlinux-hf-2012-09-18.img

最新版のインストールマニュアル(archlinux-hf-2013-07-22.img)は下記からどうぞ!
JAPANESE
ENGLISH    (12 Jan, 2013)

-----------------------------------------------------------------------------------------------------
OLD MANUAL

In my case, I use a Raspberry Pi as a robot controller. Therefore, there are some difference between my installation and common installation. For example, I don't install  a window system like 'gnome'. and games,,,

wifiのfirmwareや、Arch Linuxでのパーティション設定を含めて記述しています。
Raspberry Pi のホームページからダウンロードできるOSイメージをインストールすると8GBのSDカードでも、2GBの初期設定がされてしまいます。推奨のRaspbian “wheezy”であれば、初期化作業の時に拡張できますが、Arch Linuxでは自分でする必要があります。私は、Ubuntuで、Gpartedを使いました。
私は、32GBのカードを使っています。SDカードの相性があるので、Raspberry Piのホームページで確認したほうが良いです。
あと、pacmanを使って、glibc関連のエラー(glibc error)が出たときの対処のリンク(link)もあります。私は、この対応で半日つぶしました。

step of installation (for beginner )
1. Prepare SD-card,,,,
2. Install Arch Linux Arm
3. Environment setting
4. Back up setting
5. Add development software and tools

/****************************************************************************/
/* 1.  Preparation                                    */
/***************************************************************************/
1. 準備すること
(1) 相性の良い、SDカードを準備する。
いろいろな不具合を事前に回避するためにも重要。
SanDiskは、おおむね大丈夫のようです。
私の場合は、SILICON POWERで良くエラーが発生しました。
(2) セルフパワーのUSBハブ
RaspberryPiからの、USB電源供給は最小限に抑える。
USBからの供給が、多くなると不安定になる可能性があり、それを防ぐ。
(3) OSを選定する
一般的には、R-Pi推奨のOSを使うほうが良い。
ロボットの開発には、シンプルなArchLinuxArmを導入して、
必要な機能のみをインストールするほうが良い。
(4) ターミナル/ファイルコピーソフト
SSH接続で、他のマシンから操作できる環境を作る必要がある。
たとへば、バックアップなどに使う
Windows: ”Tera term”, “winSCP” 
Ubuntu   : FillZilla

/****************************************************************************/
/* 2.1 RaspberryPi OS用 SDカード作成 (Windows)  */
/****************************************************************************/
(1) カーネルイメージ作成
利用するOSのカーネルイメージをwww.raspberrypi.orgよりdownloadし、解凍する
(2) SDカードへの書き込み
win32diskimager-binaryを使って、SDカードに起動イメージを作成する。
(3) 後処理
Windows上の作業用ファイルを削除する


/****************************************************************************/
/* 2.2 SDカード2GB以上領域の確保 (Gpated on Ubuntu)    */
/****************************************************************************/
RaspberryPIのインストールイメージは、2GBの割当てを行う。30GBのSDカードを使った場合には、残り約30GBが、未使用の状態になる。その約30GBを使う為の処理

私は、普段Windowシステムをつかいません。
お使いの方は、(2)だけを実行してください。
It's need to install a gparted using ubuntu software center.

(1) How to change Ubuntu window system.
/etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT='text"
Using window system change as above "text" to "quiet splash" or blank.
sudo update-grub
sudo start gdm

(2) Gparted (allocate partition and format)
ex.) 32GB SD-card
swap   500MB    
/tmp     2GB
/home  10GB
/data    other
/tmp, /home, /data -> ext3 format

(3) Change CUI Mode.

/****************************************************************************/
/* 2.3   First time system upgrade                                     */
/***************************************************************************/
よほどの問題がない限り、SDカードをR-PIに差込み、電源をいれれば立ち上がる。
起動したOSは、古いので最新版にupgradeする必要がある。OSや、アプリケーションの管理をするソフトが、pacman である。

(1) 起動して、systemのアップグレードを実行する。
pacman -Sy
pacman -S pacman     最初に、Pacmanをアップグレードする。
                                     大きくシステムソフトが変わった場合には、pacmanが
                                     依存するソフトの更新が先になる。
                                     glibcエラーが発生した場合には、下記リンクを確認
                                     http://archlinuxarm.org/forum/viewtopic.php?t=3775&p=21205
pacman-key --init  
この後は、OSのプロンプトが現れるまで、キーボードからランダムに文字を入力し続ける。なかなか、プロンプトがでてこないので、根気よく続ける。
(2) pacman -Su
pacmanを更新した直後のupgradeは、数十個のソフトのupgradeが行われるので、かなり時間がかかる。SDカードとの相性が悪いと、この段階で、インストールできないなどのエラーで途中終了する。
(3) reboot
reboot後に再度、pacman -Suをしてみて、Upgradeしなければならないソフトがないか?再度確認する。
(4) pacman -S lshw
ArchLinuxは、最小限のドライバーなどしかないので、接続する機器がつながっているのか?確認する為のソフト。
(5) 接続しているHardwareの確認
lsusb, lshwなどで、無線ドングルの確認をする。
lsusb
USB接続している装置が認識されているか確認をする。接続しているのに、表示されない場合には、ハード的なトラブルを疑った方がよい。他のOSで確認する。
lshw
OSにどのように、認識されているのか?確認できる。この情報を元に、driver/firmwareが認識されていない場合には、その対処をする。
この説明では、OSインストール時に、USBをつないでいるが、一通りの環境設定が終ってから、USB接続機器の確認や設定を行っても良い。

/****************************************************************************/
/* 3.1 Wifi設定                                                                     */
/****************************************************************************/
本来は、netcfgなどの機能を使って行う。R-Pi購入初期の時に、数回試したがうまくいかなかったので、現在もこの方法で実施している。いつか、時間があるときに、netcfgに変更する。
与件として、IPアドレスを自動的に割振るDHCPが動いているサーバに接続することを前提にしています。
(1) 関連ソフトの入手
pacman -S wpa_supplicant wireless_tools
(2) wifiの暗号通信の為の設定ファイル作成
/etc/wpa_supplicant/wpa_supplicant.confを編集する。
下の例は、家とモバイルルータの設定をしている。priorityで同じ環境にあった場合の優先順位を決めている。その他は、ひょじゅんてきなWPAPA2-PSKの設定方法であり、ssidとpskの部分を変更すれば、そのまま使える。2つ記述してあるのは、自宅用と、Pockect Wifi用です。
Ppriorityの値で、自宅を優先にしています。

# ----- add my block 19/08/2012 ----------
network={
ssid="環境のESSID"
proto=RSN
priority=1
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP
psk="環境で決められているKEY"
}

network={
ssid="環境のESSID"
proto=RSN
priority=10
key_mgmt=WPA-PSK
pairwise=CCMP TKIP
group=CCMP TKIP
psk="環境で決められているKEY"
}

(3) /etc/rc.d に自動起動のためのシェル(nao)を作る。chmod +x naoを忘れずに
#!/bin/bash
/sbin/ifconfig wlan0 up
/usr/sbin/wpa_supplicant -B -Dwext -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
/usr/sbin/dhcpcd wlan0
(4) /etc/rc.confのDAEMONSに、networkの後に追加
DAEMONS=(!hwclock syslog-ng network nao openntpd @netfs @crond @sshd)

(5) ファームウェアの設定
ドライバー以外にも、firmwareが必要。現在のLinuxでは、多くのインストール済みがあるが、ない場合、もしくは最新版をインストールする場合に、この処理が必要になる。
lshwで、firmware=N/Aになっている装置があれば、その対応が必要。
メーカからダウンロードして、/lib/firmwareに、所定のfiramwareを置く。
例)
rx2870.binなど

/****************************************************************************/
/* 3.2 ディスクの拡張                                                            */
/****************************************************************************/
2.2で、SDカードには、フォーマットされた領域が確保されている。その領域を実際に使う為の処理である。swapと、通常利用のdisk領域の2つを処理する。
(1) 現在のSDカードの情報確認
SDカードなので、/dev/mmcblk0xxと領域が複数表れる。マウントするdirectoryとdeviceの対応を決める。

#fdisk /dev/mmcblk0
Welcome to fdisk (util-linux 2.21.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p

Disk /dev/mmcblk0: 16.4 GB, 16437477376 bytes
4 heads, 16 sectors/track, 501632 cylinders, total 32104448 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000c21e5

Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1   *        2048      194559       96256    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          194560     3862527     1833984   83  Linux
/dev/mmcblk0p3         3862528     5910527     1024000   82  Linux swap / Solaris
/dev/mmcblk0p4         5910528    32104447    13096960    5  Extended
/dev/mmcblk0p5         5911920    10008494     2048287+  83  Linux
/dev/mmcblk0p6        10008558    32097869    11044656   83  Linux

(2) swapの作成とマウント
/sbin/mkswap /dev/mmcblk0p3
/sbin/mkswap -L swap /dev/mmcblk0p3
/sbin/swapon -L swap
cat /proc/swaps

(3)vi /etc/rc.local に次の行を加える。
           /sbin/swapon -L swap

(4) /etc/fstab の修正
vi /etc/fstab 下記のswap, /tmp, /homeを付け加える
#
# /etc/fstab: static file system information
#
# <file system>    <dir>      <type>    <options>   <dump> <pass>
devpts             /dev/pts   devpts    defaults       0      0
shm                /dev/shm   tmpfs     nodev,nosuid   0      0
/dev/mmcblk0p1     /boot      vfat      defaults       0      0
/dev/mmcblk0p5     /tmp       ext3      defaults       0      0
/dev/mmcblk0p6     /home      ext3      defaults       0      0
/dev/mmcblk0p7     /data      ext3      defaults       0      0
LABEL=swap1        swap       swap      defaults       0      0

これで、rebootしても、大丈夫

/****************************************************************************/
/* 3.3 ユーザ登録                                                                  */
/****************************************************************************/
これまでの作業は、rootで行ってきたが、システムに対して危険なのでsudoを導入する。
(1) pacman -S sudo
(2) adduserで、ユーザを登録。グループは、wheel、uucpを指定。
Login name.......:  nao
UID..............:  100
Initial group....:  wheel
Additional groups:  uucp
Home directory...:  /home/nao
Shell............:  /bin/bash
Expiry date......:  [ Never ]

(3) visudoで、上記ユーザがいちいちパスワードを入力しないように変更
pacman -S sudo
## Same thing without a password
%wheel ALL=(ALL) NOPASSWD: ALL

/*******************************************************************************/
/* 4.1 Back Up                                                                        */
/*******************************************************************************/

I use a Macmini (1.5GHz, i5, 8GB) as a server.
I do backup data from Raspberry Pi to server(Mac) on a daily basis.
very easy way.

(1) generate RAS key (Macmini)
ssh-keygen

(2) copy RAS key  to Raspberry Pi
copy  ~/.ssh/id_rsa.pub (Macmini) to  /LOGIN USER HOME/.ssh/authorized_keys (Raspberry Pi).

(3) make backup shells (Macmini, Raspberry Pi)


ex)
Macmini
#!/bin/bash
ssh nao@192.168.11.xxx /home/nao/bin/mk_tar.sh
scp nao@192.168.11.xxx:/tmp/r-*.tar  /Users/nao/q/Rapi

Raspberry Pi
mk_tar.sh

#!/bin/bash
tar cvf /tmp/r-pi01.tar /home/nao/rcs > /dev/null

/****************************************************************************/
/* 5.1 Additional Software                                                   */
 /*          developing tools for robots only.                           */
/****************************************************************************/
pacman -S gcc
pacman -S makecmake
pacman -S pkg-config

pacman -S libusb
pacman -S openCV

openNI  (driver, openNI, Nite)
PCL
openKinect

pacman -S nginx

pacman -S fswabcam

pacman -S ttf-bitstream-vera ttf-dejavu

Peace!

Developing Robots on Raspberry Pi
 Raspberry Piを使ったロボット開発の考え方


I use Raspberry Pi as robot controllers based on Robot Distributed Computing System  (RDCS). RDCS is an architecture to develop a robot system efficiently and simply.
An agricultural work is a combination of variety of tasks. In large farms, only one robot cannot execute many agricultural tasks. Therefore, we have to control many robots and sensors. For this purpose, we designed  RDCS that is a new robot system architecture. RDCS offer one cohesive integrated control for robots, sensors and variety  of agriculture informations.
RDCS have a databese called 4DS.  4DS is a 4 Dimension database. 4 Dimension data is a very important data for agriculture. 4DS  manage   variety information to require for agricutural production . For example,  geospatial data, growing data, cost data, other many data.
Robots use 4DS information as self-control data, and store a variety of data that is scanned  by robots in work.


Raspberry Pi は、いろいろな所で取り上げられているので、ここでは私のrobot開発における利用方法の概要を記述します。

私のロボットは、「分散コンピューティング上にハードウェアを置く」と、いう考え方で作っています。
これは、これまでのハード中心のロボット作りとは、考え方がまったくことなります。しかし、実際の農場での運用を考えると、そのような考え方に立脚しないと展開できないと考えています。robotが、単機能として物を運ぶ、果実を収穫すると言うのは、大事な機能です。しかし、農場では様々な仕事があり、かつそれぞれの仕事が連動しています。そのような状況のなかで、複数のロボットやセンサーなどを使う為には、全体を統合的に制御できるarchitectureが必要になります。

その分散コンピューティングのノードコンピュータとして、Raspberry Piを位置づけています。これまでは、H8などのマイコンボードをLegacy PCで制御するような構造になっていたと思います。マイコン+Legacy PCをRaspberry Piで置き換える考え方です。それにより、ロボット開発には多くのメリットがあります。軽量化、原価低減、電源の最小化などなど多くの効果が期待できます。これまでも、ARMベースの低価格コンピュータが販売されていましたが、一気に1/3の価格になってしまいまいた。また、GPIOがあるのでデバイスに直接につなげます。
ロボット開発において、軽量化は大変重要です。私は、これまで、Dell mini9を使っていましたが、それにしても2Kg程度あります。それがバッテリー込みで、500g位になります。収穫用のactuatorは、ロボットシステム全体からみると、ひとつのApplicationとして独立していますが、Actuator専用にRaspberry Piを割当てる事も容易にできます。

システム構造です。まだ、案レベルで、実装しながら変更します。
上の図は、私のRobot Distributed Computing Model (RDCM)の構造図です。
この構造モデルに従って、全ての機能が実装されます。この図では、ControllerにARMのCPUを使うこと以外は、デバイスの規定はありません。従って、柔軟に組合わせることができます。
また、このArchitectureでは、他のコンピュータシステムと連携させることができます。例えば、農業生産管理システムとの連携も、簡単にできます。distributed computingモデルを基本にしているという事は、そのような意味です。
これまでの、ロボットは、ロボット中心の考え方をしていますが、私のロボットは、業務で人間と同等の役割を担う事を前提にしています。従って、role-definitionがあります。それらを延長した形で、私のロボットはWork Control Definition(WCD)に基づいて動きます。

温度センサーにしても、「温度を計測する」roleに基づいて役割を実行して、全体業務に貢献します。これは、別な意味で重要で、定義された役割を実行するので、それは、同一の経営体のなかであれば、どこでもいいわけです。もちろん、そのための作り方はあるわけですが、STMの評価ボード、XBee、温度センサーと単三電池を組みわせれば良いだけです。市販のおんどxxなどに比べれば、格安にかつ自由度の高い構成がとれます。

Raspberry Piは、そのような中で、Nodo Computerとして重要な役割を担っています。しかし、Raspberry Piがないと動かないわけでありません。

私のように、640KBの世界で3D-CADプログラムを開発していた人間から見れば、256MBのメモリーの世界は、はかりしれない可能性を持ちます。

人は、欲張りになりすぎました。これはコンピュータの世界だけでなく、全てす。
もっと、Simplifyに、構造化して認識することが大切です。

Simplify、いい言葉です。
ところで、Raspberry PiのOSは、Arch Linuxです。SimplifyなOSです。私は、Raspberry PiでGUIは使いません。Raspberry Piにはその必要性がありません。画像を見たければ、distributed computing上のAndroidで見れば十分です。
Simplifyです。


2012年9月19日水曜日

はじめまーす


脱サラ、トマト農家のトマト作業用 ロボット開発の記録です。

トマト収穫ロボット や、その他いろいろな 農業ロボット を開発する予定です。

今まで、ホームページに書いていたのですが、こちらに引っ越します。
最初に、10万円台の、トマト収穫ロボット の開発を目指しています。
あり得ないと、多くの方から言われておりますが、挑戦しないと始まりません。
さてさて、どうなることやら、、、

事の顛末を、ご覧下さい。