From 60712689cf91a3a48a8934b46f41f277d4f23586 Mon Sep 17 00:00:00 2001 From: kazu Date: Sat, 29 Apr 2017 20:57:12 +0200 Subject: [PATCH] current code and TeX. code fine?!?!?! --- CMakeLists.txt | 2 +- CSV.h | 0 EvalApOpt.h | 0 EvalCompareOpt.h | 0 EvalCompareOpt2.h | 9 + EvalData.h | 0 EvalWiFiSigStrength.h | 0 EvalWifiOptResult.h | 0 Helper.h | 0 README.md | 0 Settings.h | 19 +- Structs.h | 0 TestMapEarthReg.h | 0 bboxes.h | 0 main.cpp | 231 +++++++++++-------- old/main.h | 0 pf/EvalWalk.h | 398 ++++++++++++++++++++++++++++----- pf/PF.h | 98 +++++--- plots/PlotErrFunc.h | 5 + plots/PlotErrTime.h | 14 ++ plots/PlotWiFiGroundProb.h | 24 +- plots/Plotty.h | 0 tex/bare_conf.tex | 2 + tex/chapters/abstract.tex | 0 tex/chapters/conclusion.tex | 0 tex/chapters/experiments.tex | 97 ++++++-- tex/chapters/interoduction.tex | 0 tex/chapters/introduction.tex | 0 tex/chapters/relatedwork.tex | 0 tex/chapters/system.tex | 0 tex/chapters/work.tex | 14 +- tex/egbib.bib | 0 tex/gfx/build.sh | 2 +- tex/make.sh | 0 tex/misc/functions.tex | 0 tex/misc/keywords.tex | 0 wifi/EvalWiFi.h | 0 wifi/EvalWiFiConvex.h | 0 wifi/EvalWiFiGround.h | 71 +++++- wifi/EvalWiFiPathMethods.h | 48 +++- wifi/EvalWiFiPaths.h | 4 +- 41 files changed, 804 insertions(+), 234 deletions(-) mode change 100644 => 100755 CSV.h mode change 100644 => 100755 EvalApOpt.h mode change 100644 => 100755 EvalCompareOpt.h mode change 100644 => 100755 EvalCompareOpt2.h mode change 100644 => 100755 EvalData.h mode change 100644 => 100755 EvalWiFiSigStrength.h mode change 100644 => 100755 EvalWifiOptResult.h mode change 100644 => 100755 Helper.h mode change 100644 => 100755 README.md mode change 100644 => 100755 Settings.h mode change 100644 => 100755 Structs.h mode change 100644 => 100755 TestMapEarthReg.h mode change 100644 => 100755 bboxes.h mode change 100644 => 100755 main.cpp mode change 100644 => 100755 old/main.h mode change 100644 => 100755 pf/EvalWalk.h mode change 100644 => 100755 pf/PF.h mode change 100644 => 100755 plots/PlotErrFunc.h mode change 100644 => 100755 plots/PlotErrTime.h mode change 100644 => 100755 plots/PlotWiFiGroundProb.h mode change 100644 => 100755 plots/Plotty.h mode change 100644 => 100755 tex/bare_conf.tex mode change 100644 => 100755 tex/chapters/abstract.tex mode change 100644 => 100755 tex/chapters/conclusion.tex mode change 100644 => 100755 tex/chapters/experiments.tex mode change 100644 => 100755 tex/chapters/interoduction.tex mode change 100644 => 100755 tex/chapters/introduction.tex mode change 100644 => 100755 tex/chapters/relatedwork.tex mode change 100644 => 100755 tex/chapters/system.tex mode change 100644 => 100755 tex/chapters/work.tex mode change 100644 => 100755 tex/egbib.bib mode change 100644 => 100755 tex/gfx/build.sh mode change 100644 => 100755 tex/make.sh mode change 100644 => 100755 tex/misc/functions.tex mode change 100644 => 100755 tex/misc/keywords.tex mode change 100644 => 100755 wifi/EvalWiFi.h mode change 100644 => 100755 wifi/EvalWiFiConvex.h mode change 100644 => 100755 wifi/EvalWiFiGround.h mode change 100644 => 100755 wifi/EvalWiFiPathMethods.h mode change 100644 => 100755 wifi/EvalWiFiPaths.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 607fcf6..7c3f02c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ ADD_DEFINITIONS( -fstack-protector-all -g3 - -O0 + -O2 -march=native -DWITH_TESTS diff --git a/CSV.h b/CSV.h old mode 100644 new mode 100755 diff --git a/EvalApOpt.h b/EvalApOpt.h old mode 100644 new mode 100755 diff --git a/EvalCompareOpt.h b/EvalCompareOpt.h old mode 100644 new mode 100755 diff --git a/EvalCompareOpt2.h b/EvalCompareOpt2.h old mode 100644 new mode 100755 index b4d3319..f9b277d --- a/EvalCompareOpt2.h +++ b/EvalCompareOpt2.h @@ -317,6 +317,15 @@ public: const MACAddress mac(ap->mac); const std::vector fps = getFingerprints(mac); + // ensure a certain number of fingerprints + // otherwise: ignore this AP as it can not be optimized! + if (fps.size() < 3) { + std::cout << "IGNORING " << mac.asString() << " due to insufficient fingerprints! using fixed -100 entry" << std::endl; + res.model.addAP(mac, Point3(0,0,0), -100, 0, 0, false); + //res.model.addAP(mac, pos_m, params[3], params[4], params[5], false); + continue; + } + // resulting error auto errFunc = [&] (const Point3 pos_m, const float txp, const float exp, const float waf) -> K::Statistics { WiFiModelLogDistCeiling model(map); // new, empty model for this AP diff --git a/EvalData.h b/EvalData.h old mode 100644 new mode 100755 diff --git a/EvalWiFiSigStrength.h b/EvalWiFiSigStrength.h old mode 100644 new mode 100755 diff --git a/EvalWifiOptResult.h b/EvalWifiOptResult.h old mode 100644 new mode 100755 diff --git a/Helper.h b/Helper.h old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/Settings.h b/Settings.h old mode 100644 new mode 100755 index 12c45a0..dee4542 --- a/Settings.h +++ b/Settings.h @@ -6,10 +6,11 @@ namespace Settings { - const std::string pathData = "/apps/android/workspace/OTHER2017/data/"; - const std::string pathWalks = "/apps/android/workspace/OTHER2017/data/"; - const std::string pathWalksToni = "/apps/android/workspace/OTHER2017/data/toni/"; - const std::string pathWiFi = "/apps/android/workspace/OTHER2017/data/wifi/"; + const std::string pathbase = "/mnt/vm/paper/OTHER2017/"; + const std::string pathData = pathbase + "/data/"; + const std::string pathWalks = pathbase + "/data/"; + const std::string pathWalksToni = pathbase + "/data/toni/"; + const std::string pathWiFi = pathbase + "/data/wifi/"; // GPS walks const std::string path1a = pathWalks + "path1/1490208103510.csv"; @@ -51,19 +52,19 @@ namespace Settings { const std::string wifiEachOptParPos_perBBox = pathWiFi + "eachOptParPos_perBBox.xml"; - const std::string fMap = "/apps/android/workspace/IndoorMap/maps/SHL38_no_elev.xml"; - const std::string fCalib = "/apps/android/workspace/OTHER2017/data/wifi_fp_all.dat"; + const std::string fMap = pathbase + "/data/SHL38_no_elev.xml"; + const std::string fCalib = pathbase + "/data/wifi_fp_all.dat"; - const std::string fPathGFX = "/apps/android/workspace/OTHER2017/tex/gfx/"; + const std::string fPathGFX = pathbase + "/tex/gfx/"; - int numParticles = 2500; + int numParticles = 5000; float smartphoneAboveGround = 1.3; namespace IMU { const float turnSigma = 1.25;//1.5; const float stepLength = 0.70+0.3; - const float stepSigma = 0.10; + const float stepSigma = 0.15 + 0.10; const float absHeadSigma = 20; } diff --git a/Structs.h b/Structs.h old mode 100644 new mode 100755 diff --git a/TestMapEarthReg.h b/TestMapEarthReg.h old mode 100644 new mode 100755 diff --git a/bboxes.h b/bboxes.h old mode 100644 new mode 100755 diff --git a/main.cpp b/main.cpp old mode 100644 new mode 100755 index 4bffdca..9003981 --- a/main.cpp +++ b/main.cpp @@ -248,7 +248,7 @@ void errorPlotAllModels(Floorplan::IndoorMap* map) { std::vector> errors = errorStatAllModels(map); - PlotErrFunc plot("", "fingerprints (%)"); + PlotErrFunc plot("", "reference measurements (%)"); plot.getPlot().getAxisX().setTicsLabelFormat("%h dB"); plot.add("\\noOptEmpiric{}", &errors[0]); plot.add("\\optParamsAllAP{}", &errors[1]); @@ -275,14 +275,15 @@ void errorPlotAllModels(Floorplan::IndoorMap* map) { // plot.getGP() << "set rmargin 0.2\n"; // plot.getGP() << "set bmargin 1.9\n"; plot.getPlot().getMargin().set(4.2, 0.2, 0.1, 1.9); - plot.getPlot().getAxisY().setLabelOffset(3.0,0); + plot.getPlot().getAxisY().setLabelOffset(3.0 - 0.75, 0); plot.getPlot().setStringMod(new K::GnuplotStringModLaTeX()); plot.getPlot().getKey().setSampleLength(0.5); plot.getPlot().getKey().setWidthIncrement(+7.0); plot.setYRange(0, 95, 5); - plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 100)); - plot.getPlot().getAxisY().setTicsStep(0, 25, 100); + plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 95)); + //plot.getPlot().getAxisY().setTicsStep(0, 25, 100); + plot.getPlot().getAxisY().setTicsStep({0,25,50,75,95}); plot.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 4.0)); plot.getPlot().getAxisX().setTicsStep(4); // 4dB plot.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0, 16)); @@ -308,7 +309,7 @@ void errorPlotAllModels(Floorplan::IndoorMap* map) { /** error plot for the given stats. used for fingerprint errors */ void errorPlotNumFingerprints(const std::vector>& stats, const std::vector& titles, const std::string& name) { - PlotErrFunc plot("", "fingerprints (%)"); + PlotErrFunc plot("", "ref. measurements (%)"); plot.getPlot().getAxisX().setTicsLabelFormat("%h dB"); plot.getPlot().getKey().setVisible(true); @@ -335,22 +336,26 @@ void errorPlotNumFingerprints(const std::vector>& stats, co // plot.getGP() << "set rmargin 0.2\n"; // plot.getGP() << "set bmargin 1.9\n"; plot.getPlot().getMargin().set(4.2, 0.2, 0.1, 1.9); - plot.getPlot().getAxisY().setLabelOffset(3.0,0); + plot.getPlot().getAxisY().setLabelOffset(3.0 - 0.7,0); plot.getPlot().setStringMod(new K::GnuplotStringModLaTeX()); plot.getPlot().getKey().setSampleLength(0.5); plot.getPlot().getKey().setWidthIncrement(-5.0); plot.setYRange(0, 90, 5); - plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 100)); - plot.getPlot().getAxisY().setTicsStep(0, 25, 100); + plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 90)); + plot.getPlot().getAxisY().setTicsStep({0, 25, 50, 75, 90}); + //lot.getPlot().getAxisY().setTicsStep(0, 25, 100); plot.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 3.3)); plot.getPlot().getAxisX().setTicsStep(4); // 4dB - plot.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0, 16)); + plot.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0, 14)); plot.getGP().setOutput(Settings::fPathGFX + "/" + name + "_0_90.tex"); plot.writePlotToFile(Settings::fPathGFX + "/" + name + "_0_90.gp"); plot.plot(); + // changes plot.getPlot().getKey().setVisible(false); + plot.getPlot().getAxisY().setLabel(""); + plot.setYRange(90, 100, 1); plot.getPlot().getAxisY().setTicsStep(2); plot.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 2.6)); @@ -572,6 +577,8 @@ void plotEstAndRealApPosDistance(Floorplan::IndoorMap* map) { } +#warning "TODO: code um alle pfade MEHRFACH mit allen modellen durch den filter laufen zu lassen" + // build plots for the paper void paperOutputs() { @@ -666,13 +673,15 @@ void paperOutputs() { // perform varios AP-param optimizations // generate error plot showing the performance of each // save the resulting wifi-models to XML for later re-use during the walk-eval <<<<<< !!!! - if (1 == 0) { + if (1 == 1) { rebuildAllModels(map, 0); /** detailled error analysis for above optimization routine */ + errorPlotAllModels(map); } + // leaving out fingerprints and the effects on all optimization strategies if (1 == 0) { rebuildAllModels(map,4); @@ -686,6 +695,13 @@ void paperOutputs() { // analyze all 5 opt strategies. skip the empiric one: stats0[0] for (int i = 1; i < 6; ++i) { + std::cout << "leaving out fingerprints for model " << i << std::endl; + std::cout << "\t 25%: " << stats4[i].asString() << std::endl; + std::cout << "\t 50%: " << stats2[i].asString() << std::endl; + std::cout << "\t 100%: " << stats0[i].asString() << std::endl; + std::cout << "\t noStair%: " << statsNoStairs[i].asString() << std::endl; + std::cout << std::endl; + std::string name = "wifi_model_error_num_fingerprints_method_" + std::to_string(i); errorPlotNumFingerprints( {stats0[0], stats4[i], stats2[i], stats0[i], statsNoStairs[i]}, @@ -729,62 +745,36 @@ void paperOutputs() { - // error histogram all pos, all params, between in/out/stair, in/out, in/stair, in - if(1==0){ +// // error histogram all pos, all params, between in/out/stair, in/out, in/stair, in +// if(1==0){ - EvalCompareOpt e1(Settings::fMap, Settings::fCalib, false, false, false); - EvalCompareOpt e2(Settings::fMap, Settings::fCalib, true, false, false); - EvalCompareOpt e3(Settings::fMap, Settings::fCalib, false, true, false); - EvalCompareOpt e4(Settings::fMap, Settings::fCalib, true, true, false); +// EvalCompareOpt e1(Settings::fMap, Settings::fCalib, false, false, false); +// EvalCompareOpt e2(Settings::fMap, Settings::fCalib, true, false, false); +// EvalCompareOpt e3(Settings::fMap, Settings::fCalib, false, true, false); +// EvalCompareOpt e4(Settings::fMap, Settings::fCalib, true, true, false); - K::Statistics s1 = e1.optPosOptParamsForEach().errAbs; - K::Statistics s2 = e2.optPosOptParamsForEach().errAbs; - K::Statistics s3 = e3.optPosOptParamsForEach().errAbs; - K::Statistics s4 = e4.optPosOptParamsForEach().errAbs; +// K::Statistics s1 = e1.optPosOptParamsForEach().errAbs; +// K::Statistics s2 = e2.optPosOptParamsForEach().errAbs; +// K::Statistics s3 = e3.optPosOptParamsForEach().errAbs; +// K::Statistics s4 = e4.optPosOptParamsForEach().errAbs; - PlotErrFunc pef("\\small{error (dB)}", "\\small{fingerprints (\\%)}"); - pef.add("\\small{floor + stairs + out}", &s1); - pef.add("\\small{floor + out}", &s2); - pef.add("\\small{floor + stairs}", &s3); - pef.add("\\small{floor}", &s4); +// PlotErrFunc pef("\\small{error (dB)}", "\\small{fingerprints (\\%)}"); +// pef.add("\\small{floor + stairs + out}", &s1); +// pef.add("\\small{floor + out}", &s2); +// pef.add("\\small{floor + stairs}", &s3); +// pef.add("\\small{floor}", &s4); - pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.5, 5)); - pef.getGP().setOutput(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.tex"); - pef.writePlotToFile(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.gp"); - pef.getGP() << "set key right bottom width -3\n"; - pef.getGP() << "set rmargin 0.4\n"; - pef.getGP() << "set tmargin 0.4\n"; - pef.plot(); +// pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.5, 5)); +// pef.getGP().setOutput(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.tex"); +// pef.writePlotToFile(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.gp"); +// pef.getGP() << "set key right bottom width -3\n"; +// pef.getGP() << "set rmargin 0.4\n"; +// pef.getGP() << "set tmargin 0.4\n"; +// pef.plot(); - } +// } - // wifi issue for path1 - if (1 == 0) { - Offline::FileReader reader(Settings::path1a); - PlotWifiMeasurements plot; - - for (int i = 0; i < 60; ++i) { - const WiFiMeasurements mes = reader.getWiFiGroupedByTime().at(i).data; - const WiFiMeasurements mes2 = Settings::WiFiModel::vg_eval.group(mes); - plot.add(mes2); - } - - K::GnuplotObjectRectangle rect( - K::GnuplotCoordinate2(0, K::GnuplotCoordinateSystem::FIRST, 0, K::GnuplotCoordinateSystem::GRAPH), - K::GnuplotCoordinate2(10, K::GnuplotCoordinateSystem::FIRST, 1, K::GnuplotCoordinateSystem::GRAPH), - K::GnuplotFill(K::GnuplotFillStyle::SOLID, K::GnuplotColor::fromRGB(128,128,128), 0.5), - K::GnuplotStroke() - ); - - plot.getPlot().setGrid(true); - plot.getPlot().getKey().setVisible(false); - plot.getPlot().getObjects().add(&rect); - plot.plot(); - - sleep(100); - - } } @@ -799,13 +789,20 @@ void testWAF() { K::Gnuplot gp; K::GnuplotPlot gplot; K::GnuplotPlotElementLines lines; gplot.add(&lines); + K::GnuplotPlotElementLines ceils; gplot.add(&ceils); const Point3 posAP(0, 0, 8); + for (const float h : ceilings.getCeilings()) { + ceils.addSegment(K::GnuplotPoint2(h, -2), K::GnuplotPoint2(h, +4)); + } + for (float z = 0; z < 15; z += 0.1) { const Point3 posMe(0, 0, z); + //float factor = ceilings.numCeilingsBetweenLinearInt(posAP, posMe); float factor = ceilings.numCeilingsBetweenFloat(posAP, posMe); + lines.add({z, factor}); } @@ -813,7 +810,7 @@ void testWAF() { gp.draw(gplot); gp.flush(); - sleep(1000); + sleep(10); } @@ -900,6 +897,10 @@ int main(void) { Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap); //testWAF(); + //sleep(1); + + //const float rssi = LogDistanceModel::distanceToRssi(-100, 0, 999); + //int i = 0; (void) i; //paperOutputs(); return 0; @@ -908,11 +909,41 @@ int main(void) { //showFingerprintsFor(Settings::fMap, Settings::fCalib, "D8:84:66:4A:4A:E0"); //showModelFor(Settings::fMap, Settings::wifiEachOptParPos_multimodel, "D8:84:66:4A:4A:E0"); - if (1 == 1) { + if (1 == 0) { plotEstAndRealApPosDistance(map); int i = 0; (void) i; } +// // wifi issue for path1 +// if (1 == 1) { + +// Offline::FileReader reader(Settings::path1a); +// PlotWifiMeasurements plot; + +// for (int i = 0; i < 60; ++i) { +// const WiFiMeasurements mes = reader.getWiFiGroupedByTime().at(i).data; +// const WiFiMeasurements mes2 = Settings::WiFiModel::vg_eval.group(mes); +// plot.add(mes2); +// } + +// K::GnuplotObjectRectangle rect( +// K::GnuplotCoordinate2(0, K::GnuplotCoordinateSystem::FIRST, 0, K::GnuplotCoordinateSystem::GRAPH), +// K::GnuplotCoordinate2(10, K::GnuplotCoordinateSystem::FIRST, 1, K::GnuplotCoordinateSystem::GRAPH), +// K::GnuplotFill(K::GnuplotFillStyle::SOLID, K::GnuplotColor::fromRGB(128,128,128), 0.5), +// K::GnuplotStroke() +// ); + +// plot.getPlot().setGrid(true); +// plot.getPlot().getKey().setVisible(false); +// plot.getPlot().getObjects().add(&rect); +// plot.plot(); + +// sleep(100); + +// } + + + // calib error in/out if (1 == 0) { @@ -942,22 +973,31 @@ int main(void) { } - // prob on ground + // plot probability within the building for every wifi measurement if (1 == 0) { - EvalWiFiGround eval(map, Settings::wifiEachOptParPos_multimodel); + Plotty::Settings settings; + settings.outline = false; + EvalWiFiGround eval(map, Settings::wifiEachOptParPos_multimodel, settings); + //EvalWiFiGround eval(map, Settings::wifiEachOptParPos_perBBox, settings); + //EvalWiFiGround eval(map, Settings::wifiEachOptPar, settings); + //EvalWiFiGround eval(map, Settings::wifiEachOptParPos, settings); + //eval.show(Settings::path1a); - eval.show(Settings::path2a); + //eval.show(Settings::path_toni_inst_2b, Settings::GroundTruth::path_toni_inst_2); + eval.show(Settings::path_toni_inst_3a, Settings::GroundTruth::path_toni_inst_3); int i = 0; (void) i; } // walks - if (1 == 0) { + if (1 == 1) { Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);; - EvalWalk walk(map); - walk.walk1(); + //EvalWalk walk(map); + //walk.walk1(); + EvalWalk::walkEverything(map); + EvalWalk::walkEverythingBuildStats(map); return 0; } @@ -1069,21 +1109,24 @@ int main(void) { std::cout << "num scans: " << numScans << std::endl; + if (1 == 1) { - EvalWiFiPaths ewp(Settings::fMap); - ewp.loadModel(Settings::wifiAllFixed, "\\noOptEmpiric{}"); - ewp.walks(files, gtIndices); + EvalWiFiPaths ewp(Settings::fMap); + ewp.loadModel(Settings::wifiAllFixed, "\\noOptEmpiric{}"); + ewp.walks(files, gtIndices); - ewp.loadModel(Settings::wifiEachOptParPos, "\\optParamsPosEachAP{}"); - ewp.walks(files, gtIndices); + ewp.loadModel(Settings::wifiEachOptParPos, "\\optParamsPosEachAP{}"); + ewp.walks(files, gtIndices); - ewp.loadModel(Settings::wifiEachOptParPos_multimodel, "\\optPerFloor{}"); - ewp.walks(files, gtIndices); + ewp.loadModel(Settings::wifiEachOptParPos_multimodel, "\\optPerFloor{}"); + ewp.walks(files, gtIndices); - ewp.loadModel(Settings::wifiEachOptParPos_perBBox, "\\optPerRegion{}"); - ewp.walks(files, gtIndices); + ewp.loadModel(Settings::wifiEachOptParPos_perBBox, "\\optPerRegion{}"); + ewp.walks(files, gtIndices); - ewp.writeGP(Settings::fPathGFX, "modelPerformance"); + ewp.writeGP(Settings::fPathGFX, "modelPerformance"); + + } // examine various modifications if (1 == 0) { @@ -1114,27 +1157,27 @@ int main(void) { } - // compare wifi opt methods - if (1 == 0) { +// // compare wifi opt methods +// if (1 == 0) { - const bool ignoreStaircases = false; - const bool ignoreOutdoor = false; - const bool ignoreIndoor = false; - EvalCompareOpt opt(Settings::fMap, Settings::fCalib, ignoreStaircases, ignoreOutdoor, ignoreIndoor); +// const bool ignoreStaircases = false; +// const bool ignoreOutdoor = false; +// const bool ignoreIndoor = false; +// EvalCompareOpt opt(Settings::fMap, Settings::fCalib, ignoreStaircases, ignoreOutdoor, ignoreIndoor); - EvalCompareOpt::Result s1 = opt.fixedPosFixedParamsForAll(); //BREAK; - EvalCompareOpt::Result s2 = opt.fixedPosOptParamsForAll(); //BREAK; - EvalCompareOpt::Result s3 = opt.fixedPosOptParamsForEach(); //BREAK; - EvalCompareOpt::Result s4 = opt.optPosOptParamsForEach(); //BREAK; +// EvalCompareOpt::Result s1 = opt.fixedPosFixedParamsForAll(); //BREAK; +// EvalCompareOpt::Result s2 = opt.fixedPosOptParamsForAll(); //BREAK; +// EvalCompareOpt::Result s3 = opt.fixedPosOptParamsForEach(); //BREAK; +// EvalCompareOpt::Result s4 = opt.optPosOptParamsForEach(); //BREAK; - PlotErrFunc pef("error (dB)", "fingerprints (%)"); - pef.add("empiric", &s1.errAbs); - pef.add("real pos, opt params [same for all]", &s2.errAbs); - pef.add("real pos, opt params [for each]", &s3.errAbs); - pef.add("opt pos, opt params [for each]", &s4.errAbs); - pef.plot(); +// PlotErrFunc pef("error (dB)", "fingerprints (%)"); +// pef.add("empiric", &s1.errAbs); +// pef.add("real pos, opt params [same for all]", &s2.errAbs); +// pef.add("real pos, opt params [for each]", &s3.errAbs); +// pef.add("opt pos, opt params [for each]", &s4.errAbs); +// pef.plot(); - } +// } // compare leaving out fingerprints if (1 == 0) { diff --git a/old/main.h b/old/main.h old mode 100644 new mode 100755 diff --git a/pf/EvalWalk.h b/pf/EvalWalk.h old mode 100644 new mode 100755 index 93db6a5..8b7e44e --- a/pf/EvalWalk.h +++ b/pf/EvalWalk.h @@ -44,6 +44,15 @@ #include #include + +#define PLOT_LIVE +//#define PLOT_WIFI +//#define PLOT_ERROR_TIME +//#define PLOT_ERROR_FUNC + +#define PLOT_UPDATE_STEP 20 + + class EvalWalk : public Offline::Listener { Grid* grid; @@ -53,6 +62,8 @@ class EvalWalk : public Offline::Listener { Plotty plotty; PlotWifiMeasurements plotWifi; + PlotErrTime pet; + PlotErrFunc pef; Offline::FileReader reader; Offline::FilePlayer player; @@ -74,11 +85,15 @@ class EvalWalk : public Offline::Listener { EarthMapping em; + std::string walkName; + float absHead = 0; public: - EvalWalk(Floorplan::IndoorMap* map) : plotty(map), map(map), em(map) { + EvalWalk(Floorplan::IndoorMap* map) : plotty(map), map(map), em(map), + pet("\\small{time (sec)}", "\\small{error (m)}", "\\small{APs visible}"), + pef("\\small{error (m)}", "\\small{updates (\\%)}") { const std::string saveFile = Settings::pathData + "/grid.dat"; grid = new Grid(Settings::Grid::gridSize_cm); @@ -108,8 +123,8 @@ public: pf->setTransition( std::unique_ptr( new PFTrans(grid)) ); // resampling step? - //pf->setNEffThreshold(0.15); - //pf->setResampling( std::unique_ptr>(new K::ParticleFilterResamplingSimple()) ); + pf->setNEffThreshold(0.02); + pf->setResampling( std::unique_ptr>(new K::ParticleFilterResamplingSimple()) ); //pf->setNEffThreshold(0.75); //pf->setResampling( std::unique_ptr>(new K::ParticleFilterResamplingPercent(0.10)) ); @@ -117,9 +132,9 @@ public: //pf->setNEffThreshold(0.75); //pf->setResampling( std::unique_ptr>(new K::ParticleFilterResamplingPercent(0.05)) ); - K::ParticleFilterResamplingNEff* res = new K::ParticleFilterResamplingNEff(0.75, 0.05); - pf->setNEffThreshold(1.0); - pf->setResampling( std::unique_ptr>(res) ); +// K::ParticleFilterResamplingNEff* res = new K::ParticleFilterResamplingNEff(0.75, 0.05); +// pf->setNEffThreshold(1.0); +// pf->setResampling( std::unique_ptr>(res) ); // move during resampling. NOT ALLOWED! // res->setDrawCallback([&] (K::Particle& p) { @@ -145,6 +160,211 @@ public: } + struct LeWalk { + std::string name; + float absHead; + std::string walkFile; + std::vector gtIndices; + LeWalk(const std::string& name, float absHead, std::string walkFile, std::vector gtIndices) : + name(name), absHead(absHead), walkFile(walkFile), gtIndices(gtIndices) { + ; + } + }; + + struct LeModel { + std::string name; + WiFiModel* model; + LeModel(const std::string& name, WiFiModel* model) : name(name), model(model) {;} + }; + + static void serialize(const K::Statistics& stats, const LeWalk& walk, const LeModel& model, const int idx) { + const std::string file = Settings::fPathGFX + "/walks/data/" + walk.name + "_" + model.name + "_" + std::to_string(idx) + ".txt"; + std::ofstream out(file); + for (const float f : stats.getAll()) { + out << f << "\n"; + } + out.close(); + } + + static K::Statistics* deserialize(const LeWalk& walk, const LeModel& model, const int idx) { + const std::string file = Settings::fPathGFX + "/walks/data/" + walk.name + "_" + model.name + "_" + std::to_string(idx) + ".txt"; + K::Statistics* res = new K::Statistics(); + std::ifstream inp(file); + while(inp) { + float f; + inp >> f; + res->add(f); + } + return res; + } + + static std::vector allWalks() { + return { + LeWalk("path1a", M_PI/2, Settings::path1a, Settings::GroundTruth::path1), + LeWalk("path1b", M_PI/2, Settings::path1b, Settings::GroundTruth::path1), + LeWalk("toni-all-1a", M_PI/2, Settings::path_toni_all_1a, Settings::GroundTruth::path1), + LeWalk("toni-all-1b", M_PI/2, Settings::path_toni_all_1b, Settings::GroundTruth::path1), + LeWalk("path2a", 0, Settings::path2a, Settings::GroundTruth::path2), + LeWalk("path2b", 0, Settings::path2b, Settings::GroundTruth::path2), + LeWalk("toni-all-2a", M_PI/2, Settings::path_toni_all_2a, Settings::GroundTruth::path2), + LeWalk("toni-all-2b", M_PI/2, Settings::path_toni_all_2b, Settings::GroundTruth::path2), + /////////LeWalk("toni-inst-1a", M_PI/2, Settings::path_toni_inst_1a, Settings::GroundTruth::path_toni_inst_1), + LeWalk("toni-inst-1b", M_PI/2, Settings::path_toni_inst_1b, Settings::GroundTruth::path_toni_inst_1), + LeWalk("toni-inst-2a", M_PI/2, Settings::path_toni_inst_2a, Settings::GroundTruth::path_toni_inst_2), + LeWalk("toni-inst-2b", M_PI/2, Settings::path_toni_inst_2b, Settings::GroundTruth::path_toni_inst_2), + LeWalk("toni-inst-3a", M_PI/2, Settings::path_toni_inst_3a, Settings::GroundTruth::path_toni_inst_3), + LeWalk("toni-inst-3b", M_PI/2, Settings::path_toni_inst_3b, Settings::GroundTruth::path_toni_inst_3), + + }; + } + + static std::vector allModels(Floorplan::IndoorMap* map) { + WiFiModelFactory fac(map); + return { + //LeModel("empiric", fac.loadXML(Settings::wifiAllFixed)), + //LeModel("opt 1", fac.loadXML(Settings::wifiAllOptPar)), + //LeModel("opt 2", fac.loadXML(Settings::wifiEachOptPar)), + //LeModel("opt 3", fac.loadXML(Settings::wifiEachOptParPos)), + //LeModel("per floor", fac.loadXML(Settings::wifiEachOptParPos_multimodel)), + LeModel("per bbox", fac.loadXML(Settings::wifiEachOptParPos_perBBox)), + }; + } + + static constexpr int numRepeats = 1; + + /** create GFX for all previously walked parts */ + static void walkEverythingBuildStats(Floorplan::IndoorMap* map) { + + const std::vector walks = allWalks(); + const std::vector models = allModels(map); + + PlotErrFunc* pefAll = new PlotErrFunc(); + int numStuck = 0; + int numTotal = 0; + + for (const LeModel& mdl : models) { + + K::Statistics* modelStatsAvg = new K::Statistics(); + K::Statistics* modelStatsMed = new K::Statistics(); + + K::Statistics* modelStatsSingle = new K::Statistics(); + pefAll->add(mdl.name, modelStatsSingle); + + + + // ... to perform every walk... + for (const LeWalk& walk : walks) { + + for (int i = 0; i < numRepeats; ++i) { + + ++numTotal; + K::Statistics* walkStats = deserialize(walk, mdl, i); + + if (walkStats->getMedian() < 10) { + modelStatsSingle->add(*walkStats); + pefAll->plot(); + } else { + ++numStuck; + } + + } + + } + + sleep(1); + + } + + std::cout << "stuck: " << numStuck << " (" << (numStuck*100/numTotal) << "%)" << std::endl; + + sleep(100); + + + } + + /** perform all walks and write them to file */ + static void walkEverything(Floorplan::IndoorMap* map) { + + const std::vector walks = allWalks(); + const std::vector models = allModels(map); + + PlotErrFunc* pefAll = new PlotErrFunc(); + + // use every model ... + for (const LeModel& mdl : models) { + + K::Statistics* modelStatsSingle = new K::Statistics(); + pefAll->add(mdl.name, modelStatsSingle); + + // ... to perform every walk... + for (const LeWalk& walk : walks) { + + //K::Statistics curWalkRepeatStatsAvg; + //K::Statistics curWalkRepeatStatsMed; + + // ... several times + for (int i = 0; i < numRepeats; ++i) { + + EvalWalk ew(map); + ew.walkName = walk.name + " - " + mdl.name + " - " + std::to_string(i); + + // get ground-truth + ew.absHead = walk.absHead; + ew.groundTruth = FloorplanHelper::getGroundTruth(map, walk.gtIndices); + + // eval + std::unique_ptr eval = std::unique_ptr( new PFEval(ew.grid, *mdl.model, ew.em) ); + ew.pf->setEvaluation( std::move(eval) ); + + // data-file + ew.reader.open(walk.walkFile); + ew.groundTruthLive = ew.reader.getGroundTruth(map, walk.gtIndices); + ew.player.setReader(&ew.reader); + ew.player.setListener(&ew); + ew.player.start(); + + // wait for completion + ew.player.join(); + + // write plots + ew.writeToFile(); + + // add every single error for each timestamp to the overall model error + modelStatsSingle->reset(); + modelStatsSingle->add(ew.statsErr); + + // export this walks's statistics + serialize(ew.statsErr, walk, mdl, i); + + pefAll->plot(); + + } + + // all repeats done + const std::string walkname = walk.name + " - " + mdl.name; + std::cout << "walk result for " << walkname << std::endl; + //std::cout << "\t" << curWalkRepeatStatsAvg.asString() << std::endl; + //std::cout << "\t" << curWalkRepeatStatsMed.asString() << std::endl; + std::cout << std::endl; + //sleep(1); + + } + + // all walks for one model done + std::cout << "MODEL RESULTS for " << mdl.name << std::endl; + //std::cout << "\t" << modelStatsAvg->asString() << std::endl; + //std::cout << "\t" << modelStatsMed->asString() << std::endl; + std::cout << std::endl; + std::cout << std::endl; + std::cout << std::endl; + + sleep(2); + + } + + + } + void walk1() { // path1 @@ -211,7 +431,7 @@ public: ++curCtrl.numStepsSinceLastTransition; } gotSensorData(ts); - curCtrl.activityNew = actDetect.add(ts, data); + actDetect.add(ts, data); } virtual void onGravity(const Timestamp ts, const GravityData data) override { @@ -219,14 +439,18 @@ public: } virtual void onWiFi(const Timestamp ts, const WiFiMeasurements data) override { - std::cout << "WIFI" << std::endl; curObs.wifi = data; + //curObs.wifi = WiFiMeasurements::mix(curObs.wifi, data); +#ifdef PLOT_WIFI plotWifi.add(Settings::WiFiModel::vg_eval.group(data)); plotWifi.plot(); +#endif } virtual void onBarometer(const Timestamp ts, const BarometerData data) override { - ; + actDetect.add(ts, data); + curCtrl.activityNew = actDetect.get(); + curObs.activityNew = actDetect.get(); } virtual void onGPS(const Timestamp ts, const GPSData data) override { @@ -300,12 +524,48 @@ private: return set.size(); } + + void writeToFile() { + + std::string path = Settings::fPathGFX; + std::string base = path + "/walks/" + "walk-" + walkName; + + plotty.gp << "unset arrow 1\n"; + plotty.gp << "unset arrow 2\n"; + plotty.gp << "unset colorbox\n"; + plotty.gp << "unset border\n"; + plotty.gp << "set view equal xy\n"; + plotty.splot.getView().setCamera(74,30); + plotty.splot.getView().setScaleAll(3.5); + plotty.splot.getAxisX().setTicsVisible(false); + plotty.splot.getAxisY().setTicsVisible(false); + plotty.splot.getAxisZ().setTicsVisible(false); + + plotty.particles.clear(); + plotty.gp.setTerminal("epslatex", K::GnuplotSize(8.6, 4.5)); + plotty.gp.setOutput(base + "-map.tex"); + plotty.writeCodeTo(base + "-map.gp"); + plotty.plot(); + + pef.getPlot().getMargin().set(4, 0.2, 0.1, 2.0); + pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 3.0)); + pef.getGP().setOutput(base + "-error-cum.tex"); + pef.writePlotToFile(base + "-error-cum.gp"); + pef.plot(); + + pet.getPlot().getMargin().set(4, 0.2, 0.1, 2.0); + pet.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 3.0)); + pet.getGP().setOutput(base + "-error-time.tex"); + pet.writePlotToFile(base + "-error-time.gp"); + pet.plot(); + + } + /** perform a filter-update (called from a background-loop) */ void filterUpdate() { ++updateCount; - static PlotErrTime pet("\\small{time (sec)}", "\\small{error (m)}", "\\small{APs visible}"); - static PlotErrFunc pef("\\small{error (m)}", "\\small{updates (\\%)}"); + pef.showMarkers(true, true); std::cout << "update" << std::endl; @@ -319,22 +579,23 @@ private: const Point3 curGT = groundTruthLive.get(lastTransition); - plotty.setCurEst(curEst.position.inMeter()); - plotty.setGroundTruth(curGT); - - if (updateCount > 4) { + // start the error-over-time plot after some filter updates + if (updateCount > 12) { // error between ground-truth and estimation const float estRealErr = curEst.position.inMeter().getDistance(curGT); statsErr.add(estRealErr); + +#ifdef PLOT_ERROR_FUNC pef.clear(); pef.add("", &statsErr); - pef.plot(); +#endif +#ifdef PLOT_ERROR_TIME // timed error pet.addErr(lastTransition, estRealErr); pet.addB(lastTransition, getNumFHWSAPs(curObs.wifi)); - pet.plot(); +#endif // update estimated path const K::GnuplotPoint3 p3(curEst.position.x_cm, curEst.position.y_cm, curEst.position.z_cm); @@ -342,50 +603,73 @@ private: } - std::cout << statsErr.asString() << std::endl; - - // show particles - float maxWeight = 0; - float minWeight = 99; - plotty.particles.clear(); - for (const auto p : pf->getParticles()) { - const K::GnuplotPoint3 p3(p.state.position.x_cm, p.state.position.y_cm, p.state.position.z_cm); - plotty.particles.add(p3/100, p.weight); - if (p.weight > maxWeight) {maxWeight = p.weight;} - if (p.weight < minWeight) {minWeight = p.weight;} - } - plotty.gp << "set cbrange [" << minWeight << ":" << maxWeight << "] \n"; - - // show ground-truth - plotty.pathReal.clear(); - for (const Point3 pt : groundTruth) { - plotty.pathReal.add(K::GnuplotPoint3(pt.x, pt.y, pt.z)); - } - - std::string title = - " time " + std::to_string(curObs.currentTime.sec()) + - " steps: " + std::to_string(ctrlCopy.numStepsSinceLastTransition) + - " turn: " + std::to_string(ctrlCopy.turnSinceLastTransition_rad) + - " APs: " + std::to_string(curObs.wifi.entries.size()) + - " Act: " + std::to_string((int)curCtrl.activityNew); - plotty.setTitle(title); - - // relative heading and compass - { - Point2 cen(0.1, 0.9); - Point2 dir(std::cos(absHead), std::sin(absHead)); - Point2 arr = cen + dir * 0.1; - plotty.gp << "set arrow 1 from screen " << cen.x << "," << cen.y << " to screen " << arr.x << "," << arr.y << "\n"; - dir = Point2(std::cos(ctrlCopy.compassAzimuth_rad), std::sin(ctrlCopy.compassAzimuth_rad)); - arr = cen + dir * 0.05; - plotty.gp << "set arrow 2 from screen " << cen.x << "," << cen.y << " to screen " << arr.x << "," << arr.y << "\n"; - } // plot - plotty.plot(); + static int cnt = 0; + if (++cnt % PLOT_UPDATE_STEP == 0) { - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::cout << statsErr.asString() << std::endl; + + // estimation and ground-truth + plotty.setCurEst(curEst.position.inMeter()); + plotty.setGroundTruth(curGT); + + // show particles + float maxWeight = 0; + float minWeight = 99; + plotty.particles.clear(); + for (int i = 0; i < pf->getParticles().size(); i += 10) { + const auto p = pf->getParticles()[i]; + const K::GnuplotPoint3 p3(p.state.position.x_cm, p.state.position.y_cm, p.state.position.z_cm); + plotty.particles.add(p3/100, p.weight); + if (p.weight > maxWeight) {maxWeight = p.weight;} + if (p.weight < minWeight) {minWeight = p.weight;} + } + plotty.gp << "set cbrange [" << minWeight << ":" << maxWeight << "] \n"; + + // show ground-truth + plotty.pathReal.clear(); + for (const Point3 pt : groundTruth) { + plotty.pathReal.add(K::GnuplotPoint3(pt.x, pt.y, pt.z)); + } + + std::string title = + " time " + std::to_string(curObs.currentTime.sec()) + + " steps: " + std::to_string(ctrlCopy.numStepsSinceLastTransition) + + " turn: " + std::to_string(ctrlCopy.turnSinceLastTransition_rad) + + " APs: " + std::to_string(curObs.wifi.entries.size()) + + " Act: " + std::to_string((int)curCtrl.activityNew) + + " " + walkName; + plotty.setTitle(title); + + // relative heading and compass + { + Point2 cen(0.1, 0.9); + Point2 dir(std::cos(absHead), std::sin(absHead)); + Point2 arr = cen + dir * 0.1; + plotty.gp << "set arrow 1 from screen " << cen.x << "," << cen.y << " to screen " << arr.x << "," << arr.y << "\n"; + dir = Point2(std::cos(ctrlCopy.compassAzimuth_rad), std::sin(ctrlCopy.compassAzimuth_rad)); + arr = cen + dir * 0.05; + plotty.gp << "set arrow 2 from screen " << cen.x << "," << cen.y << " to screen " << arr.x << "," << arr.y << "\n"; + } + + +#ifdef PLOT_LIVE + plotty.plot(); +#endif + +#ifdef PLOT_ERROR_TIME + pet.plot(); +#endif + +#ifdef PLOT_ERROR_FUNC + pef.plot(); +#endif + + } + + //std::this_thread::sleep_for(std::chrono::milliseconds(5)); curCtrl.resetAfterTransition(); diff --git a/pf/PF.h b/pf/PF.h old mode 100644 new mode 100755 index 04c6756..3e9522c --- a/pf/PF.h +++ b/pf/PF.h @@ -98,7 +98,8 @@ struct MyObservation { // TODO: switch to a general activity enum/detector for barometer + accelerometer + ...? /** detected activity */ - ActivityButterPressure::Activity activity; + //ActivityButterPressure::Activity activity; + Activity activityNew = Activity::STANDING; /** time of evaluation */ Timestamp currentTime; @@ -119,9 +120,9 @@ struct MyControl { // TODO: switch to a general activity enum/detector using barometer + accelerometer? /** currently detected activity */ - ActivityButterPressure::Activity activity = ActivityButterPressure::Activity::STAY; + //ActivityButterPressure::Activity activity = ActivityButterPressure::Activity::STAY; - Activity activityNew; + Activity activityNew = Activity::STANDING; /** reset the control-data after each transition */ void resetAfterTransition() { @@ -150,8 +151,10 @@ public: std::uniform_real_distribution distHead(0, 2*M_PI); for (K::Particle& p : particles) { - const int idx = distIdx(gen); - const MyGridNode& node = (*grid)[idx]; + again: + const int idx = distIdx(gen); + const MyGridNode& node = (*grid)[idx]; + if (node.getNumNeighbors() != 8) {goto again;} p.state.position = node; // random position p.state.heading.direction = Heading(distHead(gen)); // random heading p.weight = 1.0 / particles.size(); // equal weight @@ -174,7 +177,7 @@ public: WalkModuleFavorZ modFavorZ; WalkModuleNodeImportance modImportance; WalkModuleFollowDestination modDestination; - WalkModuleActivityControl modActivity; + //WalkModuleActivityControl modActivity; WalkModuleHeadingControl modRelHead; WalkModuleAbsoluteHeadingControl modAbsHead; @@ -183,7 +186,11 @@ public: public: - PFTrans(Grid* grid) : grid(grid), modRelHead(&ctrl, Settings::IMU::turnSigma), modAbsHead(&ctrl, Settings::IMU::absHeadSigma), modDestination(*grid), modActivity(&ctrl) { + PFTrans(Grid* grid) : grid(grid), modRelHead(&ctrl, Settings::IMU::turnSigma), + modAbsHead(&ctrl, Settings::IMU::absHeadSigma), + modDestination(*grid) + //,modActivity(&ctrl) + { walker.addModule(&modRelHead); //walker.addModule(&modAbsHead); @@ -234,10 +241,9 @@ public: K::Particle& p = particles[i]; // first transitions: more variation as the state is unknown - if (numTrans < 50 || numTrans % 10 == 0) { + if (numTrans < 70 || numTrans % (10*1) == 0) { const MyGridNode* n = grid->getNodePtrFor(p.state.position); - std::normal_distribution distTurn(0, 0.4); for (int j = 0; j < 5; ++j) { std::uniform_int_distribution distIdx(0, n->getNumNeighbors()-1); @@ -246,9 +252,10 @@ public: } p.state.position = *n; - if (numTrans < 50) { - p.state.heading.direction += distTurn(gen); - dist_m += 0.5; + if (numTrans < 70) { + std::normal_distribution distTurn(0, 0.3); + p.state.heading.direction += distTurn(gen); + dist_m += 0.5; } } @@ -264,6 +271,11 @@ public: p.state = walker.getDestination(*grid, p.state, dist_m, prob); p.weight *= prob; // grid-walk-probability + //const GridNode gn = grid->getNodeFor(p.state.position); + //const double probNode = (gn.getNumNeighbors() >= 8) ? (0.7) : (0.3); + //p.weight *= probNode; + + if (p.weight != p.weight) { throw Exception("nan"); } @@ -320,14 +332,31 @@ public: double res = 0; - if (angularDiff > Angle::degToRad(90)) {res = 0.05;} - else if (angularDiff > Angle::degToRad(45)) {res = 0.25;} - else {res = 0.70;} + if (angularDiff > Angle::degToRad(120)) {res = 0.30;} + else {res = 0.70;} return res; } + double getActivity(const MyState& s, const MyObservation& obs) { + + const MyGridNode& n = grid->getNodeFor(s.position); + + switch(obs.activityNew) { + case Activity::WALKING: + return (n.getType() != MyGridNode::TYPE_STAIR) ? (0.7) : (0.3); + case Activity::WALKING_DOWN: + case Activity::WALKING_UP: + return (n.getType() == MyGridNode::TYPE_STAIR) ? (0.7) : (0.3); + default: + return 1; + } + + return 1.0; + + } + WiFiQualityAnalyzer wqa; double evaluation(std::vector>& particles, const MyObservation& _observation) override { @@ -343,7 +372,9 @@ public: wqa.add(wifiObs); - const float quality = wqa.getQuality(); + float quality = wqa.getQuality(); + std::cout << "wifi quality: " << quality << std::endl; + // GPS const GPSProbability gpsProb(em); @@ -353,7 +384,7 @@ public: Assert::equal((int)particles.size(), Settings::numParticles, "number of particles does not match the settings!"); // use (0.9 * p) + (0.1 * (1-p)) for error cases - wiFiProbability.setUseError(false); + wiFiProbability.setUseError(true); //#pragma omp parallel for num_threads(3) for (int i = 0; i < Settings::numParticles; ++i) { @@ -362,16 +393,15 @@ public: // WiFi free double pWiFi = wiFiProbability.getProbability(p.state.position.inMeter()+person, observation.currentTime, wifiObs); - double pWiFiMod = Distribution::Exponential::getProbability(0.20, -std::log(pWiFi)); - double pWiFiVeto = wiFiProbability.getVeto(p.state.position.inMeter()+person, observation.currentTime, wifiObs); + //double pWiFiMod = Distribution::Exponential::getProbability(0.20, -std::log(pWiFi)); + //double pWiFiMod = std::pow(pWifi, 0.2); + //double pWiFiVeto = wiFiProbability.getVeto(p.state.position.inMeter()+person, observation.currentTime, wifiObs); + const bool volatile init = observation.currentTime.sec() < 25; + //double pWiFiMod = (init) ? (std::pow(pWiFi, 0.1)) : (std::pow(pWiFi, 0.5)); + double pWiFiMod = (init) ? (std::pow(pWiFi, 0.5)) : (std::pow(pWiFi, 0.9)); - if (quality < 0.2) { - pWiFi = 1; - pWiFiVeto = 1; - std::cout << "disabling WiFi" << std::endl; - } // WiFi grid //const MyGridNode& node = grid->getNodeFor(p.state.position); @@ -379,9 +409,18 @@ public: //const double pWiFi = wiFiProbability.getProbability(node, observation.currentTime, wifiObs); //const double pStair = 1;//getStairProb(p, observation.activity); - const double pGPS = gpsProb.getProbability(p.state.position.inMeter(), observation.gps); - const double pAbsHead = getAbsHead(p.state, observation); - const double prob = pWiFi * pWiFiVeto;// * pAbsHead; + double pGPS = gpsProb.getProbability(p.state.position.inMeter(), observation.gps); + double pAbsHead = getAbsHead(p.state, observation); + double pActivty = getActivity(p.state, observation); + + // bad wifi? -> we have no idea where we are! + if (quality < 0.25 && !init) { + pWiFiMod = 1; + //p.weight = std::pow(p.weight, 0.5); + } + + // overall evaluation + const double prob = pWiFiMod * pAbsHead * pActivty; //GPS ERROR?!?!?! does it work without disabling wifi when gps is disabled? @@ -392,6 +431,11 @@ public: // TESTING //p.weight = std::pow(p.weight, 0.5); +// // do NOT update weights +// if (quality < 0.25) { +// p.weight = 1; +// } + p.weight *= prob; // NOTE: keeps the weight returned by the transition step! //p.weight = prob; // does NOT keep the weights returned by the transition step diff --git a/plots/PlotErrFunc.h b/plots/PlotErrFunc.h old mode 100644 new mode 100755 index 03a2356..8e51ced --- a/plots/PlotErrFunc.h +++ b/plots/PlotErrFunc.h @@ -49,6 +49,11 @@ class PlotErrFunc { public: + /** empty ctor */ + PlotErrFunc() { + setYRange(0, 90, 5); + } + /** ctor with x-axis label */ PlotErrFunc(const std::string& xLabel, const std::string& yLabel) { gplot.getAxisX().setLabel(xLabel); diff --git a/plots/PlotErrTime.h b/plots/PlotErrTime.h old mode 100644 new mode 100755 index 77d253a..4aa1803 --- a/plots/PlotErrTime.h +++ b/plots/PlotErrTime.h @@ -23,6 +23,11 @@ private: public: + /** empty ctor */ + PlotErrTime() { + + } + /** ctor */ PlotErrTime(const std::string& xLabel, const std::string& yLabel, const std::string& y2Label) { @@ -41,6 +46,15 @@ public: } + K::Gnuplot& getGP() { + return gp; + } + + /** write the gnuplot commands to file for later re-use */ + void writePlotToFile(const std::string& file) { + this->gp.writePlotToFile(file); + } + void clear() { for (int i = 0; i < 8; ++i) {lineErr[i].clear();} lineB.clear(); diff --git a/plots/PlotWiFiGroundProb.h b/plots/PlotWiFiGroundProb.h old mode 100644 new mode 100755 index 6a6f58e..43db093 --- a/plots/PlotWiFiGroundProb.h +++ b/plots/PlotWiFiGroundProb.h @@ -67,16 +67,13 @@ public: } /** plot the ground-probability for the given measurement */ - void show(const WiFiObserverFree& prob, const WiFiMeasurements& _mes) { - - VAPGrouper vap(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE); - const WiFiMeasurements mes = vap.group(_mes); + void show(const WiFiObserverFree& prob, const WiFiMeasurements& mes, const Timestamp ts) { // determine min/max probability double min = +99999; double max = -99999; for (Entry& e : pos) { - const double p = prob.getProbability(e.pos, mes.entries.front().getTimestamp(), mes); + const double p = prob.getProbability(e.pos, ts, mes); if (p < min) {min = p;} if (p > max) {max = p;} } @@ -84,8 +81,11 @@ public: // render for (Entry& e : pos) { - const double p = prob.getProbability(e.pos, mes.entries.front().getTimestamp(), mes); - const double f = (p-min) / diff * 255; + const double p = prob.getProbability(e.pos, ts, mes); + double f = (p-min) / diff * 255; + if (f < 0) {f = 0;} + if (f > 255) {f = 255;} + e.sum += p; e.cnt++; @@ -93,10 +93,14 @@ public: const K::GnuplotColor c = K::GnuplotColor::fromHSV(0, f, 255); e.poly->getFill().setColor(c); e.max = f; + + e.poly->setEnabled(f > 32); //} - if (f < 0.1) { - e.poly->setEnabled(false); - } +// if (f < 32) { +// e.poly->setEnabled(false); +// } else { +// e.poly->setEnabled(true); +// } //plot.cpoints.add(K::GnuplotPoint3(pt.x, pt.y, pt.z), p); } diff --git a/plots/Plotty.h b/plots/Plotty.h old mode 100644 new mode 100755 diff --git a/tex/bare_conf.tex b/tex/bare_conf.tex old mode 100644 new mode 100755 index 82b9c8e..9845214 --- a/tex/bare_conf.tex +++ b/tex/bare_conf.tex @@ -81,6 +81,8 @@ %\usepackage{ulem} +%\setcounter{figure}{0} +%\renewcommand{\thefigure}{A\arabic{section}.\arabic{figure}} % replacement for the SI package diff --git a/tex/chapters/abstract.tex b/tex/chapters/abstract.tex old mode 100644 new mode 100755 diff --git a/tex/chapters/conclusion.tex b/tex/chapters/conclusion.tex old mode 100644 new mode 100755 diff --git a/tex/chapters/experiments.tex b/tex/chapters/experiments.tex old mode 100644 new mode 100755 index cd9f55f..9ecb8ba --- a/tex/chapters/experiments.tex +++ b/tex/chapters/experiments.tex @@ -41,13 +41,13 @@ \centering \input{gfx/all_fingerprints.tex} } - \label{fig:referenceMeasurements} \caption{ Locations of the 121 reference measurements. The size of each square denotes the number of permanently installed \docAPshort{}s that are visible at this location, and ranges between 2 and 22 with an average of 9. } + \label{fig:referenceMeasurements} \end{figure} % visible APs: @@ -56,12 +56,12 @@ \begin{figure}[b] \centering \input{gfx/compare-wifi-in-out.tex} - \label{fig:wifiIndoorOutdoor} \caption{ Measurable signal strengths of a testing \docAPshort{} (black dot). While the signal diminishes slowly along the corridor (upper rectangle) the metallised windows (dashed outline) attenuate the signal by over \SI{30}{\decibel} (lower rectangle). } + \label{fig:wifiIndoorOutdoor} \end{figure} Figure \ref{fig:wifiIndoorOutdoor} depicts the to-be-expected issues by examining the signal strength @@ -105,11 +105,11 @@ \begin{figure} \input{gfx/wifi_model_error_0_95.tex} %\input{gfx/wifi_model_error_95_100.tex} - \label{fig:wifiModelError} \caption{ Comparison between different optimization strategies by examining the error (in \decibel) at each reference measurement. The higher the number of variable parameters, the better the model resembles real world conditions. } + \label{fig:wifiModelError} \end{figure} % statds: @@ -135,30 +135,77 @@ As we try to minimize the system's setup time as much as possible, we need to determine the amount of necessary reference measurements for the optimization to produce viable model parameters. - Depending on the number of to-be-optimized model parameters, more measurements are required. - This especially holds true for {\em \optPerRegion{}} where each region needs at least some measurements - to determine transmitter positions and parameters. + Depending on the chosen model and thus the number of to-be-optimized parameters, more measurements are required. + + While there was almost no difference between using 121 or 30 reference measurements for + {\em \optParamsAllAP{}} and {\em \optParamsEachAP{}} + (average \SIrange{5.3}{5.4}{\decibel} and \SIrange{4.5}{5.0}{\decibel}), + {\em \optPerRegion{}} is highly affected + (average \SIrange{2.0}{6.2}{\decibel}), as it needs at least a certain number of measurements for each + of its regions for the optimization to converge. \begin{figure}[b] \input{gfx/wifi_model_error_num_fingerprints_method_5_0_90.tex} \input{gfx/wifi_model_error_num_fingerprints_method_5_90_100.tex} - \label{fig:wifiNumFingerprints}% \caption{% - number of fingerprints + Impact of reducing the number of reference measurements during optimization on {\em \optPerRegion{}}. + The model's cumulative error distribution is determined by comparing the its signal strength prediction against all 121 measurements. + While using only \SI{50}{\percent} of the 121 scans has barely an impact on the error, + 30 measurements (\SI{25}{\percent}) are clearly insufficient. }% + \label{fig:wifiNumFingerprints}% \end{figure} - Figure \ref{fig:wifiNumFingerprints} depicts the impact of reducing the number of fingerprints - for the {\em \optPerRegion{}} strategy. Only using 60 of the 121 fingerprints yields only a slightly - increasing model error and still provides good results. While using only \SI{25}{\percent} of the reference - measurements increases the error rapidly, \SI{75}{\percent} of all considered errors are still better - than using just empiric values without any reference measurements. + Figure \ref{fig:wifiNumFingerprints} depicts the impact of reducing the number of reference measurements + during the optimization process for the {\em \optPerRegion{}} strategy. + The error is determined by using the (absolute) difference between expected signal strength and + the optimized model's corresponding prediction for all of the 121 reference measurements. + % + Considering only 60 of the 121 scans (\SI{50}{\percent}) yields a slightly increasing model error and still provides good results. + While using only \SI{25}{\percent} of the reference measurements increases the error rapidly, + for \SI{75}{\percent} of the 121 considered cases the estimation is still better than using just empiric values without optimization. + The extremely large outlier depicted in the lower half of figure \ref{fig:wifiNumFingerprints} (red line) relates to one + sub-model with only one assigned reference measurement, where the optimized result is unable to predict values + for the rest of the sub-model's region. \todo{versteht man das?} Additionally we examined the impact of skipping reference measurements for difficult locations - like aforementioned staircases, surrounded by concrete. While this slightly decreases the - estimation error for all other positions, the error within those locations is dramatically + like staircases, surrounded by steel-enforced concrete. While this slightly decreases the + estimation error for all other positions (hallway, etc) as expected, the error within the skipped locations is dramatically increasing (see lower half of figure \ref{fig:wifiNumFingerprints}). It is thus highly recommended - to include such locations. + to also perform reference measurements for locations, that are expected to strongly deviate (signal strength) + from their surroundings. + + + + %leaving out fingerprints for model 1 + % 25%: cnt(1128) min(0.007439) max(27.804710) range(27.797272) med(4.404236) avg(5.449720) stdDev(4.470373) + % 50%: cnt(1128) min(0.006027) max(27.732193) range(27.726166) med(4.367859) avg(5.437861) stdDev(4.475426) + % 100%: cnt(1128) min(0.000282) max(27.705376) range(27.705093) med(4.272881) avg(5.411202) stdDev(4.493495) + % noStair%: cnt(1128) min(0.000801) max(27.209221) range(27.208420) med(4.333328) avg(5.459918) stdDev(4.459484) + + %leaving out fingerprints for model 2 + % 25%: cnt(1128) min(0.000320) max(29.752560) range(29.752239) med(3.837357) avg(5.027578) stdDev(4.617191) + % 50%: cnt(1128) min(0.015305) max(34.152130) range(34.136826) med(3.627090) avg(4.635868) stdDev(4.135866) + % 100%: cnt(1128) min(0.000488) max(25.687740) range(25.687252) med(3.319756) avg(4.441193) stdDev(3.912525) + % noStair%: cnt(1128) min(0.017693) max(25.687740) range(25.670048) med(3.304321) avg(4.507620) stdDev(3.957071) + + %leaving out fingerprints for model 3 + % 25%: cnt(1128) min(0.003242) max(39.470978) range(39.467735) med(3.371758) avg(4.977330) stdDev(5.213937) + % 50%: cnt(1128) min(0.002808) max(30.113415) range(30.110607) med(2.941238) avg(4.015042) stdDev(3.696969) + % 100%: cnt(1128) min(0.000557) max(16.813850) range(16.813293) med(3.056915) avg(3.813013) stdDev(3.062580) + % noStair%: cnt(1128) min(0.002518) max(30.370636) range(30.368118) med(3.016884) avg(3.983101) stdDev(3.508327) + + %leaving out fingerprints for model 4 + % 25%: cnt(1128) min(0.000000) max(62.233345) range(62.233345) med(2.502831) avg(5.432897) stdDev(8.664582) + % 50%: cnt(1128) min(0.000000) max(56.843803) range(56.843803) med(1.543137) avg(2.937506) stdDev(4.417061) + % 100%: cnt(1128) min(0.000046) max(33.175812) range(33.175766) med(1.537933) avg(2.441976) stdDev(2.793499) + % noStair%: cnt(1128) min(0.000000) max(62.233345) range(62.233345) med(1.493668) avg(2.744918) stdDev(4.428092) + + %leaving out fingerprints for model 5 + % 25%: cnt(1128) min(0.000000) max(62.620842) range(62.620842) med(2.140709) avg(6.257105) stdDev(11.638572) + % 50%: cnt(1128) min(0.000000) max(57.371948) range(57.371948) med(1.357452) avg(2.982217) stdDev(5.877471) + % 100%: cnt(1128) min(0.000000) max(14.837151) range(14.837151) med(1.251358) avg(1.989277) stdDev(2.189072) + % noStair%: cnt(1128) min(0.000000) max(62.233345) range(62.233345) med(1.143669) avg(2.316189) stdDev(4.164822) @@ -198,8 +245,8 @@ at location $\mPosVec$ returned from the to-be-examined prediction model. For all comparisons we use a constant uncertainty $\sigma = $\SI{8}{\decibel}. - The quality of the estimated location is determined by comparing the estimation - $\mPosVec^*$ with the pedestrian's ground truth position at the time the scan $\mRssiVec$ + The quality of the estimated location is determined by using the Euclidean distance between estimation + $\mPosVec^*$ and the pedestrian's ground truth position at the time the scan $\mRssiVec$ has been received. @@ -226,18 +273,20 @@ \begin{figure}[b] \input{gfx/modelPerformance_meter.tex} - \label{fig:modelPerformance} \caption{ Error between ground truth and estimation using \refeq{eq:bestWiFiPos} depending - on the underlying signal strength prediction model + on the underlying signal strength prediction model. + Extremely high errors between the \SIrange{90}{100}{\percent} quartile are related to bad \docWIFI{} + coverage within outdoor areas (see figure \ref{fig:wifiIndoorOutdoor}). } + \label{fig:modelPerformance} \end{figure} %To estimate the overall performance of the prediction models, we compare the position estimation %for each \docWIFI{} measurement within the recorded paths (3756 \docAPshort{} scans in total) %against the corresponding ground-truth, which indicates the absolute 3D error in meter. - The position estimation for each \docWIFI{} measurement within the recorded walks (3756 \docAPshort{} scans in total) - is compared against its corresponding ground-truth, indicating the absolute 3D error. + The position estimation for each \docWIFI{} measurement within the recorded walks (3756 scans in total) + is compared against its corresponding ground-truth, indicating the 3D error. The resulting cumulative error distribution can be seen in figure \ref{fig:modelPerformance}. The quality of the location estimation directly scales with the quality of the signal strength prediction model. However, as discussed earlier, the maximal estimation error might increase for some setups. @@ -252,13 +301,13 @@ \begin{figure}[t] \input{gfx/wifiMultimodality.tex} - \label{fig:wifiMultimodality} \caption{ Location probability \refeq{eq:bestWiFiPos} for three scans. Higher color intensities are more likely. Ideally, places near the ground truth (black) are highly highly probable (green). Often, other locations are just as likely as the ground truth (blue), or the location with the highest probability does not match at all (red). } + \label{fig:wifiMultimodality} \end{figure} Figure \ref{fig:wifiMultimodality} depicts aforementioned issues of multimodal (blue) or wrong (red) location @@ -318,13 +367,13 @@ \begin{figure} \input{gfx/wifiCompare_normalVsExp_cross.tex} \input{gfx/wifiCompare_normalVsExp_meter.tex} - \label{fig:normalVsExponential} \caption{ Comparison between normal- (black) and exponential-distribution (red) for \refeq{eq:wifiProb}. While misclassifications are slightly reduced (upper chart), the median error between ground-truth and estimation (lower chart) increases by about \SI{1}{\meter}. } + \label{fig:normalVsExponential} \end{figure} diff --git a/tex/chapters/interoduction.tex b/tex/chapters/interoduction.tex old mode 100644 new mode 100755 diff --git a/tex/chapters/introduction.tex b/tex/chapters/introduction.tex old mode 100644 new mode 100755 diff --git a/tex/chapters/relatedwork.tex b/tex/chapters/relatedwork.tex old mode 100644 new mode 100755 diff --git a/tex/chapters/system.tex b/tex/chapters/system.tex old mode 100644 new mode 100755 diff --git a/tex/chapters/work.tex b/tex/chapters/work.tex old mode 100644 new mode 100755 index e79adc4..dd34aa6 --- a/tex/chapters/work.tex +++ b/tex/chapters/work.tex @@ -100,12 +100,12 @@ \begin{figure}[t!] \input{gfx/wifiop_show_optfunc_params} - \label{fig:wifiOptFuncTXPEXP} \caption{ The average error (in \SI{}{\decibel}) between all reference measurements and corresponding model predictions for one \docAPshort{} dependent on \docTXP{} \mTXP{} and \docEXP{} \mPLE{} [known position $\mPosAPVec{}$, fixed \mWAF{}] denotes a convex function. } + \label{fig:wifiOptFuncTXPEXP} \end{figure} For systems that demand a higher accuracy, one can choose a compromise between fingerprinting and @@ -138,12 +138,12 @@ \begin{figure}[t!] \input{gfx/wifiop_show_optfunc_pos_yz} - \label{fig:wifiOptFuncPosYZ} \caption{ The average error (in \SI{}{\decibel}) between reference measurements and model predictions for one \docAPshort{} dependent on $y$- and $z$-position [fixed $x$, \mTXP{}, \mPLE{} and \mWAF{}] usually denotes a non-convex function with multiple [here: two] local minima. } + \label{fig:wifiOptFuncPosYZ} \end{figure} Such functions demand for optimization algorithms, that are able to deal with non-convex functions, @@ -186,6 +186,9 @@ axis-aligned bounding box. This approach allows a distinction between in- and outdoor-regions or locations that are expected to highly differ from their surroundings. + \todo{AP wird in einer region nur dann beruecksichtigt, wenn mindestanzahl an messungen vorhanden ist!} + + \todo{das heißt aber, dass an unterschiedlichen stellen unterschiedlich viele APs verglichen werden. das geht ned. deshalb feste -100} \subsection{\docWIFI{} quality factor} @@ -243,8 +246,11 @@ When scanning for \docAPshort{}s one will thus receive several responses from the same hardware, all with a very small delay (micro- to milliseconds). Such measurements may be grouped using some aggregate function like average, median or maximum. - - + + Furthermore, VAP grouping can be used to suppress unlikely observations: If a physical hardware is known + to provide six virtual networks, it is unlikely to only see one of those networks. This is likely due to + temporal effects and/or multipath signal propagation and the received signal strength will often be far from + the normal average. It thus makes sense to just omit such unlikely observations, focusing on the remaining, stable ones. diff --git a/tex/egbib.bib b/tex/egbib.bib old mode 100644 new mode 100755 diff --git a/tex/gfx/build.sh b/tex/gfx/build.sh old mode 100644 new mode 100755 index 229c082..9179a01 --- a/tex/gfx/build.sh +++ b/tex/gfx/build.sh @@ -1,4 +1,4 @@ for file in *.gp do - gnuplot $file; + gnuplot "$file"; done diff --git a/tex/make.sh b/tex/make.sh old mode 100644 new mode 100755 diff --git a/tex/misc/functions.tex b/tex/misc/functions.tex old mode 100644 new mode 100755 diff --git a/tex/misc/keywords.tex b/tex/misc/keywords.tex old mode 100644 new mode 100755 diff --git a/wifi/EvalWiFi.h b/wifi/EvalWiFi.h old mode 100644 new mode 100755 diff --git a/wifi/EvalWiFiConvex.h b/wifi/EvalWiFiConvex.h old mode 100644 new mode 100755 diff --git a/wifi/EvalWiFiGround.h b/wifi/EvalWiFiGround.h old mode 100644 new mode 100755 index 15481aa..3bfcf7a --- a/wifi/EvalWiFiGround.h +++ b/wifi/EvalWiFiGround.h @@ -30,6 +30,7 @@ #include "../plots/PlotErrTime.h" #include "../plots/PlotErrFunc.h" #include "../plots/PlotWiFiGroundProb.h" +#include //#include "../CSV.h" #include @@ -46,6 +47,7 @@ private: public: PlotWiFiGroundProb* groundProb; + PlotWifiMeasurements plotWifi; public: @@ -55,25 +57,84 @@ public: obs = new WiFiObserverFree(8.0, *mdl); groundProb = new PlotWiFiGroundProb(map, settings); + // must be 34 + std::cout << "Model APs: " << mdl->getAllAPs().size() << std::endl; + int i = 0; (void) i; + } - void show(const std::string walkFile, const int idx = -1) { + void show(const std::string walkFile, const std::vector gtIndices) { Offline::FileReader reader(walkFile); + Offline::FileReader::GroundTruth gt = reader.getGroundTruth(map, gtIndices); + VAPGrouper vap(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE); + + + int cnt = 0; - for (const auto& entry : reader.getWiFiGroupedByTime()) { - const WiFiMeasurements& mes = entry.data; - groundProb->show(*obs, mes); + WiFiMeasurements mes; + + //std::vector indices = {260, 270,271,272, 280}; + //std::vector indices = {270,271,272}; + + for (size_t i = 0; i < reader.getWiFiGroupedByTime().size(); ++i) { + //for (int i : indices) { + + //mal nur zeigen welche regionen aus sicht von D8:84:66:4A:4B:C0 wahrscheinlich sind + + //beim VAP grouping mitzählen wieviele APs contributen.. wenns nur einer ist, dann vlt lieber löschen??? + + const auto& entry = reader.getWiFiGroupedByTime()[i]; + + const WiFiMeasurements& _newMes = entry.data; + std::cout << _newMes.asString() << std::endl; + + WiFiMeasurements newMes = vap.group(_newMes); + //newMes.remove(MACAddress("D8:84:66:4A:4B:C0")); + +// WiFiMeasurement leap = *(newMes.getForMac(MACAddress("D8:84:66:4A:4B:C0"))); +// newMes.entries.clear(); +// newMes.entries.push_back(leap); + + + //std::cout << newMes.entries.front().getAP().getMAC().asString() << ":" << newMes.entries.front().getRSSI() << std::endl; + //newMes.entries.erase(newMes.entries.begin()); + + // MACAddress mac("D8:84:66:4A:4B:C0"); + // const WiFiMeasurement* xxx = newMes.getForMac(mac); + // if (xxx) { + // std::cout << xxx->getRSSI() << std::endl; + // } else { + // std::cout << "MISSING" << std::endl; + // } + // mes = WiFiMeasurements::mix(mes, newMes, 2); + mes = newMes; + + plotWifi.add(newMes); + plotWifi.plot(); + + Point3 p3 = gt.get(mes.entries.front().getTimestamp()); + K::GnuplotPoint3 gp3(p3.x, p3.y, p3.z); + groundProb->getPlot().cpoints.clear(); + groundProb->getPlot().points.add(gp3); + + const Timestamp ts = newMes.entries.front().getTimestamp(); + groundProb->show(*obs, mes, ts); groundProb->plotMe(); + + //if (++cnt > 70) {break;} - std::this_thread::sleep_for(std::chrono::milliseconds(2)); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } //groundProb->update(); groundProb->plotMe(); int i = 0; (void) i; + sleep(1000); + } void add(const std::string walkFile, const int idx, const float hue) { diff --git a/wifi/EvalWiFiPathMethods.h b/wifi/EvalWiFiPathMethods.h old mode 100644 new mode 100755 index 6fed5da..113374d --- a/wifi/EvalWiFiPathMethods.h +++ b/wifi/EvalWiFiPathMethods.h @@ -242,7 +242,7 @@ public: // error calculation auto funcOrig = [&] (const float* params) -> double { return errFuncOrig(params, mes); }; - auto funcOther = [&] (const float* params) -> double { return errFuncOther(params, mes); }; + auto funcOther = [&] (const float* params) -> double { return errFuncSingleProb(params, mes); }; // ADJUST HERE // parameters (x,y,z); float paramsOrig[3] = {0,0,0}; @@ -536,6 +536,52 @@ private: } + /** TESTING */ + double errFuncSingleProb(const float* params, const WiFiMeasurements& mes) { + + // crop z to 1 meter + //params[2] = std::round(params[2]); + + // suggested position + const Point3 pos_m(params[0], params[1], params[2]); + + int cnt = 0; + double error = 0; + + //const auto comp = [] (const WiFiMeasurement& m1, const WiFiMeasurement& m2) {return m1.getRSSI() < m2.getRSSI();}; + //const auto& min = std::min_element(mes.entries.begin(), mes.entries.end(), comp); + + // calculate error for above position using the currently available measurements + for (const WiFiMeasurement& m : mes.entries) { + + // skip non-FHWS APs + if (!LeHelper::isFHWS_AP(m.getAP().getMAC())) {continue;} + + // get model's rssi for the given location + const float rssi_model = wiModel->getRSSI(m.getAP().getMAC(), pos_m); + + // skip APs unknown to the model + if (rssi_model != rssi_model) { + std::cout << "unknown ap: " << m.getAP().getMAC().asString() << std::endl; + continue; + } + + // get scan's rssi + const float rssi_scan = m.getRSSI(); + + ++cnt; + error += std::pow(std::abs(rssi_scan - rssi_model),2); + + } + + if (cnt == 0) {return 1e-50;} + double errorAvg = std::pow((error / cnt), 1.0/2.0); + double prob = Distribution::Normal::getProbability(0, 4, errorAvg); + const double err = -prob; + return err; + + } + double getVeto(const Point3& pos_m, const WiFiMeasurements& obs) const { diff --git a/wifi/EvalWiFiPaths.h b/wifi/EvalWiFiPaths.h old mode 100644 new mode 100755 index 5152882..29d6176 --- a/wifi/EvalWiFiPaths.h +++ b/wifi/EvalWiFiPaths.h @@ -95,7 +95,9 @@ public: pef.getPlot().getKey().setPosition(K::GnuplotKey::Hor::RIGHT, K::GnuplotKey::Ver::BOTTOM); pef.getPlot().getKey().setWidthIncrement(7); pef.getPlot().getAxisY().setLabelOffset(2.5, 0); - pef.getPlot().getAxisY().setTicsStep(0, 25, 95); + //pef.getPlot().getAxisY().setTicsStep(0, 25, 95); + pef.getPlot().getAxisY().setTicsStep({0, 25, 50, 75, 95}); + pef.getPlot().getAxisX().setTicsLabelFormat("%h m"); // CHECK! // MANUAL AXIS RANGE SETTINGS pef.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0,25));