This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/sensors/activity/ActivityButterPressure.h
toni 3f8d21e146 fixed two bugs in ActivityButterPressure:
1) when barometer produces false measurements, we needed some kind of upper boundary
2) coding error static.. while initializing this object over multiple test iterations isnt the best idea
2017-11-06 18:04:55 +01:00

139 lines
4.3 KiB
C++

#ifndef ACTIVITYBUTTERPRESSURE_H
#define ACTIVITYBUTTERPRESSURE_H
#include "../../data/Timestamp.h"
#include "../../math/filter/Butterworth.h"
#include "../../math/FixedFrequencyInterpolator.h"
#include "../../math/MovingAVG.h"
#include "../pressure/BarometerData.h"
#include "Activity.h"
/**
* receives pressure measurements, interpolates them to a ficex frequency, lowpass filtering
* activity recognition based on a small window given by matlabs diff(window)
*/
class ActivityButterPressure {
public:
struct History {
Timestamp ts;
BarometerData data;
History(const Timestamp ts, const BarometerData data) : ts(ts), data(data) {;}
};
private:
std::vector<History> output;
std::vector<History> baroInterpHistory;
Activity currentActivity;
MovingAVG<float> mvAvg = MovingAVG<float>(20);
/** change this values for much success
*
* Nexus 6:
* butter = Filter::ButterworthLP<float>(10,0.1f,2);
* threshold = 0.025;
* diffSize = 20;
* FixedFrequencyInterpolator<float> ffi = FixedFrequencyInterpolator<float>(Timestamp::fromMS(100));
*/
const bool additionalLowpassFilter = false;
const unsigned long diffSize = 20; //the number values used for finding the activity.
//TODO: some kind of algorithm to calculate the threshold
const float threshold = 0.025f; // if diffSize is getting smaller, treshold needs to be adjusted in the same direction!
const float upperBoundary = 0.1; // if this boundary is passed, we should have errors in barometer data
Filter::ButterworthLP<float> butter = Filter::ButterworthLP<float>(10,0.05f,2);
Filter::ButterworthLP<float> butter2 = Filter::ButterworthLP<float>(10,0.05f,2);
bool firstCall = false;
FixedFrequencyInterpolator<float> ffi = FixedFrequencyInterpolator<float>(Timestamp::fromMS(100));
public:
/** ctor */
ActivityButterPressure() : currentActivity(Activity::STANDING){
;
}
/** add new sensor readings that were received at the given timestamp */
void add(const Timestamp& ts, const BarometerData& baro) {
//init
if(!firstCall){
butter.stepInitialization(baro.hPa);
firstCall = true;
butter2.stepInitialization(0);
currentActivity = Activity::STANDING;
}
bool newInterpolatedValues = false;
//interpolate & butter
auto callback = [&] (const Timestamp ts, const float val) {
//interp
float interpValue = val;
baroInterpHistory.push_back(History(ts, BarometerData(interpValue)));
//butter
float butterValue = butter.process(interpValue);
output.push_back(History(ts, BarometerData(butterValue)));
newInterpolatedValues = true;
};
ffi.add(ts, baro.hPa, callback);
if(newInterpolatedValues == true){
//getActivity
if(output.size() > diffSize){
//diff
std::vector<float> diff;
for(unsigned long i = output.size() - diffSize; i < output.size() - 1; ++i){
float diffVal = output[i+1].data.hPa - output[i].data.hPa;
diff.push_back(diffVal);
}
float sum = 0;
for(float val : diff){
sum += val;
}
float actValue = 0;
if(additionalLowpassFilter == true){
//additional butter/moving average for the results
//mvAvg.add(sum);
//actValue = mvAvg.get();
actValue = butter2.process(sum);
}else{
actValue = sum;
}
if(actValue > threshold && actValue < upperBoundary){
currentActivity = Activity::WALKING_DOWN;
}
else if (actValue < -threshold && actValue > -upperBoundary){
currentActivity = Activity::WALKING_UP;
}
else{
currentActivity = Activity::WALKING;
}
}
}
}
/** get the current Activity */
Activity get() const {
return currentActivity;
}
};
#endif // ACTIVITYBUTTERPRESSURE_H