|
@@ -29,7 +29,6 @@ class RateOfChange : public QObject
|
29
|
29
|
int ct;
|
30
|
30
|
int st;
|
31
|
31
|
QList<Measurement> cache;
|
32
|
|
- QMap<double,double> smoothCache;
|
33
|
32
|
};
|
34
|
33
|
|
35
|
34
|
@ The interesting part of this class is in the |newMeasurement()| method. This
|
|
@@ -88,51 +87,33 @@ if(cache.size() > 2)
|
88
|
87
|
}
|
89
|
88
|
}
|
90
|
89
|
|
91
|
|
-@ The calculation method here is subject to change as this is still noisier
|
92
|
|
-than I would like. What we are doing here is calculating the rate of change
|
93
|
|
-between each pair of adjacent measurements in the cache and averaging them to
|
94
|
|
-produce something that is a little less noisy than just using the first and
|
95
|
|
-last measurements in the cache. Other techniques may be useful for reducing the
|
96
|
|
-noise further.
|
|
90
|
+@ Rather than work directly with changes from one measurement to the next and
|
|
91
|
+attempting to filter out the noise, we instead calculate the slope of a simple
|
|
92
|
+linear regression on the current window of data.
|
97
|
93
|
|
98
|
94
|
The measurement will carry the fact that it is a relative measurement.
|
99
|
95
|
|
100
|
96
|
@<Calculate rate of change@>=
|
101
|
|
-QList<double> rates;
|
102
|
|
-for(int i = 1; i < cache.size(); i++)
|
|
97
|
+int N = cache.size();
|
|
98
|
+double SXY = 0;
|
|
99
|
+double SX = 0;
|
|
100
|
+double SXX = 0;
|
|
101
|
+double SY = 0;
|
|
102
|
+double y;
|
|
103
|
+double x;
|
|
104
|
+for(int i = 0; i < N; i++)
|
103
|
105
|
{
|
104
|
|
- double mdiff = cache.at(i).temperature() - cache.at(i-1).temperature();
|
105
|
|
- double tdiff = (double)(cache.at(i-1).time().msecsTo(cache.at(i).time())) / 1000.0;
|
106
|
|
- rates.append(mdiff/tdiff);
|
|
106
|
+ y = cache.at(i).temperature();
|
|
107
|
+ SY += y;
|
|
108
|
+ x = cache.at(0).time().msecsTo(cache.at(i).time()) / 1000.0;
|
|
109
|
+ SX += x;
|
|
110
|
+ SXX += (x*x);
|
|
111
|
+ SXY += (x*y);
|
107
|
112
|
}
|
108
|
|
-double acc = 0.0;
|
109
|
|
-for(int i = 0; i < rates.size(); i++)
|
110
|
|
-{
|
111
|
|
- acc += rates.at(i);
|
112
|
|
-}
|
113
|
|
-double pavg = acc /= rates.size();
|
114
|
|
-double v2 = pavg * st;
|
115
|
|
-double refm = cache.back().temperature() - cache.front().temperature();
|
116
|
|
-double reft = (double)(cache.front().time().msecsTo(cache.back().time())) / 1000.0;
|
117
|
|
-double ref = refm/reft;
|
118
|
|
-Measurement value(v2, cache.back().time(), cache.back().scale());
|
|
113
|
+double M = ((N * SXY) - (SX * SY)) / ((N * SXX) - (SX * SX));
|
|
114
|
+Measurement value(M * st, cache.back().time(), cache.back().scale());
|
119
|
115
|
value.insert("relative", true);
|
120
|
116
|
emit newData(value);
|
121
|
|
-double calcdiff = ref - pavg;
|
122
|
|
-if(calcdiff < 0)
|
123
|
|
-{
|
124
|
|
- calcdiff = -calcdiff;
|
125
|
|
-}
|
126
|
|
-if(pavg < 0)
|
127
|
|
-{
|
128
|
|
- pavg = -pavg;
|
129
|
|
-}
|
130
|
|
-if(calcdiff > (pavg * 0.2))
|
131
|
|
-{
|
132
|
|
- Measurement save = cache.back();
|
133
|
|
- cache.clear();
|
134
|
|
- cache.append(save);
|
135
|
|
-}
|
136
|
117
|
|
137
|
118
|
@ The rest of the class implementation is trivial.
|
138
|
119
|
|