Up:[[Tutorial]]     Previous:[[人間型エージェントの操作]]     Next:[[視覚に関する操作]]
Up:[[Tutorial]]     Previous:[[Humanoid agent operations]]     Next:[[Vision sensor]]

----
#contents

*エージェント間でのメッセージのやり取り [#he80bd53]
* Exchange of messages between agents. [#ia7882aa]

※このチュートリアルはv2.1.0以降対応しています。
※This tutorial is valid only for later than v2.1.0.

前回はクライアント(SIGViewer)からエージェントにメッセージを送信し、受信したエージェントはお辞儀をするというサンプルを紹介しました。今回はエージェント間でのやり取りを行うサンプルコードを紹介します。

**メッセージの送受信 [#v4c148e5]
** Sending and receiving messages [#d353e783]

***メッセージ送信者のコントローラ作成 [#pd6017d2]
*** Controller of message sender [#zd064119]

まずSIGVerse作業ディレクトリに移動し、メッセージの送信を行うコントローラを作成します。
Create a controller for sending messages.

 $ cd ~/MyWorld
 $ emacs SendController.cpp

SendController.cpp
#highlight(cpp){{
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#gist(sigverse-git/4ec290ead83ed03833efd8cd5791531f);

#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
#define ARY_SIZE(ARY) ( (int)(sizeof(ARY)/sizeof(ARY[0])) )
This controller send a message "Hello!" to the robot agent every second.

class SendController : public Controller
{
public:
  //シミュレーション開始時に一度だけ呼出される関数onInitの利用を宣言します
  void onInit(InitEvent &evt);
  double onAction(ActionEvent &evt);
};
If you want to send a message to all of the agents in the world, you should use broadcastMsg instead of sendMsg.

void SendController::onInit(InitEvent &evt)
{
  SimObj *my = getObj(myname());

  //右手、左手を下げ、体全体を180(deg)後ろに回転させます
  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)
{
  //メッセージを作成します
  std::string msg = "Hello!!";

  //"robot_000"にメッセージを送信します
  sendMsg("robot_000", msg);

  //1秒おきにonActionが呼び出されます
  return 1.0;
}

extern "C"  Controller * createController ()
{
  return new SendController;
}
}}
これは1秒おきにメッセージ"Hello!"を送信するコントローラのサンプルです。sendMsgでは最初の引数で送信先のエージェント名を指定します。

全エンティティ(ビューワーなどのサービスも含む)にメッセージを送信する場合はsendMsgの代わりにbroadcastMsgを用います。

#highlight(cpp:firstline[33]){{
Old
#highlight(cpp:firstline[38]){{
 sendMsg("robot_000",msg);
}}
         ↓
#highlight(cpp:firstline[33]){{
New
#highlight(cpp:firstline[38]){{
 broadcastMsg(msg);
}}

***メッセージ受信者のコントローラ作成 [#sb6efc03]
次にメッセージの受信を行うエージェントコントローラを作成します。
*** Controller to receive messages [#i2790ab2]

Create a controller to receive messages.

 $ emacs RecvController.cpp

RecvController.cpp

#highlight(cpp){{
#include <string>
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#gist(sigverse-git/dfd3d5c6d9d64180ca9eb8ffba54d544);

#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )

class RecvController : public Controller
{
public:
  double onAction(ActionEvent &evt);

  //メッセージ受信時に呼び出される関数onRecvMsgの利用を宣言します
  void onRecvMsg(RecvMsgEvent &evt);
This controller put the agent's hand up if a message "Hello!!" comes.
The agent will put the hand down every 0.5 second.

private:
  bool raise_hand;
};

double RecvController::onAction(ActionEvent &evt)
{
  SimObj *my = getObj(myname());
Compiling the controller.

  //上がった手を下げます。
  if(raise_hand)
    my->setJointAngle("LARM_JOINT2", DEG2RAD(0));
 $ ./sigmake.sh SendController.cpp RecvController.cpp

  return 0.5;
}

//メッセージ受信時
void RecvController::onRecvMsg(RecvMsgEvent &evt)
{
  //自分自身の取得
  SimObj *my = getObj(myname());
*** Creating a worldfile [#w395fedb]

  // メッセージの送り主表示
  std::string sender = evt.getSender();
  LOG_MSG(("sender : %s", sender.c_str()));
 $ emacs MessageWorld.xml

  // 文字列を取得
  std::string msg = evt.getMsg();
  LOG_MSG(("message : %s", msg.c_str()));
#gist(sigverse-git/008dee0218d42c41388f7e02a2fe09c5);

  //メッセージが"Hello!!"なら手を上げます
  if(msg == "Hello!!") {
    my->setJointAngle("LARM_JOINT2", DEG2RAD(180));
    raise_hand = true;
  }
}
In this controller, a human avator will send a message to a humanoid agent.

extern "C"  Controller * createController ()
{
  return new RecvController;
}
}}
これはメッセージを受信したら手を上げるというサンプルです。また、onActionで0.5秒ごとに上がった手を下げようとします。

それではコンパイルします。
*** Execution [#tb38ac14]

 $ ./sigmake.sh SendController.cpp RecvController.cpp
 $ sigserver.sh -w ./MessageWorld.xml 

***世界ファイルの作成 [#me49924f]
First, the avatar agent put a hand down and turn back by onInit function.
Then, you can see that the agent put it's hand up every second with receiving a message.

次に世界ファイルを作成します。
#ref(./message_1.PNG,40%)

 $ emacs MessageWorld.xml

MessageWorld.xml
#highlight(xml){{
<?xml version="1.0" encoding="utf8"?>
 <world name="myworld3">
 
   <gravity x="0.0" y="-980.7" 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++"/>
 
 <!--メッセージ送信者のコントローラ指定-->
         <set-attr-value name="implementation"
 value="./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++"/>
 
 <!--メッセージ受信者のコントローラ指定-->
         <set-attr-value name="implementation"
 value="./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>
</world>
}}
人型エージェントが、ヒューマノイド型エージェントにメッセージを送信します。
***起動 [#k2bccc17]
** Specification of message reachable area [#a22b41bf]

起動して見てみましょう。
This part explains how to specify the maximum length of the reachable area of the message sending function.

 $ sigserver.sh -w ./MessageWorld.xml 
*** Controller of text message sender [#we283cc2]

SIGViewerで接続して、シミュレーションを開始するとonInitにより、人型エージェント(メッセージ送信者)が手を下して、後ろを振り返ります。そして1秒に一回ロボットが人間エージェントからメッセージを受信して手を挙げているのがわかります。
Create another controller to send messages.

#ref(エージェント間のメッセージのやりとり(v2.0系)/mess_1.PNG,40%)

**メッセージ送信範囲の指定 [#a561e72f]

次にメッセージ送信時にメッセージが届く範囲を指定するサンプルを紹介します。

***テキスト送信者のコントローラ作成 [#wb648f75]
メッセージを送信するコントローラを新しく作成します。

 $ emacs SendController2.cpp 

SendController2.cpp
#highlight(cpp){{
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"

#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
#define ARY_SIZE(ARY) ( (int)(sizeof(ARY)/sizeof(ARY[0])) )
#gist(sigverse-git/8a057f168978dd46bb2c48ae5c912a11);

class SendController : public Controller
{
public:
  //シミュレーション開始時に一度だけ呼出される関数onInitの利用を宣言します
  void onInit(InitEvent &evt);
  double onAction(ActionEvent &evt);
};
The second argument of the broadcastMsg, 300, means that the maximum distance of the message reachable area is 3 meters.
If you omit the secnod argument, the message will be reached to all of the agents irrespective of the distance.

void SendController::onInit(InitEvent &evt)
{
  SimObj *my = getObj(myname());
This agent keeps on sending a message and moving to z-axis.

  //右手、左手を下げ、体全体を180(deg)後ろに回転させます
  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)
{
  SimObj *my = getObj(myname());

  //自分の位置を得ます
  Vector3d vec;
  my->getPosition(vec);
*** Compiling [#k7a9b5fc]

  //z方向に20移動します
  my->setPosition( vec.x(), vec.y(), vec.z() + 20 );

  //メッセージを作成します
  std::string msg = "Hello!!";

  //半径3m以内のすべてのエージェントに対してメッセージを送信します
  broadcastMsg(msg, 300.0);

  //1秒おきにonActionが呼び出されます
  return 1.0;
}

extern "C"  Controller * createController ()
{
  return new SendController;
}
}}
こちらも先ほどのサンプルと同様1秒に1回"Hello!!"を送信するコントローラです。broadcastMsgの2番目の引数を300.0とすることによりメッセージが届く範囲を3mに指定しました。2番目の引数を指定しない場合は距離に関係なくメッセージが届きます。

このエージェントはz方向にどんどん移動しながらテキストを送信します。つまりメッセージを受信するエージェントからはどんどん遠ざかりながらテキストを送信します。


***コンパイル [#bbf536df]
コンパイルします。

 $ ./sigmake.sh SendController2.cpp

***世界ファイルの編集 [#m7f88908]
*** Modification of the world file [#s62dc619]

次に世界ファイルを変更します。

 $ emacs MessageWorld.xml

MessageWorld.xml
Modify the MessageWorld.xml to change the controller for sending agent

メッセージ送信者コントローラの修正
Old
#highlight(xml:firstline[13]){{
 <!--メッセージ送信者コントローラ指定-->
       <set-attr-value name="implementation"
 value="./SendController.so"/>
       <set-attr-value name="implementation" value="./SendController.so"/>
}}
    ↓

New
#highlight(xml:firstline[13]){{        
 <!--メッセージ送信者コントローラ指定-->
       <set-attr-value name="implementation"
 value="./SendController2.so"/>
       <set-attr-value name="implementation" value="./SendController2.so"/>
}}
 
***起動 [#o073f136]
それでは実行してみます。
*** Execution [#m24d78ab]

 $ sigserver.sh -w ./MessageWorld.xml

SIGVierwerで接続して、シミュレーションを開始してみます。
#ref(エージェント間のメッセージのやりとり(v2.0系)/mess_3.PNG,40%)
#ref(./message_3.PNG,40%)

メッセージ送信者が遠ざかりながらメッセージを送信しているのがわかります。
エージェントのメッセージがどこまで届くのか確認してみてください。
You can see the agent sending messages with backing away from the receiver.
Please check how far the message reaches to the receiver.

**ビューワーへメッセージ送信 [#bb25270a]
broadcastMsgを使用した場合、すべてのエンティティ、ビューワー、サービスにメッセージが届きます。メッセージを受信したビューワーはメッセージログとして表示します。

sendMsgを使ってコントローラ同様ビューワーにもメッセージを送信することができます。このときビューワーがサーバに接続する際に指定したサービス名をメッセージ送信先に指定します。
サービス名を"SIGViewer"と設定してサーバに接続した場合はSendMsg関数を以下のように修正します。
** Sending message to the SIGViewer [#sa02f588]
If the broadcastMsg is used, the message will be reached to all of the agents, SIGViewer and SIGVerse services.
The SIGViewer will show the received message as log message.

You can send messages to the SIGViewer using sendMsg.
In this case, you should specify a service name which is determined when the SIGViewer connected to the SIGverse server.
If the service name is "SIGViewer", the following modification will change the sending target from the agent to the SIGViewer.

SendController.so

Old
#highlight(cpp:firstline[33]){{
 sendMsg("robot_000",msg);
}}
         ↓
New
#highlight(cpp:firstline[33]){{
 sendMsg("SIGViewer",msg);
}}



#highlight(end)

*Old Version [#f0b7d8c0]
-[[エージェント間のメッセージのやりとり(v2.0系)]]
-[[エージェント間のメッセージのやりとり(v120330, v1.4.8)]]
Up:[[Tutorial]]     Previous:[[Humanoid agent operations]]     Next:[[Vision sensor]]

#counter

--------
Up:[[Tutorial]]     Previous:[[人間型エージェントの操作]]     Next:[[視覚に関する操作]]

[[English version>Samples/Communication between agents]]


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