2

地理的距離を計算するために、MCU の sin/cos を最適化しようとしています。式のこの部分は、特に三角法を使用しています。

double e = (MyTan( lat2 / 2 + quarter_pi ) / MyTan( lat1 / 2 + quarter_pi ));

そこで、次のようにtoの独自のsin/cosルックアップ テーブルを作成しようとしました。-PIPI

#define PARTPERDEGREE 10
double mysinlut[PARTPERDEGREE * 90 + 1];
double mycoslut[PARTPERDEGREE * 90 + 1];
void MySinCosCreate()
{
    int i;
    double angle, angleinc;

    // Each degree also divided into 10 parts
    angleinc = (M_PI / 180) / PARTPERDEGREE;
    for (i = 0, angle = 0.0; i <= (PARTPERDEGREE * 90 + 1); ++i, angle += angleinc)
    {
        mysinlut[i] = sin(angle);
    }

    angleinc = (M_PI / 180) / PARTPERDEGREE;
    for (i = 0, angle = 0.0; i <= (PARTPERDEGREE * 90 + 1); ++i, angle += angleinc)
    {
        mycoslut[i] = cos(angle);
    }
}



double MySin(double rad)
{
   int ix;
   int sign = 1;


   if(rad > (M_PI / 2))
        rad = M_PI / 2 - (rad - M_PI / 2);

   if(rad < -(M_PI / 2))
       rad = -M_PI / 2 - (rad + M_PI / 2);

   if(rad < 0)
   {
        sign = -1;
        rad *= -1;
   }

   ix = (rad * 180) / M_PI * PARTPERDEGREE;

   return sign * mysinlut[ix];
}

double MyCos(double rad)
{
   int ix;
   int sign = 1;


    if(rad > M_PI / 2)
    {
        rad = M_PI / 2 - (rad - M_PI / 2);
        sign = -1;
    }
    else if(rad < -(M_PI / 2))
    {
        rad = M_PI / 2 + (rad + M_PI / 2);
        sign = -1;
    }
    else if(rad > -M_PI / 2 && rad < M_PI / 2)
    {   
        rad = abs(rad);
        sign = 1;
    }

    ix = (rad * 180) / M_PI * PARTPERDEGREE;

    return sign * mycoslut[ix];
}

double MyTan(double rad)
{
    return MySin(rad) / MyCos(rad);
}

テーブルの分解能が 10 パーツ/度であることがわかります。少し増やすことはできますが、あまり役に立たず、補間が必要なようです。より良い結果を得るために、誰かが私の機能にいくつかの実用的な改善を提案できますか? 以下は、 の 234 の異なる結果のグラフですe。青のシリーズは理想的な sin/cos で、赤は LUT からのものです。

ここに画像の説明を入力

4

2 に答える 2

4

ルックアップ テーブルが粗すぎるようです。テーブルをあまり細かくできない場合は、導関数を使用して値を概算すると、より良い結果が得られます。我々は持っています

sin (x+h) ≈ sin x + h*cos x
cos (x+h) ≈ cos x - h*sin x

小用h。(より高い導関数を使用するか、(計算された)角度がその間にあるテーブルの両方の値を使用することで、より良い近似を得ることができますが、それには時間がかかります。そもそもLUTの理由は速度を収集することです。)

したがって、角度を正規化した後、

ix = (rad * 180) / M_PI * PARTPERDEGREE;

使用する

double h = rad - ix*angleinc;
return sign*(mysinlut[ix] + h*mycoslut[ix]);

それぞれ

return sign*(mycoslut[ix] - h*mysinlut[ix]);

これは遅すぎてはならず、LUT ポイント間の近似が大幅に改善されるはずです。

于 2012-12-06T19:19:42.710 に答える
1

ここで説明するsin/cos補間の古いが良い漸化式。

于 2012-12-06T18:59:21.850 に答える