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
2018-10-25 11:50:12 +02:00

215 lines
4.7 KiB
C++
Raw 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 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 {
static constexpr const char* name = "WiFiModelFlo";
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));
}
Log::add(name, "loaded " + std::to_string(models.size()) + " floor models");
}
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