- The added line is THIS COLOR.
- The deleted line is THIS COLOR.
[[Tutorial]]
#contents
*エージェントの衝突 [#faf7135a]
ここではエージェントが衝突したときに衝突したエンティティを検出してUターンするサンプルを紹介します。
**コントローラ作成 [#b16b5ba2]
$ cd ~/sigverse-<version>/bin/NewWorld
$ 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
**世界ファイルの作成 [#v96d9bc1]
世界ファイルを作成します。
$ 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"/>
<!--エージェントの位置-->
<set-attr-value name="x" value="60.0"/>
<set-attr-value name="y" value="60.0"/>
<set-attr-value name="z" value="-90.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>
<!--エージェント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>
**実行 [#ge5926ae]
$ ./sigserver.sh -w ColliWorld.xml -p 9001
#ref(Colli_1.jpg)
衝突したらロボットが衝突を検出してUターンします。
#ref(colli_2.jpg)
SIGViewerの下のMessagesタブを見てみると衝突時に検出したエージェントの名前"man_000"が表示されています。
LEFT:[[戻る>視覚に関する操作]]