Up:[[Tutorial]]     Previous:[[サービスプロバイダの使用方法]]     Next:[[エージェントの衝突]]
Up:[[Tutorial]]     Previous:[[Use of service provider]]     Next:[[Collision between agents]]
----
#contents

*エージェント視点の画像取得 (captureView)[#g547d565]
* Image capture from agent's perspective [#b858da08]

※このチュートリアルはv2.1.0以降対応しています。
(※This tutorial is valid only for later than v2.1.0)

ここではサービスプロバイダ機能を使用しエージェントに設置されたカメラ画像のデータをコントローラが取得するサンプルを紹介します。
This tutorial explains how to capture an image from the agent's perspective and how to use it in a controller based on service provider function.

**コントローラ作成 [#n54bccbb]
まずコントローラを作成します。
** Creating a controller [#xdb3ed39]

 $ emacs captureView.cpp

captureView.cpp

#highlight(cpp){{
#include <Controller.h>
#include <ControllerEvent.h>
#include <Logger.h>
#include <ViewImage.h>
#include <math.h>

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

class RobotController : public Controller
{
public:
  void onInit(InitEvent &evt);
  double onAction(ActionEvent &evt);
  void onRecvMsg(RecvMsgEvent &evt);

private:
  ViewService* m_view;
  double vel;
};

void RobotController::onInit(InitEvent &evt)
{
  // 移動速度
  // Setting the velocity
  vel = 10.0;
  // サービスに接続
  // Connecting service
  m_view = (ViewService*)connectToService("SIGViewer");
}

//定期的に呼び出される関数
// Callback function which is called frequently
double RobotController::onAction(ActionEvent &evt)
{
  return 10.0;
}

//メッセージ受信時に呼び出される関数
// Callback function which is called when a message comes
void RobotController::onRecvMsg(RecvMsgEvent &evt)
{
  static int iImage = 0;

  //取得したメッセージを表示します
  // Display the received message
  std::string msg = evt.getMsg();
  LOG_MSG(("msg : %s", msg.c_str()));

  //メッセージ"capture"を受信するとcaptureViewを行います
  // Execute captureView when a message "capture" comes
  if (msg == "capture") {
    if(m_view != NULL) {

      // ビット深度24,画像サイズ320X240の画像を取得します
      ViewImage *img = m_view->captureView(2, COLORBIT_24, IMAGE_320X240);
      if (img != NULL) {

        // 画像データを取得します
        // Receiving an image data
        char *buf = img->getBuffer();

        //Windows BMP 形式で保存します
        // Save in Windows BMP format
        char fname[256];
        sprintf(fname, "view%03d.bmp", iImage++);
        img->saveAsWindowsBMP(fname);

        //必要なくなったら削除します
        // Release the memory
        delete img;
      }
    }
  }

  //メッセージ"rotation"を受信すると回転します
  // Rorate the agent when a message "rotation" comes
  if (msg == "rotation"){

    SimObj *my = getObj(myname());

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

    //くオータニオンから回転角(ラジアン)を導出します
    // Calculate Euler angle from the quaternion
    double theta = 2*asin(qy);

    //体全体を回転させます
    // Rorate the body
    double y = theta + DEG2RAD(45);
    if( y >= PI)
      y = y - 2 * PI;

    my->setAxisAndAngle(0, 1.0, 0, y);
   }

  //メッセージ"move"を受信すると自分の向いている方向に進みます
  // Going forward when a message "move" comes
  if (msg == "move"){

    SimObj *my = getObj(myname());

    //自分の位置を得ます
    // Get the current position
    Vector3d pos;
    my->getPosition(pos);

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

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

    //移動距離
    // Movement distance
    double dx = 0.0;
    double dz = 0.0;

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

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

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

***captureView [#i5b342d8]
*** captureView [#aabb1384]

50行目の関数captureViewで画像データをビューワーから取得します。
Receving an image data using captureView in 50th line.
#highlight(cpp:firstline[50]){{
 ViewImage *img = m_view->captureView(2, COLORBIT_24, IMAGE_320X240);
}}

1番目の引数は取得したいカメラのID番号を指定します。ここではID番号2を指定しました。2番目と3番目に1ピクセルあたりのビット深度と画像サイズを指定します。(※v2.1.0ではビット深度24, 画像サイズ320×240のみ取得可)
The first argument of the captureView(); is the ID number of the target camera. The camera ID 2 was used in this example.
The second and third arguments are corresponded to bit depth and image size. (Only 24bits and 320x240 can be choosen in v2.1.0)

取得したViewImageから画像データを取り出すには関数getBuffer()を用います。
Use the function getBuffer() to extract the image data from the ViewImage.

このサンプルではエージェントに"capture"というメッセージを送信するとエージェントは画像を取得することができます。
In this example, the agent will
- go forward when "move" is received.
- rorate when "rotation" is received.
- capture an image when "capture" is received.

captureViewが成功すると実行ディレクトリにview000.bmp, view001.bmp...というようにbmp形式の画像ファイルが保存されます。
Image files such as view000.bmp, view001.bmp... in bmp format will be created in a starting directory.


***エージェントの移動 [#w6371583]

このエージェントはメッセージ"move"を受信すると現在向いている方向に進みます。"rotation"を受信するとエージェントは向きを変えます。
** Compilation [#qa8cd0af]

**コンパイル [#m203eb4f]

 $ ./sigmake.sh captureView.cpp


**世界ファイル作成 [#u5216d9d]
** Creating a world file [#e7dad340]

 $ emacs captureView.xml

世界ファイルは前ページ[[視覚に関する操作]]で使用したリビングルームの世界ファイルとほとんど同じものを使います。
The following world file is almost the same as the world file used in the [[Vision sensor]].

captureView.xml
#highlight(xml){{

<?xml version="1.0" encoding="utf8"?>
<world name="myworld5">

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

  <!--エージェントRobot-niiの設定-->
  <!-- Set a humanoid robot agent Robot-nii -->
  <instanciate class="Robot-nii.xml">

    <!--エージェント名-->
    <!-- Set name of a humanoid robot agent -->
    <set-attr-value name="name" value="robot_000"/>

    <!--C++言語の指定-->
    <!-- Set language type as C++ for the controller -->
    <set-attr-value name="language" value="c++"/>

    <!--コントローラの指定-->
    <set-attr-value name="implementation"
                    value="./captureView.so"/>
    <!-- Set a file name of the controller -->
    <set-attr-value name="implementation" value="./captureView.so"/>

    <!--動力学演算をfalseに設定-->
    <!-- put the flag of dynamics to false -->
    <set-attr-value name="dynamics" value="false"/>

    <!--エージェントの位置(x,y,z)-->
    <!-- Set the initial position of agent (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番号,リンク名、方向、位置の設定-->
    <!-- Set the Camera ID, name of link on which the camera is attached, direction and position -->
    <camera id="1"
            link="HEAD_LINK"
            direction="0.1 0 1"
            position="-2.0 0.0 7.0"/>
    <camera id="2"
            link="HEAD_LINK"
            direction="-0.1 0 1"
            position="2.0 0.0 7.0"/>
  </instanciate>

  <!--リビングルーム-->
  <!-- Construction of a living room -->
  <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="87.5"/>
    <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.9"/>
    <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="6.15"/>
    <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="31.85"/>
    <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="25.1"/>
    <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="56.5"/>
    <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="16.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="3.875"/>
    <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="2.215"/>
    <set-attr-value name="z" value="-30.0"/>
  </instanciate>

</world>
}}

エージェントに2つのカメラを設置し、2つのカメラで微妙に位置と方向をずらしました。
The difference between the [[Vision sensor]] is number of cameras.
The agent has two cameras. the location and orientation of the cameras are modified.

カメラID番号1が右目、2が左目に相当します。
The right camera has ID 1. The left camera has ID 2.

**画像取得 [#j88e8a70]
それでは実行してみましょう
** Execution of the image capture [#e0ef2571]

 $ sigserver.sh -w ./captureView.xml
 
SIGViewerで接続してみるとリビングルームにロボットが立っているのが見えます。

シミュレーションを開始して"rotation"や"move"などのメッセージを送信するとエージェントが向きを変えたり、移動したりして自由に部屋の中を移動できるようになります。
You can see a humanoid robot agent in a living room. 

キャプチャしたいタイミングで"capture"を送信するとエージェントに設置されたカメラ(ID番号2)で撮影した画像が得られます。
You can send "rotation" and "move" to the agent to control the position and orientation of the agent.

#ref(エージェント視点の画像取得(v2.0系)/capture_1.PNG,40%)
Please send a message "capture" when you want to capture an image.

サーバ側の実行ディレクトリにカメラ2でcaptureした画像ファイルが保存されていれば成功です。
#ref(./capture_1.PNG,40%)

An image file captured by the camera ID 2 will be created in the starting directory


#highlight(end)

*Old Version [#m54d69a2]
-[[エージェント視点の画像取得(v2.0系)]]
-[[エージェント視点の画像取得(v120330, v1.4.8)]]


----
Up:[[Tutorial]]     Previous:[[サービスプロバイダの使用方法]]     Next:[[エージェントの衝突]]
Up:[[Tutorial]]     Previous:[[Use of service provider]]     Next:[[Collision between agents]]


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