[iOS] Sphero社のBB-8をハックしてみますよ SDK編

スター・ウォーズ EP7に登場するドロイド BB-8のおもちゃが、ボール型ロボットSPHEROを発売しているSphero社から発売されています。BB-8( http://www.sphero.jp/starwars/ ) 
Sphero社製BB-8のSDKや開発情報は公開されていませんが、SPHERO SDKが「ある程度」使えるらしいので、iPhoneでどの程度使えるか調査してみます。

開発環境には、Xcode 7.2、実行にはiPhone6+ を使用しています。

##SDK入手
Sphero社に開発者登録( https://developer.gosphero.com/ )をすると、SPHERO SDKやドキュメントを入手することが出来ます。
iOSのほか、Android、Unity、WindowsなどのSDKがありますが、今回は、iOS用のSDKを試します。
2015.12.31現在、iOS用SDKのバージョンは3.1.14となっています。

##samples
SDKを解凍すると、以下の様なサンプルが含まれています。
・ButtonDrive
・HelloWorld
・HelloWorldSwift
・Locator
・MacroLoader
・MacroSample
・OrbBasicLoader
・OvalSample
・OvalSampleSwift
・SensorStreaming
とりあえず、順番に全部動かしてみましょう。

#ButtonDrive
BB-8を４方向に走らせるアプリですね。
<img width="414" alt="Screen Shot 2015-12-31 at 0.39.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/26936/706c8f36-7b01-ab9d-a6d0-37e47027f960.png">

アプリ起動時にBB-8に近づけると勝手に接続しますが、接続時に何かエラーログを吐きます。
2015-12-31 00:37:52.753 ButtonDrive[561:214537] OBX:+[RKResponseFactory responseFromRawPacket:withCommand:] - Command ID: 4
2015-12-31 00:37:52.755 ButtonDrive[561:214537] OBX:+[RKResponseFactory responseFromRawPacket:withCommand:] - Command Device ID: 1
2015-12-31 00:37:52.755 ButtonDrive[561:214537] OBX:+[RKResponseFactory responseFromRawPacket:withCommand:] - Command Packet: <ffff0104 0001f9>
2015-12-31 00:37:52.756 ButtonDrive[561:214537] OBX:+[RKResponseFactory responseFromRawPacket:withCommand:] - Error Response 0x09 for command <RKJumpToMainAppCommand 0x01:0x04 : seq=0x00> - seq:0x00

接続時のコマンドのやり取りがSPHEROとBB-8で食い違っていそうですが、アプリの動作は問題無さそうです。


#HelloWorld
ビルドすると、ヘッダが見つからんとコンパイルエラーが出ます。
HelloWorldViewController.m:6:9: 'RobotKit/RobotKit.h' file not found
Build SettingsのFramework Search Pathsに「 $(PROJECT_DIR)/../../frameworks 」と設定すれば大丈夫です。
アプリを起動してBB-8に接続すると、青い光がチカチカします。いわゆるLチカですかね。

#HelloWorldSwift
HelloWorldのSwfit版ですね、プロジェクトを読み込むと最新のSwfitに変換するか聞かれるので、流れに従って変換すれば問題ないようです。

#Locator
位置情報のサンプルでしょうか。
ビルドはそのまま通りましたが、数値入力のためにキーボードを表示すると、キーボードが消せなくなります。
各Text Fieldの「 Did End On Exit 」をdismissKeyboard: に結びつけましょう。

#MacroLoader
ビルドするとコンパイルエラーが出ますが、SDKのスペルミスを修正したのをサンプル側に反映していないようです。
	[_robot enableStablilization:YES];
を、このように修正します。
	[_robot enableStabilization:YES];
MacroはSphero制御用のバイナリデータですね、仕様はこちらにあります。
http://sdk.sphero.com/robot-languages/macros/
プロジェクトには、拡張子 .sphero のファイルが幾つか入っていますね。
<img width="414" alt="Screen Shot 2015-12-31 at 10.16.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/26936/1d4e6171-3213-af3e-722e-fe59c3c77729.png">

ボタンを押すとMacroファイルを送り込んで実行します。

#MacroSample
ビルドするとストーリーボードファイルでエラーが出ます。
/* com.apple.ibtool.errors */
: error: Not enough arguments provided; where is the input document to operate on?
MacroSample.storyboardを右クリックして、delete → Remove Reference で一旦削除します。
その後、Add Files to で再度プロジェクトに追加すると、何故かビルド出来るようになります。
enableStablilization: のスペルミスもあるので修正します。
Speed、Delay、Loopsのパラメータ付きでMacroを実行するサンプルのようです。

#OrbBasicLoader
Sphero制御用言語の一つ OrbBasicのサンプルです。
プログラムを選択してLoadボタンを押下すると、「firmware mismatch?」というエラーログが出ます。
2015-12-31 11:12:11.358 OrbBasicLoader[1237:311894] OBX:+[RKResponseFactory responseFromRawPacket:withCommand:] - Bad Command ~ firmware mismatch? ( 4 ) for command <RKOrbBasicEraseStorageCommand 0x02:0x60 : seq=0x06> - seq:0x06
2015-12-31 11:12:11.478 OrbBasicLoader[1237:311894] OBX:+[RKResponseFactory responseFromRawPacket:withCommand:] - Bad Command ~ firmware mismatch? ( 4 ) for command <RKOrbBasicAppendFragmentCommand 0x02:0x61 : seq=0x07> - seq:0x07

BB-8にはOrbBasicは搭載されてないのかな？

#OvalSample
Sphero制御用言語の一つ Ovalのサンプルです。
OvalはC言語のサブセットの簡易言語のようですね。
http://sdk.sphero.com/robot-languages/oval-language/
アプリを起動すると、BB-8が点滅をします。
Animation Speedに数値を入れてUpdateボタンを押下すると、点滅周期が変わります。

#OvalSampleSwift
OvalSampleのSwift版です、例によって最新のSwiftに変換して実行します。
が、Updateボタンを押下しても周期が変わらず、ログにエラーが出力されます。
""The following code failed to compile:
speed = Optional("0.25");...
You wrote bad Oval: Call to unknown function Optional.

Swiftやってる人なら、ピンと来ますね。コードを見ます。

```swift
        self.ovalControl.sendOvalString("speed = \(lightSpeed.text);...")
```
textがアンラップされていません。

```swift
        if let s = lightSpeed.text {
            self.ovalControl.sendOvalString("speed = \(s);...")
        }
```
こんな感じに修正します。

#SensorStreaming
センサーのサンプルですね。
例によって、enableStablilizationのスペルミスを修正します。
<img width="414" alt="Screen Shot 2015-12-31 at 11.28.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/26936/8caddf86-c9bd-e1c5-b706-64f69fe7fd42.png">
加速度と向きが取れるようです。
クォータニオンも取れますね、クォータニオンが何かについてはググってみてください。

##まとめ
SDKを一通り動かしてみましたが、思いの外ビルドエラーが出て大変でした。
OrbBasicが使えない？他、接続時と切断時にエラーログが出力されるので、SpheroとBB-8は完全互換ではないようです。
とはいえ、制御とセンサーは一通り行えたので、SPHERO SDKを用いればBB-8制御用iPhoneアプリは作れそうです。