HOME > BOIDSとは > BOIDSv1.00 ~避ケル~


09.15 BOIDSv1.00 ~避ケル~

★魚の眼

前回「爺になってからのベクトル」で自局と他ポッドをベクトルに見立て、「距離」さらには内積・外積を計算することによって、「進行方向に対する」を算出することができるようになりました。これによって「視界」「視線」等のある意味「目」を作り出せるようになりました。


目ができたら、どうやってぶつからないようにしているかです。
恒星社厚生閣 亀井まさのり著 「ああ、そうなんだ! 魚講座の中で

「人の場合は「目が良い」というと、通常は視力の良い人、つまりメガネなどを使っていない場合を指しますね。魚の場合、目が良いか悪いかは、いろいろな場合があるので一言ではいえません。まず、魚の「視野」について考えてみると、人と比べ物にならない広いのです。なにしろ魚眼レンズと呼ばれるほどですから前後、左右、広範囲に見ることができます。魚にとってみえにくい、つまり死角は体後方の一部だけといわれています。
「視力」は、おおむね0.1~0.6ですが、マグロやカジキのような大型で表層を回遊する魚は視力が良く、カサゴやアオメエソのような底魚で深海性の魚は視力が悪いといわれています。」

と書いてあります。
つまり、「視界は広い」けれども「視力はよくない」ので遠くのものまでは見えない。
写真を撮ることも趣味なのですが、ここ数年で急激に出てきたのが360度カメラという全天撮影型のカメラですが、さらにそれよりも超広角=魚眼レンズをもった魚ですからねぇ!!



★ どのように避けるか? (一般回避)

緊急ではない一般的な事例で考えてみると、多分人も魚も同じなのではないかと考えるのです、人の場合歩きではなく船・浮き輪・サーフボードに載っている場合を考えていただくと、下のようになるのではないかと思うのです。(赤色魚=自ポッド 、青色魚=他ポッド)

<原則>
外積計算時の符号で判定するため「真正面」「右に他ポッド」がいる場合は「左旋回する」。「左に他ポッド」がいる場合は「右旋回する」.この場合相手も同じ旋回行動をとる為、旋回角度が小さくても2倍の旋回角度で回避したことになるのではないかと読んでいます。



<諸事例>
・横から他ポッドが来た場合
横から来た場合回避距離が長い場合は避けられますが、短いとぶつかってしまいます。
回避距離パラメータに注意が必要になります。

・後方から来た場合
現在考えているのは同じ論理で除けはしますが、速度がほぼ同じなため最終的には避けない方がよいのではないか?



★ 複数の論理

問題になるのは下記のように複数になった場合をどうするかです。
現在は一番接近している他ポッドを回避することを最優先とするように考えていますが、実際にはダメなケースが出るのではないかと予想しています。一番わかりやすいのが周囲にすべて一定の距離をおいた鰯で移動しているときに下の黄色魚のようなのが接近してきたら、逃げようがありません。ですので、速度だけで回避するのには限界があるのではないかと考えています。






では、まずここまでの論理をプログラムにしてみましょう。
ちょっとここで1つ秘策をご紹介。

多分ネットで「isRight」や「Vector_s」「isLeft」などで検索すると同じような名称が出てくると思います。あまり詳しくないのですがゲームなどを作る際に使用されるパッケージ「DirectX」とかいうライブラリーに同じ名称のものがあります。実際にはどのように持ってきてどのように使用するかがわからないので、同じような名称で自分で作成してみましたので、同じような名称の関数や構造体が使用されていますので、DirectXを使用できる方は多分自作の方が格段に遅いのでDirectXを使用してください。


/************************************************************************
* 対象が右にいるかの確認                        *
************************************************************************/
bool isRight(Iwashi_str *IwashiThis, Iwashi_str *IwashiOther)
{
  double   inprod;


  inprod = (IwashiOther->Vec.y * (IwashiThis->Pos.x - IwashiOther->Pos.x)) -
        (IwashiOther->Vec.x * (IwashiThis->Pos.y - IwashiOther->Pos.y));

  if (inprod >= 0)
  {
    return true;
  }
  else
  {
    return false;
  }
}
 
/************************************************************************
* 分離(Separation)の導入                        *
* 前方視野角度内で一定距離ない個体を規定角度で避ける          *
* 相手の進行方向に関係なく、相手の位置と反対に逃げる          *
************************************************************************/
void separation(int index,Iwashi_str *IwashiThis)
{
  int       nearIwashi;
  double     isFront;
  int       isLeft;
  Vector_str   Vec;
  double     dist;

  nearIwashi = 0;

  for (int i = 0; i < iwashi_kazu; i++)
  {
    if (i != index)
    {
      isCrosDot(IwashiThis , &iwashi[i] , &isFront , &isLeft);
          /* 自分以外との角度・回転方向算出  */
      if (fabs(isFront) <= _SEPARATION_VIEW_ANGLE)
      {    /* Iwashiの視野設定   */
        dist = distanceTo(&iwashi[i].Pos, &IwashiThis->Pos);
        if ( dist <= (PodSize + _SEPARATION_VIEW_DIST))
        {    /* 視野内距離の算出   */
          if (nearIwashi != 0)
          {
            if (dist <= distanceTo(&iwashi[nearIwashi-1].Pos , &IwashiThis->Pos))
            {
              nearIwashi = i+1;
            }
          }
          else
          {
            nearIwashi = i+1;
          }
        }
      }
    }
  }

  if (nearIwashi != 0)
  {
    if ( isRight( &iwashi[nearIwashi - 1], IwashiThis) )
    {      /* 向かって右にいる場合 */
      Vec.x = IwashiThis->Vec.x * cos_separation - IwashiThis->Vec.y * sin_separation;
      Vec.y = IwashiThis->Vec.x * sin_separation + IwashiThis->Vec.y * cos_separation;
    }
    else
    {
      Vec.x = IwashiThis->Vec.x * cos_separation + IwashiThis->Vec.y * sin_separation;
      Vec.y = -IwashiThis->Vec.x * sin_separation + IwashiThis->Vec.y * cos_separation;
    }

    IwashiThis->Vec.x = Vec.x;
    IwashiThis->Vec.y = Vec.y;
  }
}




ここで少々復習しておくと、二次元の座標を回転させる際は下記のような行列で計算していました。
さらに算術演算を実際に実行すると時間がかかる為、決まった角度回転するため予め計算しておきます。今回は複数ではないので配列ではなく定数を用います。さらに実際に計算するとわかりますが、回転方向が変わるとマイナスの位置が変更されるだけで定数値は変化しないので、回転方向で2つに分ければ済みます。
 
cos θ 2 - sin θ 2 sin θ 2 cos θ 2 x y = x cos θ 2 - y sin θ 2 x sin θ 2 + y cos θ 2



【BOISV1.00 ~避ケル~】




HOME   > BOIDSv1.00 ~爺になってからのベクトル~ > BOIDSv1.00 ~避ケル~