2010-07-11

Tokyo-Jogging for iPhone を作りました

Tokyo-Jogging のための iPhone コントローラアプリを作りました。

Tokyo-Jogging とは?

Tokyo-Jogging というのは、友人の @ryo_katsuma が 2008 年に作ったもので、 Wii リモコン( wiimote )やバランス Wii ボードの各種ボタン・センサーを利用して Google Streat View 画面内を操作することで、バーチャルジョギングを楽しむことができます。 GizmodoCrunchGear など海外メディアでも取り上げられています。すごい。

Tokyo-Jogging の全体の動きは、ざっくりと次のような感じです(詳しくはプロジェクトページ参照)。
構成要素は次の4つ( Wii リモコンをデバイスとして使う場合)。
  • (A) Wii リモコン
  • (B) Wii リモコンからの Bluetooth 信号をブラウザ内 JavaScript に仲介してくれるサーバ
  • (C) 仲介サーバから HTTP で信号データを取得し、それに従い Google Streat View API を呼び出すブラウザ内 JavaScript
  • (D) Google Streat View
(A) 〜 (D) が次のように連携します。
  1. Wii リモコン (A) をポケットに入れてジョギングっぽく足踏みをする
  2. Wii リモコン (A) の加速度センサーが反応する
  3. Wii リモコン (A) から信号が Bluetooth 経由で仲介サーバ (B) に伝わる
  4. 仲介サーバ (B) に HTTPリクエストすることによりブラウザ内 JavaScript (C) がデータを受け取る
  5. JavaScript (C) が Google Streat View (D) の API をコールする
  6. API コールにより、 Google Streat View (D) 内の視点が前進してバーチャルジョギング!
バランス Wii ボードをデバイスとして使う場合も、ノリはこんな感じです。

作ったモノ

 そして、今回作ったモノは次の通り。
  • Wii リモコンの代替デバイスとしての iPhone コントローラアプリ「 Tokyo-Jogging for iPhone 」(右のスクリーンショット)
  • 仲介サーバ側で iPhone アプリからの信号を受信処理するインターフェース部分
ソースコードはこちら

遊び方

  1.  iPhone からの信号を Google Streat View (の API を呼び出すブラウザ内 JavaScript )に仲介してくれるサーバソフトのソースコードをプロジェクトページからダウンロード
  2. 仲介サーバを設定( config.properties ファイル内で、「 IS_IPHONE_AVAILABLE = true 」と編集)
  3. Google Streat View 画面を表示する予定の PC 上で、仲介サーバを起動
  4. ブラウザ上のプロジェクトページの「 How to start 」から「 Start 」ボタン > 「 Start Jogging 」ボタンをクリック。 Google Streat View 画面が表示されます
  5. Tokyo-Jogging for iPhone アプリを起動し、「 TJServerAddess: 」の右にある TextForm に「 http://< 仲介サーバのアドレス >:8081/command 」と入力
  6. 以上で準備完了です。十字キータップで視点移動、プラス・マイナスボタンタップで視点拡大・縮小、Aボタンタップで前進、 iPhone を振ると前進します

解説

以下、説明をいくつか。
デバイスからの信号を受信処理する仲介サーバのインターフェース
Google Streat View API をコールする JavaScript にコマンドを渡すためのスケルトンクラスは次の通り。このスケルトンに、デバイスからの信号を受け取る実装を肉付けすると、デバイスインターフェースの実装が完了します。
import org.json.simple.JSONObject;
import tj.server.HttpServer;

public class SkeletonDeviceManager {
    private HttpServer httpServer;

    public SkeletonDeviceManager(HttpServer httpServer){
        this.httpServer = httpServer;
        this.start();
    }

    // デバイスからの信号を受け取る何かから、ここに通知が来るようにする
    void inputReceived(double xAcceleration, double yAcceleration, double zAcceleration, byte action) {
        JSONObject obj = new JSONObject();
        obj.put("xAcceleration", xAcceleration);
        obj.put("yAcceleration", yAcceleration);
        obj.put("zAcceleration", zAcceleration);
        obj.put("action", ACTION_JOG);
   
        this.httpServer.setMessage(obj.toString());
 }

    void start() {
        // デバイスからの信号を受け取る何かをここでスタート!(たぶん別スレッド)
    }
}
このクラスは、 tj.TokyoJoggingMain#main(String[] args) 内で
new SkeletonDeviceManager(httpServer);
という感じに使われます。

inputReceived メソッドについて、 tj.jog.WiimoteManager クラス( Wii リモコンのための信号受信処理インターフェースクラス)では、ボタン入力イベント用メソッドと加速度センサー入力イベント用メソッドを分けていたので、今回作成した tj.jog.iPhoneManager でも倣って、
  • ボタン入力イベント用に
    • tj.jog.IPhoneManager#buttonInputReceived(byte action)
  • 加速度センサー入力イベント用に
    • tj.jog.IPhoneManager#accelerationInputReceived(double xAcceleration, double yAcceleration, double zAcceleration)
を作りました。
またさらに、 iPhone からの信号を受け取るリスナーも、 tj.jog.iPhoneListener に分けてあります。
デバイスから仲介サーバへ送る信号
Wii リモコンから仲介サーバへは Bluetooth で信号を送信していました。
Tokyo-Jogging for iPhone では、 Wifi + HTTP GET リクエストにより送信しています(仲介サーバ側の HTTP リクエスト受付には Jetty を利用しています)。

なお、副産物として、今回実装したサーバ側実装を流用して、 Tokyo-Jogging for iPhone に限らず容易に信号送信することができます。
例えばブラウザのアドレス欄から、「 http://<仲介サーバのアドレス>:8081/command?xa=0.1&ya=0.1&za=0.1&action=5 」なんてリクエストすると、 Google Streat View 内で前進します。
GET パラメータの説明は次の通り。
  • xa : x 方向の加速度値
  • ya : y 方向の加速度値
  • za : z 方向の加速度値
  • action : アクション ID ( 1:UP, 2:Right, 3:Down, 4:Left, 5:Jog, 6:ZoomIn, 7:ZoomOut )
      加速度に関しては、 xa/ya/za いずれかについて前回との差分が閾値以上で、かつ、actionパラメータが無い場合に、 action=5 と同じ信号と見なすようにしています。閾値は、試行錯誤の結果 0.2 としました。


      以上です。
      サーバ側の実装箇所( tj.jog.IPhoneManager と tj.jog.IPhoneListener )をもっと綺麗にしたい。

      0 件のコメント: