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/model/WiFiModelPerFloor.h
k-a-z-u a8123d532d added wifi per-floor optimization
added plot to wifi-quality-analyzer
changes to per-floor wifi models
minor fixes
2018-05-16 13:02:06 +02:00

201 lines
4.2 KiB
C++

#ifndef WIFIMODELPERFLOOR_H
#define WIFIMODELPERFLOOR_H
#include "../AccessPoint.h"
#include "../../../geo/Point3.h"
#include <vector>
#include "WiFiModelFactory.h"
/**
* FOR TESTING
*
* this model allows using a different sub-models for each floor to reduce the error
*/
class WiFiModelPerFloor : public WiFiModel {
public:
struct ModelForFloor {
float fromZ;
float toZ;
WiFiModel* mdl;
/** ctor */
ModelForFloor(const float fromZ, const float toZ, WiFiModel* mdl) : fromZ(fromZ), toZ(toZ), mdl(mdl) {;}
/** does this entry apply to the given z-position? */
bool matches(const float z) const {
return (fromZ <= z && z < toZ);
}
};
private:
Floorplan::IndoorMap* map;
/** all contained models [one per floor] */
std::vector<ModelForFloor> models;
public:
WiFiModelPerFloor(Floorplan::IndoorMap* map) : map(map) {
;
}
/** dtor */
virtual ~WiFiModelPerFloor() {
}
/** get a list of all models for the distinct floors */
std::vector<ModelForFloor>& getFloorModels() {
return models;
}
/** get a list of all APs known to the model */
std::vector<AccessPoint> getAllAPs() const override {
// combine all submodels
std::vector<AccessPoint> res;
for (const ModelForFloor& sub : models) {
for (const AccessPoint& ap : sub.mdl->getAllAPs()) {
if (std::find(res.begin(), res.end(), ap) == res.end()) { // TODO use map instead?
res.push_back(ap);
}
}
}
return res;
}
void add(WiFiModel* mdl, const Floorplan::Floor* floor) {
ModelForFloor mff(floor->atHeight, floor->atHeight+floor->height, mdl);
models.push_back(mff);
}
float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const override {
#if (1==0)
float res = -120;
// find the best matching one
for (const ModelForFloor& mff : models) {
if (mff.matches(position_m.z)) {
const float rssi = mff.mdl->getRSSI(accessPoint, position_m);
if (rssi > res) {res = rssi;}
}
}
return res;
#elif (1==0)
// nearest matching model
float nearest = 9999;
float res = -120;
for (const ModelForFloor& mff : models) {
const float distToFloor = std::abs(position_m.z - mff.fromZ);
if (distToFloor < nearest) {
const float rssi = mff.mdl->getRSSI(accessPoint, position_m);
if (rssi == rssi) {
res = rssi;
nearest = distToFloor;
}
}
}
Assert::isNotNaN(res, "detected NaN");
return res;
#elif (1==1)
// average of all matching models
float sum = 0;
int cnt = 0;
// find the best matching one
for (const ModelForFloor& mff : models) {
if (mff.matches(position_m.z)) {
const float rssi = mff.mdl->getRSSI(accessPoint, position_m);
if (rssi == rssi) {
sum += rssi; ++cnt;
}
}
}
Assert::isNotNaN(sum, "detected NaN");
return (cnt > 0) ? (sum/cnt) : (-120);
#endif
// for (const ModelForFloor& mff : models) {
// if (mff.matches(position_m.z)) {return mff.mdl->getRSSI(accessPoint, position_m);}
// }
// return -120;
}
void readFromXML(XMLDoc* doc, XMLElem* src) override {
// check type
if (std::string("WiFiModelPerFloor") != src->Attribute("type")) {throw Exception("invalid model type");}
models.clear();
// model factory [create models based on XMl content]
WiFiModelFactory fac(map);
// parse all contained models [one per floor]
XML_FOREACH_ELEM_NAMED("floor", xfloor, src) {
// floor params
const float z1 = xfloor->FloatAttribute("z1");
const float z2 = xfloor->FloatAttribute("z2");
// node for the model
XMLElem* xmodel = xfloor->FirstChildElement("model");
// let the factory instantiate the model
WiFiModel* mdl = fac.readFromXML(doc, xmodel);
// add
models.push_back(ModelForFloor(z1, z2, mdl));
}
}
void writeToXML(XMLDoc* doc, XMLElem* dst) override {
// set my type
dst->SetAttribute("type", "WiFiModelPerFloor");
for (const ModelForFloor& mff : models) {
XMLElem* xfloor = doc->NewElement("floor"); {
xfloor->SetAttribute("z1", mff.fromZ);
xfloor->SetAttribute("z2", mff.toZ);
XMLElem* xmodel = doc->NewElement("model"); {
mff.mdl->writeToXML(doc, xmodel);
}; xfloor->InsertEndChild(xmodel);
}; dst->InsertEndChild(xfloor);
}
}
};
#endif // WIFIMODELPERFLOOR_H