Tutorial?

エージェントの衝突

ここではエージェントが衝突したときに衝突したエンティティを検出してUターンするサンプルを紹介します。

コントローラ作成

$ emacs Colli.cpp

Colli.cpp

#include "Controller.h"
#include "ControllerEvent.h"
#include "Logger.h"
#include "math.h"

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

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

  //衝突時に呼出される関数onCollisionの利用を宣言します。                               
  void onCollision(CollisionEvent &evt);

private:

  //衝突フラグ                                                                          
  bool Colli;

};

//衝突時に呼び出されます。
void AgentController::onCollision(CollisionEvent &evt) {

  if (Colli == false){
    typedef CollisionEvent::WithC C;

    // 衝突相手の名前を得る。                                                           
     const C & with = evt.getWith();
    for (C::const_iterator i=with.begin(); i!=with.end(); i++) {

      //衝突相手の名前をsに代入します。                                                 
       std::string s = *i;

      //衝突相手の名前表示します。                                                      
       LOG_MSG(("\"%s\"", s.c_str()));

      SimObj *my = getObj(myname());
 
      // 自分のy軸周りの回転を得ます(クオータニオン)                                        
      double qy = my->qy();

       //くオータニオンから回転角を導出します。                                                            
       double theta = 2*asin(qy);


      double dy = theta + DEG2RAD(-180);
      if (dy <= -PI)
       {
         dy = -1*dy - PI;
       }

      //体全体を180°後に回転します。                                                   
       my->setAxisAndAngle(0, 1.0, 0, dy);
      Colli = true;
    }
  }
}

double AgentController::onAction(ActionEvent &evt) {
 
  try {

    SimObj *my = getObj(myname());

    //自分の位置を得ます。                                                              
    double x = my->x();
    double y = my->y();
    double z = my->z();
 

    //y軸周りの自分の回転を得ます。(クオータニオン)                                               
    double qy = my->qy();

    //クオータニオンから回転角を導出します。
    double theta = 2*asin(qy);

    double dx = 0;
    double dz = 0;

    //移動する速度を設定します。                                                        
    double vel = 5;

    //移動する方向を決定します。                                                        
    dx = sin(theta) * vel;
    dz = cos(theta) * vel;

    //移動します。                                                                      
    my->setPosition( x + dx, y , z + dz ); 

  } catch (SimObj::Exception &) {
  }

  return 0.5;

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

このサンプルコードは衝突を検出したら衝突した相手のエンティティ名を表示して、Uターンするというものです。onCollisionで衝突時に180°後ろに体を回転させ、onActionでは常に自分の向いている方向に進みます。

それではコンパイルします。

$ emacs Makefile

変更前

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

変更後

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

世界ファイルの作成

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

$ emacs xml/ColliWorld.xml
<?xml version="1.0" encoding="utf8"?>
<world name="VisTest2">

  <gravity x="0.0" y="-9.8" z="0.0"/>

  <instanciate class="Robot-nii.xml">

<!--エージェント名-->
       <set-attr-value name="name" value="robot_000"/>

       <set-attr-value name="language" value="c++"/>

<!--オブジェクトファイルColli.soの指定-->
       <set-attr-value name="implementation"
value="./NewWorld/Colli.so"/>

       <set-attr-value name="dynamics" value="false"/>


<!--エージェントの向き(x,y,z)  -->
       <set-attr-value name="qw" value="0.707"/>
       <set-attr-value name="qx" value="0.0"/>
       <set-attr-value name="qy" value="-0.707"/>
       <set-attr-value name="qz" value="0.0"/>

</instanciate>

<!--エージェント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="x" value="-60.0"/>
       <set-attr-value name="y" value="60.0"/>
       <set-attr-value name="z" value="-100.0"/>

<!--エージェントの向き(x,y,z)  -->
       <set-attr-value name="qw" value="0.707"/>
       <set-attr-value name="qx" value="0.0"/>
       <set-attr-value name="qy" value="0.707"/>
       <set-attr-value name="qz" value="0.0"/>


 </instanciate>
</world>

実行

 ./sigserver.sh -w ColliWorld.xml -p 9001

Colli_1.jpg

衝突したらロボットが衝突を検出してUターンします。


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