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
衝突したらロボットが衝突を検出してUターンします。