opentrack/opentrack — pull request #33 by dbaarda (2014-06-13 04:40:05+00:00)
Title: Improve ewma2 filter.

Note the diff shows the file as completely changed, but this is because I also fixed the DOS line terminators. If you do git diff -w to ignore whitespace changes you will see that the changes are not that extensive.

This does significantly change the way it works, but it does try to keep to the spirit of the original ewma2 filter. The main differences are;

1) It fixes an error on line 82 where min() should have been max(). This was introduced in a commit sthalik asked me about but I didn't get a chance to respond. EWMA filters like this are not idempotent by design and should be executed at regular "frame" intervals (which opentrack now does). This error adversely affected the filters ability to detect and react to movements that didn't affected all axis;
https://github.com/opentrack/opentrack/commit/d41bc9d228ba4bb600f94afb480ed6f84a64f9d5

2) It removes a nonsensical alpha_smoothing setting (0.02) which meant that the dynamic alpha adjustment was smoothed over the last 50 frames, effectively guaranteeing that it could not detect/react to movements quickly.

3) It attempts to learn the difference between movement and noise by measuring the signal variance instead of using a fixed scale[]. I have no idea if the fixed scale values were sensible, and may have seriously messed up the dynamic filtering, but this was probably "fixed" by the aggressive alpha_smoothing that effectively disabled the dynamic filtering anyway. This "learning" approach should make this work well for both noisy and non-noisy trackers.

4) It dynamically adjusts the filtering for each axis independently, instead of using the same filtering for all axis. This means it should avoid excessive noise in static axis when only some axis are changing, like excessive roll noise when only pitch is changing.

Note when testing this that it will take about 2mins at 30Hz (1min at 60Hz) to "learn the noise levels" and stabilize. The minSmooth and maxSmooth settings are effectively "frames of lag", and the SmoothingScaleCurve adjusts how much movement changes it from min to max smoothing, where big means tend towards less lag. I suggest for 30Hz starting with something like minSmooth=3(0.1sec lag), maxSmooth=30(1sec lag), smoothingScaleCurve=10 (changes of 1.5*stddev give 1/2 way between minSmooth and maxSmooth lag) . For 60Hz you want to double lags to minSmooth=6 and MaxSmooth=60 for the same effect.

For no movement, increase maxSmooth if you want less jitter, decrease it if you want faster reaction to movements. For fast movements, decrease minSmooth if you want less lag, and increase it if you want less jitter. For slow movements, increase smoothScaleCurve if you want less lag, and increase it if you want more smoothing, noting that minSmooth and maxSmooth also affect slow movements by setting the lower/upper bounds on the amount of smoothing.