LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

Oculus Riftのヘッドトラック情報をArduinoに送ってサーボモータを動かした話

f:id:nextdeveloper:20150206172330j:plain

こんにちは、上津原です。
今度はUnity x Arduinoの話です。

Unityは様々な開発プラットフォームとして活用されますが、なんとArduinoとつながります。
Arduinoと言うのは、いわゆるマイコンボードで、いろんなセンサーとかモーターとかを動かすことが出来るやつです。

そしてこれとUnityをつなぐ、「Uniduino」というUnityアセットがあります。コレは名前のとおりですがUnityでArduinoを動かすためのものです。

コレを使えば、Oculusのヘッドトラッキング情報を取得して、そのとおりに物を動かすことが出来るのでは!?となりました。
以前にちょっとUniduinoを触っていたこともあり、再びArduino熱が上がってきて、弊社のクリエイターの日を利用してそれを作ってみることにしました。

どうやってヘッド情報を取得するか?

コレはとても簡単でした。
OculusのOVRCameraRigのCenterEyeAnchorのRotationから取得することが出来ました。
f:id:nextdeveloper:20150213100251p:plain

さて、これらのデータをどのようにしてArduinoに伝えるか?というところでUniduinoの出番です。
Uniduinoの動かし方は、こちらから見てもらえればOKです。

これのSERVOモードを利用すれば、角度情報をサーボモーターに与えてモーターを動かすことが出来ます!

サーボモーターとUnityの角度の回転が逆!

結構さくっと動くので、順調だなーと思ってた矢先に問題が。Oculusで右を向くとサーボモーターは左を向く。
上を向くと下を向く、といったかんじであまのじゃくな動きに。

角度を調べてみるとこんな感じになっていました。
f:id:nextdeveloper:20150213101546j:plain

0の起点がそもそも違うし、角度の増加方向も逆向き。悲しい。
ということでコレの角度の補正ロジックを書くことにしました。

法則性を見つけて一つの公式を導き出して〜という方がかっこいいですが、面倒臭かったので360度を4つに区切って、それぞれの角度領域で角度補正をすることにしました。

// jouge

// Seigen Kakudo
int jougeSeigen = 35;

if (270 < jouge && jouge <= 360) 
{	// left
	servoJouge = 180 - (jouge - 270);
}
else if(0 <= jouge && jouge <= 90)
{	// right

	//// Kakudo Seigen////
	if(jouge > jougeSeigen){
		jouge = jougeSeigen;
	}
	//////////////////////

	servoJouge = 90 - jouge;

}
else if (91 <= jouge && jouge <= 180)
{	// right over
	servoJouge = 0;
}
else
{	// left over
	servoJouge = 180;
}

うわー地味。でも動くんだから気にしない。
サーボモータは180度のものを利用しているので、0度、180度を超えたものは0,180度以上に行かないようにしています。
コレを書いておかないとサーボモータが逆方向に動き始めて大変なことになります。

とりあえずコレを使うことでサーボの向きとOculusの向きを一緒にすることが出来るようになりました。

サーボを360度のものを使ったらさらなる罠が待っていた

首を左右に動かすのは360度のサーボのほうがいいのでは?という話題が出てきて、そうしてみた。
なんの考えもなしに180の値を渡すとなんと2回転もするじゃないですか。

おいまて、誰が2回も回れといった。

360度角だから、Unityの値をまんま渡してやれば余裕っしょとか思ってた自分が馬鹿だった。

コレも動かしながら確かめてみると、どうやらサーボに90の値を渡すと1週するようになっているようだった。
それでいて0の起点ももちろん違う。また絵に書くとこんな感じ。
f:id:nextdeveloper:20150213103701j:plain

というわけで、Oculusの向きをサーボのものに変換してかつ、4で割ることで360度角を90度角にして利用することにした。

// sayuu

// Sayuu Seigen
int sayuuSeigen = 3;

// Front left
if (270 < sayuu && sayuu < 360) 
{	// left
	servoSayuu = 270 - (sayuu - 270);
}
// Front right
else if(0 <= sayuu && sayuu <= 90)
{	// right
	servoSayuu = 180 - sayuu;

}
// Back right
else if (90 < sayuu && sayuu <= 180)
{	// right over
	servoSayuu = 90 - (sayuu - 90);

	// Seigen
	if(servoSayuu < 10){
		servoSayuu = 10;
	}

}
else
{	// left over
	servoSayuu = 360 - (sayuu - 180); 

	// Seigen
	if (servoSayuu > 350){
		servoSayuu = 350;
	}
}

int Servo360Sayuu = (int)servoSayuu;
Servo360Sayuu = (Servo360Sayuu / 4);

とりあえずコレで360度回るようになった。
そしてなんやかんや接着して動かしてみたのがこちら


OculusとArduinoをUniduinoで連携させてみた。 - YouTube

キャタピラがついてますがそれはまた別の話で。
とりあえずはOculusとサーボを連携させることに成功しました!
最終的にはサーボの先端にカメラを付けて、遠隔の位置に視点を持っていく、と言うものにしてみました。

電子工作楽しい

ソフトウェアばっかりやってましたが、こんなふうに動くものを作れるっていうのはコレまた楽しいものです。
コレをきっかけに作って見たいものが出来たので、またなにか作ってみようと思います。