48

ハードウェアコンパスから時間の経過とともに一連の値を取得している瞬間に、何かをコーディングしています。このコンパスは非常に正確で、頻繁に更新されるため、コンパスがわずかに揺れると、隣のコンパスとはまったく一致しない奇妙な値になってしまいます。それらの値を滑らかにしたい。

いくつか読んだ後、私が必要としているのはハイパス フィルター、ローパス フィルター、または移動平均であることがわかります。移動平均は、最後の 5 つの値などの履歴を保持し、最新の値を使用していたコードの下流でそれらの値の平均を使用することができます。

それは、これらのジグルをうまく滑らかにするはずだと思いますが、おそらく非常に非効率的であり、これはおそらく、本当にきちんとした賢い数学ソリューションがある適切なプログラマーへの既知の問題の1つです.

しかし、私は、CompSci や数学に漠然と関連するものでさえ、正式な教育の断片を持たない、ひどい独学プログラマーの 1 人です。少し読んでみると、これはハイパスフィルターまたはローパスフィルターである可能性がありますが、私のようなハックが理解できる用語でこれらのアルゴリズムが値の配列に与える影響を説明するものは何も見つかりません。数学は機能します。たとえば、ここで与えられた答えは、技術的には私の質問に答えますが、おそらく問題を解決する方法をすでに知っている人に理解できる用語でのみです.

これがどのような問題なのか、そしてその解決策がどのように機能するのかを、文系の卒業生が理解できる言葉で説明できるのは、実に素敵で賢い人でしょう。

4

5 に答える 5

59

ときどき奇数の値を削除しようとしている場合は、特定した3つのオプションの中でローパスフィルターが最適です。ローパスフィルターは、コンパスを手で回転させるなどの低速の変化を可能にし、道路の凹凸などの高速の変化を排除します。

移動平均ウィンドウのサイズに応じて、データ内の1つの「ブリップ」の影響が後続のいくつかの値に影響するため、移動平均ではおそらく十分ではありません。

奇数の値が簡単に検出される場合は、それらを完全に無視するグリッチ除去アルゴリズムを使用する方がよい場合があります。

if (abs(thisValue - averageOfLast10Values) > someThreshold)
{
    thisValue = averageOfLast10Values;
}

これは、説明するためのギックグラフです。

グラフ比較

最初のグラフは入力信号で、不快なグリッチが1つあります。2番目のグラフは、10サンプルの移動平均の効果を示しています。最終的なグラフは、10サンプルの平均と上記の単純なグリッチ検出アルゴリズムの組み合わせです。グリッチが検出されると、実際の値の代わりに10サンプルの平均が使用されます。

于 2010-09-21T13:38:14.060 に答える
39

必要な平滑化を達成するために移動平均を長くする必要があり、カーネルの特定の形状が実際に必要ない場合は、指数関数的に減衰する移動平均を使用する方が良いでしょう:

a(i+1) = tiny*data(i+1) + (1.0-tiny)*a(i)

ここでtiny、適切な定数を選択します (たとえば、tiny = 1- 1/N を選択すると、サイズ N のウィンドウと同じ量の平均化が行われますが、古いポイントでは異なる分布になります)。

とにかく、移動平均の次の値は前の値とデータのみに依存するため、キューなどを保持する必要はありません。これは、次のようなことを考えることもできます。「新しい点が得られましたが、あまり信用できないので、以前の測定値の 80% を維持します。この新しいデータ ポイントを 20% 信頼してください。」これは、「この新しいポイントを 20% だけ信頼し、同じ量だけ信頼する他の 4 つのポイントを使用する」と言うのとほとんど同じですが、他の 4 つのポイントを明示的に取得する代わりに、前回行った平均化が適切であったため、以前の作業を使用できると仮定します。

于 2010-09-21T14:27:32.760 に答える
6

移動平均は理解できますが、おそらく非常に非効率的だと思います。

移動平均が非効率的であるべき理由は本当にありません。必要なデータ ポイントの数を何らかのバッファー (循環キューなど) に保持します。新しいデータ ポイントごとに、最も古い値をポップして合計から減算し、最新の値をプッシュして合計に追加します。したがって、すべての新しいデータ ポイントは、実際にはポップ/プッシュ、加算、および減算のみを必要とします。移動平均は常に、このシフト合計をバッファ内の値の数で割ったものです。

複数のスレッドから同時にデータを受信して​​いる場合は少し複雑になりますが、データがハードウェアデバイスから送信されているため、私には非常に疑わしいと思われます.

ああ、それから、ひどい独学のプログラマーが団結します! ;)

于 2010-09-21T13:20:21.980 に答える
2

指数関数的に減衰する移動平均は、適切な値を使用すれば、トレンドのみを使用して「手で」計算できます。「10% 平滑化による指数平滑移動平均」を探している場合、紙とペンを使ってこれをすばやく行う方法については、http://www.fourmilab.ch/hackdiet/e4/を参照してください。しかし、あなたはコンピューターを持っているので、おそらく 10 進シフトではなく 2 進シフトをしたいと思うでしょう ;)

このように、必要なのは現在の値の変数と平均の変数だけです。次の平均は、そこから計算できます。

于 2010-09-21T14:39:03.470 に答える
1

発生頻度の低いスプリアス サンプルに適したレンジ ゲートと呼ばれる手法があります。上記のフィルター手法 (移動平均、指数関数) のいずれかを使用すると仮定すると、「十分な」履歴 (1 つの時定数) があれば、新しい着信データ サンプルを計算に追加する前に妥当性をテストできます。

信号の最大の妥当な変化率に関するある程度の知識が必要です。生のサンプルが最新の平滑化された値と比較され、その差の絶対値が許容範囲よりも大きい場合、そのサンプルは破棄されます (または、勾配に基づく予測、微分または二重指数平滑法による「トレンド」予測値)

于 2016-04-30T06:56:24.023 に答える