#ifndef WIFIMODELLOGDISTCEILING_H #define WIFIMODELLOGDISTCEILING_H #include "../../../floorplan/v2/Floorplan.h" #include "../../../Assertions.h" #include "WiFiModel.h" #include "LogDistanceModel.h" /** * signal-strength estimation using log-distance model * including ceilings between AP and position */ class WiFiModelLogDistCeiling : public WiFiModel { 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 accessPoints; /** position (height) of all ceilings (in meter) */ std::vector ceilingsAtHeight_m; public: /** ctor */ WiFiModelLogDistCeiling(const Floorplan::IndoorMap* map) { // position of all ceilings for (Floorplan::Floor* f : map->floors) { ceilingsAtHeight_m.push_back(f->atHeight); } } /** make the given AP (and its parameters) known to the model */ void addAP(const MACAddress& accessPoint, const APEntry& params) { // sanity check Assert::isBetween(params.waf, -99.0f, 0.0f, "WAF out of bounds [-99:0]"); Assert::isBetween(params.txp, -50.0f, -30.0f, "TXP out of bounds [-50:-30]"); Assert::isBetween(params.exp, 1.0f, 4.0f, "EXP out of bounds [1:4]"); // add accessPoints.insert( std::pair(accessPoint, params) ); } 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 * numCeilingsBetween(position_m, params.position_m); // combine return rssiLOS + wafLoss; } protected: FRIEND_TEST(LogDistanceCeilingModel, numCeilings); /** get the number of ceilings between z1 and z2 */ int numCeilingsBetween(const Point3 pos1, const Point3 pos2) const { int cnt = 0; const float zMin = std::min(pos1.z, pos2.z); const float zMax = std::max(pos1.z, pos2.z); for (const float z : ceilingsAtHeight_m) { if (zMin < z && zMax > z) {++cnt;} } return cnt; } }; #endif // WIFIMODELLOGDISTCEILING_H