81 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef ONEEURO_H
 | |
| #define ONEEURO_H
 | |
| /*
 | |
| 1-Euro Filter, template-compliant version
 | |
| Jonathan Aceituno <join@oin.name>
 | |
| 
 | |
| 25/04/14: fixed bug with last_time_ never updated on line 40
 | |
| 
 | |
| For details, see http://www.lifl.fr/~casiez/1euro
 | |
| 
 | |
| Updates:
 | |
| 
 | |
| - 23 May 2019 by Haimo Zhang <zh.hammer.dev@gmail.com>
 | |
|   - Included Arduino header
 | |
| 
 | |
| */
 | |
| 
 | |
| #ifdef ARDUINO
 | |
| /**
 | |
|  * cmath is not included in Arduino library, but we have the Arduino.h header
 | |
|  * which defines the abs macro.
 | |
|  */
 | |
| #include <Arduino.h>
 | |
| #else
 | |
| #include <cmath>
 | |
| #endif
 | |
| 
 | |
| template <typename T = double>
 | |
| struct low_pass_filter {
 | |
| 	low_pass_filter() : hatxprev(0), xprev(0), hadprev(false) {}
 | |
| 	T operator()(T x, T alpha) {
 | |
| 		T hatx;
 | |
| 		if(hadprev) {
 | |
| 			hatx = alpha * x + (1-alpha) * hatxprev;
 | |
| 		} else {
 | |
| 			hatx = x;
 | |
| 			hadprev = true;
 | |
| 		}
 | |
| 		hatxprev = hatx;
 | |
| 		xprev = x;
 | |
| 		return hatx;
 | |
| 	}
 | |
| 	T hatxprev;
 | |
| 	T xprev;
 | |
| 	bool hadprev;
 | |
| };
 | |
| 
 | |
| template <typename T = double, typename timestamp_t = double>
 | |
| struct one_euro_filter {
 | |
| 	one_euro_filter(double _freq, T _mincutoff, T _beta, T _dcutoff) : freq(_freq), mincutoff(_mincutoff), beta(_beta), dcutoff(_dcutoff), last_time_(-1) {}
 | |
| 	T operator()(T x, timestamp_t t = -1) {
 | |
| 		T dx = 0;
 | |
| 		
 | |
| 		if(last_time_ != -1 && t != -1 && t != last_time_) {
 | |
| 			freq = 1.0 / (t - last_time_);
 | |
| 		}
 | |
| 		last_time_ = t;
 | |
| 		
 | |
| 		if(xfilt_.hadprev)
 | |
| 			dx = (x - xfilt_.xprev) * freq;
 | |
| 		
 | |
| 		T edx = dxfilt_(dx, alpha(dcutoff));
 | |
| 		T cutoff = mincutoff + beta * abs(static_cast<double>(edx));
 | |
| 		return xfilt_(x, alpha(cutoff));
 | |
| 	}
 | |
| 	
 | |
| 	double freq;
 | |
| 	T mincutoff, beta, dcutoff;
 | |
| private:
 | |
| 	T alpha(T cutoff) {
 | |
| 		T tau = 1.0 / (2 * M_PI * cutoff);
 | |
| 		T te = 1.0 / freq;
 | |
| 		return 1.0 / (1.0 + tau / te);
 | |
| 	}
 | |
| 	
 | |
| 	timestamp_t last_time_;
 | |
| 	low_pass_filter<T> xfilt_, dxfilt_;
 | |
| };
 | |
| 
 | |
| #endif
 |