2010年9月28日火曜日

先週勉強したこと

おれ先週なに勉強したかな。

・パーティクルフィルタ
樋口知之, 粒子フィルタ, 電子情報学会誌. 2005 Vol88,NO12.P.989.

・位置ベースビジュアルサーボ
Chaumette and Hutchinson, Visual Servo Control, Part I: Basic Approaches. IEEE Robotics and Automation Magazine, 13(4):82-90, December 2006.

・擬似逆行列
G.ストラング, 線形代数とその応用,産業図書,1978

・Lucas-Kanade Tracking Algorithm
B. D. Lucas and T. Kanade: An Iterative Image Registration Technique with an Application to Stereo Vision, Proc. 7th International Conference on Artificial Intelligence, pp.674-679, 1981.
金出先生、ようやくあなたの論文読みました、はいw 当時にしていかにそれが斬新かが良く分かりました。てか先生に会いに行く前に読むべきでしたね。ダメ学生ここにあり。

何か勉強しかしてないんじゃないかと思われるかもしれないですが、
一応研究進めつつやってますよ?w
休みの日はちゃんと街で友達と遊んでますよ?w

さてさて、
--
今週中に勉強したいこと。

・コンピュータビジョンの復習
出口光一郎, ロボットビジョンの基礎, コロナ社, 2000

・c言語の理解
ピーター ヴァン・デ・リンデン, エキスパートCプログラミング―知られざるCの深層, アスキー, 1996
c言語は使えるだけじゃデバッグできませんよね。

両者俺の脳みそじゃさくっといかなそうな気がしますが、まぁよいでしょう。
てかコンピュータビジョンの勉強はもう2回くらいやった気がするんですが、いざ使うときに大事なところの理解があいまい。
指導教員の授業で勉強して、アメリカでまた授業を取って、散々教わったのに申し訳ない。
何かコンピュータビジョンの話って、行列がいっぱいすぎて、いつも忘れちゃうのは僕だけでしょうか?w
とにもかくにも、ここらでいっちょたたきなおす必要があると思った。

この辺さっさと終わらせて確率の勉強をしっかりしておきたい。10月までには今机に積みあがってる教科書の勉強終わらせたいなぁ。
特に片山先生のカルマンフィルタの本とかまじで熱そう。この前読んだら一ページ目で撃沈したw
すみません、バカは出直してきます。

あぁ、今週末も来週末の研究の大事なミーティングがある。
ビジネスゲーム関係もある。
同窓会関係も動かないと。

でも、勉強はしたい。

時間は...作るものだ。

2010年9月23日木曜日

東北大学交換留学生同窓会

組織としてではなくて、個人的にお知らせします。申し訳ありませんが、対象者は東北大学在学生または卒業者となっております。

この度、2009年度の東北大学交換留学生の有志が募り、「東北大学交換留学生同窓会」を設立致します。
こちらは東北大学の理事にも承認される、正規の同窓会となっております。

私は当該同窓会の副会長及び広報を勤めさせていただく予定ですので、このような形でご紹介させていただいております、はい。

目的は、東北大学から派遣された留学生同士の親睦と、情報の蓄積及び留学希望者へのサポート等としております。

つまり、今後留学を考えている学生の入会も大歓迎しています。
また、「交換留学」とはありますが、東北大学を通じて派遣された学生ならば、プログラムを問わずに入会が可能となっております。

東北大学OB、OGで海外経験のある方も是非ご入会いただき、後輩へのアドバイスを頂ければと考えております。

その他私たち幹事会が承認すれば入会可能です。(例えば、私費留学や海外インターンシップとかも)

本同窓会は、10月1日に理事に承認され、10月9日に幹事会の発足が承認されます。

9日(土曜日)は同時に、留学体験発表会が記念イベントとして行われます。

場所:青葉記念講堂4F会議室
プログラム
14:00 当該同窓会年次総会
14:30~16:00 交換留学発表会等
17:00 懇親会(学生無料♪)

学部生2人、大学院生2人が発表を行う予定となっており、私も後者を担当させていただくことになりました。
オープンキャンパスでの発表のような、ある意味うわべだけではない内容を発表することになりますので、興味のある方は是非ご来場ください。

単純に、こいつどんなことしてきたの?ってことでなんとなく聞きに来たい人も大歓迎です。

ご来場いただければその場での同窓会登録も可能となっております。(年会費1000円を徴収させていただいております。このような組織運営のためには必要不可欠な経費となっております。これでもぎりぎりまで安く設定しておりますので、どうかご了承願います…)

そうそう。10月9日はホームカミングデーです。OB、OGもいらっしゃいますので、貴重な留学経験をアピールするチャンスです。
懇親会もありますので、経験者はこれを機にその積極性をアピールをしてみませんか?

そもそも、経験者じゃなくても懇親会自体は普通にリクルーターとの交流ができるチャンスといえるでしょう。ついでに顔を出してみませんか?

というわけで、一人でも多くの方にご参加いただければ幸いです。

何卒よろしくお願いいたします。


何てことしてっからカオスになってんだよな。ぐはぁ!!!!

2010年9月14日火曜日

ベイズの法則

自分の研究見据えていたら,非常に必要そうな気がして,改めて勉強してみました.

分かりにくいないようだなー,と思ったときには,いつもこんな感じでスライド形式にして勉強しているんです.
ゼミ資料は英語が書くことになっているので,いつでもみんなに紹介できるように出来る限り英語で書くようにしています.

言うまでもありませんが,以下の画像の著作権は私に属します.

エンジニアのたまご

エンジニアのたまご

エンジニアのたまご

エンジニアのたまご
あ,この例題は英訳するのが激しく面倒くさかったというだけの話ですw(ダメ学生…)

つーか帰国してから英語で文章書く習慣も読む習慣も減った…やっぱ日本語に頼るとやりやすいです.

しかも条件付確率が英語で頭に出てこなかったのはさすがにショック….留学するしかないな,こりゃ.

さて,このスライド実はちゃんとアニメーションになってますw

自分があとで復習するときにすんげーーーー分かりやすいんですw

まぁ自分が分かるように書いてるんですからあたりまえですよねw

しっかし統計って分かりにくくてどうも苦手なんだよなぁ….すんげー興味あるんだけどな….

2010年9月7日火曜日

LU分解

色々合って自分でLU分解しなければならなくなりました.

行列方程式の解を求めたいのですが,諸事情により,よく使ってた便利なOpenCVの関数を使えないということなのです.

いい勉強の機会だと思い,まずはLU分解の勉強.

線形代数とその応用という本で勉強したのですが,こいつがとんでもなく良い本ですね.

こういう語り口調でわかりやすい本は大好きです.

とりあえず仕組みは分かった.じゃあ分かりやすいソースコードがどこかに無いかなーと探すw

読みやすいソースコードを発見した.

神奈川大学の内田先生の公開コードを参照させていただきました.当該コードの著作権は内田先生に帰属します.参照元: http://www.inf.ie.kanagawa-u.ac.jp/c_learn/index.html#ouyou
よって私が改変した以下のコードはその二次的著作物となります.

上記コードではピボット選択をしない仕様でしたので,改変しできるようにしました.これで特異でない行列を含む行列方程式なら解を導出できることになります.

pivotが0の時のよさげなpivotを探して行を交換.それに伴いL行列も更新する.という操作を加えただけなんですが.

改変した主要な部分はLUpivot()とLUsolve()を加えた点です.うごかねーぞこら!ということに関して一切責任を負いかねます.もし参照するなら自己責任でお願いします.

いやはやエラー処理があまりに適当すぎるのが難点…

main.c
#include 
#include 
#include 
#include 
#include "LUutil.h"

int main( void )
{
int      n ; /* 次数 n : カウンタ i         */
double *A, *b ; /* 係数行列 A : 定数ベクトル b */
double *x; /* ベクトル x      */

n = get_dimension( MAX_DIM, MIN_DIM );           /* 次数を取得する */
if( ( A = get_matrix( n ) ) == (double *) NULL || /* 行列の A 領域   */
( b = get_vector( n ) ) == (double *) NULL || /* ベクトル b の領域 */
( x = get_vector( n ) ) == (double *) NULL )  /* ベクトル x の領域 */
{
fprintf( stderr, "メモリ取得エラーです!!\n" );
}
else
{
set_matrix( n, A );    /* 行列要素の入力      */
set_vector( n, b );    /* ベクトル要素の入力 */

// LU分解法によって行列方程式を解く
if( LUsolve(n, x, A, b) == -1 ) {
printf("LUsolve failure\n");
return -1;
}
MulMatandVec(b, A, x, n); /* 検算 */
printf( "LU2の解: " );
pr_vector( n, x ) ; /* 計算結果の出力 */
printf( "LU2の検算: " );
pr_vector( n, b ) ; /* 計算結果の出力 */
}

system("pause");
return EXIT_SUCCESS;
}


LUutil.h
#define MAX_DIM     10 /* 次数の最大値 */
#define MIN_DIM      1 /* 次数の最小値 */
#ifndef TRUE
#define TRUE      1
#endif
#ifndef FALSE
#define FALSE      0
#endif

void   MulMatandVec(double result[], double matA[], double vecB[], int size);
extern int      get_dimension( int max, int min );
double *get_matrix( int n );
double *get_vector( int n );
void   set_matrix( int n, double *a );
void   set_vector( int n, double *b );
void   mswap( double *a, double *b );
void   LU( int n, double *a, double *l, double *u );
int   LUsolve( int n, double *x, double *A, double *b );
int   LUpivot( int n, double *a, double *b, double *l, double *u );
void   L_equ( int n, double *l, double *c, double *b );
void   U_equ( int n, double *u, double *x, double *c );
void   pr_vector( int n, double *b );
void   matrixcpy( int n, double *u, double *a );
void   make_I( int n, double *l );


LUutil.c
#pragma once
#include 
#include 
#include 
#include 
#include "LUutil.h"

/* ----------------------------------------------------- *
* 行列とベクトルの積
*/
void MulMatandVec(double result[], double matA[], double vecB[], int size)
{
double sum;
int i, k;
for(i = 0; i < size; i++) {
sum = 0;
for(k = 0; k < size; k++)
sum += matA[i*size + k]*vecB[k];
result[i] = sum;
}
}
/* ------------------------------------------------------ *
*   行列・ベクトルの次数を取得する。
*   max minで指定された範囲が入力されるまで繰り返す。
*/
int get_dimension( int max, int min )
{
int d ; /* Dimension */

for ( ; ; )      /* 無限ループ */
{
printf( "行列・ベクトルの次数を入力してください >>>" );
scanf( "%d", &d );
if ( d > max || d < min )
{
fprintf( stderr, "その値は、許されていません。\n" );
}
else
{
return d;
}
}
}

/* ------------------------------------------------------ *
*    与えられたサイズの行列を格納する領域を確保する。
*    確保された領域の先頭アドレスを返す。
*    エラーならば、NULLを返す。
*/
double *get_matrix( int n )
{
return ( double * ) malloc( sizeof( double ) * n * n );
}

/* ------------------------------------------------------ *
*    与えられたサイズのベクトルを格納する領域を確保する。
*    確保された領域の先頭アドレスを返す。
*    エラーならば、NULLを返す。
*/
double *get_vector( int n )
{
return ( double * ) malloc( sizeof( double ) * n );
}


/* ------------------------------------------------------ *
*    与えられた行列に要素を格納する。
*/
void set_matrix( int n, double *a )
{
int i, j ; /* カウンタ */

for ( i = 0 ; i < n ; i ++ )
{
for ( j = 0 ; j < n ; j ++ )
{
printf( "行列の %d行 %d列の要素は ? >>>", i+1 , j+1 );
scanf( "%lf", &a[ i*n + j ] );
}
}
}


/* ------------------------------------------------------ *
*    与えられたベクトルに要素を格納する。
*/
void set_vector( int n, double *b )
{
int i ; /* カウンタ */

for ( i = 0 ; i < n ; i ++ )
{
printf( "ベクトルの %d行の要素は ? >>>", i+1 );
scanf( "%lf", &b[ i ] );
}
}

/* ------------------------------------------------------ *
*    与えられた値の入れ替えを行う。
*/
void mswap( double *a, double *b )
{
double temp;

temp = *a;
*a = *b;
*b = temp;
}

/* ------------------------------------------------------ *
*   LU分解を行う(ピボットの選択は行わない)。
*   エラー時の動作は不定。
*/
void LU( int n, double *a, double *l, double *u )
{
int p, i, j;
double    c;

matrixcpy( n, (double *)u, (double *)a ); /* 行列 Uに 行列 Aをコピーする */
make_I( n, (double *)l );              /* 行列 Lを単位行列にする       */

for ( p = 0 ; p < n ; p++ ) /* 掃き出し操作を行いながら */
{                     /* 行列を L,Uに分解する      */
for ( i = p + 1 ; i < n ; i++ )
{
c = u[ i*n + p ] / u[ p*n + p ];
l[ i*n + p ] = c;
for ( j = p ; j < n ; j++ )
{
u[ i*n + j ] -= c * u[ p*n + j ];
}
}
}
}


int LUsolve( int n, double *x, double *A, double *b)
{
double   *L, *U ; /* 下三角行列 L : 上三角行列 U */
double   *c;

if(   ( L = get_matrix( n ) ) == (double *) NULL || /* 行列の L 領域   */
( U = get_matrix( n ) ) == (double *) NULL || /* 行列の U 領域   */
( c = get_vector( n ) ) == (double *) NULL ) /* ベクトル c の領域 */
{
fprintf( stderr, "メモリ取得エラーです!!\n" );
}

if( LUpivot( n, A, b, L, U) == -1) {    /* LU分解を行う */
system("pause");
return -1;
}
L_equ( n, L, c, b ); /* Lに関する連立方程式を解く */
U_equ( n, U, x, c ); /* Uに関する連立方程式を解く */
//   printf( "LU2の解は," );
//   pr_vector( n, x ); /* 計算結果の出力 */
return 0;
}

/* ------------------------------------------------------ *
*   LU分解を行う(ピボットの選択を行う)。
*/
int LUpivot( int n, double *a, double *b, double *l, double *u )
{
int      p, i, j, maxPos, ii;
int      pflg;
double   max = 0;
double   c;

matrixcpy( n, (double *)u, (double *)a ); /* 行列 Uに 行列 Aをコピーする */
make_I( n, (double *)l );              /* 行列 Lを単位行列にする       */

for ( p = 0 ; p < n ; p++ ) /* 掃き出し操作を行いながら */
{                     /* 行列を L,Uに分解する      */
maxPos = p;
pflg = FALSE;
// u[p][p]が0のとき,ピボット選択が必要
if( u[ p*n + p ] == 0) {
// permulation flug を立ち上げる
pflg = TRUE;
// 同一列(第p列)中の最大値(絶対値)を検索
for ( j = p + 1 ; j < n ; j++ ) {
max = 0;
if(fabs(u[ j*n + p ]) > max) {
max = u[ j*n + p ];
maxPos = j;
}
}
// もし最大値が0のままなら,Aは特異行列
if(max == 0) {
printf("Matrix A is singular! (in a column)\n");
return -1;
}
// 行列uの第p行と第maxPos行を交換する
for( j = p; j < n; j++)
mswap( &u[ p*n + j ], &u[ maxPos*n + j ]);

// 定数ベクトルの第i行と第maxPos行を交換する
mswap( &b[ p ], &b[ maxPos ]);

// L行列を更新する
// 行を交換したので,Lについても交換した行を更新する必要がある
for(ii = 0; ii < p; ii++) {
mswap( &l[maxPos*n + ii], &l[p*n + ii]);
}
}
for ( i = p + 1 ; i < n ; i++ )
{
c = u[ i*n + p ] / u[ p*n + p ];
l[ i*n + p ] = c;

for ( j = p ; j < n ; j++ )
{
u[ i*n + j ] -= c * u[ p*n + j ];
}
}
}
// もしu[n][n]が0なら,それは特異行列
if(u[ n*n - 1 ]==0) {
printf("Matrix A is singular! (in a row)\n");
return -1;
}
return 0;
}

/* ------------------------------------------------------ *
*   下三角行列・ベクトルで与えられた連立一次方程式を解く。
*/
void L_equ( int n, double *l, double *c, double *b )
{
int i, j ;

for ( i = 0 ; i < n ; i++ )
{
c[ i ] = b[ i ];
for ( j = 0 ; j < i ; j++ )
{
c[ i ] -= c[ j ] * l[ i*n + j ];
}
}
}


/* ------------------------------------------------------ *
*   上三角行列・ベクトルで与えられた連立一次方程式を解く
*   (後退代入)。
*/
void U_equ( int n, double *u, double *x, double *c )
{
int i, j;

for ( i = n - 1 ; i >= 0 ; i-- )
{
x[ i ] = c[ i ];
for ( j = i + 1 ; j < n ; j++ )
{
x[ i ] -= x[ j ] * u[ i*n + j ];
}
x[ i ] /= u[ i*n + i ];
}
}



/* ------------------------------------------------------ *
*    与えられたベクトルの要素を出力する。
*/
void pr_vector( int n, double *b )
{
int i ; /* カウンタ */

for( i = 0 ; i < n ; i ++ )
{
printf ( " %g ", b[ i ] );
}
printf ( "\n" );
}

/* ------------------------------------------------------ *
*   行列のコピーを行う。
*/
void matrixcpy( int n, double *u, double *a )
{
int max, i;

max = n * n ;
for ( i = 0 ; i < max ; i++ )  /* 一次元配列としてコピー */
{
u[ i ] = a[ i ];
}
}


/* ------------------------------------------------------ *
*   行列を単位行列化する。
*/
void make_I( int n, double *l )
{
int i, j ; /* カウンタ */

for ( i = 0 ; i < n ; i++ )      /* 行列の要素を 0にする */
{
for ( j = 0 ; j < n ; j++ )
{
l[ i*n + j ] = 0;
}
}
for ( i = 0 ; i < n ; i++ )      /* 対角要素を 1にする   */
{
l[ i*n + i ] = 1;
}
}


あぁ,何とかできた.てかこれくらいのコードもっとちゃちゃっとかけるようになりたいわ.

2010年9月4日土曜日

ハッキントッシュ

Macがほしい今日この頃。

しかし金は無い。

Windowsマシンなら無駄にごろごろある。じゃあOSだけ買ってWindowsに入れられないものか。

そんなことをしていたような人に聞いたら「ハッキントッシュをググレ」とのこと。

ただし規約違反らしい。そんなものもってインターンシップはいけないよね… 変なことしてiPhone壊したくないしね.

でもまぁ参考までに調べてみる。

ネットブックについての情報は多そうね。幸運にもおいらはアメリカで仕方なく買ったAsus Eee PC 1005を持っているから何とかならんかと見てみる。

うん、フォーラムにあったぞ
http://www.hackint0sh.org/f181/78046.htm

とりあえず動くらしい。ワイヤレスLANとディスプレイの明るさ調整がきかないらしいが。

しかしアプリ開発用には激しく使いたくないな。しかもワイヤレスLANを失うとか致命的に終わってるし。

アプリ開発につかわんにしてもせめてサブPCくらいにならんかとWifi使えるバージョンを求めて、もう少し探してみる。
ネットブックでMacとかちょっとおしゃれそう。しかもこのEeePCなら全然躊躇無く使える(おい)。

こいつがステップバイステップでわかりやすい
http://www.famegadget.com/how-to-install-snow-leopard-mac-osx-into-asus-eee-pc-1005ha-1008ha-1018pe.htm
一応
http://jpmcgarrity.com/blog/index.php/2009/08/asus-1005ha-hackintosh/

まだネットワークについての記述が見当たらないと思ってみてたら
その辺に詳しいブログあったぞーーーー!!!!
http://maceee.blogspot.com/2010/02/snoweee-install-mac-os-x-snow-leopard.html

ワイヤレス使うにはこれを買えばよいのですね。

インストールするのにMacが必要なのね。どうにしろMac持ってないしw

やっぱ買うか。IT系ベンチャーのバイトの応募したんです。どうか通っていますように!!!!

たまたまubuntuの入れ方見っけたからついでに
http://www.robotgeek.org/blog/2009/08/08/asus-eeepc-1005-ha/

2010年9月1日水曜日

愛しのヤコビ行列

近々あるミーティングで発表できるだけの内容にするべく研究を進めなければならないのに,8月は放浪してて実験ができずに先生にせかせれぎみのmorimoriです.

あんまブログで研究の細かい話はしてはいけないと思うので,このカテゴリは一般的なお話に絞って書くつもりです.てか,もはやだたの独り言日記w

そもそもどんな研究してんの?という話ですが,要はカメラを用いて,ロボットと何か物体を両方認識して,何かの作業が自動で出来るようなシステムを作りたいなー,ということなのです.

今はですねー,とにもかくにもロボットアームを動かしたいなーと思っており,それをビジュアルサーボで速度制御したいと思っているのです(要は画像を用いたフィードバック制御をしたいのだ).

画像から得られたロボットの手先速度(並進および回転)を元に,多関節ロボットの各関節の角速度を導出して,ロボット側にえい!と指令を与えられるようにしたいのです.

この仲介役を担ってくれるのがヤコビ行列さんなのです.ここで重要なのは,このヤコビ行列を求めるためには,その時刻での各関節の変位が必要となることです.

素人も素人の状態から初めて(順運動学と逆運動学からスタートですたい),ヤコビ行列を求めるプログラムが書けた感じがしたので,さぁシミュレータでいっちょ動かすかというところで動かんかったのです.
正確に言えば,いっちゃん最初だけ動いているようでそれ以降音沙汰が無いのです.

ここで俺のヤコビさんが間違ってるのでは…という懸念が…そんなぁ…

てなわけで3週間前に書いたコードだったのでちと思い出しながら読んでいたら…あ,変位が積分されてない….アホだ.そりゃ止まるわw 報告するのも恥ずかしかったw

制御周期も適当に30msとか入れてやってたら先生方にこのバカモノと怒られたw すみません,1ms にしますとも.

そしたらジャーン!動きました.俺は何をやっていたんだ….バカ学生で申し訳ないす.

とりあえず俺のヤコビさんが合ってて良かった.ありがとう,ヤコビさん.

てーのはMatlabでやってたので,Cに移して動作確認しました.しかしMatlabって行列計算どんだけ便利なんだよ!って,あらためて感じました.

ちなみにCでの行列計算は若干使い慣れてるOpenCVの関数で済ませちゃってます.Intelを信用してるのですよw

BLASが速いという話もありますね.しかし高々6x6行列の計算にそこまでする必要があるのかなーという印象を持っているのですが,どうなんでしょう.

最後に,今回シミュレータは自分で書いたものではないのですが,使っていると自分でOpenGL使ってシミュレータが作れるようになりたいと心から思った今日この頃でした.