added wifi per-floor optimization
added plot to wifi-quality-analyzer changes to per-floor wifi models minor fixes
This commit is contained in:
@@ -99,7 +99,7 @@ namespace WiFiOptimizer {
|
||||
return (waf > 0) ||
|
||||
(txp < -50) ||
|
||||
(txp > -30) ||
|
||||
(exp > 4) ||
|
||||
(exp > 4) ||
|
||||
(exp < 1);
|
||||
}
|
||||
|
||||
@@ -138,18 +138,29 @@ namespace WiFiOptimizer {
|
||||
|
||||
};
|
||||
|
||||
using APFilter = std::function<bool(const int numFingerprints, const MACAddress& mac)>;
|
||||
using APFilter = std::function<bool(const Stats& stats, const MACAddress& mac)>;
|
||||
|
||||
const APFilter NONE = [] (const int numFingerprints, const MACAddress& mac) {
|
||||
(void) numFingerprints; (void) mac;
|
||||
const APFilter NONE = [] (const Stats& stats, const MACAddress& mac) {
|
||||
(void) stats; (void) mac;
|
||||
return false;
|
||||
};
|
||||
|
||||
const APFilter MIN_5_FPS = [] (const int numFingerprints, const MACAddress& mac) {
|
||||
const APFilter MIN_2_FPS = [] (const Stats& stats, const MACAddress& mac) {
|
||||
(void) mac;
|
||||
return numFingerprints < 5;
|
||||
return stats.usedFingerprins < 2;
|
||||
};
|
||||
|
||||
const APFilter MIN_5_FPS = [] (const Stats& stats, const MACAddress& mac) {
|
||||
(void) mac;
|
||||
return stats.usedFingerprins < 5;
|
||||
};
|
||||
|
||||
const APFilter MIN_10_FPS = [] (const Stats& stats, const MACAddress& mac) {
|
||||
(void) mac;
|
||||
return stats.usedFingerprins < 10;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
@@ -179,15 +190,21 @@ namespace WiFiOptimizer {
|
||||
float errSum = 0; int errCnt = 0;
|
||||
std::vector<APParamsMAC> res;
|
||||
for (const MACAddress& mac : getAllMACs()) {
|
||||
|
||||
// perform optimization, get resulting parameters and optimization stats
|
||||
Stats stats;
|
||||
const APParams params = optimize(mac, stats);
|
||||
if (!filter(stats.usedFingerprins, mac)) {
|
||||
|
||||
// filter based on stats (option to ignore/filter some access-points)
|
||||
if (!filter(stats, mac)) {
|
||||
res.push_back(APParamsMAC(mac, params));
|
||||
errSum += stats.error_db;
|
||||
++errCnt;
|
||||
} else {
|
||||
std::cout << "ignored due to filter!" << std::endl;
|
||||
Log::add(name, "ignoring opt-result for AP " + mac.asString() + " due to filter");
|
||||
//std::cout << "ignored due to filter!" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const float avgErr = errSum / errCnt;
|
||||
@@ -222,8 +239,8 @@ namespace WiFiOptimizer {
|
||||
LeOpt::MinMax(mapBBox.getMin().y - 20, mapBBox.getMax().y + 20), // y
|
||||
LeOpt::MinMax(mapBBox.getMin().z - 5, mapBBox.getMax().z + 5), // z
|
||||
LeOpt::MinMax(-50, -30), // txp
|
||||
LeOpt::MinMax(1, 4), // exp
|
||||
LeOpt::MinMax(-15, -0), // waf
|
||||
LeOpt::MinMax(1, 4), // exp
|
||||
LeOpt::MinMax(-15, -0), // waf
|
||||
};
|
||||
|
||||
|
||||
|
||||
141
sensors/radio/setup/WiFiOptimizerPerFloor.h
Normal file
141
sensors/radio/setup/WiFiOptimizerPerFloor.h
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifndef WIFIOPTIMIZERPERFLOOR_H
|
||||
#define WIFIOPTIMIZERPERFLOOR_H
|
||||
|
||||
#include "WiFiOptimizerLogDistCeiling.h"
|
||||
#include "../model/WiFiModelPerFloor.h"
|
||||
#include "../../../floorplan/v2/FloorplanHelper.h"
|
||||
#include <mutex>
|
||||
|
||||
#define WITH_DEBUG_PLOT
|
||||
#ifdef WITH_DEBUG_PLOT
|
||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
||||
#include <KLib/misc/gnuplot/objects/GnuplotObjectPolygon.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementColorPoints.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementLines.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* uses the log-distance model, but one per floor.
|
||||
* the model is optimized using all fingerprints that belong to this floor
|
||||
*/
|
||||
class WiFiOptimizerPerFloor {
|
||||
|
||||
WiFiModelPerFloor* mdl = nullptr;
|
||||
|
||||
WiFiFingerprints fps;
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
std::mutex mtx;
|
||||
|
||||
#ifdef WITH_DEBUG_PLOT
|
||||
K::Gnuplot gp;
|
||||
K::GnuplotSplot splot;
|
||||
K::GnuplotSplotElementColorPoints pts;
|
||||
K::GnuplotSplotElementLines lines;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
WiFiOptimizerPerFloor(Floorplan::IndoorMap* map) : map(map) {
|
||||
|
||||
// the overall model (contains one sub-model per floor)
|
||||
mdl = new WiFiModelPerFloor(map);
|
||||
|
||||
#ifdef WITH_DEBUG_PLOT
|
||||
splot.add(&pts); pts.setPointSize(1); pts.setPointType(7);
|
||||
splot.add(&lines);
|
||||
BBox3 bb = FloorplanHelper::getBBox(map);
|
||||
splot.getAxisX().setRange(bb.getMin().x, bb.getMax().x);
|
||||
splot.getAxisY().setRange(bb.getMin().y, bb.getMax().y);
|
||||
splot.getAxisZ().setRange(bb.getMin().z, bb.getMax().z);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** make the given fingerprint known to the optimizer */
|
||||
void addFingerprint(const WiFiFingerprint& fp) {
|
||||
fps.add(fp);
|
||||
}
|
||||
|
||||
WiFiModelPerFloor* optimizeAll() {
|
||||
|
||||
const VAPGrouper vg = VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::MAXIMUM, VAPGrouper::TimeAggregation::AVERAGE, 1);
|
||||
|
||||
// optimize each floor on its own
|
||||
//for (WiFiModelPerFloor::ModelForFloor& mdlForFloor : mdl->getFloorModels()) {
|
||||
for (size_t i = 0; i < map->floors.size(); ++i) {
|
||||
|
||||
const Floorplan::Floor* floor = map->floors[i];
|
||||
|
||||
// 1) create a new optimizer for the current floor
|
||||
WiFiOptimizer::LogDistCeiling opt(map, vg);
|
||||
|
||||
// 2) create the model for this floor
|
||||
mtx.lock();
|
||||
WiFiModelLogDistCeiling* mdlForFloor = new WiFiModelLogDistCeiling(map);
|
||||
mdl->add(mdlForFloor, floor);
|
||||
mtx.unlock();
|
||||
|
||||
// 3) get the floor's bbox and adjust the z-region (needed for museum in Rothenburg)
|
||||
BBox3 bb = FloorplanHelper::getBBox(floor);
|
||||
bb.setMinZ(floor->atHeight+0.25);
|
||||
bb.setMaxZ(floor->atHeight+2);
|
||||
|
||||
// 4) find all fingerprints that belong to the floor/model and add them to the optimizer
|
||||
for (const WiFiFingerprint& fp : fps.getFingerprints()) {
|
||||
//if (mdlForFloor.matches(fp.pos_m.z)) {
|
||||
// std::cout << fp.pos_m.z << std::endl;
|
||||
// opt.addFingerprint(fp);
|
||||
//}
|
||||
if (bb.contains(fp.pos_m)) {
|
||||
//if (fp.pos_m.z >= floor->atHeight && fp.pos_m.z < floor->atHeight+floor->height) {
|
||||
std::cout << fp.pos_m.z << std::endl;
|
||||
opt.addFingerprint(fp);
|
||||
|
||||
#ifdef WITH_DEBUG_PLOT
|
||||
pts.add(K::GnuplotPoint3(fp.pos_m.x, fp.pos_m.y, fp.pos_m.z), i);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_PLOT
|
||||
for (Floorplan::FloorOutlinePolygon* poly : floor->outline) {
|
||||
for (const Point2 pt : poly->poly.points) {
|
||||
lines.add(K::GnuplotPoint3(pt.x, pt.y, floor->atHeight));
|
||||
}
|
||||
lines.splitFace(); lines.splitFace();
|
||||
for (const Point2 pt : poly->poly.points) {
|
||||
lines.add(K::GnuplotPoint3(pt.x, pt.y, floor->atHeight+floor->height));
|
||||
}
|
||||
lines.splitFace(); lines.splitFace();
|
||||
}
|
||||
gp.draw(splot);
|
||||
gp.flush();
|
||||
pts.clear();
|
||||
lines.clear();
|
||||
sleep(1);
|
||||
#endif
|
||||
|
||||
// 5) run the optimizer
|
||||
const WiFiOptimizer::LogDistCeiling::APParamsList res = opt.optimizeAll(opt.MIN_2_FPS);
|
||||
|
||||
// 6) add all optimized APs to the floor's model
|
||||
for (const WiFiOptimizer::LogDistCeiling::APParamsMAC& ap : res.get()) {
|
||||
// model is per-floor. so model cant optimize waf.. set to VERY HIGH manually
|
||||
const WiFiModelLogDistCeiling::APEntry entry(ap.params.getPos(), ap.params.txp, ap.params.exp, ap.params.waf);
|
||||
mdlForFloor->addAP(ap.mac, entry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mdl;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // WIFIOPTIMIZERPERFLOOR_H
|
||||
Reference in New Issue
Block a user