- The added line is THIS COLOR.
- The deleted line is THIS COLOR.
[[音声認識]]
Up:[[Tutorial]] Previous:[[エージェント間のメッセージのやりとり]] Next:[[サービスプロバイダの使用方法]]
Up:[[Tutorial]] Previous:[[音声認識]] Next:[[複数個のカメラ設置]]
----
#contents
*視覚に関する操作方法 [#f37ce459]
視覚に関する操作方法を説明します。~
//なお、ここで説明する機能はSIGViewer1.3.5以降のバージョンでは、サポートされていません。
**周りを見渡す [#scce7ec9]
エージェントがいろいろな方向を見渡すことができるサンプルコードを紹介します。(バージョン110830以降正常に動作)
エージェントがいろいろな方向を見渡すことができるサンプルを紹介します。
***コントローラ作成 [#t10e6f74]
$ cd ~/sigverse-<version>/bin/NewWorld
$ emacs WatchController.cpp
WatchController.cpp
#highlight(cpp){{
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
class WatchController : public Controller
{
public:
void onRecvMessage(RecvMessageEvent &evt);
};
void WatchController::onRecvMessage(RecvMessageEvent &evt)
{
SimObj *my = getObj(myname());
//受け取ったメッセージをint型に変換します。
const char *value(evt.getString(0));
int angle = atoi(value);
if (angle <= 180 && angle >=-180){
//体全体をz軸から指定した角度だけ回転します.
my->setAxisAndAngle(0, 1.0, 0, DEG2RAD(angle));
}
}
extern "C" Controller * createController ()
{
return new WatchController;
}
}}
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
これは回転する角度をメッセージとして受信して、その角度だけ体を回転させるサンプルです。
#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
z軸方向(ロボットが最初に前を向いている方向)からの角度を指定します。回転する角度は-180°から180°まで指定することができます。
class WatchController : public Controller
{
public:
void onRecvMsg(RecvMsgEvent &evt);
};
void WatchController::onRecvMsg(RecvMsgEvent &evt)
{
SimObj *my = getObj(myname());
//受け取ったメッセージをint型に変換します
const char *value = evt.getMsg();
int angle = atoi(value);
if (angle <= 180 && angle >=-180){
それではコンパイルします。
$ emacs Makefile
変更前
#オブジェクトファイルの指定
OBJS = SendText.so RecvText.so
//体全体をz軸から指定した角度だけ回転します
my->setAxisAndAngle(0, 1.0, 0, DEG2RAD(angle));
}
}
変更後
#オブジェクトファイルの指定
OBJS = WatchController.so
extern "C" Controller * createController ()
{
return new WatchController;
}
}}
$ make
これは回転する角度をメッセージとして受信して、その角度だけ体を回転させるサンプルです。
z軸方向(ロボットが最初に前を向いている方向)からの角度を指定します。回転する角度は-180°から180°まで指定することができます。
***コンパイル [#ebdcf9b7]
Makefileの変数OBJSにWatchController.soを追加してコンパイルします。
***リビングルームの世界ファイル作成 [#iea3d264]
新しく世界ファイルを作成します。
//前回の世界ファイルは一応残しておきます。
$ cd ~/sigverse-<version>/bin
// $ mv xml/MyWorld.xml xml/MoveWorld.xml
$ emacs xml/WatchWorld.xml
WatchWorld.xml
#highlight(xml){{
<?xml version="1.0" encoding="utf8"?>
<world name="myworld5">
<gravity x="0.0" y="-9.8" z="0.0"/>
<!--エージェントRobot-niiの設定-->
<instanciate class="Robot-nii.xml">
<!--エージェント名-->
<set-attr-value name="name" value="robot_000"/>
<!--C++言語の指定-->
<set-attr-value name="language" value="c++"/>
<!--コントローラの指定-->
<set-attr-value name="implementation"
value="./NewWorld/WatchController.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="60.0"/>
<set-attr-value name="z" value="-40.0"/>
<!--カメラ1を設置するリンク名の設定-->
<set-attr-value name="elnk1" value="HEAD_LINK"/>
<!--カメラ1の位置-->
<set-attr-value name="epx1" value="0.0"/>
<set-attr-value name="epy1" value="0.0"/>
<set-attr-value name="epz1" value="10.0"/>
<!--カメラ1の方向-->
<set-attr-value name="evx1" value="0.0"/>
<set-attr-value name="evy1" value="-1.0"/>
<set-attr-value name="evz1" value="1.0"/>
</instanciate>
<!--リビングルーム作成-->
<instanciate class="seTV.xml">
<set-attr-value name="name" value="TV_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-20.0"/>
<set-attr-value name="y" value="82.0"/>
<set-attr-value name="z" value="-250.0"/>
<set-attr-value name="visStateAttrName" value="switch"/>
<set-attr-value name="switch" value="on"/>
</instanciate>
<instanciate class="seDoll_Bear.xml">
<set-attr-value name="name" value="kuma_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="0.0"/>
<set-attr-value name="y" value="5.0"/>
<set-attr-value name="z" value="0.0"/>
<set-attr-value name="vpx" value="0.0"/>
</instanciate>
<instanciate class="seToy_D.xml">
<set-attr-value name="name" value="penguin_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="50.0"/>
<set-attr-value name="y" value="10.0"/>
<set-attr-value name="z" value="-40.0"/>
<set-attr-value name="vpx" value="0.0"/>
<set-attr-value name="vpy" value="10.0"/>
<set-attr-value name="vpz" value="0.0"/>
<set-attr-value name="vvx" value="0.0"/>
<set-attr-value name="vvy" value="0.0"/>
<set-attr-value name="vvz" value="1.0"/>
<world name="myworld5">
<gravity x="0.0" y="-980.7" z="0.0"/>
<!--エージェントRobot-niiの設定-->
<instanciate class="Robot-nii.xml">
<!--エージェント名-->
<set-attr-value name="name" value="robot_000"/>
<!--C++言語の指定-->
<set-attr-value name="language" value="c++"/>
<!--コントローラの指定-->
<set-attr-value name="implementation"
value="./NewWorld/WatchController.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="54.0"/>
<set-attr-value name="z" value="-40.0"/>
<!--カメラのID番号,リンク名、方向、位置の設定-->
<camera id="1"
link="HEAD_LINK"
direction="0 -1 1"
position="0.0 0.0 5.0"/>
</instanciate>
<!--リビングルーム-->
<instanciate class="seTV.xml">
<set-attr-value name="name" value="TV_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-20.0"/>
<set-attr-value name="y" value="70.0"/>
<set-attr-value name="z" value="-250.0"/>
<set-attr-value name="visStateAttrName" value="switch"/>
<set-attr-value name="switch" value="on"/>
</instanciate>
<instanciate class="seDoll_Bear.xml">
<set-attr-value name="name" value="kuma_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="0.0"/>
<set-attr-value name="y" value="9.0"/>
<set-attr-value name="z" value="0.0"/>
</instanciate>
<instanciate class="seToy_D.xml">
<set-attr-value name="name" value="penguin_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="50.0"/>
<set-attr-value name="y" value="7.0"/>
<set-attr-value name="z" value="-40.0"/>
</instanciate>
<instanciate class="seSofa_2seater.xml">
<set-attr-value name="name" value="sofa_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-200.0"/>
<set-attr-value name="y" value="20.0"/>
<set-attr-value name="z" value="-100.0"/>
<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"/>
<set-attr-value name="name" value="sofa_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-200.0"/>
<set-attr-value name="y" value="30.0"/>
<set-attr-value name="z" value="-100.0"/>
<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>
<instanciate class="seTVbass_B.xml">
<set-attr-value name="name" value="TVdai_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-20.0"/>
<set-attr-value name="y" value="13.0"/>
<set-attr-value name="z" value="-250.0"/>
<set-attr-value name="name" value="TVdai_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-20.0"/>
<set-attr-value name="y" value="8.0"/>
<set-attr-value name="z" value="-250.0"/>
</instanciate>
<instanciate class="sePlant_B.xml">
<set-attr-value name="name" value="ki_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="100.0"/>
<set-attr-value name="y" value="35.0"/>
<set-attr-value name="z" value="-250.0"/>
<set-attr-value name="name" value="ki_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="100.0"/>
<set-attr-value name="y" value="35.0"/>
<set-attr-value name="z" value="-250.0"/>
</instanciate>
<instanciate class="seSidetable_B.xml">
<set-attr-value name="name" value="sidetable_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-100.0"/>
<set-attr-value name="y" value="23.0"/>
<set-attr-value name="z" value="-100.0"/>
<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"/>
<set-attr-value name="name" value="sidetable_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-100.0"/>
<set-attr-value name="y" value="23.0"/>
<set-attr-value name="z" value="-100.0"/>
<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>
<instanciate class="seApple.xml">
<set-attr-value name="name" value="apple_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-50.0"/>
<set-attr-value name="y" value="10.0"/>
<set-attr-value name="z" value="30.0"/>
<set-attr-value name="name" value="apple_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="-50.0"/>
<set-attr-value name="y" value="3.0"/>
<set-attr-value name="z" value="30.0"/>
</instanciate>
<instanciate class="seOrange.xml">
<set-attr-value name="name" value="orange_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="70.0"/>
<set-attr-value name="y" value="10.0"/>
<set-attr-value name="z" value="-30.0"/>
<set-attr-value name="name" value="orange_0"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="70.0"/>
<set-attr-value name="y" value="2.0"/>
<set-attr-value name="z" value="-30.0"/>
</instanciate>
</world>
}}
これはリビングルームにヒューマノイドロボット(Robot-nii.xml)が立っているというxmlファイルです。リビングルームにはテレビやソファなどがおかれています。
このxmlファイルではエージェントの視点の位置や、視点の向きの設定がされています。
視点の位置は"elnk1"でカメラを設置するリンク名を指定することができます。(デフォルトでは"elnk1"は"HEAD_LINK"に設定されています。つまりエージェントの顔にカメラが設置されています。リンク名は[[Joint定義一覧]]を参照してください。次に"epx1","epy1","epz1"でカメラの位置を指定します。これらはすべてエージェント座標系で設定されます。エージェント座標系とはエージェントが基準となる座標系で、x軸がエージェントから見て左右(左が正方向)、y軸が上下(上が正方向)、z軸が前後(前が正方向)となります。このとき原点はリンクの位置になります。
この世界ファイルではロボットエージェントにカメラが設置されています。カメラの位置や方向などは以下のように設置します。
視点の向きはベクトルで表されます。今回視点の向きを(evx1,evy1,evz1)=(0,-1,1)と設定しました。つまりエージェントはまっすぐ前を向いた方向から、下方向45°に目線があるということになります。
#highlight(xml){{
<camera id="1"
link="HEAD_LINK"
direction="0 -1 1"
position="0.0 0.0 5.0"/>
}}
また、ヒューマノイド以外のエージェント(ここではseToy_D.xml)のカメラの位置、方向を設定するときは位置(vpx,vpy,vpz), 視線(vvx,vvy,vvz)で設定します。このときの原点はエージェントの位置になります。
***起動 [#s12fde3f]
それでは起動してみましょう。
linkでカメラを設置するパーツ名を指定します。このサンプルではを"HEAD_LINK"に設置しました。ヒューマノイドロボットのパーツ名は[[Joint定義一覧]]のLink名を参照してください。関節やパーツを持たないエンティティにカメラを設置する場合はlink名を設定することはできません。
$ ./sigserver.sh -w WatchWorld.xml -p 9001
カメラの位置はlinkを設定した場合はlinkの位置からの相対位置となります。
SIGViewerでサーバに接続して、シミュレーションを開始します。リビングルームに立っているヒューマノイドロボット型のエージェントが見えると思います。
direction, position でカメラの方向ベクトル、位置を設定します。このサンプルではまっすぐ前を向いた方向から、下方向45°に目線があるということになります。
#ref(watch_1.jpg)
同様にaspectRatio, FOV(field of view)なども設定できます。
次に、ヒューマノイドロボットをクリックすると、左上の小さい画面にロボットの目線から見た映像が表示されます。
1エージェントに複数個のカメラを設置する場合はidを1,2,3と順番につけていきます。
#ref(Watch_3.jpg)
ロボットの目線からはりんごが見えているのがわかります。右のDetected Entitiesを見てみると、ロボットから見て、りんごが検出されているのがわかります。
#ref(watch_2.jpg)
次に右側のコマンドタブをクリックして、ヒューマノイド型ロボットのエージェントに回転する角度を指定して、実行ボタンを押し、メッセージを送信します。例えば180を送信します。
#ref(watch_3_5.jpg)
#br
#ref(watch_4.jpg)
ロボットが180°回転して今度はテレビや、木、テーブルなどが検出されているのがわかります。
**オブジェクトの検出(detectEntities) [#b15d4040]
次にオレンジを見つけたら手を挙げるサンプルを紹介します。
※注意)このサンプルはポートフォワーディングによる接続の場合、SIGViewerのバージョン1.3以上で動作します。また、サービスプロバイダを利用するため、双方向のポートフォワーディングが必要です。クライアントpcのファイアーウォールの設定によっては正常に動作しない場合があります。
***コントローラ作成[#cef2b65c]
コントローラを作成します。
$ cd ..
$ emacs WatchOrange.cpp
WatchOrange.cpp
#highlight(cpp){{
#include <string>
#include <iostream>
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
//利用する名前空間の宣言
using namespace std;
class WatchController : public Controller
{
public:
double onAction(ActionEvent &evt);
void onRecvMessage(RecvMessageEvent &evt);
};
//能動的行動を行います。
double WatchController::onAction(ActionEvent &evt)
{
try {
SimObj *my = getObj(myname());
//手をさげます。
my->setJointAngle("LARM_JOINT2", DEG2RAD(0));
//視野内のEntityを得ます。
vector<string> ent;
bool b = detectEntities(ent);
if(b && ent.size() > 0) {
//検出したEntityの名前を取得します。
vector<string>::iterator i;
for ( i = ent.begin(); i!= ent.end(); i++) {
string name = *i;
//検出したEntityを表示します。
LOG_MSG(("detected %s\n", name.c_str()));
if (name == "orange_0"){
LOG_MSG(("This is orange"));
//オレンジを見つけると手を挙げます。
my->setJointAngle("LARM_JOINT2", DEG2RAD(180));
}
}
}
} catch(SimObj::Exception &) {
LOG_ERR(("Exception"));
}
return 1.0;
}
//受動的行動を行います。
void WatchController::onRecvMessage(RecvMessageEvent &evt)
{
SimObj *my = getObj(myname());
const char *value(evt.getString(0));
int angle = atoi(value);
if (angle <= 180 && angle >=-180){
//体全体をz軸から指定した角度だけ回転します.
my->setAxisAndAngle(0, 1.0, 0, DEG2RAD(angle));
}
}
extern "C" Controller * createController ()
{
return new WatchController;
}
#highlight(xml){{
<camera id="1"
link="HEAD_LINK"
direction="0 -1 1"
position="0.0 0.0 5.0"/>
<camera id="2"
link="LARM_LINK7"
direction="0 0 1"
position="0.0 0.0 0.0"/>
}}
これはオレンジを見つけたら手を挙げるサンプルです。detectEntitiesで視野内にあるエンティティを検出します。
***起動 [#s12fde3f]
それでは起動してみましょう。
それではコンパイルします。
$ ./sigserver.sh -w WatchWorld.xml -p 9001
$ emacs Makefile
SIGViewerでサーバに接続して、シミュレーションを開始します。リビングルームに立っているヒューマノイドロボット型のエージェントが見えると思います。
編集前
#オブジェクトファイルの指定
OBJS = WatchController.so
#ref(./watch_1.PNG,40%)
編集後
#オブジェクトファイルの指定
OBJS = WatchOrange.so
次に、ヒューマノイドロボットをクリックすると、左上の小さい画面にロボットの目線から見た映像が表示されます。
$ make
#ref(./watch_2.PNG)
***世界ファイル編集 [#d02191e6]
次に世界ファイルを編集します。
さらにその枠の右上にあるボタンを押すとロボットから見た映像がメイン画面に切り替わります。
$ cd ..
$ emacs xml/WatchWorld.xml
#ref(./watch_3.PNG,40%)
WatchWorld.xml
元に戻したい場合はもう一度左上のサブウィンドウの右上にあるボタンを押します。
#highlight(cpp:firstline[15]){{
<!--コントローラの指定-->
<set-attr-value name="implementation"
value="./NewWorld/WatchController.so"/>
}}
↓
#highlight(cpp:firstline[15]){{
<!--コントローラの指定-->
<set-attr-value name="implementation"
value="./NewWorld/WatchOrange.so"/>
}}
***実行 [#i1a28c90]
それでは実行してみましょう。
次に右下のトレイにある"Message"ボタンをクリックして、ヒューマノイド型ロボットのエージェントに回転する角度を指定して、メッセージを送信します。例えば90を送信します。
$ ./sigserver.sh -w WatchWorld.xml -p 9001
#ref(./watch_4.PNG,80%)
#ref(watch_5.jpg)
するとロボットが90°回転してロボットの視線からはオレンジやペンギンのおもちゃが見えているのがわかります。
オレンジを見つけたら手を挙げます。
***複数カメラの場合 [#t3c10224]
エージェントに複数のカメラを設置することができます。複数個のカメラ設置方法については次のページ[[複数個のカメラ設置]]を参考にしてください。
#ref(./watch_5.PNG,40%)
このときdetectEntitiesの最後の引数にカメラ番号を指定することができます。
以下はカメラ番号2を指定する場合
bool b = detectEntities(ent);
↓
bool b = detectEntities(ent, 2);
何も指定しない場合は自動的にデフォルトで設置されているカメラ1が指定されます。
*更新履歴 [#e5d66315]
-[[視覚に関する操作(v120330, v1.4.8)]]
#highlight(end)
Up:[[Tutorial]] Previous:[[音声認識]] Next:[[複数個のカメラ設置]]
Up:[[Tutorial]] Previous:[[エージェント間のメッセージのやりとり]] Next:[[サービスプロバイダの使用方法]]