歩行

前のページ
目次
次のページ


このページの内容


歩行モード

 Tekkotsuは次の2種類の歩行エンジンを持ちます。
    ・CMPack ・・・カーネギーメロン大学 2001年ロボカップサッカー用
    ・UPennalizers ・・・ ペンシルバニア大学 2004年ロボカップサッカー用

 これらはコントローラ画面の Walk Remote Control で試せます(下記)。

Walk Remote Control を試す

注意: 安全のため、AIBOを広い床に置き、進行方向に障害物を置かないで下さい

  1. AIBOを起動する。

  2. コントローラ画面でAIBOに接続後、StopモードからRunningモードにする。

  3. コントローラ画面 Root Control メニューから、TekkotsuMon を選ぶ。

  4. TekkotsuMon メニューから、Walk Remote Control または UPenn Walk Remote Control を選ぶ。

  5. 座標画面の中心点が赤色になったら、マウスで赤い点をドラッグして操作する。

  6. Walk Remote Control と UPenn Walk Remote Control を切り替えるには、使いたい方だけを赤字にしてください

 CMPack は滑らかな歩調なので、歩きながら物を探す場合に有利です。
 UPenn は滑らかではありませんが、速く歩く場合に有利です。

 両方とも3種類の速度ベクトルを持ちます:

 通常、Walk Remote Control ではマウスを使って dx と da をコントロールします。Horizontal is strafe ボタンを押すと、dx と dy をコントロールできます。

 AIBOは、決められたペースとパターンで足を繰り返し動かして歩きます。歩く速度を変えるにはペースでなく、歩幅を変えます(人や動物は歩幅とペースの両方を変えます)。


WalkMC モーションコマンド

 WalkMCモーションコマンドは、今まで勉強したモーションコマンド(LedMC, HeadPointerMC, PostureMC, MotionSequenceMC)と似ています。
 WalkMCモーションコマンドを実行するとき、速度や方向を変更するために MMAccessor を利用できます。


ボール追跡プログラム例 BallChaser.h

 下記のサンプルコードは、AIBOにピンクボールを追跡させるプログラムです。
 このプログラムでは、ボールの方向に頭を向けるために、HeadPointerMC を使用します。
 そして、頭の向いている方角へ歩くために WalkMC を使います。
 processEvent() では、ボールが検出されるたびに、VisionObjectEvent を受け取り、追跡のための処理を行います。
 赤色の箇所がWalkMCに関するコードです:

#ifndef INCLUDED_BallChaser_h_
#define INCLUDED_BallChaser_h_

#include "Behaviors/BehaviorBase.h"
#include "Events/EventRouter.h"
#include "Events/VisionObjectEvent.h"
#include "Motion/HeadPointerMC.h"
#include "Motion/MMAccessor.h"
#include "Motion/MotionManager.h"
#include "Motion/MotionSequenceMC.h"
#include "Motion/WalkMC.h"
#include "Shared/ProjectInterface.h"
#include "Shared/WorldState.h"

#define PI acos(-1.)                 // PI(3.14)の定義

class BallChaser : public BehaviorBase {
 protected:
	MotionManager::MC_ID stand_id;	// 立たせるモーションのidを宣言
	MotionManager::MC_ID headpointer_id;	// 頭部モーションのidを宣言
	MotionManager::MC_ID walker_id;	// 歩行モーションのidを宣言
 public:
  BallChaser() : BehaviorBase("BallChaser"),
    // 各idを初期化
    stand_id(MotionManager::invalid_MC_ID),
    headpointer_id(MotionManager::invalid_MC_ID),
    walker_id(MotionManager::invalid_MC_ID) {}

  virtual void DoStart() {
    BehaviorBase::DoStart();

    // 座位から歩行体勢に移行するためのモーションコマンド
    SharedObject<MediumMotionSequenceMC> stand_mc("sitwalk.mot");
    stand_id = motman->addPrunableMotion(stand_mc);

    // 頭の向きを制御するモーションコマンド
    SharedObject<HeadPointerMC> head_mc;
    headpointer_id = motman->addPersistentMotion(head_mc);

    // 歩行モーションコマンド
    SharedObject<WalkMC> walk_mc;
    walker_id = motman->addPersistentMotion(walk_mc);

    // ビジョンリスナーを追加
    erouter->addListener(this,EventBase::visObjEGID,ProjectInterface::visPinkBallSID);
  }
  
  virtual void DoStop() {
    motman->removeMotion(headpointer_id);

    motman->removeMotion(walker_id);
    BehaviorBase::DoStop();
  }

  static std::string getClassDescription()
    { return "Follows ball with head and walks whereever the head is pointing"; }

  virtual std::string getDescription() const { return getClassDescription(); }

 上記コード内で、getClassDescriptionを定義しています。この関数は、コントローラ画面でBallChaserにマウスを近づけたときに、文字列を表示します。

 紫色のコードは、AIBOを立たせるためのコードです。このコードはAIBOを立たせるときの基本になるので参考にしてください。

 下記の processEvent() について説明します。

 deactivateETIDはボールを見失ったときに起こるイベントです。また、visev.getObjectArea() は視野におけるボールの面積(%)です。ボールを見失ったり、ボール面積が1%未満になると、歩行を停止します(MMAccessor<WalkMC>(walker_id)->setTargetVelocity(0, 0, 0);)。
 ボールが見えている間は、ボールの方角に頭を向けるために画像内のボールの方角を計算します。注意すべきことは、頭を回す角度に限界があることです。コードmin(U,max(L,x))は、下限値L、上限値Uの間にxの範囲を設定します。

 ボールが3度以内の方角にあれば、AIBOを160mm/秒の速度で歩かせます。3度以内の範囲にボールがなければ、ボールの方角を向くように、AIBOを100mm/秒の速度で旋回させます。

  virtual void processEvent(const EventBase& event) {
    const VisionObjectEvent &visev =
      *reinterpret_cast<const VisionObjectEvent*>(&event);
    float const minBallArea = 0.01;  // 画像の1%

    // ボールを見失う、または、画像の1%未満なら停止
    if ( visev.getTypeID() == EventBase::deactivateETID ||
	 visev.getObjectArea() < minBallArea ) {

      MMAccessor<WalkMC>(walker_id)->setTargetVelocity(0, 0, 0);
      return;
    };

    float const ball_horiz_angle = visev.getCenterX() * CameraFOV/2;
    float const ball_vert_angle = visev.getCenterY() * CameraFOV/2;

    double const head_pan_angle = state->outputs[HeadOffset+PanOffset];
    double const head_tilt_angle = state->outputs[HeadOffset+TiltOffset];

    double const new_pan = 
      min(80.0*PI/180.0, max((-80.0)*PI/180.0, head_pan_angle - ball_horiz_angle));
    double const new_tilt = 
      min(40.0*PI/180.0, max((-20.0)*PI/180.0, head_tilt_angle - ball_vert_angle));

    // 頭をボールの方角に向ける
    MMAccessor<HeadPointerMC>(headpointer_id)->setJoints(new_tilt, new_pan, 0);

    // 頭を向けている方角に歩く
    MMAccessor<WalkMC> walker_acc(walker_id);
    if ( fabs(new_pan) < 0.05 )
	walker_acc->setTargetVelocity(160, 0, 0);        // 全速力で前進
    else
	walker_acc->setTargetVelocity(100, 0, new_pan);  // ボールの方向へ旋回

  }

};

#endif

 上記2つのプログラムを合体させて、次のように保存してください。

    保存する場所 : マイドキュメント → usXX → project
    ファイル名  : BallChaser.h
    ファイルの種類: C言語ヘッダーファイル(*.h)

 ファイルを保存したら、次の手順を実行してください。


補足(読み飛ばして構いません)

 画像の計算について、もう少し詳しく説明します。
 関数 getCenterX() と getCenterY()は、座標を -1と+1の間にした値を返します。
 カメラ中心座標は[0,0]です。
 実際のAIBOのカメラは、横長に写ります。
 X座標は-1と+1の間ですが、Y座標は-0.76と+0.76の間です。

 定数 RobotInfo::CameraFOV (ERS7Infoで定義) は、カメラの視野をラジアンで与えます。
 ERS-7の場合は、56.9度ですから0.99ラジアンです。
 水平視野はカメラ座標で-1と+1の範囲なので、画像中心からの距離getCenterX()を計算するために、CameraFOVを2で割ります。
 例えば、getCenterX()が1というのは、中心から右28度の位置に相当します。
 垂直視野は45.2度しかありません。
 これはY座標で0.76になるように調整されます。

 角度の計算は厳密ではありません。
 AIBOの頭がまっすぐ立っていれば、カメラのレンズ面が地面と垂直になるのでボールの方向は水平角になります。
 しかし、頭が下を向いていれば、カメラの「水平」は実際の水平線とは異なります。
 厳密さに欠けますが、ボールを追いかけるには充分です。
 なぜなら、AIBOは画像を逐次取り込んでモーションを調整するからです。
 厳密に計算するには「順方向運動学」という知識を使わなければなりませんが難しいので省略します。

発展:
  1. #include文で、WalkMC の代わりに UPennWalkMC を使用した場合、AIBOの歩き方は変わるでしょうか?

  2. BallChaserを次のように改造しなさい。getObjectArea() の値を使用して、AIBOがボールとの距離を一定に保つようにしなさい。ボールが近すぎると(Object Areaが大きすぎると)、AIBOが後退するようにしなさい。ボールが遠すぎると(Object Areaが小さすぎると)、AIBOが前進するようにしなさい。

  3. オリジナルのBallChaserを次のように改造しなさい。AIBOが決められた歩数で歩くようにしなさい。ボールを発見したとき(activateETIDのとき)、4歩前進し、停止するようにしなさい。getObjectArea()とdeactivateETIDは無視してよい。


前のページ
目次
次のページ