forked from auduno/headtrackr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsmoother.js
89 lines (71 loc) · 2.12 KB
/
smoother.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
* Smoother for smoothing tracked positions of face
*
* Double Exponential Smoothing-based Prediction
* see: http://www.cs.brown.edu/people/jjl/pubs/kfvsexp_final_laviola.pdf
* "Double Exponential Smoothing: An alternative to Kalman Filter-based Predictive Tracking"
*
* @author auduno / github.com/auduno
* @param {number} a Smoothing parameter, between 0 and 1. 0 is max smoothing, 1 no smoothing.
* @param {number} interval The ms interval between tracking events
* @constructor
*/
headtrackr.Smoother = function(alpha, interval) {
// alpha = 0.35 smoothes ok while not introducing too much lag
var sp, sp2, sl, newPositions, positions;
var updateTime = new Date();
this.initialized = false;
// whether to use linear interpolation for times in intervals
this.interpolate = false;
this.init = function(initPos) {
this.initialized = true;
sp = [initPos.x, initPos.y, initPos.z, initPos.width, initPos.height];
sp2 = sp;
sl = sp.length;
}
this.smooth = function(pos) {
positions = [pos.x, pos.y, pos.z, pos.width, pos.height];
if (this.initialized) {
// update
for (var i = 0;i < sl;i++) {
sp[i] = alpha*positions[i]+(1-alpha)*sp[i];
sp2[i] = alpha*sp[i]+(1-alpha)*sp2[i];
}
// set time
updateTime = new Date();
var msDiff = (new Date())-updateTime;
var newPositions = predict(msDiff);
pos.x = newPositions[0];
pos.y = newPositions[1];
pos.z = newPositions[2];
pos.width = newPositions[3];
pos.height = newPositions[4];
return pos;
} else {
return false;
}
}
function predict(time) {
var retPos = [];
if (this.interpolate) {
var step = time/interval;
var stepLo = step >> 0;
var ratio = alpha/(1-alpha);
var a = (step-stepLo)*ratio;
var b = (2 + stepLo*ratio);
var c = (1 + stepLo*ratio);
for (var i = 0;i < sl;i++) {
retPos[i] = a*(sp[i]-sp2[i]) + b*sp[i] - c*sp2[i];
}
} else {
var step = time/interval >> 0;
var ratio = (alpha*step)/(1-alpha);
var a = 2 + ratio;
var b = 1 + ratio;
for (var i = 0;i < sl;i++) {
retPos[i] = a*sp[i] - b*sp2[i];
}
}
return retPos;
}
}