[[視覚に関する操作]]

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;
 }
}}

これは回転する角度をメッセージとして受信して、その角度だけ体を回転させるサンプルです。

z軸方向(ロボットが最初に前を向いている方向)からの角度を指定します。回転する角度は-180°から180°まで指定することができます。



それではコンパイルします。
 $ emacs Makefile
 
変更前
 
 #オブジェクトファイルの指定
 OBJS     = SendText.so RecvText.so

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

 $ make

***リビングルームの世界ファイル作成 [#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"/>
 
  </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"/>
  </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"/>
  </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"/>
  </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"/>
  </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"/>
  </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"/>
  </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°に目線があるということになります。

また、ヒューマノイド以外のエージェント(ここではseToy_D.xml)のカメラの位置、方向を設定するときは位置(vpx,vpy,vpz), 視線(vvx,vvy,vvz)で設定します。このときの原点はエージェントの位置になります。
***起動 [#s12fde3f]
それでは起動してみましょう。

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

SIGViewerでサーバに接続して、シミュレーションを開始します。リビングルームに立っているヒューマノイドロボット型のエージェントが見えると思います。

#ref(watch_1.jpg)

次に、ヒューマノイドロボットをクリックすると、左上の小さい画面にロボットの目線から見た映像が表示されます。

#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;
 }
}}
これはオレンジを見つけたら手を挙げるサンプルです。detectEntitiesで視野内にあるエンティティを検出します。

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

 $ emacs Makefile

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

編集後
 
 #オブジェクトファイルの指定
 OBJS     = WatchOrange.so

 $ make

***世界ファイル編集 [#d02191e6]
次に世界ファイルを編集します。

 $ cd ..
 $ emacs xml/WatchWorld.xml

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]
それでは実行してみましょう。

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

#ref(watch_5.jpg)

オレンジを見つけたら手を挙げます。

***複数カメラの場合 [#t3c10224]
エージェントに複数のカメラを設置することができます。複数個のカメラ設置方法については次のページ[[複数個のカメラ設置]]を参考にしてください。

このときdetectEntitiesの最後の引数にカメラ番号を指定することができます。

以下はカメラ番号2を指定する場合
     bool b = detectEntities(ent);
      ↓
     bool b = detectEntities(ent, 2);
何も指定しない場合は自動的にデフォルトで設置されているカメラ1が指定されます。
 
#highlight(end)
Up:[[Tutorial]]     Previous:[[音声認識]]     Next:[[複数個のカメラ設置]]

Front page   Edit Diff Backup Upload Copy Rename Reload   New List of pages Search Recent changes   Help   RSS of recent changes