[[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]


Front page   New List of pages Search Recent changes   Help   RSS of recent changes