遠隔地のチョロQ(キューステア)をUSTREAM.TVのストリーミングビデオで見ながら、Webブラウザ上でのキーボード操作で操縦できるWebアプリを作ってみました。以下、その仕組みについて詳しく解説していきます。

http://jp.youtube.com/watch?v=-n3XV6GGdWY
http://www.nicovideo.jp/watch/sm2432398

WebカメラとWebブラウザだけで動画配信できてしまうWebサービスです。今回はこのサービスを動画中継に使用しました。
USBと電子部品の橋渡しをしてくれるI/Oモジュール。FlashやRubyなどから電子部品を簡単に扱えるようになります。今回はミニリレーの制御に使用しています。
Gainerについては以下のショップで購入すると良いかもしれません。
使用方法については、以下の書籍が非常に参考になります。
付属の赤外線リモコンで制御できるチョロQ(キューステア)。今回はこれを操縦します。
Amazonでも購入することができます。
rubyとgainerの接続ができれば、他のOSでも動作すると思います。
config/environments/development.rb あたりの最後に以下のような記述を追加してください。
$gainer = Gainer::Serial.new('/dev/cu.usbserial-A2002mcq')
$gainer.digital_output = 0xf
sleep(1)
$gainer.digital_output = 0
sleep(1)
class TopController < ApplicationController
def frontleft
$gainer.digital_output[0] = false
$gainer.digital_output[1] = true
$gainer.digital_output[2] = false
$gainer.digital_output[3] = true
end
def front
$gainer.digital_output[0] = false
$gainer.digital_output[1] = true
$gainer.digital_output[2] = true
$gainer.digital_output[3] = true
end
def frontright
$gainer.digital_output[0] = false
$gainer.digital_output[1] = true
$gainer.digital_output[2] = true
$gainer.digital_output[3] = false
end
def stop
$gainer.digital_output[0] = true
$gainer.digital_output[1] = true
$gainer.digital_output[2] = false
$gainer.digital_output[3] = false
end
def backleft
$gainer.digital_output[0] = true
$gainer.digital_output[1] = false
$gainer.digital_output[2] = false
$gainer.digital_output[3] = true
end
def back
$gainer.digital_output[0] = true
$gainer.digital_output[1] = false
$gainer.digital_output[2] = true
$gainer.digital_output[3] = true
end
def backright
$gainer.digital_output[0] = true
$gainer.digital_output[1] = false
$gainer.digital_output[2] = true
$gainer.digital_output[3] = false
end
end
difital_output[0] = true などとすることで、gainerのデジタル出力を操作することができます。
<script type="text/javascript">
function keyput(event){
switch(event.keyCode){
case 81: key_q(); break;
case 87: key_w(); break;
case 69: key_e(); break;
case 90: key_z(); break;
case 88: key_x(); break;
case 67: key_c(); break;
}
}
function key_q(){
new Ajax.Request('/top/frontleft', {asynchronous:true, evalScripts:true, parameters:'authenticity_token='
+ encodeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
function key_w(){
new Ajax.Request('/top/front', {asynchronous:true, evalScripts:true, parameters:'authenticity_token=' + enc
odeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
function key_e(){
new Ajax.Request('/top/frontright', {asynchronous:true, evalScripts:true, parameters:'authenticity_token=
' + encodeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
function key_z(){
new Ajax.Request('/top/backleft', {asynchronous:true, evalScripts:true, parameters:'authenticity_token='
+ encodeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
function key_x(){
new Ajax.Request('/top/back', {asynchronous:true, evalScripts:true, parameters:'authenticity_token=' + en
codeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
function key_c(){
new Ajax.Request('/top/backright', {asynchronous:true, evalScripts:true, parameters:'authenticity_token='
+ encodeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
function keyputup(event){
new Ajax.Request('/top/stop', {asynchronous:true, evalScripts:true, parameters:'authenticity_token=' + enc
odeURIComponent('5c2a0299f9f219731bb72866e9831ce211999fad')}); return false;
}
document.onkeydown=keyput;
document.onkeyup=keyputup;
</script>
</head>
<body>
<embed width="416" height="340" flashvars="autoplay=true" src="http://ustream.tv/SxQwT0VkmQeydBJKd2fj1pniqS2xUiuz.us
c" type="application/x-shockwave-flash" allowfullscreen="true" />
<embed width="563" height="266" type="application/x-shockwave-flash" flashvars="channel=#gainer&server=chat1.ustream
.tv" pluginspage="http://www.adobe.com/go/getflashplayer" src="http://ustream.tv/IrcClient.swf" allowfullscreen="tru
e" />
<hr>
<table>
<tr>
<td><%= link_to_remote("left", :url => { :action => "frontleft" }) %></td>
<td><%= link_to_remote("front", :url => { :action => "front" }) %></td>
<td><%= link_to_remote("right", :url => { :action => "frontright" }) %></td>
</tr>
<tr>
<td><%= link_to_remote("left", :url => { :action => "backleft" }) %></td>
<td><%= link_to_remote("back", :url => { :action => "back" }) %></td>
<td><%= link_to_remote("right", :url => { :action => "backright" }) %></td>
</tr>
</table>
</body>
</html>
JavaScriptでキーイベントを取得して、AJAXでサーバー側にリクエストを飛ばしています。なのでustreamによる映像配信がページ遷移で途絶えることはありません。
Railsのlink_to_remote()を用いたリンクも用意しています。
使用しているリレーは941H-2C-5Dというもの。
秋葉原の秋月電子にて1個100円で購入しました。

この仕組みを使えば、色々と楽しそうなことができそうですね。
他にも面白いネタを考えています。次回もお楽しみに!
個人ブログ : 拡張現実ライフ