ARToolkit

拡張現実、ARToolkitを使いこなしてロボットに実装しよう!
はい、欲張りですねぇー。自滅しない程度に広く浅くやっていきます。
使えるものは全部コピペだ!
USBカメラでリアルタイムに画像解析、及び3Dでオブジェクト表示をしようと思ったらこれ、ARToolKitですね。


導入編


細かいことは参照ページに記載されているので、そちらをどうぞ。↓画像をクリック!
Copyright (C) Sunao Hashimoto. All Rights Reserved.

こちらも参考図書として紹介しておきます。


設定編


実際にプログラムしていて間もないですが(2010年5月3日現在)、行き詰ったところを以下にリストにしておきます。

OpenGLを参考書通りに設定したけど、ビルドした時にリンカエラーが出る!

参考書のP82~P83あたりを熟読しましたか?

msvcp71d.dllが見つかりませんとエラーが出るのですが・・・

どうやらDSVLのコンパイル時に正常に作られなかったようですね。
Googleで検索するとだるんロードできますので、それをARToolkitフォルダ下のbinフォルダに入れてやってください。
それでもだめならプロジェクトフォルダに直接ぶちこんでもいいでしょう。


プログラム「ゲームパッドを使おう!」


とりあえずこれ↓でゲームパッド使えます。タグは各自用意で書き換えてください。

#define
_CRT_SECURE_NO_WARNINGS
#pragma
warning(disable : 4819)
<windows.h>
<stdio.h>
<stdlib.h>
<GL\gl.h>
<GL\glut.h>
<AR\gsub.h>
<AR\video.h>
<AR\param.h>
<AR\ar.h>
/* カメラ構成 */
char *vconf = "C:/ARToolKit/bin/Data/WDM_camera_flipV.xml"; // 既定のカメラ構成
int xsize; // ウィンドウサイズ
int ysize; // ウィンドウサイズ
int thresh = 100; // 閾値
int count = 0; // 処理フレーム数

/* カメラパラメータ */
char *cparam_name = "C:/ARToolKit/bin/Data/502_camera_para.dat"; // 既定のカメラパラメータ
ARParam cparam; // カメラパラメータ

/* パターンファイル */
char *patt_name = "C:/ARToolKit/bin/Data/JinjaMark.hiro"; // パターンファイル名
int patt_id; // パターンID
double patt_width = 80.0; // パターンの幅(mm単位)
double patt_center[2] = {0.0, 0.0}; // パターンの中心
double patt_trans[3][4]; // 座標変換行列

/* オブジェクトの移動量 */
extern float exTx = 0.0; // x軸方向の移動量
extern float exTy = 0.0; // y軸方向の移動量

static void init(void);
static void mainLoop(void);
static void draw(void);
static void setupLighting(void);
static void setupMaterial(void);
static void cleanup(void);
static void keyEvent(unsigned char key, int x, int y);
void joystick(unsigned int ButtonMask, int x, int y, int z);
void idle(void);

int main(int argc, char **argv)
{
/* GLUTの初期化 */
glutInit(&argc, argv);
glutIdleFunc(idle);

/* ARアプリケーションの初期化*/
init();
glutJoystickFunc(joystick, 10);
glutForceJoystickFunc();

/* キャプチャ開始 */
arVideoCapStart();

/* メインループの呼び出し */
argMainLoop( NULL, keyEvent, mainLoop );
return (0);
}
static void init( void )
{
ARParam  wparam;	// カメラパラメータ

/* ビデオデバイスの設定 */
if( arVideoOpen( vconf ) < 0 ) exit(0);

/* ウィンドウサイズの取得 */
if( arVideoInqSize(&xsize, &ysize) < 0 ) exit(0);
printf("Image size (x,y) = (%d,%d)\n", xsize, ysize);

/* カメラパラメータの読み込み */
if( arParamLoad(cparam_name, 1, &wparam) < 0 ) {
	printf("Camera parameter load error !!\n");
	exit(0);
}

/* カメラパラメータの初期化 */
arParamChangeSize( &wparam, xsize, ysize, &cparam );
arInitCparam( &cparam );
printf("*** Camera Parameter ***\n");
arParamDisp( &cparam );

/* パターンファイルの読み込み */
if( (patt_id=arLoadPatt(patt_name)) < 0 ) {
	printf("pattern load error !!\n");
	exit(0);
}

/* gsubライブラリの初期化 */
argInit( &cparam, 1.0, 0, 0, 0, 0 );
}
static void mainLoop(void)
{
ARUint8			*dataPtr;		// カメラ画像
ARMarkerInfo	*marker_info;	// マーカー検出用の情報
int				marker_num;		// マーカーらしき部分の個数
int				j, k;			// ループカウンタ

/* カメラ画像の取得 */
if( (dataPtr = (ARUint8 *)arVideoGetImage()) == NULL ) {
	arUtilSleep(2);
	return;
}
if( count == 0 ) arUtilTimerReset();
count++;

/* キャプチャした画像の表示 */
argDrawMode2D();
argDispImage( dataPtr, 0, 0 );

/* マーカーの検出 */
if( arDetectMarker(dataPtr, thresh, &marker_info, &marker_num) < 0 ) {
	cleanup();
	exit(0);
}

/* 次の画像をキャプチャ */
arVideoCapNext();

/* マーカーの一致度を判定 */
k = -1;
for( j = 0; j < marker_num; j++ ) {
	if( patt_id == marker_info[j].id ) {
		if( k == -1 ) k = j;
		else if( marker_info[k].cf < marker_info[j].cf ) k = j;
	}
}

/* マーカーが見つからなかったとき */
if( k == -1 ) {
	argSwapBuffers();

	// 移動量を初期化
	exTx = 0.0;
	exTy = 0.0;
	return;
}

/* 座標変換行列を取得 */
arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);

/* 3次元オブジェクトの描画処理 */
draw();

/* バッファの内容を出力 */
argSwapBuffers();
}
static void draw( void )
{
double	gl_para[16];	// ARToolkit->OpenGL変換行列

/* 3次元オブジェクトの描画準備 */
argDrawMode3D();
argDraw3dCamera(0, 0);

/* 隠面消去 */
glClearDepth(1.0);				// デプス・バッファの消去値
glClear(GL_DEPTH_BUFFER_BIT);	// デプス・バッファの初期化
glEnable(GL_DEPTH_TEST);		// 隠面消去・有効
glDepthFunc(GL_LEQUAL);			// デプス・テスト

/* 座標変換行列の読み込み */
argConvGlpara(patt_trans, gl_para);		// ARToolkit -> OpenGL
glMatrixMode(GL_MODELVIEW);				// 行列変換モード・モデルビュー
glLoadMatrixd(gl_para);					// 読み込む行列を指定

/* ライティング */
setupLighting();		// ライトの定義
glEnable(GL_LIGHTING);	// ライティング・有効
glEnable(GL_LIGHT0);	// ライト0・オン
glEnable(GL_LIGHT1);	// ライト1・オン

/* オブジェクトの材質 */
setupMaterial();

/* 3次元オブジェクトの描画 */
glTranslatef(exTx, exTy, 25.0);		// オブジェクトの平行移動
glutSolidCube(50.0);				// ソリッドキューブを描画(1辺のサイズ50mm)

/* 終了処理 */
glDisable(GL_LIGHTING);		// ライティング・無効
glDisable(GL_DEPTH_TEST);	// デプス・テスト・無効
}
static void setupLighting(void)
{
/* ライトの定義 */
GLfloat	lt0_position[] = {100.0, -200.0, 200.0, 0.0};	// ライト0の位置
GLfloat	lt0_ambient[]  = {0.1, 0.1, 0.1, 1.0};			//          環境光
GLfloat	lt0_diffuse[]  = {0.8, 0.8, 0.8, 1.0};			//          拡散光
//
GLfloat	lt1_position[] = {-100.0, 200.0, 200.0, 0.0};	// ライト1の位置
GLfloat	lt1_ambient[]  = {0.1, 0.1, 0.1, 1.0};			//          環境光
GLfloat	lt1_diffuse[]  = {0.8, 0.8, 0.8, 1.0};			//          拡散光

/* ライトの設定 */
glLightfv(GL_LIGHT0, GL_POSITION, lt0_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, lt0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lt0_diffuse);
//
glLightfv(GL_LIGHT1, GL_POSITION, lt1_position);
glLightfv(GL_LIGHT1, GL_AMBIENT, lt1_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lt1_diffuse);
}
static void setupMaterial(void)
{
/* オブジェクトの材質 */
GLfloat	mat_ambient[]   = {0.0, 0.0, 1.0, 1.0};		// 材質の環境光
GLfloat	mat_specular[]  = {0.0, 0.0, 1.0, 1.0};		// 鏡面光
GLfloat	mat_shininess[] = {50.0};					// 鏡面係数
//
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}
static void cleanup(void)
{
/* 終了処理 */
arVideoCapStop();	// キャプチャを停止
arVideoClose();		// ビデオデバイスを終了
argCleanup();		// ARToolkitの終了処理
}
static void keyEvent( unsigned char key, int x, int y)
{
switch (key){
	/* ESCキーで終了 */
	case 0x1b:
		printf("*** %f (frame/sec)\n", (double)count/arUtilTimer());
		cleanup();
		exit(0);

	/* H, h:x軸の-方向に移動 */
	case 'H':
	case 'h':
		exTx = exTx - 5.0;
		break;

	/* L, l :x軸の+方向に移動 */
	case 'L':
	case 'l':
		exTx = exTx + 5.0;
		break;

	/* J, j :y軸の+方向に移動 */
	case 'J':
	case 'j':
		exTy = exTy + 5.0;
		break;

	/* K, k :y軸の-方向に移動 */
	case 'K':
	case 'k':
		exTy = exTy - 5.0;
		break;

	default:
		break;
}
}

void joystick(unsigned int ButtonMask, int x, int y, int z)
{
if(10<x) printf("右"),exTy = exTy - 5.0;
if(x<-10) printf("左"),exTy = exTy + 5.0;
if(10<y) printf("上"),exTx = exTx - 5.0;
if(y<-10) printf("下"),exTx = exTx + 5.0;

if(ButtonMask & 1) printf("△");
if(ButtonMask & 2) printf("○");
if(ButtonMask & 4) printf("×");
if(ButtonMask & 8) printf("□");
if(ButtonMask & 16) printf("L2");
if(ButtonMask & 32) printf("R2");
if(ButtonMask & 64) printf("L1");
if(ButtonMask & 128) printf("R1");
if(ButtonMask & 256) printf("START");
   if(ButtonMask & 512) printf("SELECT");

glutPostRedisplay();/* 画面再描画 */
}
void idle(void)
{
glutForceJoystickFunc();/* これを追加 */
}


今後のプログラム予定

タグのトラッキング(ロボットのヘッドで追従・未検出時は探索もしくはニュートラル)

ロックオン、シューティング的な何かw




















最終更新:2010年05月06日 23:11