SyntaxHighlighter

2011-02-07

webgl+websocket+arduino

先日、webglの勉強会で、kinectをインターフェイスとしてwebglを動かすというデモを見て、感動しました。node.jsやwebsocketを使うと、外部機器からのデータをブラウザに取得出来るようだという事を知ったので、自分も試してみようと思いました。

ここは是非、自分もkinectを!と言いたいところだけど、現在kinectを買うだけの持ち合わせが無いので、とりあえず手元にあるもので、何となく外部機器をwebglを連携してみようかと考え、結局今手元にあるのが、
・Arduino
・ArduinoのEthernetシールド
・ずっと前MTMで買った脈拍センサー
#これ全部そろえると、kinectの半分の値段にはなりそうなんだけどね〜〜〜

とりあえず、今回はこれを使ってみる事にしました。

[Arduino+Ethernetシールド]
node.jsを使ってみようかと思っていたけど、きっとArduino用websocketライブラリがあるに違いないと、探してみたら、cwebsocketというモノが見つかりました。このライブラリのサンプル(echo.pde)を見て、使い方を確認してみた。
120行目あたりにある、

while (!client.available() && client.connected())

が、websocketをopenした後の、クライアントからのデータ待ちを表しているようなので、この部分に、サーバからクライアントへのデータ出力を実施すれば、一方的にクライアントにArduinoが取得したセンサデータを垂れ流せるよう、という事で、以下のようなコードを作成。
while (!client.available() && client.connected()) {
char data[BUF_LEN];
size_t data_len = BUF_LEN;
out_len = BUF_LEN;

HB_GetNextData(&beat_mean, &beat_isbeat, &beat_rate);
HB_toString(beat_mean, beat_isbeat, beat_rate, data, &data_len);
frame_type = ws_make_frame((uint8_t*)data, data_len, buffer, &out_len, WS_TEXT_FRAME);
if (frame_type != WS_TEXT_FRAME) {
terminate();
}
client.write(buffer, out_len);
//        delay(1000);

}; // wait for data


HB_GetNextDataは脈拍センサからデータを取得する(以前自分が勝手に作ったものを少し手直ししただけ)関数で、過去データの平均値と、データが大きく変化したかを表すboolean、計算した心拍数を返します。HB_toStringはそれらデータを文字列に変換する関数でJSON形式にする。以下のような感じになります。

{ "mean":300,"isbeat":false,"rate":60}

これを、websocketで送ります。

このライブラリで複数クライアントへのブロードキャストとかどうするんだろうと気になりますが、気が向いたらやってみたいなあ。。。

[websocket+webgl]

websocketデータの取得は、よくあるサンプルコードそのままです。
var ws;
var heartData;
function initWS() {
ws = new WebSocket("ws://xxx.xxx.xxx.xxx:8080/echo");  #websocketライブラリのechoサンプルを少し改造しただけなので、こんなURLに。。。

ws.onopen = function() {
console.log("Open ws");
};

ws.onmessage = function(evt) {
heartData = JSON.parse(evt.data);
var node = document.getElementById("mean");
node.replaceChild(document.createTextNode(heartData.mean), node.childNodes[0]);
var node = document.getElementById("beat");
node.replaceChild(document.createTextNode(heartData.isbeat), node.childNodes[0]);
var node = document.getElementById("rate");
node.replaceChild(document.createTextNode(heartData.rate), node.childNodes[0]);
}
}


Arduinoからは色々データを送ってみたものの、今回は平均値(mean)に応じて、モデルの大きさを変えるだけの単純なものにしてみました。モデルは単純な球でwebglのプログラムや使用したツール、モデル作成法は以前の記事と大して変わりません。サイズ変更は、球のレンダリングの前に、
function valuemap(value, low1, high1, low2, high2) {
if (value <= low1) return low2;
if (value >= high1) return high2;
return (high2-low2)/(high1-low1) * (value - low1) + low2;
}

if (heartData) {
var s = valuemap(heartData.mean, 200, 700, 0.3, 3);
mvMatrix.scale([s,s,s]);  #現在のモデル行列をスケールするオレオレ関数です。
}

を実行するだけです。heartData.mean値に比例して球のサイズが変わります。

下記のような動画の通り動きます。iPhoneで撮ったので幅が狭いとか、脈拍数低過ぎとか、突っ込みどころは満載ですが。。。



やってみての感想として、Arduino自体がwebsocketのサーバになる今回の構成だとあまり使い道と言うか発展性が無い気がしてます。node.jsとかでサーバを立てておいた方が、細かい事が簡単にできるだろうし(Cはやっぱり文字列とか面倒だし・・・)、複数のArduinoを使いたいとなった場合に、データを集約するサーバにいったん送信して、そのサーバに対してクライアントはアクセスした方が良いんだろうなあと思った次第です。

という事で何の役に立つか分かりませんが、参考までに。

0 件のコメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...