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/WiFiModelLogDistCeiling.h
mail@toni-fetzer.de 96c63ac3ec added measurement grouping for beacons
had to change the parameter boundaries of the wifi optimizer to be able to use it for bluetooth... this should be refactored to something more generic..
some minor changes in ble
2019-06-10 16:57:02 +02:00

247 lines
8.6 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 WIFIMODELLOGDISTCEILING_H
#define WIFIMODELLOGDISTCEILING_H
#include "../../../floorplan/v2/Floorplan.h"
#include "../../../floorplan/v2/FloorplanCeilings.h"
#include "../../../Assertions.h"
#include "WiFiModel.h"
#include "LogDistanceModel.h"
#include "../VAPGrouper.h"
#include "../../../misc/Debug.h"
#include "../../../data/XMLserialize.h"
/**
* signal-strength estimation using log-distance model
* including ceilings between AP and position
*/
class WiFiModelLogDistCeiling : public WiFiModel {
static constexpr const char* name = "WifiModelLDC";
public:
/** parameters describing one AP to the model */
struct APEntry {
Point3 position_m; // the AP's position (in meter)
float txp; // sending power (-40)
float exp; // path-loss-exponent (~2.0 - 4.0)
float waf; // attenuation per ceiling/floor (~-8.0)
/** ctor */
APEntry(const Point3 position_m, const float txp, const float exp, const float waf) :
position_m(position_m), txp(txp), exp(exp), waf(waf) {;}
};
private:
/** map of all APs (and their parameters) known to the model */
std::unordered_map<MACAddress, APEntry> accessPoints;
// /** position (height) of all ceilings (in meter) */
// std::vector<float> ceilingsAtHeight_m;
Floorplan::Ceilings ceilings;
public:
/** ctor with floorplan (needed for ceiling position) */
WiFiModelLogDistCeiling(const Floorplan::IndoorMap* map) : ceilings(map) {
// sanity checks
Assert::isTrue(map->floors.size() >= 1, "map has no floors?!");
}
/** get the entry for the given mac. exception if missing */
const APEntry& getAP(const MACAddress& mac) const {
const auto& it = accessPoints.find(mac);
if (it == accessPoints.end()) {throw Exception("model does not contain an entry for " + mac.asString());}
return it->second;
}
/** get a list of all APs known to the model */
std::vector<AccessPoint> getAllAPs() const {
std::vector<AccessPoint> aps;
for (const auto it : accessPoints) {aps.push_back(AccessPoint(it.first));}
return aps;
}
/** load AP information from the floorplan. use the given fixed TXP/EXP/WAF for all APs */
void loadAPs(const Floorplan::IndoorMap* map, const float txp = -40.0f, const float exp = 2.5f, const float waf = -8.0f, const bool assertSafe = true) {
for (const Floorplan::Floor* floor : map->floors) {
for (const Floorplan::AccessPoint* ap : floor->accesspoints) {
const APEntry ape(ap->getPos(floor), txp, exp, waf);
addAP(MACAddress(ap->mac), ape, assertSafe);
}
}
}
/**
* load AP information from the floorplan.
* use the given fixed TXP/EXP/WAF for all APs.
* usually txp,exp,waf are checked for a sane range. if you know what you are doing, set assertSafe to false!
*/
void loadAPs(const Floorplan::IndoorMap* map, const VAPGrouper& vg, const float txp = -40.0f, const float exp = 2.5f, const float waf = -8.0f, const bool assertSafe = true) {
for (const Floorplan::Floor* floor : map->floors) {
for (const Floorplan::AccessPoint* ap : floor->accesspoints) {
const APEntry ape(ap->getPos(floor), txp, exp, waf);
const MACAddress mac = vg.getBaseMAC(MACAddress(ap->mac));
Log::add("WiModLDC", "AP added! given: " + ap->mac + " -> after VAP: " + mac.asString());
addAP(MACAddress(mac), ape, assertSafe);
}
}
}
/**
* make the given AP (and its parameters) known to the model
* usually txp,exp,waf are checked for a sane range. if you know what you are doing, set assertSafe to false!
*/
void addAP(const MACAddress& accessPoint, const APEntry& params, const bool assertSafe = true) {
// sanity check
if (assertSafe) {
Assert::isBetween(params.waf, -99.0f, 0.0f, "WAF out of bounds [-99:0]");
Assert::isBetween(params.txp, -65.0f, -30.0f, "TXP out of bounds [-65:-30]");
Assert::isBetween(params.exp, 1.0f, 5.0f, "EXP out of bounds [1:5]");
}
Assert::equal(accessPoints.find(accessPoint), accessPoints.end(), "AccessPoint already present! VAP-Grouping issue?");
// add
accessPoints.insert( std::pair<MACAddress, APEntry>(accessPoint, params) );
}
/**
* make the given AP (and its parameters) known to the model
* usually txp,exp,waf are checked for a sane range. if you know what you are doing, set assertSafe to false!
*/
void addAP(const MACAddress& accessPoint, const Point3 pos_m, const float txp, const float exp, const float waf, const bool assertSafe = true) {
addAP(accessPoint, APEntry(pos_m, txp, exp, waf), assertSafe);
}
/** remove all added APs */
void clear() {
accessPoints.clear();
}
/** does the model know the given AP? */
bool knowsAP(const MACAddress& accessPoint) {
// try to get the corresponding parameters
const auto it = accessPoints.find(accessPoint);
// AP known?
return (it != accessPoints.end());
}
float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const override {
// try to get the corresponding parameters
const auto it = accessPoints.find(accessPoint);
// AP unknown? -> NAN
if (it == accessPoints.end()) {return NAN;}
// the access-points' parameters
const APEntry& params = it->second;
// free-space (line-of-sight) RSSI
const float distance_m = position_m.getDistance(params.position_m);
const float rssiLOS = LogDistanceModel::distanceToRssi(params.txp, params.exp, distance_m);
// WAF loss (params.waf is a negative value!) -> WAF loss is also a negative value
//const float wafLoss = params.waf * ceilings.numCeilingsBetween(position_m, params.position_m);
const float wafLoss = params.waf * ceilings.numCeilingsBetweenFloat(position_m, params.position_m);
//const float wafLoss = params.waf * ceilings.numCeilingsBetweenLinearInt(position_m, params.position_m);
// combine
const float res = rssiLOS + wafLoss;
// sanity check
Assert::isNotNaN(res, "detected NaN within WiFiModelLogDistCeiling::getRSSI()");
// ok
return res;
}
void writeToXML(XMLDoc* doc, XMLElem* dst) override {
// set my type
dst->SetAttribute("type", "WiFiModelLogDistCeiling");
for (const auto& it : accessPoints) {
const MACAddress& mac = it.first;
const APEntry& ape = it.second;
XMLElem* xap = doc->NewElement("ap");
xap->SetAttribute("mac", mac.asString().c_str());
xap->SetAttribute("px", ape.position_m.x);
xap->SetAttribute("py", ape.position_m.y);
xap->SetAttribute("pz", ape.position_m.z);
xap->SetAttribute("txp", ape.txp);
xap->SetAttribute("exp", ape.exp);
xap->SetAttribute("waf", ape.waf);
dst->InsertEndChild(xap);
}
for (const float atHeight_m : ceilings.getCeilings()) {
XMLElem* xceil = doc->NewElement("ceiling");
xceil->SetAttribute("atHeight", atHeight_m);
dst->InsertEndChild(xceil);
}
}
void readFromXML(XMLDoc* doc, XMLElem* src) override {
// check type
if (std::string("WiFiModelLogDistCeiling") != src->Attribute("type")) {throw Exception("invalid model type");}
accessPoints.clear();
ceilings.clear();
XML_FOREACH_ELEM_NAMED("ap", xap, src) {
MACAddress mac = MACAddress(xap->Attribute("mac"));
APEntry ape(
Point3(xap->FloatAttribute("px"), xap->FloatAttribute("py"), xap->FloatAttribute("pz")),
xap->FloatAttribute("txp"),
xap->FloatAttribute("exp"),
xap->FloatAttribute("waf")
);
accessPoints.insert( std::make_pair(mac, ape) );
}
XML_FOREACH_ELEM_NAMED("ceiling", xceil, src) {
const float atHeight_m = xceil->FloatAttribute("atHeight");
ceilings.addCeiling(atHeight_m);
}
Log::add(name, "loaded " + std::to_string(accessPoints.size()) + " APs");
}
};
#endif // WIFIMODELLOGDISTCEILING_H