GestureRecognitionToolkit  Version: 0.1.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
Derivative.cpp
1 /*
2  GRT MIT License
3  Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
4 
5  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6  and associated documentation files (the "Software"), to deal in the Software without restriction,
7  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9  subject to the following conditions:
10 
11  The above copyright notice and this permission notice shall be included in all copies or substantial
12  portions of the Software.
13 
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "Derivative.h"
22 
23 GRT_BEGIN_NAMESPACE
24 
25 //Register the Derivative module with the PreProcessing base class
26 RegisterPreProcessingModule< Derivative > Derivative::registerModule("Derivative");
27 
28 Derivative::Derivative(UINT derivativeOrder,Float delta,UINT numDimensions,bool filterData,UINT filterSize){
29  classType = "Derivative";
30  preProcessingType = classType;
31  debugLog.setProceedingText("[DEBUG Derivative]");
32  errorLog.setProceedingText("[ERROR Derivative]");
33  warningLog.setProceedingText("[WARNING Derivative]");
34  if( derivativeOrder == FIRST_DERIVATIVE || derivativeOrder == SECOND_DERIVATIVE ){
35  init(derivativeOrder,delta,numDimensions,filterData,filterSize);
36  }
37 }
38 
40 
41  this->derivativeOrder = rhs.derivativeOrder;
42  this->filterSize = rhs.filterSize;
43  this->delta = rhs.delta;
44  this->filterData = rhs.filterData;
45  this->filter = rhs.filter;
46  this->yy = rhs.yy;
47  this->yyy = rhs.yyy;
48 
49  classType = "Derivative";
50  preProcessingType = classType;
51  debugLog.setProceedingText("[DEBUG Derivative]");
52  errorLog.setProceedingText("[ERROR Derivative]");
53  warningLog.setProceedingText("[WARNING Derivative]");
54 
56 }
57 
59 
60 }
61 
63  if( this != &rhs ){
64  this->derivativeOrder = rhs.derivativeOrder;
65  this->filterSize = rhs.filterSize;
66  this->delta = rhs.delta;
67  this->filterData = rhs.filterData;
68  this->filter = rhs.filter;
69  this->yy = rhs.yy;
70  this->yyy = rhs.yyy;
72  }
73  return *this;
74 }
75 
76 bool Derivative::deepCopyFrom(const PreProcessing *preProcessing){
77 
78  if( preProcessing == NULL ) return false;
79 
80  if( this->getPreProcessingType() == preProcessing->getPreProcessingType() ){
81 
82  Derivative *ptr = (Derivative*)preProcessing;
83 
84  //Clone the Derivative values
85  this->derivativeOrder = ptr->derivativeOrder;
86  this->filterSize = ptr->filterSize;
87  this->delta = ptr->delta;
88  this->filterData = ptr->filterData;
89  this->filter = ptr->filter;
90  this->yy = ptr->yy;
91  this->yyy = ptr->yyy;
92 
93  //Clone the base class variables
94  return copyBaseVariables( preProcessing );
95  }
96 
97  errorLog << "clone(const PreProcessing *preProcessing) - PreProcessing Types Do Not Match!" << std::endl;
98 
99  return false;
100 }
101 
102 bool Derivative::process(const VectorFloat &inputVector){
103 
104  if( !initialized ){
105  errorLog << "process(const VectorFloat &inputVector) - Not initialized!" << std::endl;
106  return false;
107  }
108 
109  if( inputVector.getSize() != numInputDimensions ){
110  errorLog << "process(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.size() << ") does not match that of the filter (" << numInputDimensions << ")!" << std::endl;
111  return false;
112  }
113 
114  computeDerivative( inputVector );
115 
116  if( processedData.size() == numOutputDimensions ) return true;
117  return false;
118 }
119 
121  if( initialized ) return init(derivativeOrder, delta, numInputDimensions,filterData,filterSize);
122  return false;
123 }
124 
125 bool Derivative::saveModelToFile(std::string filename) const{
126 
127  if( !initialized ){
128  errorLog << "saveModelToFile(string filename) - The DeadZone has not been initialized" << std::endl;
129  return false;
130  }
131 
132  std::fstream file;
133  file.open(filename.c_str(), std::ios::out);
134 
135  if( !saveModelToFile( file ) ){
136  file.close();
137  return false;
138  }
139 
140  file.close();
141 
142  return true;
143 }
144 
145 bool Derivative::saveModelToFile(std::fstream &file) const{
146 
147  if( !file.is_open() ){
148  errorLog << "saveModelToFile(fstream &file) - The file is not open!" << std::endl;
149  return false;
150  }
151 
152  file << "GRT_DERIVATIVE_FILE_V1.0" << std::endl;
153 
154  file << "NumInputDimensions: " << numInputDimensions << std::endl;
155  file << "NumOutputDimensions: " << numOutputDimensions << std::endl;
156  file << "DerivativeOrder: " << derivativeOrder << std::endl;
157  file << "FilterSize: " << filterSize << std::endl;
158  file << "Delta: " << delta << std::endl;
159  file << "FilterData: " << filterData << std::endl;
160 
161  return true;
162 }
163 
164 bool Derivative::loadModelFromFile(std::string filename){
165 
166  std::fstream file;
167  file.open(filename.c_str(), std::ios::in);
168 
169  if( !loadModelFromFile( file ) ){
170  file.close();
171  initialized = false;
172  return false;
173  }
174 
175  file.close();
176 
177  return true;
178 }
179 
180 bool Derivative::loadModelFromFile(std::fstream &file){
181 
182  if( !file.is_open() ){
183  errorLog << "loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
184  return false;
185  }
186 
187  std::string word;
188 
189  //Load the header
190  file >> word;
191 
192  if( word != "GRT_DERIVATIVE_FILE_V1.0" ){
193  errorLog << "loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
194  return false;
195  }
196 
197  //Load the number of input dimensions
198  file >> word;
199  if( word != "NumInputDimensions:" ){
200  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumInputDimensions header!" << std::endl;
201  return false;
202  }
203  file >> numInputDimensions;
204 
205  //Load the number of output dimensions
206  file >> word;
207  if( word != "NumOutputDimensions:" ){
208  errorLog << "loadModelFromFile(fstream &file) - Failed to read NumOutputDimensions header!" << std::endl;
209  return false;
210  }
211  file >> numOutputDimensions;
212 
213  //Load the DerivativeOrder
214  file >> word;
215  if( word != "DerivativeOrder:" ){
216  errorLog << "loadModelFromFile(fstream &file) - Failed to read DerivativeOrder header!" << std::endl;
217  return false;
218  }
219  file >> derivativeOrder;
220 
221  //Load the FilterSize
222  file >> word;
223  if( word != "FilterSize:" ){
224  errorLog << "loadModelFromFile(fstream &file) - Failed to read FilterSize header!" << std::endl;
225  return false;
226  }
227  file >> filterSize;
228 
229  //Load the Delta
230  file >> word;
231  if( word != "Delta:" ){
232  errorLog << "loadModelFromFile(fstream &file) - Failed to read Delta header!" << std::endl;
233  return false;
234  }
235  file >> delta;
236 
237  //Load if the data should be filtered
238  file >> word;
239  if( word != "FilterData:" ){
240  errorLog << "loadModelFromFile(fstream &file) - Failed to read FilterData header!" << std::endl;
241  return false;
242  }
243  file >> filterData;
244 
245  //Init the derivative module to ensure everything is initialized correctly
246  return init(derivativeOrder,delta,numInputDimensions,filterData,filterSize);
247 }
248 
249 bool Derivative::init(UINT derivativeOrder,Float delta,UINT numDimensions,bool filterData,UINT filterSize){
250 
251  initialized = false;
252 
253  if( derivativeOrder != FIRST_DERIVATIVE && derivativeOrder != SECOND_DERIVATIVE ){
254  errorLog << "init(UINT derivativeOrder,Float delta,UINT numDimensions,bool filterData,UINT filterSize) - Unknown derivativeOrder!" << std::endl;
255  return false;
256  }
257 
258  if( numDimensions == 0 ){
259  errorLog << "init(UINT derivativeOrder,Float delta,UINT numDimensions,bool filterData,UINT filterSize) - NumDimensions must be greater than 0!" << std::endl;
260  return false;
261  }
262 
263  if( delta <= 0 ){
264  errorLog << "init(UINT derivativeOrder,Float delta,UINT numDimensions,bool filterData,UINT filterSize) - Delta must be greater than 0!" << std::endl;
265  return false;
266  }
267 
268  if( filterSize == 0 ){
269  errorLog << "init(UINT derivativeOrder,Float delta,UINT numDimensions,bool filterData,UINT filterSize) - FilterSize must be greater than zero!" << std::endl;
270  return false;
271  }
272 
273  this->derivativeOrder = derivativeOrder;
274  this->delta = delta;
275  this->numInputDimensions = numDimensions;
276  this->numOutputDimensions = numDimensions;
277  this->filterData = filterData;
278  this->filterSize = filterSize;
279  filter.init(filterSize, numDimensions);
280  yy.clear();
281  yy.resize(numDimensions,0);
282  yyy.clear();
283  yyy.resize(numDimensions,0);
284  processedData.clear();
285  processedData.resize(numDimensions,0);
286  initialized = true;
287  return true;
288 }
289 
290 Float Derivative::computeDerivative(const Float x){
291 
292  if( numInputDimensions != 1 ){
293  errorLog << "computeDerivative(const Float x) - The Number Of Input Dimensions is not 1! NumInputDimensions: " << numInputDimensions << std::endl;
294  return 0;
295  }
296 
298 
299  if( y.size() == 0 ) return 0 ;
300 
301  return y[0];
302 }
303 
305 
306  if( !initialized ){
307  errorLog << "computeDerivative(const VectorFloat &x) - Not Initialized!" << std::endl;
308  return VectorFloat();
309  }
310 
311  if( x.size() != numInputDimensions ){
312  errorLog << "computeDerivative(const VectorFloat &x) - The Number Of Input Dimensions (" << numInputDimensions << ") does not match the size of the input vector (" << x.size() << ")!" << std::endl;
313  return VectorFloat();
314  }
315 
316  VectorFloat y;
317  if( filterData ){
318  y = filter.filter( x );
319  }else y = x;
320 
321  for(UINT n=0; n<numInputDimensions; n++){
322  processedData[n] = (y[n]-yy[n])/delta;
323  yy[n] = y[n];
324  }
325 
326  if( derivativeOrder == SECOND_DERIVATIVE ){
327  Float tmp = 0;
328  for(UINT n=0; n<numInputDimensions; n++){
329  tmp = processedData[n];
330  processedData[n] = (processedData[n]-yyy[n])/delta;
331  yyy[n] = tmp;
332  }
333  }
334 
335  return processedData;
336 }
337 
338 bool Derivative::setDerivativeOrder(UINT derivativeOrder){
339  if( derivativeOrder == FIRST_DERIVATIVE || derivativeOrder == SECOND_DERIVATIVE ){
340  this->derivativeOrder = derivativeOrder;
341  if( initialized ) init(derivativeOrder, delta, numInputDimensions,filterData,filterSize);
342  return true;
343  }
344  errorLog << "setDerivativeOrder(UINT derivativeOrder) - Unkown derivativeOrder" << std::endl;
345  return false;
346 }
347 
348 bool Derivative::setFilterSize(UINT filterSize){
349  if( filterSize > 0 ){
350  this->filterSize = filterSize;
351  if( initialized ) init(derivativeOrder, delta, numInputDimensions,filterData,filterSize);
352  return true;
353  }
354  errorLog << "setFilterSize(UINT filterSize) - FilterSize must be greater than zero!" << std::endl;
355  return false;
356 }
357 
358 bool Derivative::enableFiltering(bool filterData){
359  this->filterData = filterData;
360  if( initialized ) init(derivativeOrder, delta, numInputDimensions,filterData,filterSize);
361  return true;
362 }
363 
364 Float Derivative::getDerivative(UINT derivativeOrder){
365 
366  switch( derivativeOrder ){
367  case 0:
368  return processedData[0];
369  break;
370  case( FIRST_DERIVATIVE ):
371  return yy[0];
372  break;
373  case( SECOND_DERIVATIVE ):
374  return yyy[0];
375  break;
376  default:
377  warningLog << "getDerivative(UINT derivativeOrder) - Unkown derivativeOrder: " << derivativeOrder << std::endl;
378  break;
379  }
380 
381  return 0;
382 }
383 
385 
386  switch( derivativeOrder ){
387  case 0:
388  return processedData;
389  break;
390  case( FIRST_DERIVATIVE ):
391  return yy;
392  break;
393  case( SECOND_DERIVATIVE ):
394  return yyy;
395  break;
396  default:
397  warningLog << "getDerivative(UINT derivativeOrder) - Unkown derivativeOrder: " << derivativeOrder << std::endl;
398  break;
399  }
400 
401  return VectorFloat();
402 }
403 
404 GRT_END_NAMESPACE
bool init(UINT filterSize, UINT numDimensions)
UINT filterSize
The size of the filter used to filter the input data before the derivative is computed.
Definition: Derivative.h:233
virtual bool resize(const unsigned int size)
Definition: Vector.h:133
bool setDerivativeOrder(UINT derivativeOrder)
Definition: Derivative.cpp:338
VectorFloat yy
A buffer holding the previous input value(s)
Definition: Derivative.h:237
Float getDerivative(UINT derivativeOrder=0)
Definition: Derivative.cpp:364
VectorFloat yyy
A buffer holding the previous first derivative values.
Definition: Derivative.h:238
Float computeDerivative(const Float x)
Definition: Derivative.cpp:290
unsigned int getSize() const
Definition: Vector.h:193
virtual bool loadModelFromFile(std::string filename)
Definition: Derivative.cpp:164
virtual bool reset()
Definition: Derivative.cpp:120
Derivative & operator=(const Derivative &rhs)
Definition: Derivative.cpp:62
Float filter(const Float x)
VectorFloat getDerivatives(UINT derivativeOrder=0)
Definition: Derivative.cpp:384
std::string getPreProcessingType() const
virtual bool process(const VectorFloat &inputVector)
Definition: Derivative.cpp:102
bool filterData
Flags if the input data should be filtered before the derivative is computed.
Definition: Derivative.h:235
Float delta
The estimated time between sensor samples.
Definition: Derivative.h:234
virtual bool saveModelToFile(std::string filename) const
Definition: Derivative.cpp:125
bool copyBaseVariables(const PreProcessing *preProcessingModule)
virtual ~Derivative()
Definition: Derivative.cpp:58
bool enableFiltering(bool filterData)
Definition: Derivative.cpp:358
UINT derivativeOrder
The order of the derivative that will be computed (either FIRST_DERIVATIVE or SECOND_DERIVATIVE) ...
Definition: Derivative.h:232
Derivative(UINT derivativeOrder=FIRST_DERIVATIVE, Float delta=1, UINT numDimensions=1, bool filterData=true, UINT filterSize=3)
Definition: Derivative.cpp:28
bool setFilterSize(UINT filterSize)
Definition: Derivative.cpp:348
virtual bool deepCopyFrom(const PreProcessing *preProcessing)
Definition: Derivative.cpp:76
The Derivative class computes either the first or second order derivative of the input signal...
MovingAverageFilter filter
The filter used to low pass filter the input data.
Definition: Derivative.h:236