#contents
*Control of humanoit agent [#y5ff04bf]

** Control of joint angle [#a808e370]
This section explains sample controller in which the humanoid agent hold its hand.
*** Creation of controller [#p45172d0]
Create AgentController.cpp on NewWorld.
 $ cd ~/sigverse-<version>/bin/NewWorld
 $ emacs AgentController.cpp

AgentController.cpp

 #include "Controller.h"
 #include "Logger.h"
 
 #define PI 3.141592
 
 #define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 ) 
 
 class AgentController : public Controller
 {
 public:
   double onAction(ActionEvent &evt);
 }; 
 
 
 //定期的に呼び出される関数です。
 double AgentController::onAction(ActionEvent &evt)
 {
   try {
     SimObj *my = getObj(myname());
     if (!my->dynamics()) { 
 
       my->setJointAngle("LARM_JOINT2", DEG2RAD(45));
 
    }
 
  } catch(SimObj::Exception &) {
    ;
  }
 
  return 5.0;
 }
 
 
 extern "C"  Controller * createController ()
 {
   return new AgentController;
 }

This controller make the humanoid agent hold tis left hand by 45deg by setJointAngle.
This controller makes the humanoid agent hold his left hand by 45deg by setJointAngle.

*** Compilation [#c1742244]
Modify your Makefile as follows

 $ emacs Makefile

Changes
Change
// #Target source
// CPP_SRCS = MoveController.cpp
// 
 #specification of object file
 OBJS = MoveController.so
//

Into
// #Target source
// CPP_SRCS = AgentController.cpp/
// 

 #specification of object file
 OBJS = AgentController.so

Execute make to compile the controller
 $ make

*** Creation of world file [#t278f07b]

 $ cd ~/sigverse-<version>/bin
 $ ln -s ../share/sigverse/data/xml/ xml

Here, symbolic link is used becase the directory which holds xml files are apart from the working directory.
Here, symbolic link is used becase the directory which holds xml files is apart from the working directory.

 $ emacs xml/AgentWorld.xml

AgentWorld.xml

 <?xml version="1.0" encoding="utf8"?>
 <world name="newworld">
 
 <!--重力の設定-->
   <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"/> 
 
 <!--C++言語の指定-->
         <set-attr-value name="language" value="c++"/> 
 
 <!--オブジェクトファイルAgentController.soの指定-->
         <set-attr-value name="implementation"
 value="./NewWorld/AgentController.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="50.0"/>
        <set-attr-value name="z" value="0.0"/>
 
 </instanciate>
Change the target agent as Man-nii.xml; set the dynamics simulation switch as "false"

*** Execution of SIGVerse server [#t9bd0518]

 $ ./sigserver.sh -w AgentWorld.xml -p 9001

You must see the humanoid agent stands with holding its hands.
The humanoid agent will hold its left hand for 45 degree when you start the simulation.
You should see the humanoid agent standing while holding his hands.
The humanoid agent will hold his left hand for 45 degree when you start the simulation.

#ref(man_1.jpg)

今回setJointAngleという関数を用いて"LARM_JOINT2" を45°にする設定を行いました。"LARM_JOINT2"は左肩のz軸での回転として定義された関節の名前です。同様に"LARM_JOINT0","LARM_JOINT1"はそれぞれ左肩のx軸、y軸の回転として定義されています。(エージェント座標系。)これらの関節名はsigverse-<version>/share/sigverse/data/shape/にあるx3dファイル(nii_man.x3d)で定義されています。

AgentWorld.xmlファイルはMan-nii.xmlファイルを読み込みMan-nii.xmlファイルは人間型エージェントの形状を記述したnii_man.x3dを読み込んでいます。

**エージェントの属性 [#nb731d79]
***属性の確認 [#g984fed9]
SIGViewerでエージェントをクリックするとエージェントの名前や位置(x,y,z)、エージェントの向き(qw,qx,qy,qz)、視点の位置(vpx,vpy,vpz)などの属性を見ることができます。これらは属性の値はxmlファイルで設定されています。

#ref(atr_1.jpg)


人間型エージェントMan-niiはAgentクラスを継承したクラスです。Agentクラスの属性のデフォルトの値はAgent.xmlで設定されています。見てみましょう。

 $ less xml/Agent.xml

 <?xml version="1.0" encoding="utf8"?>
 
 <define-class name="Agent" inherit="Entity.xml">
 
 <attr name="language" type="string" group="model"/>
 <attr name="implementation" type="string" group="model"/>
 
 
    <!-- view point(agent coordinate) -->
 <attr name="vpx" type="double" group="viewpoint" value="0.0"/>
 <attr name="vpy" type="double" group="viewpoint" value="0.0"/>
 <attr name="vpz" type="double" group="viewpoint" value="0.0"/>
 
    <!-- view vector(view coordinate) -->
 <attr name="vvx" type="double" group="viewvector" value="0.0"/>
 <attr name="vvy" type="double" group="viewvector" value="0.0"/>
 <attr name="vvz" type="double" group="viewvector" value="-1.0"/>
                  ・ 
                    ・
                    ・
上で見たvpx,vvxなどの値が設定されているのがわかります。
さらにAgentクラスはEntityクラスを継承しています。Entityクラスは自律動作を行わない物体のクラスです。

***エージェント、エンティティの基本的な属性 [#g14c1ee2]
エンティティ、エージェントの基本的な属性を紹介します。

エンティティの属性
|属性名| 意味 | 備考|
|x,y,z|エンティティの位置 |xは緑矢印 ,yは赤矢印 zは黄色矢印に対応 |
|fx,fy,fz|エンティティにかかる力||
|vx,vy,vz|エンティティの速度||
|qw,qx,qy,qz|エンティティの向き|クオータニオン表記|

エージェントの属性
|属性名| 意味 | 備考|
|vpx,vpy,vpz|エージェントの視点の位置 |エージェント座標、原点はエージェントの位置|
|vvx,vvy,vvz|視線の方向|ベクトル表記|
|FOV|エージェントの視野角||
|voiceReachRadius|エージェント声が届く範囲||

これらの属性はすべてxmlファイルで設定が行えます。
**コマンドによるエージェントの操作 [#ta077379]
前回は定期的に呼び出されるonActionで手を上げるサンプルコードを紹介しました。次はSIGViewerからのメッセージを送信することによりエージェントがお辞儀をするようなサンプルコードを紹介します。

まずAgentController.cppを変更します。
 $ cd NewWorld
 $ emacs AgentController.cpp

 #include <string>  //stringをインクルード
 #include "Controller.h"
 #include "Logger.h"
 #include "ControllerEvent.h"
 
 
 #define PI 3.141592
 #define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 ) 
 
 using namespace std;  //利用名前空間の定義
 
 class AgentController : public Controller
 {
 public:
   double onAction(ActionEvent &evt);
 
   // メッセージを受信したときの関数onRecvMessageの利用を宣言します。
   void onRecvMessage(RecvMessageEvent &evt);
 };
 
 double AgentController::onAction(ActionEvent &evt)
 {
   try {
     SimObj *my = getObj(myname());
     if (!my->dynamics()) { 
 
       // 左手を90°下に下げます。
       my->setJointAngle("LARM_JOINT2", DEG2RAD(-90));
 
       // 右手を90°下に下げます。
      my->setJointAngle("RARM_JOINT2", DEG2RAD(90));
 
     }
   } catch(SimObj::Exception &) {
     ;
   }
   return 5.0;
 }
 
 
 void AgentController::onRecvMessage(RecvMessageEvent &evt)
 {
 
   //自分自身の取得
   SimObj *my = getObj(myname());
 
   //string型のメッセージを取得します。
   string value(evt.getString(0)); 
   if (value =="Hello"){
 
     //腰の関節を45°曲げます。
     my->setJointAngle("WAIST_JOINT1", DEG2RAD(45));
   } 
 
 }
 
 extern "C"  Controller * createController ()
 {
   return new AgentController;
 }

onRecvMessageはメッセージを受信したときに呼び出される関数です。メッセージが"Hello"だったときにお辞儀をします。

それではコンパイルして実行してみましょう。

 $ make
 $ cd ..
 $ ./sigserver.sh -w AgentWorld.xml -p 9001

SIGViewerで接続して、
sendボタンをクリックしてシミュレーションを開始すると、まずonActionが呼び出されて右手と左手を下に下げます。
#ref(man_2.jpg)
***メッセージ送信 [#hb68ba23]

まずSIGViewerの右上にあるCommandタブをクリックします。
一番上の入力欄でvoiceとgeneralが選択できるようになっています。ここではgeneralを選択します。次に送信対象選択ボタンをクリックして画面上のエージェントをクリックします。エージェント名が自動的に入力されると思います。そしてSendMessage引数のところにHelloと入力します。
#ref(man_3.jpg)
入力が完了したら、実行ボタンを押します。
#ref(man_4.jpg)
お辞儀をしました。

LEFT:[[戻る>動力学シミュレーションのサンプル]]
RIGHT:[[次へ>エージェント間のメッセージのやりとり]]


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