BOIDSv2.00 ~行動(ス)ル~ HOME > BOIDSとは > BOIDSv2.00 ~行動(ス)ル~

10.04 BOIDSv2.00 ~行動(ス)ル~

検知(ミ)ル」では実際に自ポッドからみた障害物を検知しました。 「知識(シ)ル」では、その情報を「知識として」蓄えることができました。
前回AI将棋のお話で出てきたように、「知識」に該当する「行動パターン」により実際に「どう動かすか」を指示します。旧態のプログラムですと「もし~なら XXXXする ~じゃなかったら ****する」といった、いわゆるフローチャート的な思考は止めにして、視覚情報をパターン化してすべての組み合わせに対し、どう行動するかを指示するということです。言葉ではなかなか難しい言い回しになってしまいますので実施プログラムを作ってみましょう。

【AIいわし知識ベース】
【 AIいわし知識ベース 】
CollisionStatus 0 進行方向右に壁あり(近接)
1 進行方向左に壁あり(近接)
2 進行方向中央に壁あり(近接)
3 進行方向右に壁あり
4 進行方向左に壁あり
5 進行方向中央に壁あり
6 進行方向右にポッドあり(近接)
7 進行方向左にポッドあり(近接)
8 進行方向中央にポッドあり(近接)
9 進行方向右にポッドあり
10 進行方向左にポッドあり
11 進行方向中央にポッドあり


この視覚情報(CollisionStatus)から視覚パターン(patternNo)にビット情報として移し替えます。

【視覚パターン(patternNo)】
    ビット 0    :    進行方向右に壁(真正面も含む)
    ビット 1    :    進行方向左に壁
    ビット 2    :    進行方向右にポッド(真正面も含む)
    ビット 3    :    進行方向左にポッド

この時序に視覚深度(目標位置までの距離を2パターン)に分類し同様にパターン化します。
    Far_Wal    :  ビットONしている場合は遠くにある場合 
        ビット 0    :    進行方向右に壁(真正面も含む)
        ビット 1    :    進行方向左に壁

    Far_Pod    :  ビットONしている場合は遠くにある場合 
        ビット 2    :    進行方向右にポッド(真正面も含む)
        ビット 3    :    進行方向左にポッド


/************************************************************************
*  ステータス設定部                          *
************************************************************************/
    void  SetupStatus(int index, Iwashi_str  *IwashiThis)
    {
      Vector_str   Vec;
      int       patternNo;
      int       Far_Wal;
      int       Far_Pod;
      double     theta;
      int       dir;
      int       rot;


      patternNo  = 0;
      Far_Pod = 0;
      Far_Wal = 0;
      if ((IwashiThis->CollisionStatus[0] != 0)
            ||
        (IwashiThis->CollisionStatus[2] != 0)
            ||
        (IwashiThis->CollisionStatus[3] != 0)
            ||
        (IwashiThis->CollisionStatus[5] != 0))
      {  /* 進行方向右に壁            */
        patternNo |= 0x0001;
        if ((IwashiThis->CollisionStatus[3] != 0)
              ||
          (IwashiThis->CollisionStatus[5] != 0))
        {
          Far_Wal |= 0x0001;
        }
      }

      if ((IwashiThis->CollisionStatus[1] != 0)
            ||
        (IwashiThis->CollisionStatus[4] != 0))
      {  /* 進行方向左に壁            */
        patternNo |= 0x0002;
        if (IwashiThis->CollisionStatus[4] != 0)
        {
          Far_Wal |= 0x0002;
        }
      }

      if (  (IwashiThis->CollisionStatus[6] != 0)
                ||
          (IwashiThis->CollisionStatus[8] != 0)
                ||
          (IwashiThis->CollisionStatus[9] != 0)
                ||
          (IwashiThis->CollisionStatus[11] != 0) )
      {  /* 進行方向右にポッド            */
        patternNo |= 0x0004;
        if (  (IwashiThis->CollisionStatus[9] != 0)
                ||
            (IwashiThis->CollisionStatus[11] != 0) )
        {
          Far_Pod |= 0x0004;
        }
      }

      if (  (IwashiThis->CollisionStatus[7] != 0)
                ||
          (IwashiThis->CollisionStatus[10] != 0) )
      {  /* 進行方向左にポッド            */
        patternNo |= 0x0008;
        if (IwashiThis->CollisionStatus[10] != 0)
        {
          Far_Pod |= 0x0008;
        }
      }


次に視覚パターン(patternNo)は、0以外の場合前方に障害物があることになりますので、≠0の場合に行動パターンが実行されます。

先にも説明したように「検知(ミ)ル」→「知識(シ)ル」→「行動(ス)ル」というのが必ず1セットで実行されますので、視覚パターンが4ビット構成なのですべてのパターンは16パターンあって、何もしない0以外は15パターンについて、どう動くかを考えればよいわけです。しかし行動は決まっていて、必ず「どちらかへ旋回する」わけなので、次の2つを指示します。

    dir     : 回転する方向(_ROT_MIGI:右旋回 、_ROT_HIDARI:左旋回)
    rot    : 回転角度
                    _COLLISION_ANGLE_00  : 微弱旋回
                    _COLLISION_ANGLE_01  :  一般旋回
                    _COLLISION_ANGLE_02  : 矛盾旋回 
                    _COLLISION_ANGLE_03  : 緊急旋回 

例題 パターン=6の場合
    ビット 1    :    進行方向左に壁
    ビット 2    :    進行方向右にポッド(真正面も含む)
 
右ポッド、左に壁がいるケースになります。
黒色が自ポッドの場合、下のような2つのケースが考えられます。
この場合壁もポッドも距離を加味すると、こちらの方がこんがらかってしまいますので、とりあえず最初は壁の距離を気にせずポッドの位置だけを考慮すると、ポッドが近い場合は急激に、遠い場合は一般的な旋回角度で旋回するように指示します。






      if (patternNo != 0)
      {
        theta  = 0.0;
        dir   = 0;
        switch(patternNo)
        {
        case  1: /* 右壁     */
          dir   = _ROT_HIDARI;
          rot   = _COLLISION_ANGLE_01;
          break;

        case  2: /* 左壁     */
          dir   = _ROT_MIGI;
          rot   = _COLLISION_ANGLE_01;
          break;

        case  3: /* 左右壁    */
          dir   = _ROT_HIDARI;
          rot   = _COLLISION_ANGLE_02;
          break;

        case  4: /* 右ポッド   */
          dir   = _ROT_HIDARI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_01;
          }
          else
          {
            rot   = _COLLISION_ANGLE_00;
          }
          break;

        case  5: /* 右ポッド 右壁 */
          dir   = _ROT_HIDARI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_01;
          }
          else
          {
            rot   = _COLLISION_ANGLE_00;
          }
          break;

        case  6: /* 右ポッド 左壁 */
          dir   = _ROT_MIGI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_02;
          }
          else
          {
            rot   = _COLLISION_ANGLE_01;
          }
          break;

        case  7: /* 右ポッド 左右壁 */
          dir   = _ROT_HIDARI;
          rot   = _COLLISION_ANGLE_03;
          break;

        case  8: /* 左ポッド   */
          dir   = _ROT_MIGI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_01;
          }
          else
          {
            rot   = _COLLISION_ANGLE_00;
          }
          break;

        case  9: /* 左ポッド 右壁 */
          dir   = _ROT_HIDARI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_01;
          }
          else
          {
            rot   = _COLLISION_ANGLE_01;
          }
          break;

        case  10: /* 左ポッド 左壁 */
          dir   = _ROT_MIGI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_01;
          }
          else
          {
            rot   = _COLLISION_ANGLE_00;
          }
          break;

        case  11: /* 左ポッド 左右壁 */
          dir   = _ROT_MIGI;
          if (Far_Pod == 0)
          {
            rot   = _COLLISION_ANGLE_02;
          }
          else
          {
            rot   = _COLLISION_ANGLE_02;
          }
          break;

        case  12: /* 左右ポッド  */
          if ((Far_Pod & 0x04) == 0)
          {
            dir   = _ROT_HIDARI;
          }
          else
          {
            dir   = _ROT_MIGI;
          }
          rot   = _COLLISION_ANGLE_02;
          break;

        case  13: /* 左右ポッド 右壁 */
          dir   = _ROT_HIDARI;
          if ((Far_Pod & 0x08) == 0)
          {
            rot   = _COLLISION_ANGLE_02;
          }
          else
          {
            rot   = _COLLISION_ANGLE_01;
          }
          break;

        case  14: /* 左右ポッド 左壁 */
          dir   = _ROT_MIGI;
          if ((Far_Pod & 0x04) == 0)
          {
            rot   = _COLLISION_ANGLE_02;
          }
          else
          {
            rot   = _COLLISION_ANGLE_01;
          }
          break;

        case  15: /* 左右ポッド 左右壁 */
          dir   = _ROT_MIGI;
          rot   = _COLLISION_ANGLE_03;
          break;
        }

        if ( dir == 0 )
        {              /* 向かって右にいる場合     */
          Vec.x = IwashiThis->Vec.x * cosAngle[rot] - IwashiThis->Vec.y * sinAngle[rot];
          Vec.y = IwashiThis->Vec.x * sinAngle[rot] + IwashiThis->Vec.y * cosAngle[rot];
        }
        else
        {
          Vec.x = IwashiThis->Vec.x * cosAngle[rot] + IwashiThis->Vec.y * sinAngle[rot];
          Vec.y = -IwashiThis->Vec.x * sinAngle[rot] + IwashiThis->Vec.y * cosAngle[rot];
        }

        if (index == 0)
        {
          textBox3->Text = dir.ToString();
          textBox4->Text = patternNo.ToString();
        }
        IwashiThis->Vec.x = Vec.x;
        IwashiThis->Vec.y = Vec.y;
      }
   }



★予想される問題点
一番危惧される問題点は、数が多くり周辺に固まった場合逃げ場がなくなってしまうケースです。

次に下のように壁の角に向かっているケースでは左右の壁がほぼ同じ距離にある為、右旋回すると右の壁、左旋回すると左の壁となり、一種の振動してしまい結局まっすぐ進むことになってしまうケースです。このためいくら壁厳守のルールにしても絶えず動くという前提では矛盾を来すことが分かっています。





HOME   > BOIDSv2.00 ~行動(ス)ル~