#ifndef WIFIEVALUATION_H #define WIFIEVALUATION_H #include "../particles/MyState.h" #include "WiFiObservation.h" #include "PositionedWiFiAP.h" #include "Settings.h" #include "../particles/MyObservation.h" #include class WiFiEvaluation { private: Settings settings; WiFiObservation obs; WiFiObservationEntry strongest; public: void nextObservation(const WiFiObservation& _obs) { if (_obs.entries.empty()) {return;} obs = filter(_obs); strongest = getStrongest(&obs); } double getProbability(const MyState& state, const MyObservation& observation) const { if (obs.entries.empty()) {return 1.0;} double prob = 0;//1.0; //const double tx = -48; // tablet //const double pl = 3.15; const float waf = 8;//10.0; // was 7 before?! has something todo with the floor heights / levels // get the ap the client had the strongest measurement for //const PositionedWifiAP* relAP = settings.getAP(strongest.mac); assert(relAP); //const double distToStrongest_m = state.getDistance2D(relAP->xCM, relAP->yCM) / 100.0; //const double strongestFloorDist = std::abs(relAP->zNr - state.z_nr); //const double mdlStrongestRSSI = distanceToRssi(relAP->tx, distToStrongest_m, relAP->pl) - (strongestFloorDist * waf); // process each detected AP for (const WiFiObservationEntry& entry : obs.entries) { // get the AP data from the settings const PositionedWifiAP* ap = settings.getAP(entry.mac); assert(ap); // distance (in meter) between particle and AP const float distToAP_m = state.pCur.getDistance(*ap) / 100.0; // floor difference? const float floorDiff = std::abs(Helper::getFloorNrFloat(ap->z) - Helper::getFloorNrFloat(state.pCur.z)); //const float floorDiff = std::round(std::abs(Helper::getFloorNr(ap->z) - Helper::getFloorNr(state.pCur.z))); //const float floorDiff = std::abs(ap->z - state.pCur.z) / 340; // estimate the rssi depending on above distance const double mdlRSSI = distanceToRssi(ap->tx, distToAP_m, ap->pl) - (floorDiff * waf); // the measured rssi const double realRSSI = entry.rssi; // the measured relative rssi //const double realRelRSSI = strongest.rssi - realRSSI; //const double mdlRelRSSI = mdlStrongestRSSI - mdlRSSI; // probability? (sigma grows with measurement's age) const double sigma = (8) + ((observation.latestSensorDataTS - entry.ts) / 1000.0) * 3.5; const double p = K::NormalDistribution::getProbability(mdlRSSI, sigma, realRSSI); // absolute //const double p = K::NormalDistribution::getProbability(mdlRelRSSI, sigma, realRelRSSI); // relative //prob *= p; prob += std::log(p); } //const double lambda = 0.05;//0.15; //0.12; //return lambda * exp(- lambda * (-prob)); return std::pow(std::exp(prob), 0.1); // if (prob < -30) {return 0.01;} // if (prob < -15) {return 0.50;} // else {return 1.00;} //return prob; } WiFiObservation filter(const WiFiObservation& obs) const { WiFiObservation out; for (const WiFiObservationEntry& entry : obs.entries) { // alter the mac WiFiObservationEntry ne = entry; //ne.mac[ne.mac.length()-1] = '0'; // enabled = VAP grouping. also adjust settings to use ending "0" if (settings.getAP(ne.mac)) {out.entries.push_back(ne);} } return out; } /** get the strongest AP within all measurements */ WiFiObservationEntry getStrongest(const WiFiObservation* obs) const { WiFiObservationEntry max = obs->entries.front(); for (const WiFiObservationEntry& entry : obs->entries) { if (entry.rssi > max.rssi) {max = entry;} } return max; } static double rssiToDistance(double txPower, double rssi, double pathLoss) { return pow(10, (txPower - rssi) / (10 * pathLoss)); } static double distanceToRssi(double txPower, double distance, double pathLoss) { if (distance <= 1) {return txPower;} return (txPower - (10 * pathLoss * log10(distance))); } }; #endif // WIFIEVALUATION_H