2014年11月25日火曜日

ベジェ曲線の均等化について

マイクロマウスで使った技術についてつらつら書いていきます。

つってもそんなにないけど
あそこの界隈、なにが常識なのかよくわからん



まず、ベジェ曲線を使った加速について

ベジェ曲線とはなんなのかというと、

http://cubic-bezier.com/#.57,.11,.76,.16

↑これ

見たほうがわかりやすい


説明しとくと、

接線を指定することで、それに沿う曲線のこと

イラストレーターとか使われるパスツールがこれをつかってる

簡単に滑らかな曲線ができて便利


ただそれをロボットとかの加速に用いると変なことになる

なにが問題かというと式をそのまま用いると得られるデータが下の画像みたいになる



縦線が等間隔なので、xが小さいところはすごいデータが密集していることになる

描画するだけなら問題ないんだろうけど、加速とか制御に用いるときは困る

というわけで等間隔にする補正プログラムを作った


const int VejyeNumber = 70;

float vejyeAccelData[VejyeNumber];

void
make_vejye(float x1, float y1, float x2, float y2)
{
  float bejyu_x = 0;
  float bejyu_y = 0;
  float x = 0.01;
  int data_num = 0;

  for (float t = 0; t < 1; t += 1/((float)VejyeNumber*10.0))
    {
      bejyu_x = 3 * x1 * t * (1 - t) * (1 - t) + 3 * x2 * t * t * (1 - t) + t
          * t * t;
      bejyu_y = 3 * y1 * t * (1 - t) * (1 - t) + 3 * y2 * t * t * (1 - t) + t
          * t * t;

      if (bejyu_x > x)
        {
          vejyeAccelData[data_num] = bejyu_y;
          x += 1/(float)VejyeNumber;
          data_num++;
        }
    }
  vejyeAccelData[0] = 0;
  vejyeAccelData[VejyeNumber] = 1;
}

引数はさっきのURL先と同じなので、URL先を参考にしてください
たぶん、ベジェ曲線のときに与える値と同じはず

こうすると下の画像みたいになって、データがちゃんと等間隔に得られる





一応、加速度から速度と距離を算出するやつもおいときます。

const int VejyeNumber = 70;

float vejyeAccelData[VejyeNumber];
float vejyeVeloData[VejyeNumber];
float vejyeLengthData[VejyeNumber];

void
make_vejye(float x1, float y1, float x2, float y2)
{
  float bejyu_x = 0;
  float bejyu_y = 0;
  float x = 0.01;
  int data_num = 0;

  for (float t = 0; t < 1; t += 1/((float)VejyeNumber*10.0))
    {
      bejyu_x = 3 * x1 * t * (1 - t) * (1 - t) + 3 * x2 * t * t * (1 - t) + t
          * t * t;
      bejyu_y = 3 * y1 * t * (1 - t) * (1 - t) + 3 * y2 * t * t * (1 - t) + t
          * t * t;

      if (bejyu_x > x)
        {
          vejyeAccelData[data_num] = bejyu_y;
          x += 1/(float)VejyeNumber;
          data_num++;
        }
    }
  vejyeAccelData[0] = 0;
  vejyeAccelData[VejyeNumber] = 1;
  vejyeVeloData[0] = 0;
  vejyeLengthData[0] = 0;

  for (int i = 0; i < VejyeNumber; i++)
    {
      vejyeVeloData[i + 1] = vejyeVeloData[i] + vejyeAccelData[i + 1];
    }
  for (int i = 0; i < VejyeNumber; i++)
    {
      vejyeLengthData[i + 1] = vejyeLengthData[i] + vejyeVeloData[i + 1];
    }

}


0 件のコメント:

コメントを投稿