2013年4月21日日曜日

[Android]RPiラジコンを操作するAndroidアプリってどう作るの

Interface 12月号に載ってるRPiをラジコンにする記事の元ネタがあるんだけど、
ブラウザだと操作しにくいからAndroidアプリにしたらいいじゃないって話。
作ってみたアプリの動作画面はこんな感じ

RPi側の実装を軽くまとめると
・動画配信
 Webカメラをmjpg-streamerで配信
・ラジコン操作
 PythonでHttpサーバクラスを使ってHTTP公開、ブラウザで開いてボタン押されたらGPIO操作

ハードはよくある感じに作ればOK

一応こっちで作った構成は、
 頭 :RaspberrypiModelA
 筺体 :10式たん→【CCP】 1/24 MBT 陸上自衛隊10式戦車
 モータドライバ :フルブリッジドライバ L298N(使ってみたかっただけ)
 Webカメラ :Buffalo BSW13KM04H
 Wifiドングル:GW-USMicroN
 USBハブ :BSH3U02PK
 バッテリ :適当なモバイルバッテリー1個(Piとモータ兼用)
 ヘッドライト付きだす。

じゃあAndroidアプリを作ろうって話になるけど、
動画配信部分とラジコン操作部分をそれぞれ考えたら出来ちゃう算段。
■動画配信
 mjpg-streamerはJavaScriptとmotionJPG配信できる。
 それぞれ考えると、
 ・JavaScript
  ブラウザ表示できるWebViewを使えばすぐできると思うけど、遅延大きい。
 ・MJPEG
  早い。うまくやると遅延少ない。
  やたらすごいサンプル公開している方がいる
  ⇒neuralassemblyのメモ:AndroidでWifiカメラからのMJPEGストリームを表示する

 というわけでKanamaruさんが公開しているソースをありがたくお借りして、
 ラジコン操作部分を作ります。

■ラジコン操作
 元ネタはブラウザでボタン作って、ボタン押したらPOSTしてるだけなんで、
 アプリ上でボタン押したらPOSTするような何かを実装するだけでOK。
 android POSTでググルといっぱい出るから簡単に紹介するね。
 
 UIタスクでPOSTすると厳格モード先生がExeption起こすから、
 POST部分だけAsynctaskで実装するんだよ。
 今回実装したとこ抜粋するとこんな感じ。
//宣言して
 DoPost mPostTask;
//インスタンス作ってAsynctaskをexecute
        mPostTask = new DoPost();
     mPostTask.execute(mOldcode);
//UIとは別タスクにしないとstrictmodeに怒られる
    class DoPost extends AsyncTask<String, Void, Void> {
        @Override
        protected Void doInBackground(String... params) {
         String post =params[0];
         post("code",post);
         return null;
        }

        private void post(String name, String value1) {
         //ここら辺はよくあるPOSTスニペッド使う
         Log.d("posttest", "post "+ value1);
         HttpClient client = new DefaultHttpClient();
         HttpPost httppost = new HttpPost(mPostAddres);
         List<NameValuePair> params = new ArrayList<NameValuePair>();
         params.add(new BasicNameValuePair(name, value1));
         try{
             httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
             HttpResponse res = client.execute(httppost);
             ByteArrayOutputStream os = new ByteArrayOutputStream();
             res.getEntity().writeTo(os);
             Log.v("posttest", "result "+os.toString());
             Log.v("posttest", "status "+res.getStatusLine().getStatusCode());
             client.getConnectionManager().shutdown();
         }
         catch(Exception e){
             e.printStackTrace();
         } finally {
         }
        }
スニペッドを2つ組み合わせるだけでWebカメラジコンアプリ作れちゃうんだから世の中すごいよね。
Chick LabさんとKanamaruさんに多謝。

今回作ったアプリはここに置いときます。
Eclipceでインポートして使ってね。
Postview/bin/Postview.apkインスコしてね


一応使う時のポイントとかつぼとか
・表示直後に設定画面が出るから、server側のIPアドレスとWebカメラのサイズ合わせてね
・サーバ側のGPIO設定、デフォルトからいじってるよ。
 Postview_server/server_motor.pyみて。
  4:Front Light
 17:Light-Front
 18:Light-Back
 22:Reft-Front
 23:Reft-Back
・PythonのPostした時の戻り値を100→200にしたよ。Androidが200ほしいって言ったから。。。
 ここだけ修正したらChickLabさんの公開してるやつのままでいけるとおもうよ。
・アプリがボタン少ないのは、この後HWの構成変えるから、作りこみたくなかっただけ!

みんな頑張って

0 件のコメント:

コメントを投稿