Kinect x Android3.1 で LED+モータ+3軸加速度 (カメラ・マイクは動かないよ)

第1回 関西Kinect勉強会でLTネタにした内容。
最初に言っておきますがRGBカメラとIRカメラは今のところ使えません。(Android3.1ではAPIで一部サポートされていない。後述します。)
また、Kinectに搭載されているAudio(マイク)の情報も取得してません。
なので非常に残念なシロモノです。
ですがKinectプロトコルと、Android3.1のUSB APIを知るには丁度いいネタだと思います。


ちなみに、このネタはネイティブAndroid(root化なし、カスタムROMなしってことで、NDKのことじゃないよ)でやってます。
Android 3.1 のUSBホストモードを使っていて、Accessoryモードは使ってません。

        • -

ということで、LTネタの話。
フラワーロックならぬキネクトロックを作りました。
タブレットから音量を拾って、Kinectが上下に首を振ってRockするというものです。


以下簡単なアプリ解説と、Kinectを制御する際のポイントをば。


準備

準備するもの

APKファイル
http://dl.dropbox.com/u/3858050/hatena/KinectRock.apk
ソースコード
http://dl.dropbox.com/u/3858050/hatena/KinectRock.zip

Androidアプリは書いたこと少ないので「ソースコードこれこうしたほうがいいよ」とかアドバイスあると嬉しいです。)

アプリ解説

KinectTabletにつなげると起動します。
起動画面がこちら。(勉強会のときから少し変更)

Volume Thresholdで音量しきい値を変更できます。
1000くらいにすると、話し声でKinectくんがRock'n Rollしてくれます。10000くらいでほとんど反応しなくなります。


ChangeModeボタンを押すと、下側のUIが有効になって、Kinectを手動でぐりぐり動かすことができるようになります。

ソースコード解説

以下、ソースコードレベルでKinect制御しているポイントだけ解説します。
USBの初期化まわりはSDKディレクトリにあるsamples/android-12/USB/AdbTestを参考に。
USBプロトコルについては 「USB通信プログラムテクニック - http://www.picfun.com/usb00.html」 あたり参考にすると幸せになれます。

KinectのLEDを制御する

最終的にKinectへコントロール転送しているところ。

UsbDeviceConnection.controlTransfer(0x40, 0x06, ledNum, 0x0, (byte[])null, 0, 0);

このledNumを変更することでGreen/Red/Yellowを変更することができます。
あとの意味ありげな謎の数値なんなの?って人はOpenKinect - Protocol Documentationの記事と対比させてみてください。
謎が解けるはずです。


以下該当箇所抜粋

Setting LED
The led can be set by sending:
 request  request  value        index   data   length
 0x40     0x06     led_option   0x0     empty  0

where the led_options are enumerated as follows:
   LED_OFF    = 0,
   LED_GREEN  = 1,
   LED_RED    = 2,
   LED_YELLOW = 3, (actually orange)
   LED_BLINK_YELLOW = 4, (actually orange)
   LED_BLINK_GREEN = 5,
   LED_BLINK_RED_YELLOW = 6 (actually red/orange)

引用 : OpenKinect - Protocol Documentation http://openkinect.org/wiki/Protocol_Documentation

Kinectのモータを制御する

これと同じようにモータもコントロール転送で制御できます。

UsbDeviceConnection.controlTransfer(0x40, 0x31, tiltNum, 0x0, (byte[])null, 0, 0);

このtiltNumに-64〜64の数値を放りこんでやればOKです。

Kinectの3軸加速度センサ情報を取得する

これも同じようにコントロール転送で、戻り値をbufに格納します。

UsbDeviceConnection.controlTransfer(0xC0, 0x32, 0x0000, 0x0, buf, 10, 0);

bufの値は以下の式でintに変換されます。

ux = ((uint16_t)buf[2] << 8) | buf[3];
uy = ((uint16_t)buf[4] << 8) | buf[5];
uz = ((uint16_t)buf[6] << 8) | buf[7];

引用 : OpenKinect - Protocol Documentation http://openkinect.org/wiki/Protocol_Documentation

Audioについて

かおるんさんの講演で、マイクが4つもあることを知りました。
Audio情報の取得もできれば今後やってみたい。

RGB/IRカメラについて

さて、最後にRGB/IRカメラですが、KinectのRGB/IRカメラはアイソクロナス転送という転送方式が使われていて
現状Androidではサポートされていないようです。
(今回使った転送方式はコントロール転送のみ)

http://developer.android.com/reference/android/hardware/usb/UsbConstants.html#USB_ENDPOINT_XFER_ISOC

このあたりサポートされたらぼちぼち実装再開してみようと思っています。


参考サイト

あと余談ですが Kinect x 組込み という組み合わせ面白そうだなーと思っていて
このAndroidアプリもそのテーマの一環でやってみました。
ミドルレンジくらいのMPU(mbedとかArduinoとか)でも使えるくらいになるとおもしろそうですよね。


同じような趣味・趣向の方いらっしゃいましたら気軽にフォローしてください。 Twitter ID : [twitter:@ksksue]



参考:


KINECTセンサープログラミング