|
|
|
このページの内容
イベント名 Event Generator ID(EGID) 説明 タイマーイベント timerEGID タイマーが設定時間に到達したら発生する テキストメッセージイベント textmsgEGID パソコン等からテキストメッセージが届いたら発生する ボタンイベント buttonEGID AIBOのボタンが押されたら発生する ビジョンオブジェクトイベント visObjEGID AIBOが物体を見たら発生する モーションマネージャイベント motmanEGID AIBOが特定の動きをしたとき、または動きを終了したとき発生する
イベントに応じた処理プログラムは、processEvent() 関数に書きます。
processEvent() 関数は、イベントが発生するたびに自動的に呼び出されます。
したがって、main()関数は存在せず、processEvent()関数の中にイベントに応じた処理プログラムを書きます(下図)。
イベントが発生しても、そのイベントに対する処理プログラムがprocessEvent()関数に書かれていない場合、そのイベントは無視されます。
イベントは次に示す3組の値で区別されます。
これらの値は、それぞれ関数を使用して求めることができます。
その関数が、getGeneratorID()、getSourceID()、getTypeID()です。
ボタンが押されたときは、次の値を求めることができます。
ちなみに、すべてのイベントは EventBaseの派生クラスです。
リスナーを追加するための構文 erouter->addListener(this, generatorID, sourceID, typeID); sourceidとtypeidは省略可能
課題
練習: イベントリスナーを設定しよう Behaviorのプログラムを改造して、イベントリスナーを設定する練習をします。下記プログラムは、AIBOのボタンを押したり、離したりしたときに発生するイベント情報をTelnet画面に表示するプログラムです。
このプログラムをコピーして、秀丸に貼り付けてください。
そして次の通り保存してください。保 存 先: マイドキュメント → usXX → projectフォルダ
ファイル名: MyButtonEvent.h
ファイル種類: C言語ヘッダーファイル(*.h)プログラムで赤字の箇所が新しく追加された部分です。
また、ファイル名が MyButtonEvent.h になったので、茶色の部分も変更しています。
ファイルを保存したら、次の手順を実行してください。
#ifndef INCLUDED_MyButtonEvent_h_ #define INCLUDED_MyButtonEvent_h_ #include "Behaviors/BehaviorBase.h" #include "Events/EventRouter.h" // イベントを処理するためのヘッダファイル class MyButtonEvent : public BehaviorBase { public: MyButtonEvent() : BehaviorBase("MyButtonEvent") {} virtual void DoStart() { BehaviorBase::DoStart(); std::cout << getName() << " is starting up." << std::endl; erouter->addListener(this,EventBase::buttonEGID); // ボタンイベントのリスナーを追加 } virtual void DoStop() { std::cout << getName() << " is shutting down." << std::endl; BehaviorBase::DoStop(); } // イベントを処理する関数 virtual void processEvent(const EventBase &event) { // ボタンイベントを聞き取ったことを表示する std::cout << "MyButtonEvent got event: " << event.getDescription() << std::endl; } }; #endif
switch
文を使用します。switch ( event.getGeneratorID() ) と記せば、generator IDを識別して、generator IDに応じた処理を行うことができるようになります。
練習: ピンクボールとテキストメッセージを検出しよう ピンクボールをカメラの前に置いたり、パソコンからテキストメッセージを送ったりすると、これらイベント情報をTelnet画面に表示するプログラムを作りましょう。
上で作成したプログラムを下記の通り改造します。追加した箇所は赤字で示しています。
このプログラムをコピーして、秀丸に貼り付けて保存してください。保 存 先: マイドキュメント → usXX → projectフォルダ
ファイル名: MyTextEvent.h
ファイル種類: C言語ヘッダーファイル(*.h)
ファイルを保存したら、次の手順を実行してください。
#ifndef INCLUDED_MyTextEvent_h_ #define INCLUDED_MyTextEvent_h_ #include "Behaviors/BehaviorBase.h" #include "Events/EventRouter.h" #include "Events/TextMsgEvent.h" // TextMsgEventを処理するためのヘッダファイル #include "Events/VisionObjectEvent.h" // VisonObjectEventを処理するためのヘッダファイル #include "Shared/ProjectInterface.h" // visPinkBallSIDを定義しているヘッダファイル class MyTextEvent : public BehaviorBase { public: MyTextEvent() : BehaviorBase("MyTextEvent") {} virtual void DoStart() { BehaviorBase::DoStart(); std::cout << getName() << " is starting up." << std::endl; erouter->addListener(this,EventBase::buttonEGID); // ボタンイベントのリスナー erouter->addListener(this,EventBase::visObjEGID, // ピンクボールのリスナー ProjectInterface::visPinkBallSID); erouter->addListener(this,EventBase::textmsgEGID); // テキストメッセージのリスナー } virtual void DoStop() { std::cout << getName() << " is shutting down." << std::endl; BehaviorBase::DoStop(); } virtual void processEvent(const EventBase &event) { // generator IDに応じてスイッチする switch ( event.getGeneratorID() ) { // generator IDがvisObjEGIDの場合 case EventBase::visObjEGID: { // eventをvisevにキャスト変換 const VisionObjectEvent &visev = *reinterpret_cast<const VisionObjectEvent*>(&event); // ボールを見つけたときのtype IDの場合 if ( visev.getTypeID() == EventBase::activateETID || visev.getTypeID() == EventBase::statusETID ) // ピンクボールを見たよ、と表示する std::cout << "MyTextEvent saw a pink ball at ( " << // ボールのX座標、Y座標を表示する visev.getCenterX() << " , " << visev.getCenterY() << " )" << std::endl; // ボールを見失った場合 else // ボールを見失ったよ、と表示する std::cout << "MyTextEvent lost sight of the pink ball." << std::endl; break; }; // generator IDがtextmsgEGIDの場合 case EventBase::textmsgEGID: { // eventをtxtevにキャスト変換 const TextMsgEvent &txtev = *reinterpret_cast<const TextMsgEvent*>(&event); // 受け取ったメッセージを表示する std::cout << "MyTextEvent heard: '" << txtev.getText() << "'" << std::endl; break; }; case EventBase::buttonEGID: std::cout << "MyTextEvent got event: " << event.getDescription() << std::endl; break; default: std::cout << "Unexpected event: " << event.getDescription() << std::endl; } } }; #endif
Behaviorにタイマーを設定するためには、Event Routerを使用します。
タイマーはBehaviorごとに設定するので、タイマー同士が衝突することはありません。
1つのBehaviorが同時に複数のタイマーを動かすこともできます。これらのタイマーは整数のIDで区別されます。プログラマは addTimer()関数を用いて任意のIDを与えることができます。
Behaviorは、同じIDを持つタイマーを1回だけ使用できます。もし、同じIDでaddTimer()を使用すると、以前に設定されたタイマーはリセットされます。
タイマーは removeTimer()関数を使用して、タイマーをキャンセルできます。
タイマーイベントID(timerEGID)を聞き取るためのリスナーはプログラムで追加する必要はありません。addTimer()でタイマーを設定すると自動的にリスナーが追加されます。
タイマーを設定するための構文
erouter->addTimer(this,id,msec,false);
idは任意の整数、msecはミリ秒(設定したい時間)
タイマーを解除するための構文
erouter->removeTimer(this,id);
idは設定したときの値
練習: タイマーの設定と解除 以下のプログラムはタイマーを使用する例です。
AIBOの左前足の肉球が押されたときに、タイマーをID 1234で設定します。
タイマーは5秒(5000ミリ秒)動きます。タイマーの単位はミリ秒(千分の1秒)です。
タイマー設定後、5秒以内に右前足の肉球が押されると、タイマーが削除されます。
タイマー設定後、5秒以内に右前足の肉球が押されなければ、タイマーが時間切れになります。時間切れになると、タイマーイベントが発生し、Telnet画面に "Timer expired!"と表示されます。 このプログラムをコピーして、秀丸に貼り付けて保存してください。
保 存 先: マイドキュメント → usXX → projectフォルダ
ファイル名: MyTimerEvent.h
ファイル種類: C言語ヘッダーファイル(*.h)
ファイルを保存したら、次の手順を実行してください。
#ifndef INCLUDED_MyTimerEvent_h_ #define INCLUDED_MyTimerEvent_h_ #include "Behaviors/BehaviorBase.h" #include "Events/EventRouter.h" class MyTimerEvent : public BehaviorBase { public: MyTimerEvent() : BehaviorBase("MyTimerEvent") {} virtual void DoStart() { BehaviorBase::DoStart(); std::cout << getName() << " is starting up." << std::endl; erouter->addListener(this,EventBase::buttonEGID); // ボタンイベントのリスナー } virtual void DoStop() { std::cout << getName() << " is shutting down." << std::endl; BehaviorBase::DoStop(); } virtual void processEvent(const EventBase &event) { // generator IDに応じて処理を切り替える switch ( event.getGeneratorID() ) { // generator IDがbuttonEGID(ボタンイベントの場合) case EventBase::buttonEGID: // type IDがactivateETID(ボタンを押されたとき) if ( event.getTypeID() == EventBase::activateETID ) { std::cout << "MyTimerEvent got event: " << event.getDescription() << std::endl; // source IDがLFrPawOffset(押されたのが左前足のとき) if ( event.getSourceID() == RobotInfo::LFrPawOffset ) // タイマーを設定する。ID 1234、時間5秒 erouter->addTimer(this,1234,5000,false); // source IDがRFrPawOffset(押されたのが右前足のとき) else if ( event.getSourceID() == RobotInfo::RFrPawOffset ) // タイマーを解除する。ID 1234 erouter->removeTimer(this,1234); }; break; // generator IDがtimerEGID(タイマーイベントの場合) case EventBase::timerEGID: // Timer expired! を表示 std::cout << "Timer expired! " << event.getDescription() << std::endl; break; default: std::cout << "Unexpected event: " << event.getDescription() << std::endl; } } }; #endif
|
|
|