28

v(x,y,z) データを測定する 3D センサーがあります。x と y のデータのみを使用しています。x と y だけを平滑化するだけで十分です。

ログを使用してデータを表示すると、 (time) 0.1 ... (Data log) x = 1.1234566667 (time) 0.2 ... (Data log) x = 1.1245655666 (time) 0.3 のように表示されます。 .. (データログ) x = 1.2344445555

データは実際にはより正確ですが、1.1234 値と 1.2344 値の間を滑らかにしたいのです。私にとっては同じなので、整数を使用して「x = 1」のみを表示できますが、小数も必要です。 、ここで一種の「平滑化された」値を表示する必要があります。

誰でも何か考えがありますか?私は C# でプログラミングしていますが、すべての関数が機能しているわけではないため、独自の関数を作成する必要があります。

4

6 に答える 6

66

最も簡単なのは、データの移動平均を行うことです。つまり、センサー データの読み取り値の配列を保持し、それらを平均化します。このようなもの(疑似コード):

  data_X = [0,0,0,0,0];

  function read_X () {
      data_X.delete_first_element();
      data_X.push(get_sensor_data_X());
      return average(data_X);
   }

これを行う場合、トレードオフがあります。使用する配列が大きいほど、結果は滑らかになりますが、結果と実際の読み取り値の間のラグが大きくなります。例えば:

                           /\_/\
                        /\/     \_/\
  Sensor reading:  __/\/            \/\
                                       \/\  _/\___________
                                          \/
                              _
                           __/ \_
                       ___/      \__
  Small array:     ___/             \_/\_       _
                                         \   __/ \________
                                          \_/

                                 ____
                              __/    \__
                           __/           \__
  Large array:     _______/                 \__      __
                                               \_   /  \__
                                                 \_/


(forgive my ASCII-ART but I'm hoping it's good enough for illustration).

とにかく高速な応答が必要であるが、良好な平滑化が必要な場合は、配列の加重平均を使用します。これは基本的にデジタル信号処理 (大文字の DSP を使用) であり、その名前に反してアナログ設計により密接に関連しています。これについてのウィキペディアの短い記事を次に示します (このパスをたどりたい場合は、適切な外部リンクを参照してください): http://en.wikipedia.org/wiki/Digital_filter

あなたのニーズに合ったローパスフィルターに関するSOのコードを次に示します。ローパスフィルターソフトウェア?. その回答のコードでは、サイズ 4 (信号処理用語では 4 次) の配列を使用していることに注意してください。このようなフィルターは 4 次フィルターと呼ばれるため、実際には 4 次多項式 ax^4 + bx でモデル化できます。 ^3 + cx^2 + dx) .

于 2011-01-06T04:35:36.193 に答える
26

そこで、同じ問題 (Android でのセンサー入力の平滑化) を解決するためにここに来ました。

/*
 * time smoothing constant for low-pass filter
 * 0 ≤ α ≤ 1 ; a smaller value basically means more smoothing
 * See: http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization
 */
static final float ALPHA = 0.2f;

protected float[] accelVals;

public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        accelVals = lowPass( event.values, accelVals );

    // use smoothed accelVals here; see this link for a simple compass example:
    // http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html
}

/**
 * @see http://en.wikipedia.org/wiki/Low-pass_filter#Algorithmic_implementation
 * @see http://en.wikipedia.org/wiki/Low-pass_filter#Simple_infinite_impulse_response_filter
 */
protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
        output[i] = output[i] + ALPHA * (input[i] - output[i]);
    }
    return output;
}

ウィキペディアのリンクを教えてくれた @slebetman に感謝します。少し読んだ後、ウィキペディアのローパス フィルターの記事のアルゴリズムにたどり着きました。私が最高のアルゴリズムを持っている (または正しい!) と断言するつもりはありませんが、事例証拠はそれがうまく機能していることを示しているようです。

于 2011-04-25T16:30:06.720 に答える
2

これは、iOS のイベント処理ガイドの MotionEvents セクションのロジックに基づく例です。

float ALPHA = 0.1;

protected float[] lowPass( float[] input, float[] output ) {
    if ( output == null ) return input;

    for ( int i=0; i<input.length; i++ ) {
        output[i] = (input[i] * ALPHA) + (ouptut[i] * (1.0 - ALPHA));
    }
    return output;
}
于 2012-12-18T21:09:43.930 に答える
0

ここで古い質問を掘り下げますが、.NET ランドにいる場合は、RX を使用してこれを行うことができます。

たとえば、RX を WebClient.DownloadFileAsync と組み合わせて使用​​して、「スムーズな」ダウンロード速度を計算します。

double interval = 2.0; // 2 seconds
long bytesReceivedSplit = 0;

WebClient wc = new WebClient();
var downloadProgress = Observable.FromEventPattern<
    DownloadProgressChangedEventHandler, DownloadProgressChangedEventArgs>(
    h => wc.DownloadProgressChanged += h,
    h => wc.DownloadProgressChanged -= h)
    .Select(x => x.EventArgs);

downloadProgress.Sample(TimeSpan.FromSeconds(interval)).Subscribe(x =>
    {
        Console.WriteLine((x.BytesReceived - bytesReceivedSplit) / interval);
        bytesReceivedSplit = x.BytesReceived;
    });

Uri source = new Uri("http://someaddress.com/somefile.zip");
wc.DownloadFileAsync(source, @"C:\temp\somefile.zip");

明らかに間隔が長いほど、平滑化が大きくなりますが、最初の読み取りまでの待ち時間も長くなります。

于 2012-05-22T13:50:47.477 に答える