2014/03/21からのアクセス回数 3913
Artisocとjavaで作られたクラスの橋渡しをするために、javaで作られたスクリプト言語pnutsを使用します。 Pnuts連携機能を使うことで、Artisocのモデルの変数の値を読み込んだり、変更することが可能となり、 ArtisocのモデルにjavaのGUIを利用した画面を追加することも可能になります。
Artisocでpnutsスクリプト機能を利用するには、Artisocプロフェッショナルバージョンが必要です。
pnutsと連携するためにArtisocに以下の2つの組み込み関数が用意されています。
これらの使い分けとしては、pnutsで関数を定義し、Artisocで使えるようにExcecPnutsでスクリプトファイルを実行するのに、 ExcecPnutsを利用し、pnutsの関数呼び出しにEvalPnutsを利用すると便利です。
ExecPnutsの動きを確認するために、最も簡単なモデル(p01.model)とpnutsスクリプト(
p01.pnuts)を使って、
どの動作をみてみます。
Artisocのモデルは、Universeの直下に変数vがあるだけで、Universeのステップの開始Univ_Step_Beginでpuntsスクリプトを実行し、 Universeのステップの終わりUniv_Step_Endで変数vの値をプリントするという簡単なものです。
p01.pnutsのスクリプトは、Universe.vの値を取得し、その値に1を足した値を新たにUniverse.vにセットする 簡単なものです。printlnの出力は、Artisocの画面にはでませんが、ArtisocのLinux版では端末の画面に出力されます。
pnutsからArtisocの変数の値を取得する場合には、PnutsUtil::getValue関数を使い、 値をセットする場合には、PnutsUtil::setValue関数を使用します。
v = PnutsUtil::getValue(engine, "Universe.v") println(v) PnutsUtil::setValue(engine, "Universe.v", v + 1)
実行するとUniverse.vの値が1ずつ増えていることが確認できます。
先の例では、変数vの値を1ずつ増やす簡単なものでしたが、JavaのGUIを使ってユーザがモデルの外から 値を設定する例を次に示します。*1
モデルには、p02.modelを使用し、pnutsスクリプトには
p02.pnutsを使用します。
モデルの変更点は、Univ_Initでp02.pnutsのスクリプトを実行している部分だけです。 これを実行すると、以下のようなJava Swingのフレームが表示され、テキストフィールドに値をセットすると、 Artisocのコンソール画面に表示される値が変更されます。
p02.pnutsのスクリプトをみてみましょう。説明のために行番号を付けています。
1 import("pnuts.awt.*") 2 import("javax.swing.*") 3 4 f = JFrame("pnuts test") 5 l = JLabel("Univser.v") 6 tf = JTextField(10) 7 tf.setText("") 8 b = JButton("変更") 9 b.setToolTipText("This is a JButton"); 10 layout(f, 11 [PnutsLayout, "cols=1,padx=10,pady=5", 12 [PnutsLayout, "cols=2,padx=2", 13 l, tf 14 ], 15 b 16 ] 17 ) 18 //f.setSize(200, 200) 19 f.pack() 20 f.show() 21 22 /**** 変更ボタンを押されたときのコールバック関数 ****/ 23 function do_b_update() 24 { 25 v = tf.getText() 26 println(v) 27 PnutsUtil::setValue(engine, "Universe.v", v) 28 } 29 30 bind(b, "actionPerformed", function(e) do_b_update()) 31 32 JOptionPane::setRootFrame(f)
このようにpnuts連携機能を使うとArtisocでjavaのGUI機能を使った独自のモデルを構築することができます。
先の例で、ArtisocにPnutsを使って別の処理を追加する場合、シミュレーションのエラー(PLAY_ERRORMSG) やシミュレーションの終了(PLAY_STOPPED)のタイミングが必要になります。
このような場合、pnutsのbind関数を使ってArtisocのengineからPLAY_ERRORMSG, PLAY_STOPPED等のイベントを取得し、 それに対するコールバック関数で処理することができます。
p02.pnutsにシミュレーションの終了時にGUIを閉じる処理を追加してみましょう。32行目の前に以下の処理を追加します。
function do_close(e) { id = e.getID() if (id == MASActionEvent::PLAY_ERRORMSG || id == MASActionEvent::PLAY_STOPPED) { f.dispose() } } bind(engine, "actionPerformed", do_close)
シミュレーションの終了ボタンを押すとjavaで作ったGUIが連動して閉じます。
pnutsで記述したスクリプトは、Artisocの外部で別のスレッドとして動いているため、 Artisocの実行環境設定で、実行ウェイトとして、1ミリ以上の値をセットしてください。
pnutsからArtisocの配列を参照する時には、PnutsUtil::getArray関数を使用し、セットするときにはPnuts::setArray関数を使用します。
例としては、p04.modelと
p04.pnutsを使用します。
この例題では、sia, sba, sda, ssaの配列の値をdia, dba, dda, dsaの配列にコピーしています。
配列変数の値を取得するには、getValueと同様にengineとモデルのパス(以下ではUniverse.sia)を指定します。
sia = PnutsUtil::getArray(engine, "Universe.sia")
配列の値をセットする場合には、pnutsで[]内に値をカンマ区切りでセットすると配列が作成されます。 以下のようにsa変数にHello, Mr., Takemotoとセットすると、Universe.dsaにその値がセットされます。
sa = ["Hello", "Mr.", "Takemoto"] PnutsUtil::setArray(engine, "Universe.dsa", sa)
pnutsからArtisocのエージェントを生成することができます。
エージェント生成の例として、アリの例題を作成してみます。 初期設定でランダムな方向に直進するアリエージェントをJavaで生成したボタンを押して 生成してみます。
モデルには、p_ant.modelを使用し、スクリプトには、
p_ant.pnutsを使用します。
p_ant.pnutsのSpawn Antボタンのコールバック関数を以下の様に定義します。 PnutsUtil::CreateAgt関数の引数は、engineと生成するエージェントのパスです。
function do_b_update() { PnutsUtil::CreateAgt(engine, "Universe.ground.ant") }
pnutsには、デバッガが組み込まれており、Pnutsスクリプト内からデバッガを起動することができます。
p_ant.pnutsの代わりにdebug.pnutsを起動します。(p_debug.model参照)
Univ_Init{ ExecPnuts("debug.pnuts") }
debug.pnuts の内容は、以下の様にします。loadFileの中にデバッグするスクリプトをセットします。
import("pnuts.tools.VisualDebugger") function debug() { loadFile(modelDir + "/p_ant.pnuts", VisualDebugger().createContext(getContext())) } fork(debug)
これを実行すると、以下の様なデバッガ画面が現れます。マウスで右クリックするとブレークポイントをセット することができますが、以下の様にコールバックにブレークポイントをセットするとフリーズしてしまいます。 (要検討)
しかし、Pnutsスクリプトの処理の流れや、変数の設定値をチェックしながらデバッグするにはとても助かります。
皆様のご意見、ご希望をお待ちしております。