2010年3月5日金曜日

電メモ工学第一

どうも、だんだん日記のタイトルがめちゃくちゃになってきたQです、こんちには。

人生は色々あるものです。それは必ずしも良いことではないものです。つまり、プログラムがメンドクサイのである。何がメンドクサイって例のprocessing。言語自体が鋭意開発中?かつ、ライブラリ類もまあちょっと時間が経てばすぐbackward compatibilityが失われていたりするわけです。

知る人ぞ知るあれの中で、roombaを動かす為のプログラムがprocessingで書かれているのだがこれがちょっと古くて今のprocessingやライブラリに合って無いんだよな…。いくつかのプログラムを検索してみたら見つからないのもまあ頷ける。

1.RoombaThereminToo
とりあえずまねして作ってみたが、全く駄目駄目だったので、現在のライブラリの仕様にあわせて書き直してみた。


import krister.Ess.*;
import roombacomm.*;

String roombacommPort = "COMxx";

RoombaCommSerial roombacomm;
AudioChannel mySoundA;
SineWave myWave;
RateShift myRateShift;

int pshift;

void roombacommPortSelected()
{
roombacomm = new RoombaCommSerial();
if( roombacommPort.equals("testdummy") ) return;
println("opening roomba serial port '" +roombacommPort+"'");
if( ! roombacomm.connect( roombacommPort ) ) {
println("oh noes");
}
println("Roomba startup");
roombacomm.startup();
roombacomm.control();
roombacomm.full();
roombacomm.pause(50);
println("Playing some notes");
roombacomm.playNote( 72, 8 );
roombacomm.pause( 200 );
roombacomm.playNote( 72, 10 );
roombacomm.pause( 200 );
}

void roombacommSetup()
{
if( roombacommPort != null ) {
roombacommPortSelected();
return;
}

RoombaComm rc = new RoombaCommSerial();
final String portlist[] = rc.listPorts();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
String port = (String) javax.swing.JOptionPane.showInputDialog( null,
"Select Roomba Port",
"RoombaThereminToo",
javax.swing.JOptionPane.QUESTION_MESSAGE,
null, portlist, null);
if( port == null ) {
javax.swing.JOptionPane.showMessageDialog(null, "No port chosen, goodbye");
System.exit(1);
}
roombacommPort = port;
roombacommPortSelected();
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}

void setup() {
roombacommSetup();
Ess.start(this);
mySoundA = new AudioChannel();
mySoundA.initChannel(mySoundA.frames(250));
myWave = new SineWave(960,.75);
myWave.generate(mySoundA,0,mySoundA.frames(250));
myRateShift = new RateShift(0);
pshift = 0;
println("start");
}

void parseRoombaSensors(){
if(!roombacomm.cliffLeft()){
pshift++;
}
if(!roombacomm.cliffFrontLeft()){
pshift++;
}
if(!roombacomm.cliffRight()){
pshift--;
}
if(!roombacomm.cliffFrontRight()){
pshift--;
}
if(!roombacomm.wheelDropLeft()){
pshift++;
}
if(!roombacomm.wheelDropRight()){
pshift--;
}

if(!roombacomm.wheelDropLeft() && !roombacomm.wheelDropRight()){
pshift = 0;
mySoundA.stop();
myWave.generate(mySoundA,0,mySoundA.frames(250));
}else if(roombacomm.bump() && mySoundA.state == Ess.STOPPED){
mySoundA.play(Ess.FOREVER);
}
}

void audioChannelLoop(AudioChannel ch){
if(pshift != 0){
myRateShift.percent = Ess.calcShift(0.03*pshift);
myRateShift.filter(mySoundA);
pshift = 0;
}
}

void draw() {
roombacomm.sensors();
parseRoombaSensors();
}

はっきりいって、まともに音出ません。なんか知らんけど最初のうちは動くけど、途中からザーザー言い出すし。で、そもそもrate変更とかする必要ないんじゃね?と思って次のように変えてみた。


2.RoombaThereminToo2
変更点
void setup() {
roombacommSetup();
Ess.start(this);
mySoundA = new AudioChannel();
mySoundA.initChannel(mySoundA.frames(100));
myWave = new SineWave(960,.75);
myWave.generate(mySoundA,0,mySoundA.frames(100));
pshift = 0;
println("start");
}

void audioChannelLoop(AudioChannel ch){
if(pshift != 0){
myWave.frequency += 2*pshift;
myWave.generate(mySoundA);
pshift = 0;
}
}

かなりましになったけど、まだグリッチが入る。おそらく位相が合わないせいとかマシンパワーのせいとかだと思うけど、本質的にprocessingもEssも理解して無いので絶対どっかにバグはある。まあ、そもそもこれを勉強する気は今のところ全く無いのでこんなものでいいや。
//確かに楽な言語ではある。クリティカルな用途じゃなければまあ意外と使い勝手はいいのかも。





3.%gの注意点
printf("%g",i);
とするときに%gにiが代入されるが、iが整数型だとおかしくなる。doubleを使うか、明示的にキャストをする必要がある。





プログラムを書けるようになる、という経過を辿る時、サンプルソースを見るというのは避けられないことだと思う。しかし、サンプルソースはベストなケースで「それを書いた人の環境と時期でしか動くことは保証されていない」と考えるべきだということが良く分かった。ひどい場合はバグだらけなんてこともままある。只おかげで勉強になったりすることもあるんだけど…

あんまり人のソース読んでどうこうっていう経験がないからなぁ…今更なんだよな。





面倒に
感謝されない
理解あり

0 件のコメント:

コメントを投稿