Up:Tutorial?     Previous:動力学シミュレーションのサンプル     Next:エージェント間のメッセージのやりとり

エージェントの動きに関する操作

人間またはロボットの形をしたエージェントの関節の操作方法を説明します。

関節の操作

人間が手を上げるサンプルコードを紹介します。

コントローラの作成

NewWorldディレクトリに新しくAgentController.cppを作成します。

$ 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()) { 

     // "LARM_JOINT2" を45度に設定する
      my->setJointAngle("LARM_JOINT2", DEG2RAD(45));

   }

 } catch(SimObj::Exception &) {
   ;
 }

 return 5.0;
}


extern "C"  Controller * createController ()
{
  return new AgentController;
}

このサンプルはシミュレーション開始と同時に my->setJointAngleでエージェントの左腕が上に45°に上がるというものです。

コンパイル

次にMakefileを変更します。

$ emacs Makefile

変更前

#オブジェクトファイルの指定
OBJS = MoveController.so

変更後

#オブジェクトファイルの指定
OBJS = AgentController.so

コンパイルします。

$ make

世界ファイル作成

次に世界ファイルを作成します。

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

xmlファイルがあるディレクトリまで遠いのでリンクを貼りました。

$ 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>

エージェントとしてMan-nii.xmlを読み込むように設定し、動力学演算をfalseにしました。

SIGVerse起動

それではSIGVerseを起動してみましょう。

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

SIGViewerを起動して見てみると人間のエージェントが手を広げてスタンバイしていると思います。 シミュレーションを開始するとエージェントの左腕が45°上がります。

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を読み込んでいます。

エージェントの属性

属性の確認

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

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クラスは自律動作を行わない物体のクラスです。

エージェント、エンティティの基本的な属性

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

エンティティの属性

属性名意味備考
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ファイルで設定が行えます。

コマンドによるエージェントの操作

前回は定期的に呼び出される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が呼び出されて右手と左手を下に下げます。

man_2.jpg

メッセージ送信

まずSIGViewerの右上にあるCommandタブをクリックします。 一番上の入力欄でvoiceとgeneralが選択できるようになっています。ここではgeneralを選択します。次に送信対象選択ボタンをクリックして画面上のエージェントをクリックします。エージェント名が自動的に入力されると思います。そしてSendMessage引数のところにHelloと入力します。

man_3.jpg

入力が完了したら、実行ボタンを押します。

man_4.jpg

お辞儀をしました。

Up:Tutorial?     Previous:動力学シミュレーションのサンプル     Next:エージェント間のメッセージのやりとり

English version?


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