- worked on about everything - grid walker using plugable modules - wifi models - new distributions - worked on geometric data-structures - added typesafe timestamps - worked on grid-building - added sensor-classes - added sensor analysis (step-detection, turn-detection) - offline data reader - many test-cases
140 lines
3.0 KiB
C++
140 lines
3.0 KiB
C++
#ifndef BAROMETER_H
|
|
#define BAROMETER_H
|
|
|
|
#include "../../data/Timestamp.h"
|
|
#include "../../math/MovingAVG.h"
|
|
|
|
#include "BarometerData.h"
|
|
|
|
/**
|
|
* calculates the pressure realtive to a startup-calibration of a barometer
|
|
* hereafter all returned values are relative to the calibration
|
|
*
|
|
*/
|
|
class RelativePressure {
|
|
|
|
private:
|
|
|
|
/** barometer history entries (timestamp -> value) */
|
|
struct History {
|
|
Timestamp ts;
|
|
BarometerData data;
|
|
History(const Timestamp ts, const BarometerData data) : ts(ts), data(data) {;}
|
|
};
|
|
|
|
/** barometer calibration helper */
|
|
struct Calibration {
|
|
|
|
Timestamp neededTimeframe = Timestamp::fromMS(5000);
|
|
|
|
std::vector<History> history;
|
|
bool isCalibrated = false;
|
|
float baseAvg = 0;
|
|
float sigma = 0;
|
|
|
|
// prevent sensor-startup-issues and skip the first 25% of measurement values
|
|
float skipStart = 0.25;
|
|
|
|
void tryToCalibrate() {
|
|
|
|
// determine the timeframe contained within the history
|
|
const Timestamp timeframe = history.back().ts - history.front().ts;
|
|
|
|
// do we have enough values to perform a calibration?
|
|
if (timeframe < neededTimeframe) {return;}
|
|
|
|
// we need double as float would lead to huge rounding errors!
|
|
double sum = 0;
|
|
double sum2 = 0;
|
|
int cnt = 0;
|
|
|
|
// calculate sum and sum²
|
|
for (int i = (int)(skipStart*history.size()); i < (int)history.size(); ++i) {
|
|
const History& h = history[i];
|
|
sum += h.data.hPa;
|
|
sum2 += ((double)h.data.hPa * (double)h.data.hPa);
|
|
++cnt;
|
|
}
|
|
|
|
// calculate E(x) and E(x²)
|
|
double avg = sum / (double)cnt;
|
|
double avg2 = sum2 / (double)cnt;
|
|
|
|
// set calibrated values
|
|
this->baseAvg = avg;
|
|
this->sigma = std::sqrt( avg2 - (avg*avg) );
|
|
this->isCalibrated = true;
|
|
|
|
}
|
|
|
|
void reset() {
|
|
history.clear();
|
|
isCalibrated = false;
|
|
sigma = 0;
|
|
baseAvg = 0;
|
|
}
|
|
|
|
} calib;
|
|
|
|
float latesthPa;
|
|
|
|
|
|
public:
|
|
|
|
/** ctor */
|
|
RelativePressure() {
|
|
|
|
}
|
|
|
|
/** set the timeframe used for the startup calibration (e.g. 5 seconds) */
|
|
void setCalibrationTimeframe(const Timestamp timeframe) {
|
|
this->calib.neededTimeframe = timeframe;
|
|
}
|
|
|
|
/** add new sensor readings that were received at the given timestamp */
|
|
void add(const Timestamp& ts, const BarometerData& baro) {
|
|
|
|
// perform calibration?
|
|
if (!calib.isCalibrated) {
|
|
calib.history.push_back(History(ts, baro));
|
|
calib.tryToCalibrate();
|
|
}
|
|
|
|
// most recent pressure reading
|
|
latesthPa = baro.hPa;
|
|
|
|
}
|
|
|
|
/** get the most recent pressure reading realtive to the startup calibration. returns 0 until the sensor is calibrated */
|
|
float getPressureRealtiveToStart() {
|
|
if (calib.isCalibrated) {
|
|
return latesthPa - calib.baseAvg;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/** reset the sensor's calibration */
|
|
void reset() {
|
|
calib.reset();
|
|
}
|
|
|
|
/** get the barometer's calibrated uncertainty determined during the startup calibration */
|
|
float getSigma() {
|
|
return calib.sigma;
|
|
}
|
|
|
|
/** get the barometer's calibrated average during the startup calibration */
|
|
float getBaseAvg() {
|
|
return calib.baseAvg;
|
|
}
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
#endif // BAROMETER_H
|