[[Tutorial]] #contents *エージェントの動きに関する操作 [#v2485f29] 人間またはロボットの形をしたエージェントの関節の操作方法を説明します。 **関節の操作 [#f5cb7768] 人間が手を上げるサンプルコードを紹介します。 ***ソースコードの作成 [#oc032119] NewWorldディレクトリに新しくAgentController.cppを作成します。 $ cd ~/sigverse-<version>/bin/NewWorld $ emacs AgentController.cpp AgentController.cpp #include "Controller.h" #include "Logger.h" #define PI 3.141592 #define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 ) class AgentController : public Controller { public: double onAction(ActionEvent &evt); }; double AgentController::onAction(ActionEvent &evt) { try { // 自分自身を得る SimObj *my = getObj(myname()); if (!my->dynamics()) { // "LARM_JOINT2" を45度に設定する my->setJointAngle("LARM_JOINT2", DEG2RAD(45)); } } catch(SimObj::Exception &) { ; } return 5.0; } extern "C" Controller * createController () { return new AgentController; } my->setJointAngle("LARM_JOINT2", DEG2RAD(45));で左肩を上に45°に上げます。 ***コンパイル [#o78ee00f] Makefileの以下の2行を変更します。 変更前 // #自作コード // CPP_SRCS = MoveController.cpp // #オブジェクトファイルの指定 OBJS = MoveController.so // 変更後 // #自作コード // CPP_SRCS = AgentController.cpp/ // #オブジェクトファイルの指定 OBJS = AgentController.so コンパイルします。 $ make ***世界ファイル作成 [#l5dd7972] 次に世界ファイルを作成します。SIGVerse起動時に-wオプションで毎回世界ファイルを指定するのは面倒なので、MyWorld.xmlに記述します。 $ cd ~/sigverse-<version>/bin $ ln -s ../share/sigverse/data/xml/ xml xmlファイルがあるディレクトリまで遠いのでリンクを貼りました。 $ cp xml/MyWorld.xml xml/MyWorld_org.xml 念のためデフォルトのMyWorld.xmlファイルを残しておきました。 $ emacs xml/MyWorld.xml MyWorld.xml <?xml version="1.0" encoding="utf8"?> <world name="newworld"> <!--重力の設定--> <gravity x="0.0" y="-9.8" z="0.0"/> <!--エージェントMan-niiの設定--> <instanciate class="Man-nii.xml"> <!--エージェント名--> <set-attr-value name="name" value="man_000"/> <!--C++言語の指定--> <set-attr-value name="language" value="c++"/> <!--オブジェクトファイルAgentController.soの指定--> <set-attr-value name="implementation" value="./NewWorld/AgentController.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="50.0"/> <set-attr-value name="z" value="0.0"/> </instanciate> エージェントとしてMan-nii.xmlを読み込むように設定し、動力学演算をfalseにしました。 ***SIGVerse起動 [#g6cf60e0] それではSIGVerseを起動してみましょう。 $ ./sigserver.sh -p 9001 SIGViewerを起動して見てみると人間のエージェントが手を広げてスタンバイしていると思います。 シミュレーションを開始するとエージェントの左腕が45°上がります。 #ref(man_1.jpg) 今回setJointAngleという関数を用いて"LARM_JOINT2" を45°にする設定を行いました。"LARM_JOINT2"は左肩のz軸での回転として定義された関節の名前です。同様に"LARM_JOINT0","LARM_JOINT1"はそれぞれ左肩のx軸、y軸の回転として定義されています。(エージェント座標系。)これらの関節名はsigverse-<version>/share/sigverse/data/shape/にあるx3dファイルで定義されています。 **エージェントの属性 [#nb731d79] ***属性の確認 [#g984fed9] SIGViewerでエージェントをクリックするとエージェントの名前や位置、視点の位置(vpx,vpy,vpz)などの属性を見ることができます。これらは属性の値はxmlファイルで設定されています。 #ref(atr_1.jpg) 人間型エージェントMan-niiはAgentクラスを継承したクラスです。Agentクラスの属性のデフォルトの値はAgent.xmlで設定されています。見てみましょう。 $ less xml/Agent.xml <?xml version="1.0" encoding="utf8"?> <define-class name="Agent" inherit="Entity.xml"> <attr name="language" type="string" group="model"/> <attr name="implementation" type="string" group="model"/> <!-- view point(agent coordinate) --> <attr name="vpx" type="double" group="viewpoint" value="0.0"/> <attr name="vpy" type="double" group="viewpoint" value="0.0"/> <attr name="vpz" type="double" group="viewpoint" value="0.0"/> <!-- view vector(view coordinate) --> <attr name="vvx" type="double" group="viewvector" value="0.0"/> <attr name="vvy" type="double" group="viewvector" value="0.0"/> <attr name="vvz" type="double" group="viewvector" value="-1.0"/> ・ ・ ・ 上で見たvpx,vvxなどの値が設定されているのがわかります。 さらにAgentクラスはEntityクラスを継承しています。Entityクラスは自律動作を行わない物体のクラスです。 **コマンドによるエージェントの操作 [#ta077379] 前回は定期的に呼び出されるonActionで手を上げるサンプルコードを紹介しました。次はSIGViewerからのメッセージを送信することによりエージェントがお辞儀をするようなサンプルコードを紹介します。 まずAgentController.cppを変更します。 $ cd NewWorld $ emacs AgentController.cpp #include <string> //stringをインクルード #include "Controller.h" #include "Logger.h" #include "ControllerEvent.h" #define PI 3.141592 #define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 ) using namespace std; //利用名前空間の定義 class AgentController : public Controller { public: double onAction(ActionEvent &evt); // メッセージを受信したときの関数onRecvMessageの利用を宣言します。 void onRecvMessage(RecvMessageEvent &evt); }; double AgentController::onAction(ActionEvent &evt) { try { SimObj *my = getObj(myname()); if (!my->dynamics()) { // 左手を90°下に下げます。 my->setJointAngle("LARM_JOINT2", DEG2RAD(-90)); // 右手を90°下に下げます。 my->setJointAngle("RARM_JOINT2", DEG2RAD(90)); } } catch(SimObj::Exception &) { ; } return 5.0; } void AgentController::onRecvMessage(RecvMessageEvent &evt) { //自分自身の取得 SimObj *my = getObj(myname()); //string型のメッセージを取得します。 string value(evt.getString(0)); if (value =="Hello"){ //腰の関節を45°曲げます。 my->setJointAngle("WAIST_JOINT1", DEG2RAD(45)); } } extern "C" Controller * createController () { return new AgentController; } onRecvMessageはメッセージを受信したときに呼び出される関数です。メッセージが"Hello"だったときにお辞儀をします。 それではコンパイルして実行してみましょう。 $ make $ cd .. $ ./sigserver.sh -p 9001 SIGViewerで接続して、 sendボタンをクリックしてシミュレーションを開始すると、まずonActionが呼び出されて右手と左手を下に下げます。 #ref(man_2.jpg) ***メッセージ送信 [#hb68ba23] まずSIGViewerの右上にあるCommandタブをクリックします。 一番上の入力欄でvoiceとgeneralが選択できるようになっていますが、generalを選択します。次に送信対象選択ボタンをクリックして画面上のエージェントをクリックします。エージェント名が自動的に入力されると思います。そしてSendMessage引数のところにHelloと入力します。 #ref(man_3.jpg) 入力が完了したら、実行ボタンを押します。 #ref(man_4.jpg) お辞儀をしました。 [[戻る>動力学シミュレーションのサンプル]] [[次へ>視覚に関する操作]]