Up:[[Tutorial]] Previous:[[動力学シミュレーションのサンプル]] Next:[[エージェント間のメッセージのやりとり]] ---- #contents *エージェントの動きに関する操作 [#v2485f29] ※このチュートリアルはv2.1.0以降対応しています。 人間またはロボットの形をしたエージェントの関節の操作方法を説明します。 **関節の操作 [#f5cb7768] 人間が手を上げるサンプルコードを紹介します。 ***コントローラの作成 [#oc032119] MyWorldディレクトリの中に新しくAgentController.cppを作成します。 $ emacs AgentController.cpp AgentController.cpp #highlight(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でエージェントの左腕が上に45°に上がるというものです。 ***コンパイル [#o78ee00f] コンパイルします。 $ ./sigmake.sh AgentController.cpp ***世界ファイル作成 [#l5dd7972] 次に世界ファイルを作成します。 $ emacs AgentWorld.xml AgentWorld.xml #highlight(xml){{ <?xml version="1.0" encoding="utf8"?> <world name="myworld2"> <!--重力の設定--> <gravity x="0.0" y="-980.7" 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++"/> <!--コントローラファイルの指定--> <set-attr-value name="implementation" value="./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="57.0"/> <set-attr-value name="z" value="0.0"/> </instanciate> </world> }} エージェントとしてMan-nii.xmlを読み込むように設定し、動力学演算をfalseにしました。動力学演算をtrueにするとエージェントの関節角度などを直接指定することができないので注意が必要です。 ***SIGVerse起動 [#g6cf60e0] それではSIGVerseを起動してみましょう。 $ sigserver.sh -w ./AgentWorld.xml SIGViewerを起動して見てみると人間のエージェントが手を広げてスタンバイしています。 シミュレーションを開始するとエージェントの左腕が45°上がります。 #ref(人間型エージェントの操作(v2.0系)/man_1.PNG,40%) 今回setJointAngleという関数を用いて"LARM_JOINT2" を45°にする設定を行いました。"LARM_JOINT2"は左肩のz軸での回転として定義された関節の名前です。同様に"LARM_JOINT0","LARM_JOINT1"はそれぞれ左肩のx軸、y軸の回転として定義されています。(エージェント座標系。)これらの関節名はsigverse-<version>/share/sigverse/data/shape/にあるx3dファイル(nii_man.x3d)で定義されています。サンプルモデルのジョイント名と回転軸は[[Joint定義一覧]]を参照ください。 世界ファイルは人間の設定ファイルMan-nii.xmlを読み込みMan-nii.xmlファイルは人間型エージェントの形状を記述したnii_man.x3dを読み込んでいます。 **コマンドによるエージェントの操作 [#ta077379] 前回は定期的に呼び出されるonActionで手を上げるサンプルコードを紹介しました。次はSIGViewerからのメッセージを送信することによりエージェントがお辞儀をするようなサンプルコードを紹介します。 新しくコントローラを作成します。 $ emacs AgentController2.cpp AgentController2.cpp #highlight(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: //シミュレーション開始時に一度だけ呼出される関数onInitの利用を宣言します。 void onInit(InitEvent &evt); double onAction(ActionEvent &evt); // メッセージを受信時に呼び出される関数onRecvMsgの利用を宣言します void onRecvMsg(RecvMsgEvent &evt); }; void AgentController::onInit(InitEvent &evt) { try { SimObj *my = getObj(myname()); if (!my->dynamics()) { // 左手を下に下げます my->setJointAngle("LARM_JOINT2", DEG2RAD(-90)); // 右手を下に下げます my->setJointAngle("RARM_JOINT2", DEG2RAD(90)); } } catch(SimObj::Exception &) { ; } } double AgentController::onAction(ActionEvent &evt) { return 10.0; } void AgentController::onRecvMsg(RecvMsgEvent &evt) { //自分自身の取得 SimObj *my = getObj(myname()); //string型のメッセージを取得します string msg = evt.getMsg(); if (msg =="Hello"){ //腰の関節を45(deg)曲げます my->setJointAngle("WAIST_JOINT1", DEG2RAD(45)); } } extern "C" Controller * createController () { return new AgentController; } }} メッセージ受信時に関数onRecvMsgが呼び出されます。メッセージが"Hello"だったときにお辞儀をします。 $ ./sigmake.sh AgentController2.cpp **世界ファイル [#rc50f412] 次に世界ファイルAgentWorld.xmlでコントローラを読み込んでいる個所をAgentContoroller2.soに修正します。 #highlight(xml:firstline[16]){{ <!--コントローラファイルの指定--> <set-attr-value name="implementation" value="./AgentController.so"/> }} ↓ #highlight(xml:firstline[16]){{ <!--コントローラファイルの指定--> <set-attr-value name="implementation" value="./AgentController2.so"/> }} **実行 [#d5c0a11e] それでは実行してみましょう。 $ sigserver.sh -w AgentWorld.xml $ sigserver.sh -w ./AgentWorld.xml SIGViewerで接続して、 "Connect"ボタンをクリックしてシミュレーションを開始すると、まずonActionが呼び出されて右手と左手を下に下げます。 #ref(人間型エージェントの操作(v2.0系)/man_2.PNG,40%) ***メッセージ送信 [#hb68ba23] まずSIGViewerの右下にあるMessageボタンをクリックします。 するとSendMessageトレイが現れます。TargetEntityでメッセージを送信するターゲット"man_000"を選択します。次にMessage:のところで"Hello"と入力します。 #ref(人間型エージェントの操作(v2.0系)/man_3.PNG,70%) 入力が完了したら、"Send"ボタンを押します。 #ref(人間型エージェントの操作(v2.0系)/man_4.PNG,40%) お辞儀をしました。 **クオータニオンによる関節の回転 [#ecbdc67b] 関節の回転はクオータニオンによって設定することもできます。 関節回転箇所を以下のように修正します。 AgentController2.cpp #highlight(cpp:firstline[51]){{ //腰の関節を45°曲げます。 my->setJointAngle("WAIST_JOINT1", DEG2RAD(45)); }} ↓ #highlight(cpp:firstline[51]){{ //腰の関節をx軸周りに90°回転させます。 my->setJointQuaternion("WAIST_JOINT1", 0.707, 0.707, 0.0, 0.0); }} setJointQuaternionという関数を使って関節のクオータニオンを設定します。引数で関節名の次にクオータニオンのw,x,y,z成分を指定します。 クオータニオンを指定した場合はあらかじめ設定されている関節の回転軸に関係なく回転します。 正常に関節が回転するか確認してみてください。 *Old version [#o627ede7] -[[人間型エージェントの操作(v2.0系)]] -[[人間型エージェントの操作(v120330, v1.4.8)]] #highlight(end) ---- Up:[[Tutorial]] Previous:[[動力学シミュレーションのサンプル]] Next:[[エージェント間のメッセージのやりとり]] #counter