Firefox OSを載せたXperia arcと、node.jsが動作するRaspberry Piで三輪オムニホイールロボットを操作してみました。動画はこちら。
以下、動画について解説していきます。
はじめに
最近、Google Glass、Firefox OS、Windows ストアアプリ、enchantMOONのようにJavaScriptを用いて開発する環境が増えています。
私のWeb関係の知識ははHTML3.2時代で止まっていて、このままではとてもこれらの流れについていけそうにないので、少し知識をアップデートすることにしました。
また、別ジャンルで名刺サイズの小型PCであるRaspberry Piが去年から流行っていますが、この流行にも乗り遅れた感があるので、合わせて触ってみようと思い立ちました。
というわけで、これらを満たす目標として
- Firefox OSでnode.jsが動作するRaspberry PiとWebSocket通信し、ロボットを動かす
ことを目指してみます。
動かすロボットは、
で用いた三輪オムニホイールロボットとします。こちらはandroidアプリでbluetooth通信してロボットを動かしていましたが、こちらと同じ動作を目指します。
なお、androidでは画像処理による対象物追跡を行いましたが、さすがにJavaScriptで画像処理はキツイ気がするので今回は割愛しました。
システム
node.jsを動かしてモーターを動かすなら、
こちらでやられているようにmbedを用いた方がスマートな気がしますが、mbedは未体験ということもあり今回は見送りました。
方針が決まれば、あとは様々な方の成果を活用させて頂くだけ、ということで、以下でそれらへのポインタを示したいと思います。
Raspberry Pi上のnode.js
Raspberry Piにnode.jsをインストールし、Firefox OS(というよりブラウザ)からの指令を受け取れるようにする方法は
Interface誌2013年9月号の記事「ARMコンピュータRaspberryPi×HTML5でスマートI/O」に書いてあります。
この例では、指令に基づいてRaspberry Piのピンに接続したLEDを点灯させていましたが、その部分をシリアル通信でのaruduinoへの指令に変更します。
Raspberry Piからのシリアル通信は、
こちらのページのC言語のプログラムを用いました。リンク先の例ではRaspberry Pi上のピンでシリアル通信しているので/dev/ttyAMA0を用いていますが、今回私はUSBシリアルアダプタを用いたので/dev/ttyUSB0を指定します。(3.3V←→5Vのレベル変換が面倒だったので)
また、送る文字列ですが、コマンドラインの引数で与えた文字列をそのままaruduinoに送りたかったので、以下のようにしました。
main関数の引数部
int main(int argc, char *argv[]){
送信文字列の定義部
p_tx_buffer = &tx_buffer[0];
char *num_buffer = argv[1];
while(*num_buffer != '\0')
{
*p_tx_buffer++ = *num_buffer++;
}
*p_tx_buffer++ = '\0';
なお、このシリアル通信プログラムを起動する部分のJavaScriptは以下のような感じです。「[value]」の部分がブラウザから送られる文字列で、serialtestという名前をつけた上のシリアル通信用プログラムの引数となります。
server.on('connection', function(socket) {
socket.on('message', function(data){
console.log('Receive: ' + data);
send_to_arduino(data);
});
});
var send_to_arduino = function (value){
var spawn = require('child_process').spawn;
var sendexec = spawn('./serialtest', [value]);
sendexec.stdout.on('data', function(data){});
}
なお、「
Raspberry PiとNode.jsで作る独立稼働モバイルサーバ (Think IT)」によると、
node-serialportを用いるとnode.jsを通してRaspberry Pi/arduino間でJavaScriptで通信できるそうなので、そちらでもよさそうですね。
Firefox OSアプリ
Firefox OSアプリは実質Webアプリなので、HTML/CSS/JavaScriptで記述します。
- Raspberry PiにSSHでログインしてエディタでJavaScriptを編集
- Android上のChromeとFirefoxで動作確認
という手順で開発しました。ブラウザのリロードでアプリのアップデートが完了するのは、当たり前といえ新鮮な体験です。
AndroidのFirefoxで動作確認するとFirefox OSでもほぼ同じ動作をするので、あまりFirefox OSの出番はなく開発を進められました(Firefox OSの存在意義は…)。
今回は小さなアプリなのでそれほど苦労する部分はありませんでしたが、端末の画面の回転の検出にChromeとFirefoxで違いがあったので注意が必要でした。
var mqOrientation = window.matchMedia("(orientation: portrait)");
mqOrientation.addListener(function() {
// 画面回転検出時の処理
});
によってChromeとFirefox両方で画面回転を検出できます。
また、IP Webcamからの画像取得ですが、今回は簡易的に済まそうということで、IP Webcamのスナップショット画像を得る機能をひたすら呼び出してcanvasに描画し続けるという方法を取っています。
Firefox OSアプリのpackaged app化
Firefox OSでは、通常ブラウザ上で動作するWeb アプリを、zipで固めたpackaged appとして端末にインストールすることができます。
packaged appを作成するためのテンプレートとして今回は
kassy-kzさんのFirefoxOS_Templateを用いました。
packaged appをインストールする方法としては
- マーケットからインストール
- Firefox OSシミュレーターからインストール
- ローカルネットワーク上のサーバーからのインストール
などがあります。私は公式端末であるKeonやPeakを購入しておらず、Nexus SやGalaxy S2などといった端末に自分でビルドしたFirefox OSをインストールするという方法でFirefox OSを試しています。
この自前ビルドの端末ですが、上記の2の方法でのインストールがうまくいきませんでした。Remote Debuggingを有効にしてはいるのですが。
仕方ないので、3の方法でインストールしました。リンク先の解説の通りですが、package.manifest は、アプリのmanifest.webappをコピーして、package_pathの行を追加するだけで良さそうでした。インストール後、「XXXX downloading...」という通知が、端末を再起動するまで消えないのですが、気にしないことにします。
感想など
Androidアプリで行っていたbluetoothでのロボット操作を、Firefox OSでも実現できました。ただし、いくつか気になる点もありました。
まず、モーターへ指令が到達するまでのステップ数がかなり増えているので若干遅延が発生することがあります。Wifiを利用しているので、Wifiの干渉が大きい場所ではこの遅延がより大きくなることが予想されます。
また、タッチイベントを全て送ると処理が追いつかなくなり、やはり遅延が大きくなるので、指令を送信する回数を減らすなどの工夫が必要な場面がありました。
一方、良い面ですが、Firefox OS用に作成したアプリはWebアプリなので、androidでもiOSデバイスでも動作する(はず)というのはなかなか魅力的に思えました。
ただ、どうしても機能が最大公約数的になりますし、結局各端末でデバッグしなければいけないということも起こりがちなので良し悪しかなあと思います。なんだかこの辺はJavaが出てきたときに言われたことの繰り返しですね。
あと個人的には、ビルドだけして放っておいたFirefox OS端末の使いみちができてよかったな、と。
そんな感じで今回は以上です。
こちらもどうぞ
「ラズパイ4対応 カラー図解 最新 Raspberry Piで学ぶ電子工作」、「実例で学ぶRaspberry Pi電子工作」、「Raspberry Piではじめる機械学習」を執筆しました。