2010年5月15日土曜日

WiiRemoteのイベントをScratchに送信してみる

動機
1. WiiRemoteの値(加速度)をScratchに送信はできた
2. ボタンイベントとかのイベント系をやってみよう.


やってみた
1. 前回までできていることを前提.

2. WRLImpl.javaをさらに(?)いじる
WRLImpl.javaに追加
ボタン処理をしている所,とりあえずOneボタンを押している処理を探して追加.
sendtoscratch(out, "broadcast \"OneButton\"");


3.動かす…できた.

'にゃー'.

WiiRemoteの値(加速度)をScratchに送信してみる

動機
1. Scratchに外から値は送れた
2. NXTだとBluetooth通信だなぁ…。JavaでBluetooth通信制御ってどうやるんだろう?あった.これ(JavaでBluetoothデバイスを探索するサンプルプログラムを作ってみた).
3. JavaでWii Remoteと通信する例なんてあるんだ.これ(JavaとWiiリモコンをBluetoothでつなげてみよう).
4. WiiRemoteJってのがあるんだね.これ(WiiリモコンからTwitterにPostしてみた)が参考になりそうだ.
5. やってみよう.
(上記各ページに感謝)


やってみた
1. bluecoveについて
1.1 MacOSX 10.6 ( Snow Leopard )では 2.1.0版 だとうまくないらしい.2.1.1-SNAPSHOT版 を使うことにする

2. WiiRemoteJ
2.1 1.6があったのでこれを使ってみる.
2.2 bluecove-2.1.1-SNAPSHOT.jarとWiiRemoteJ.jarにClass Pathを通してサンプルであるWRLImpl.javaを実行.
2.3 接続はうまくいかない場合は接続解除やプログラムの再実行などやりながら…QCのパッチのときよりは簡単に思えるw.できた.


3. WRLImpl.javaをいじる
WRLImpl.javaにあれこれ追加
とりあえず通信用の出力先と送信タイミングを空けるためのタイムスタンプ用の変数を用意
 private static PrintStream out;
private static long stamp;


送信用のメソッドを追加
 static void sendtoscratch(PrintStream out, String dataOut) {
if (out==null) return;
byte[] sizeBytes = { 0, 0, 0, 0 };
sizeBytes[3] = (byte) (dataOut.length());
for (int i = 0; i < 4; i++) {
out.write(sizeBytes[i]);
}
out.print(dataOut);
}


mainの最初あたりでsocketと出力先の確保, stamp初期化.
  Socket socket = new Socket("127.0.0.1", 42001);
out = new PrintStream(socket.getOutputStream());
stamp = 0;


加速度を描画している場所での値を利用して送信(graphic.drawLine(…)とかしているあたりとか)
     if (stamp < System.currentTimeMillis()) {
StringBuffer message = new StringBuffer("sensor-update");
message.append(" \"AccX\" ");
message.append((x - 300));
message.append(" \"AccY\" ");
message.append((y - 300));
message.append(" \"AccZ\" ");
message.append((z - 300));
sendtoscratch(out, message.toString());
stamp = System.currentTimeMillis() + 500;
}


4:試す
4.1: Scratch側は前回のように遠隔地センサ接続を有効にしておく
4.2: '〜センサーの値'に'AccX', 'AccY', 'AccZ'がでる,

4.3: 左のチェック入れて表示したらこんな感じ.

当然プログラム中でもこの値は使えます.

Scratchに外から値を送ってみた

動機
1: これ(MTM05 - こどもプログラミングサークル スクラッチ)をみてScratchとArduinoの連携を知る.
2: これ(Scratch+Arduino)でやり方と動作を確認.とりあえず自分でもできた.
3: どうやってやっているのか中身を確認.とググるなどで,picoboardを知る.
4: 自作はできないのかなーとおもっていたらこれ(YouTube - Scratch and LEGO NXT)を見つける.
5: これで42001ポートで通信できることを知る.


やってみる
コード(Port42001.java):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class Port42001 {
public static void main(String[] args) {
String ip = "127.0.0.1";
int port = 42001;
try {
Socket socket = new Socket(ip, port);
PrintStream out = new PrintStream(socket.getOutputStream());
BufferedReader systemin = new BufferedReader(new InputStreamReader(
System.in));
String line;
System.out.println("'q' is 'quit'.");

while (true) {
System.out.print(">");
line = systemin.readLine();
sendtoscratch(out, "sensor-update \"Scratch-Value0\" " + line);
if (line.equals("q")) {
break;
}
}
systemin.close();
out.close();
socket.close();
} catch (IOException e) {
System.out.println("Can not connect to the server (" + ip + ") .");
System.exit(1);
}
}

static void sendtoscratch(PrintStream out, String dataOut) {
byte[] sizeBytes = { 0, 0, 0, 0 };
sizeBytes[3] = (byte) (dataOut.length());
for (int i = 0; i < 4; i++) {
out.write(sizeBytes[i]);
}
out.print(dataOut);
}
}

もちろんJavaである必要はない


実行
1: Scratchで'遠隔地センサを有効にする'をする.
1.1: '調べる'にする.

1.2: '〜センサーの値'でコンテクストメニューを出し,.'遠隔地センサを有効にする'を選ぶ.


2: Java実行
2.1: とりあえず'11'とか送ってみる

2.2: 送信したセンサ名が選択可能になる

2.3: 選択して左側チェックボックスにチェックを入れる.

2.4: 画面に表示される


2.5: 空白がなければ文字列もいけた