- The added line is THIS COLOR.
- The deleted line is THIS COLOR.
[[Tutorial]]
#contents
*エージェント間でのメッセージのやり取り [#he80bd53]
前回はSIGViewerからエージェントにメッセージを送信して受信したエージェントはお辞儀をするというサンプルを紹介しました。今回はエージェント間でのメッセージのやりとりを行う、サンプルコードを紹介します。
**メッセージ送信者のコントローラ作成 [#pd6017d2]
まずメッセージの送信を行うコントローラを作成します。
$ emacs SendController.cpp
SendController.cpp
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#define ARY_SIZE(ARY) ( (int)(sizeof(ARY)/sizeof(ARY[0])) )
class SendController : public Controller
{
public:
//シミュレーション開始時に一度だけ呼出される関数onInitの利用を宣言します。
void onInit(InitEvent &evt);
double onAction(ActionEvent &evt);
};
void SendController::onInit(InitEvent &evt)
{
SimObj *my = getObj(myname());
if (!my->dynamics()) {
//右手、左手を下に下げ、180°後ろに回転します。
my->setJointAngle("LARM_JOINT2", DEG2RAD(-90));
my->setJointAngle("RARM_JOINT2", DEG2RAD(90));
my->setAxisAndAngle(0, 1.0, 0, DEG2RAD(180));
}
}
double SendController::onAction(ActionEvent &evt)
{
//メッセージを作成します。
char *strs[] = {
"Hello!!",
};
//メッセージを送信します。
broadcastMessage(ARY_SIZE(strs),strs);
//5秒置きにメッセージを送信します。
return 5.0;
}
extern "C" Controller * createController ()
{
return new SendController;
}
これは5秒置きにメッセージ"Hello!"を送信するコントローラのサンプルです。broadcastMessageでは近くにいる周りのエージェント全員にメッセージを送信します。
これは5秒置きにメッセージ"Hello!"を送信するコントローラのサンプルです。broadcastMessageではエージェント全員にメッセージを送信します。
メッセージを送る相手を指定したいときはbroadcastMessageの代わりにsendMessageを用いて以下のように、メッセージを送る相手を指定します。
broadcastMessage(ARY_SIZE(strs),strs);
↓
sendMessaage("robot_000",ARY_SIZE(strs), strs);
**メッセージ受信者のコントローラ作成 [#sb6efc03]
次にメッセージの受信を行うエージェントコントローラを作成します。
$ emacs RecvController.cpp
RecvController.cpp
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
class RecvController : public Controller
{
public:
double onAction(ActionEvent &evt);
//メッセージ受信時に呼び出される関数onRecvMessageの利用を宣言します。
void onRecvMessage(RecvMessageEvent &evt);
};
double RecvController::onAction(ActionEvent &evt)
{
SimObj *my = getObj(myname());
if (!my->dynamics()) {
//上がった手を下げます。
my->setJointAngle("LARM_JOINT2", DEG2RAD(0));
}
return 1.0;
}
//メッセージ受信時
void RecvController::onRecvMessage(RecvMessageEvent &evt)
{
//自分自身の取得
SimObj *my = getObj(myname());
// メッセージの送り主表示
LOG_MSG(("sender : %s", evt.getSender()));
// getSize で送られてきた文字列数を取得する
int n = evt.getSize();
LOG_MSG(("# of string : %d", n));
for (int i=0; i<n; i++) {
// 文字列を順に取得する
LOG_MSG(("string[%d] : %s", i, evt.getString(i)));
//手を上げます。
if (!my->dynamics() ) {
my->setJointAngle("LARM_JOINT2", DEG2RAD(180));
}
}
}
extern "C" Controller * createController ()
{
return new RecvController;
}
これはメッセージを受信したら手を上げるというサンプルです。また、onActionで1秒ごとに上がった手を下げようとします。
それではコンパイルします。
$ make
**世界ファイルの作成 [#me49924f]
次に世界ファイルの作成をします。
$ cd ..
$ emacs xml/MyWorld.xml
<?xml version="1.0" encoding="utf8"?>
<world name="VisTest2">
<gravity x="0.0" y="-9.8" z="0.0"/>
<!--メッセージ送信エージェントMan-niiの設定-->
<instanciate class="Man-nii.xml">
<set-attr-value name="name" value="man_000"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="language" value="c++"/>
<!--オブジェクトファイルSendController.soの指定-->
<set-attr-value name="implementation"
value="./NewWorld/SendController.so"/>
<!--エージェントの位置(x,y,z)-->
<set-attr-value name="x" value="0.0"/>
<set-attr-value name="y" value="60.0"/>
<set-attr-value name="z" value="60.0"/>
</instanciate>
<!--メッセージ受信エージェントRobot-niiの設定-->
<instanciate class="Robot-nii.xml">
<set-attr-value name="name" value="robot_000"/>
<set-attr-value name="language" value="c++"/>
<!--オブジェクトファイルRecvController.soの指定-->
<set-attr-value name="implementation"
value="./NewWorld/RecvController.so"/>
<!--動力学演算をfalseに設定-->
<set-attr-value name="dynamics" value="false"/>
<!--エージェントの位置(x,y,z)-->
<set-attr-value name="x" value="0.0"/>
<set-attr-value name="y" value="60.0"/>
<set-attr-value name="z" value="-60.0"/>
</instanciate>
人型エージェントが、ヒューマノイド型エージェントにメッセージを送信します。
**起動 [#k2bccc17]
起動して見てみましょう。
$ ./sigserver.sh -p 9001
SIGViewerで接続して、シミュレーションを開始するとonInitにより、人型エージェント(メッセージ送信者)が手を下して、後ろを振り返ります。そして5秒に一回ロボット(メッセージ受信者)がメッセージに反応して手を挙げているのがわかります。
#ref(mess_1.jpg)
SIGViewerの下のほうにあるmessagesタブをクリックします。するとロボットがメッセージに反応して送信者と、文字列数、とその内容が表示されます。
#ref(mess_2.jpg)
文字列は同時に複数送ることができます。送信者コントローラのメッセージ作成時に以下のように記述します。
//メッセージを作成します。
char *strs[] = {
"Hello!!",
"How are you",
};
**エージェント間でのテキスト文字列の送受信 [#a561e72f]
次にエージェント間でのテキスト文字列の送受信について説明します。テキスト文字列は人間が声を出すのと同じように、自分の声が届く範囲を指定することができます。
***テキスト送信者のコントローラ作成 [#wb648f75]