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/radio/WiFiProbabilityGrid.h
2018-10-25 11:50:12 +02:00

143 lines
4.0 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © Copyright 2014 Urheberrechtshinweis
* Alle Rechte vorbehalten / All Rights Reserved
*
* Programmcode ist urheberrechtlich geschuetzt.
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
* Keine Verwendung ohne explizite Genehmigung.
* (vgl. § 106 ff UrhG / § 97 UrhG)
*/
#ifndef WIFIPROBABILITYGRID_H
#define WIFIPROBABILITYGRID_H
#include <fstream>
#include "../../math/distribution/Normal.h"
#include "../../data/Timestamp.h"
#include "WiFiGridNode.h"
#include "WiFiProbability.h"
#include <unordered_set>
/**
* probability is calculated by comparing pre-calculated wifi-signal-strengths
* attached to each grid-node with a given WiFiMeasurements data structure
*/
template <typename Node> class WiFiObserverGrid : public WiFiProbability {
private:
/** base-sigma to use for comparison */
float sigma = 8.0f;
/** additional sigma-per-second (measurement age) to*/
float sigmaPerSecond = 3;
std::unordered_set<MACAddress> knownAPs;
public:
/** ctor with uncertainty */
WiFiObserverGrid(const float sigma) : sigma(sigma) {
//StaticAssert::AinheritsB<Node, WiFiGridNode>();
for (const AccessPoint& ap : Node::getMapAPs()) {
knownAPs.insert(ap.getMAC());
}
Assert::isFalse(knownAPs.empty(), "no APs known to the grid nodes?!");
}
/**
* get the given GridNode's probability.
* compares the predicted signal-strengths stored on the given node
* with the provided WiFi measurements
*/
double getProbability(const Node& n, const Timestamp curTime, const WiFiMeasurements& obs) const {
// compile-time sanity check. Node must be a subclass off WiFiGridNode
//StaticAssert::AinheritsB<Node, WiFiGridNode>();
double prob = 1;
int numMatchingAPs = 0;
// after some runtime, check whether the wifi timestamps make sense
// those must not be zero, otherwise something is wrong!
if (!obs.entries.empty()) {
Assert::isFalse(curTime.ms() > 10000 && obs.entries.front().getTimestamp().isZero(), "WiFiMeasurement timestamp is 0. this does not make sense...");
}
// process each observed measurement
for (const WiFiMeasurement& measurement : obs.entries) {
// if an AP is not known to any of the nodes, just skip it
if (knownAPs.find(measurement.getAP().getMAC()) == knownAPs.end()) {
continue;}
// determine the age for this measurement
const Timestamp age = curTime - measurement.getTimestamp();
// sigma grows with measurement age
float sigma = this->sigma + this->sigmaPerSecond * age.sec();
// the RSSI from the scan
const float measuredRSSI = measurement.getRSSI();
// the RSSI from the model (if available!)
float modelRSSI = n.getRSSI(measurement.getAP().getMAC());
// if no model RSSI is available, that means,
// the AP in question is not / only barely visible at this location
// assume a very low signal-strength and increase the sigma
if (modelRSSI == 0) {
modelRSSI = -100;
sigma *= 2;
}
// compare both
const double p = Distribution::Normal<double>::getProbability(measuredRSSI, sigma, modelRSSI);
//const double p = Distribution::Region<double>::getProbability(measuredRSSI, sigma, modelRSSI);
// adjust using log
//prob += std::log(p);
prob *= p;
++numMatchingAPs;
}
// sanity check
//Assert::isTrue(numMatchingAPs > 0, "not a single measured AP was matched against known ones. coding error? model error?");
// as not every node has the same number of visible/matching APs
// we MUST return something like the average probability
return prob;
//return std::pow(prob, 1.0/3.0);
}
/** gnuplot debug dump */
void dump(Grid<Node>& grid, const Timestamp curTime, const WiFiMeasurements& obs, const std::string& fileName) {
std::ofstream out(fileName);
out << "splot '-' with points palette\n";
for (const Node& n : grid) {
const float p = getProbability(n, curTime, obs);
out << n.x_cm << " " << n.y_cm << " " << n.z_cm << " " << p << "\n";
}
out << "e\n";
out.close();
}
};
#endif // WIFIPROBABILITYGRID_H