current code and TeX. code fine?!?!?!
This commit is contained in:
@@ -58,7 +58,7 @@ ADD_DEFINITIONS(
|
|||||||
-fstack-protector-all
|
-fstack-protector-all
|
||||||
|
|
||||||
-g3
|
-g3
|
||||||
-O0
|
-O2
|
||||||
-march=native
|
-march=native
|
||||||
|
|
||||||
-DWITH_TESTS
|
-DWITH_TESTS
|
||||||
|
|||||||
0
EvalApOpt.h
Normal file → Executable file
0
EvalApOpt.h
Normal file → Executable file
0
EvalCompareOpt.h
Normal file → Executable file
0
EvalCompareOpt.h
Normal file → Executable file
9
EvalCompareOpt2.h
Normal file → Executable file
9
EvalCompareOpt2.h
Normal file → Executable file
@@ -317,6 +317,15 @@ public:
|
|||||||
const MACAddress mac(ap->mac);
|
const MACAddress mac(ap->mac);
|
||||||
const std::vector<WiFiFingerprint> fps = getFingerprints(mac);
|
const std::vector<WiFiFingerprint> 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
|
// resulting error
|
||||||
auto errFunc = [&] (const Point3 pos_m, const float txp, const float exp, const float waf) -> K::Statistics<float> {
|
auto errFunc = [&] (const Point3 pos_m, const float txp, const float exp, const float waf) -> K::Statistics<float> {
|
||||||
WiFiModelLogDistCeiling model(map); // new, empty model for this AP
|
WiFiModelLogDistCeiling model(map); // new, empty model for this AP
|
||||||
|
|||||||
0
EvalData.h
Normal file → Executable file
0
EvalData.h
Normal file → Executable file
0
EvalWiFiSigStrength.h
Normal file → Executable file
0
EvalWiFiSigStrength.h
Normal file → Executable file
0
EvalWifiOptResult.h
Normal file → Executable file
0
EvalWifiOptResult.h
Normal file → Executable file
19
Settings.h
Normal file → Executable file
19
Settings.h
Normal file → Executable file
@@ -6,10 +6,11 @@
|
|||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
||||||
const std::string pathData = "/apps/android/workspace/OTHER2017/data/";
|
const std::string pathbase = "/mnt/vm/paper/OTHER2017/";
|
||||||
const std::string pathWalks = "/apps/android/workspace/OTHER2017/data/";
|
const std::string pathData = pathbase + "/data/";
|
||||||
const std::string pathWalksToni = "/apps/android/workspace/OTHER2017/data/toni/";
|
const std::string pathWalks = pathbase + "/data/";
|
||||||
const std::string pathWiFi = "/apps/android/workspace/OTHER2017/data/wifi/";
|
const std::string pathWalksToni = pathbase + "/data/toni/";
|
||||||
|
const std::string pathWiFi = pathbase + "/data/wifi/";
|
||||||
|
|
||||||
// GPS walks
|
// GPS walks
|
||||||
const std::string path1a = pathWalks + "path1/1490208103510.csv";
|
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 wifiEachOptParPos_perBBox = pathWiFi + "eachOptParPos_perBBox.xml";
|
||||||
|
|
||||||
|
|
||||||
const std::string fMap = "/apps/android/workspace/IndoorMap/maps/SHL38_no_elev.xml";
|
const std::string fMap = pathbase + "/data/SHL38_no_elev.xml";
|
||||||
const std::string fCalib = "/apps/android/workspace/OTHER2017/data/wifi_fp_all.dat";
|
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;
|
float smartphoneAboveGround = 1.3;
|
||||||
|
|
||||||
namespace IMU {
|
namespace IMU {
|
||||||
const float turnSigma = 1.25;//1.5;
|
const float turnSigma = 1.25;//1.5;
|
||||||
const float stepLength = 0.70+0.3;
|
const float stepLength = 0.70+0.3;
|
||||||
const float stepSigma = 0.10;
|
const float stepSigma = 0.15 + 0.10;
|
||||||
const float absHeadSigma = 20;
|
const float absHeadSigma = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
TestMapEarthReg.h
Normal file → Executable file
0
TestMapEarthReg.h
Normal file → Executable file
231
main.cpp
Normal file → Executable file
231
main.cpp
Normal file → Executable file
@@ -248,7 +248,7 @@ void errorPlotAllModels(Floorplan::IndoorMap* map) {
|
|||||||
|
|
||||||
std::vector<K::Statistics<float>> errors = errorStatAllModels(map);
|
std::vector<K::Statistics<float>> errors = errorStatAllModels(map);
|
||||||
|
|
||||||
PlotErrFunc plot("", "fingerprints (%)");
|
PlotErrFunc plot("", "reference measurements (%)");
|
||||||
plot.getPlot().getAxisX().setTicsLabelFormat("%h dB");
|
plot.getPlot().getAxisX().setTicsLabelFormat("%h dB");
|
||||||
plot.add("\\noOptEmpiric{}", &errors[0]);
|
plot.add("\\noOptEmpiric{}", &errors[0]);
|
||||||
plot.add("\\optParamsAllAP{}", &errors[1]);
|
plot.add("\\optParamsAllAP{}", &errors[1]);
|
||||||
@@ -275,14 +275,15 @@ void errorPlotAllModels(Floorplan::IndoorMap* map) {
|
|||||||
// plot.getGP() << "set rmargin 0.2\n";
|
// plot.getGP() << "set rmargin 0.2\n";
|
||||||
// plot.getGP() << "set bmargin 1.9\n";
|
// plot.getGP() << "set bmargin 1.9\n";
|
||||||
plot.getPlot().getMargin().set(4.2, 0.2, 0.1, 1.9);
|
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().setStringMod(new K::GnuplotStringModLaTeX());
|
||||||
plot.getPlot().getKey().setSampleLength(0.5);
|
plot.getPlot().getKey().setSampleLength(0.5);
|
||||||
plot.getPlot().getKey().setWidthIncrement(+7.0);
|
plot.getPlot().getKey().setWidthIncrement(+7.0);
|
||||||
|
|
||||||
plot.setYRange(0, 95, 5);
|
plot.setYRange(0, 95, 5);
|
||||||
plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 100));
|
plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 95));
|
||||||
plot.getPlot().getAxisY().setTicsStep(0, 25, 100);
|
//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.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 4.0));
|
||||||
plot.getPlot().getAxisX().setTicsStep(4); // 4dB
|
plot.getPlot().getAxisX().setTicsStep(4); // 4dB
|
||||||
plot.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0, 16));
|
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 */
|
/** error plot for the given stats. used for fingerprint errors */
|
||||||
void errorPlotNumFingerprints(const std::vector<K::Statistics<float>>& stats, const std::vector<std::string>& titles, const std::string& name) {
|
void errorPlotNumFingerprints(const std::vector<K::Statistics<float>>& stats, const std::vector<std::string>& titles, const std::string& name) {
|
||||||
|
|
||||||
PlotErrFunc plot("", "fingerprints (%)");
|
PlotErrFunc plot("", "ref. measurements (%)");
|
||||||
plot.getPlot().getAxisX().setTicsLabelFormat("%h dB");
|
plot.getPlot().getAxisX().setTicsLabelFormat("%h dB");
|
||||||
|
|
||||||
plot.getPlot().getKey().setVisible(true);
|
plot.getPlot().getKey().setVisible(true);
|
||||||
@@ -335,22 +336,26 @@ void errorPlotNumFingerprints(const std::vector<K::Statistics<float>>& stats, co
|
|||||||
// plot.getGP() << "set rmargin 0.2\n";
|
// plot.getGP() << "set rmargin 0.2\n";
|
||||||
// plot.getGP() << "set bmargin 1.9\n";
|
// plot.getGP() << "set bmargin 1.9\n";
|
||||||
plot.getPlot().getMargin().set(4.2, 0.2, 0.1, 1.9);
|
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().setStringMod(new K::GnuplotStringModLaTeX());
|
||||||
plot.getPlot().getKey().setSampleLength(0.5);
|
plot.getPlot().getKey().setSampleLength(0.5);
|
||||||
plot.getPlot().getKey().setWidthIncrement(-5.0);
|
plot.getPlot().getKey().setWidthIncrement(-5.0);
|
||||||
|
|
||||||
plot.setYRange(0, 90, 5);
|
plot.setYRange(0, 90, 5);
|
||||||
plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 100));
|
plot.getPlot().getAxisY().setRange(K::GnuplotAxis::Range(0, 90));
|
||||||
plot.getPlot().getAxisY().setTicsStep(0, 25, 100);
|
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.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 3.3));
|
||||||
plot.getPlot().getAxisX().setTicsStep(4); // 4dB
|
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.getGP().setOutput(Settings::fPathGFX + "/" + name + "_0_90.tex");
|
||||||
plot.writePlotToFile(Settings::fPathGFX + "/" + name + "_0_90.gp");
|
plot.writePlotToFile(Settings::fPathGFX + "/" + name + "_0_90.gp");
|
||||||
plot.plot();
|
plot.plot();
|
||||||
|
|
||||||
|
// changes
|
||||||
plot.getPlot().getKey().setVisible(false);
|
plot.getPlot().getKey().setVisible(false);
|
||||||
|
plot.getPlot().getAxisY().setLabel("");
|
||||||
|
|
||||||
plot.setYRange(90, 100, 1);
|
plot.setYRange(90, 100, 1);
|
||||||
plot.getPlot().getAxisY().setTicsStep(2);
|
plot.getPlot().getAxisY().setTicsStep(2);
|
||||||
plot.getGP().setTerminal("epslatex", K::GnuplotSize(8.6, 2.6));
|
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
|
// build plots for the paper
|
||||||
void paperOutputs() {
|
void paperOutputs() {
|
||||||
|
|
||||||
@@ -666,13 +673,15 @@ void paperOutputs() {
|
|||||||
// perform varios AP-param optimizations
|
// perform varios AP-param optimizations
|
||||||
// generate error plot showing the performance of each
|
// generate error plot showing the performance of each
|
||||||
// save the resulting wifi-models to XML for later re-use during the walk-eval <<<<<< !!!!
|
// save the resulting wifi-models to XML for later re-use during the walk-eval <<<<<< !!!!
|
||||||
if (1 == 0) {
|
if (1 == 1) {
|
||||||
rebuildAllModels(map, 0);
|
rebuildAllModels(map, 0);
|
||||||
/** detailled error analysis for above optimization routine */
|
/** detailled error analysis for above optimization routine */
|
||||||
|
|
||||||
errorPlotAllModels(map);
|
errorPlotAllModels(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// leaving out fingerprints and the effects on all optimization strategies
|
||||||
if (1 == 0) {
|
if (1 == 0) {
|
||||||
|
|
||||||
rebuildAllModels(map,4);
|
rebuildAllModels(map,4);
|
||||||
@@ -686,6 +695,13 @@ void paperOutputs() {
|
|||||||
|
|
||||||
// analyze all 5 opt strategies. skip the empiric one: stats0[0]
|
// analyze all 5 opt strategies. skip the empiric one: stats0[0]
|
||||||
for (int i = 1; i < 6; ++i) {
|
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);
|
std::string name = "wifi_model_error_num_fingerprints_method_" + std::to_string(i);
|
||||||
errorPlotNumFingerprints(
|
errorPlotNumFingerprints(
|
||||||
{stats0[0], stats4[i], stats2[i], stats0[i], statsNoStairs[i]},
|
{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
|
// // error histogram all pos, all params, between in/out/stair, in/out, in/stair, in
|
||||||
if(1==0){
|
// if(1==0){
|
||||||
|
|
||||||
EvalCompareOpt e1(Settings::fMap, Settings::fCalib, false, false, false);
|
// EvalCompareOpt e1(Settings::fMap, Settings::fCalib, false, false, false);
|
||||||
EvalCompareOpt e2(Settings::fMap, Settings::fCalib, true, false, false);
|
// EvalCompareOpt e2(Settings::fMap, Settings::fCalib, true, false, false);
|
||||||
EvalCompareOpt e3(Settings::fMap, Settings::fCalib, false, true, false);
|
// EvalCompareOpt e3(Settings::fMap, Settings::fCalib, false, true, false);
|
||||||
EvalCompareOpt e4(Settings::fMap, Settings::fCalib, true, true, false);
|
// EvalCompareOpt e4(Settings::fMap, Settings::fCalib, true, true, false);
|
||||||
|
|
||||||
K::Statistics<float> s1 = e1.optPosOptParamsForEach().errAbs;
|
// K::Statistics<float> s1 = e1.optPosOptParamsForEach().errAbs;
|
||||||
K::Statistics<float> s2 = e2.optPosOptParamsForEach().errAbs;
|
// K::Statistics<float> s2 = e2.optPosOptParamsForEach().errAbs;
|
||||||
K::Statistics<float> s3 = e3.optPosOptParamsForEach().errAbs;
|
// K::Statistics<float> s3 = e3.optPosOptParamsForEach().errAbs;
|
||||||
K::Statistics<float> s4 = e4.optPosOptParamsForEach().errAbs;
|
// K::Statistics<float> s4 = e4.optPosOptParamsForEach().errAbs;
|
||||||
|
|
||||||
PlotErrFunc pef("\\small{error (dB)}", "\\small{fingerprints (\\%)}");
|
// PlotErrFunc pef("\\small{error (dB)}", "\\small{fingerprints (\\%)}");
|
||||||
pef.add("\\small{floor + stairs + out}", &s1);
|
// pef.add("\\small{floor + stairs + out}", &s1);
|
||||||
pef.add("\\small{floor + out}", &s2);
|
// pef.add("\\small{floor + out}", &s2);
|
||||||
pef.add("\\small{floor + stairs}", &s3);
|
// pef.add("\\small{floor + stairs}", &s3);
|
||||||
pef.add("\\small{floor}", &s4);
|
// pef.add("\\small{floor}", &s4);
|
||||||
|
|
||||||
pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.5, 5));
|
// pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.5, 5));
|
||||||
pef.getGP().setOutput(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.tex");
|
// pef.getGP().setOutput(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.tex");
|
||||||
pef.writePlotToFile(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.gp");
|
// pef.writePlotToFile(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.gp");
|
||||||
pef.getGP() << "set key right bottom width -3\n";
|
// pef.getGP() << "set key right bottom width -3\n";
|
||||||
pef.getGP() << "set rmargin 0.4\n";
|
// pef.getGP() << "set rmargin 0.4\n";
|
||||||
pef.getGP() << "set tmargin 0.4\n";
|
// pef.getGP() << "set tmargin 0.4\n";
|
||||||
pef.plot();
|
// 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::Gnuplot gp;
|
||||||
K::GnuplotPlot gplot;
|
K::GnuplotPlot gplot;
|
||||||
K::GnuplotPlotElementLines lines; gplot.add(&lines);
|
K::GnuplotPlotElementLines lines; gplot.add(&lines);
|
||||||
|
K::GnuplotPlotElementLines ceils; gplot.add(&ceils);
|
||||||
|
|
||||||
const Point3 posAP(0, 0, 8);
|
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) {
|
for (float z = 0; z < 15; z += 0.1) {
|
||||||
|
|
||||||
const Point3 posMe(0, 0, z);
|
const Point3 posMe(0, 0, z);
|
||||||
|
//float factor = ceilings.numCeilingsBetweenLinearInt(posAP, posMe);
|
||||||
float factor = ceilings.numCeilingsBetweenFloat(posAP, posMe);
|
float factor = ceilings.numCeilingsBetweenFloat(posAP, posMe);
|
||||||
|
|
||||||
lines.add({z, factor});
|
lines.add({z, factor});
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -813,7 +810,7 @@ void testWAF() {
|
|||||||
gp.draw(gplot);
|
gp.draw(gplot);
|
||||||
gp.flush();
|
gp.flush();
|
||||||
|
|
||||||
sleep(1000);
|
sleep(10);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -900,6 +897,10 @@ int main(void) {
|
|||||||
Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);
|
Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);
|
||||||
|
|
||||||
//testWAF();
|
//testWAF();
|
||||||
|
//sleep(1);
|
||||||
|
|
||||||
|
//const float rssi = LogDistanceModel::distanceToRssi(-100, 0, 999);
|
||||||
|
//int i = 0; (void) i;
|
||||||
|
|
||||||
//paperOutputs(); return 0;
|
//paperOutputs(); return 0;
|
||||||
|
|
||||||
@@ -908,11 +909,41 @@ int main(void) {
|
|||||||
//showFingerprintsFor(Settings::fMap, Settings::fCalib, "D8:84:66:4A:4A:E0");
|
//showFingerprintsFor(Settings::fMap, Settings::fCalib, "D8:84:66:4A:4A:E0");
|
||||||
//showModelFor(Settings::fMap, Settings::wifiEachOptParPos_multimodel, "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);
|
plotEstAndRealApPosDistance(map);
|
||||||
int i = 0; (void) i;
|
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
|
// calib error in/out
|
||||||
if (1 == 0) {
|
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) {
|
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::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;
|
int i = 0; (void) i;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// walks
|
// walks
|
||||||
if (1 == 0) {
|
if (1 == 1) {
|
||||||
Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);;
|
Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);;
|
||||||
EvalWalk walk(map);
|
//EvalWalk walk(map);
|
||||||
walk.walk1();
|
//walk.walk1();
|
||||||
|
EvalWalk::walkEverything(map);
|
||||||
|
EvalWalk::walkEverythingBuildStats(map);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,21 +1109,24 @@ int main(void) {
|
|||||||
|
|
||||||
std::cout << "num scans: " << numScans << std::endl;
|
std::cout << "num scans: " << numScans << std::endl;
|
||||||
|
|
||||||
|
if (1 == 1) {
|
||||||
|
|
||||||
EvalWiFiPaths ewp(Settings::fMap);
|
EvalWiFiPaths ewp(Settings::fMap);
|
||||||
ewp.loadModel(Settings::wifiAllFixed, "\\noOptEmpiric{}");
|
ewp.loadModel(Settings::wifiAllFixed, "\\noOptEmpiric{}");
|
||||||
ewp.walks(files, gtIndices);
|
ewp.walks(files, gtIndices);
|
||||||
|
|
||||||
ewp.loadModel(Settings::wifiEachOptParPos, "\\optParamsPosEachAP{}");
|
ewp.loadModel(Settings::wifiEachOptParPos, "\\optParamsPosEachAP{}");
|
||||||
ewp.walks(files, gtIndices);
|
ewp.walks(files, gtIndices);
|
||||||
|
|
||||||
ewp.loadModel(Settings::wifiEachOptParPos_multimodel, "\\optPerFloor{}");
|
ewp.loadModel(Settings::wifiEachOptParPos_multimodel, "\\optPerFloor{}");
|
||||||
ewp.walks(files, gtIndices);
|
ewp.walks(files, gtIndices);
|
||||||
|
|
||||||
ewp.loadModel(Settings::wifiEachOptParPos_perBBox, "\\optPerRegion{}");
|
ewp.loadModel(Settings::wifiEachOptParPos_perBBox, "\\optPerRegion{}");
|
||||||
ewp.walks(files, gtIndices);
|
ewp.walks(files, gtIndices);
|
||||||
|
|
||||||
ewp.writeGP(Settings::fPathGFX, "modelPerformance");
|
ewp.writeGP(Settings::fPathGFX, "modelPerformance");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// examine various modifications
|
// examine various modifications
|
||||||
if (1 == 0) {
|
if (1 == 0) {
|
||||||
@@ -1114,27 +1157,27 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// compare wifi opt methods
|
// // compare wifi opt methods
|
||||||
if (1 == 0) {
|
// if (1 == 0) {
|
||||||
|
|
||||||
const bool ignoreStaircases = false;
|
// const bool ignoreStaircases = false;
|
||||||
const bool ignoreOutdoor = false;
|
// const bool ignoreOutdoor = false;
|
||||||
const bool ignoreIndoor = false;
|
// const bool ignoreIndoor = false;
|
||||||
EvalCompareOpt opt(Settings::fMap, Settings::fCalib, ignoreStaircases, ignoreOutdoor, ignoreIndoor);
|
// EvalCompareOpt opt(Settings::fMap, Settings::fCalib, ignoreStaircases, ignoreOutdoor, ignoreIndoor);
|
||||||
|
|
||||||
EvalCompareOpt::Result s1 = opt.fixedPosFixedParamsForAll(); //BREAK;
|
// EvalCompareOpt::Result s1 = opt.fixedPosFixedParamsForAll(); //BREAK;
|
||||||
EvalCompareOpt::Result s2 = opt.fixedPosOptParamsForAll(); //BREAK;
|
// EvalCompareOpt::Result s2 = opt.fixedPosOptParamsForAll(); //BREAK;
|
||||||
EvalCompareOpt::Result s3 = opt.fixedPosOptParamsForEach(); //BREAK;
|
// EvalCompareOpt::Result s3 = opt.fixedPosOptParamsForEach(); //BREAK;
|
||||||
EvalCompareOpt::Result s4 = opt.optPosOptParamsForEach(); //BREAK;
|
// EvalCompareOpt::Result s4 = opt.optPosOptParamsForEach(); //BREAK;
|
||||||
|
|
||||||
PlotErrFunc pef("error (dB)", "fingerprints (%)");
|
// PlotErrFunc pef("error (dB)", "fingerprints (%)");
|
||||||
pef.add("empiric", &s1.errAbs);
|
// pef.add("empiric", &s1.errAbs);
|
||||||
pef.add("real pos, opt params [same for all]", &s2.errAbs);
|
// pef.add("real pos, opt params [same for all]", &s2.errAbs);
|
||||||
pef.add("real pos, opt params [for each]", &s3.errAbs);
|
// pef.add("real pos, opt params [for each]", &s3.errAbs);
|
||||||
pef.add("opt pos, opt params [for each]", &s4.errAbs);
|
// pef.add("opt pos, opt params [for each]", &s4.errAbs);
|
||||||
pef.plot();
|
// pef.plot();
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
// compare leaving out fingerprints
|
// compare leaving out fingerprints
|
||||||
if (1 == 0) {
|
if (1 == 0) {
|
||||||
|
|||||||
0
old/main.h
Normal file → Executable file
0
old/main.h
Normal file → Executable file
398
pf/EvalWalk.h
Normal file → Executable file
398
pf/EvalWalk.h
Normal file → Executable file
@@ -44,6 +44,15 @@
|
|||||||
#include <Indoor/sensors/offline/FileReader.h>
|
#include <Indoor/sensors/offline/FileReader.h>
|
||||||
#include <Indoor/sensors/offline/Listener.h>
|
#include <Indoor/sensors/offline/Listener.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PLOT_LIVE
|
||||||
|
//#define PLOT_WIFI
|
||||||
|
//#define PLOT_ERROR_TIME
|
||||||
|
//#define PLOT_ERROR_FUNC
|
||||||
|
|
||||||
|
#define PLOT_UPDATE_STEP 20
|
||||||
|
|
||||||
|
|
||||||
class EvalWalk : public Offline::Listener {
|
class EvalWalk : public Offline::Listener {
|
||||||
|
|
||||||
Grid<MyGridNode>* grid;
|
Grid<MyGridNode>* grid;
|
||||||
@@ -53,6 +62,8 @@ class EvalWalk : public Offline::Listener {
|
|||||||
|
|
||||||
Plotty plotty;
|
Plotty plotty;
|
||||||
PlotWifiMeasurements plotWifi;
|
PlotWifiMeasurements plotWifi;
|
||||||
|
PlotErrTime pet;
|
||||||
|
PlotErrFunc pef;
|
||||||
|
|
||||||
Offline::FileReader reader;
|
Offline::FileReader reader;
|
||||||
Offline::FilePlayer player;
|
Offline::FilePlayer player;
|
||||||
@@ -74,11 +85,15 @@ class EvalWalk : public Offline::Listener {
|
|||||||
|
|
||||||
EarthMapping em;
|
EarthMapping em;
|
||||||
|
|
||||||
|
std::string walkName;
|
||||||
|
|
||||||
float absHead = 0;
|
float absHead = 0;
|
||||||
|
|
||||||
public:
|
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";
|
const std::string saveFile = Settings::pathData + "/grid.dat";
|
||||||
grid = new Grid<MyGridNode>(Settings::Grid::gridSize_cm);
|
grid = new Grid<MyGridNode>(Settings::Grid::gridSize_cm);
|
||||||
@@ -108,8 +123,8 @@ public:
|
|||||||
pf->setTransition( std::unique_ptr<PFTrans>( new PFTrans(grid)) );
|
pf->setTransition( std::unique_ptr<PFTrans>( new PFTrans(grid)) );
|
||||||
|
|
||||||
// resampling step?
|
// resampling step?
|
||||||
//pf->setNEffThreshold(0.15);
|
pf->setNEffThreshold(0.02);
|
||||||
//pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingSimple<MyState>>(new K::ParticleFilterResamplingSimple<MyState>()) );
|
pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingSimple<MyState>>(new K::ParticleFilterResamplingSimple<MyState>()) );
|
||||||
|
|
||||||
//pf->setNEffThreshold(0.75);
|
//pf->setNEffThreshold(0.75);
|
||||||
//pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingPercent<MyState>>(new K::ParticleFilterResamplingPercent<MyState>(0.10)) );
|
//pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingPercent<MyState>>(new K::ParticleFilterResamplingPercent<MyState>(0.10)) );
|
||||||
@@ -117,9 +132,9 @@ public:
|
|||||||
//pf->setNEffThreshold(0.75);
|
//pf->setNEffThreshold(0.75);
|
||||||
//pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingPercent<MyState>>(new K::ParticleFilterResamplingPercent<MyState>(0.05)) );
|
//pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingPercent<MyState>>(new K::ParticleFilterResamplingPercent<MyState>(0.05)) );
|
||||||
|
|
||||||
K::ParticleFilterResamplingNEff<MyState>* res = new K::ParticleFilterResamplingNEff<MyState>(0.75, 0.05);
|
// K::ParticleFilterResamplingNEff<MyState>* res = new K::ParticleFilterResamplingNEff<MyState>(0.75, 0.05);
|
||||||
pf->setNEffThreshold(1.0);
|
// pf->setNEffThreshold(1.0);
|
||||||
pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingNEff<MyState>>(res) );
|
// pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingNEff<MyState>>(res) );
|
||||||
|
|
||||||
// move during resampling. NOT ALLOWED!
|
// move during resampling. NOT ALLOWED!
|
||||||
// res->setDrawCallback([&] (K::Particle<MyState>& p) {
|
// res->setDrawCallback([&] (K::Particle<MyState>& p) {
|
||||||
@@ -145,6 +160,211 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LeWalk {
|
||||||
|
std::string name;
|
||||||
|
float absHead;
|
||||||
|
std::string walkFile;
|
||||||
|
std::vector<int> gtIndices;
|
||||||
|
LeWalk(const std::string& name, float absHead, std::string walkFile, std::vector<int> 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<float>& 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<float>* 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<float>* res = new K::Statistics<float>();
|
||||||
|
std::ifstream inp(file);
|
||||||
|
while(inp) {
|
||||||
|
float f;
|
||||||
|
inp >> f;
|
||||||
|
res->add(f);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<LeWalk> 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<LeModel> 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<LeWalk> walks = allWalks();
|
||||||
|
const std::vector<LeModel> models = allModels(map);
|
||||||
|
|
||||||
|
PlotErrFunc* pefAll = new PlotErrFunc();
|
||||||
|
int numStuck = 0;
|
||||||
|
int numTotal = 0;
|
||||||
|
|
||||||
|
for (const LeModel& mdl : models) {
|
||||||
|
|
||||||
|
K::Statistics<float>* modelStatsAvg = new K::Statistics<float>();
|
||||||
|
K::Statistics<float>* modelStatsMed = new K::Statistics<float>();
|
||||||
|
|
||||||
|
K::Statistics<float>* modelStatsSingle = new K::Statistics<float>();
|
||||||
|
pefAll->add(mdl.name, modelStatsSingle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ... to perform every walk...
|
||||||
|
for (const LeWalk& walk : walks) {
|
||||||
|
|
||||||
|
for (int i = 0; i < numRepeats; ++i) {
|
||||||
|
|
||||||
|
++numTotal;
|
||||||
|
K::Statistics<float>* 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<LeWalk> walks = allWalks();
|
||||||
|
const std::vector<LeModel> models = allModels(map);
|
||||||
|
|
||||||
|
PlotErrFunc* pefAll = new PlotErrFunc();
|
||||||
|
|
||||||
|
// use every model ...
|
||||||
|
for (const LeModel& mdl : models) {
|
||||||
|
|
||||||
|
K::Statistics<float>* modelStatsSingle = new K::Statistics<float>();
|
||||||
|
pefAll->add(mdl.name, modelStatsSingle);
|
||||||
|
|
||||||
|
// ... to perform every walk...
|
||||||
|
for (const LeWalk& walk : walks) {
|
||||||
|
|
||||||
|
//K::Statistics<float> curWalkRepeatStatsAvg;
|
||||||
|
//K::Statistics<float> 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<PFEval> eval = std::unique_ptr<PFEval>( 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() {
|
void walk1() {
|
||||||
|
|
||||||
// path1
|
// path1
|
||||||
@@ -211,7 +431,7 @@ public:
|
|||||||
++curCtrl.numStepsSinceLastTransition;
|
++curCtrl.numStepsSinceLastTransition;
|
||||||
}
|
}
|
||||||
gotSensorData(ts);
|
gotSensorData(ts);
|
||||||
curCtrl.activityNew = actDetect.add(ts, data);
|
actDetect.add(ts, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onGravity(const Timestamp ts, const GravityData data) override {
|
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 {
|
virtual void onWiFi(const Timestamp ts, const WiFiMeasurements data) override {
|
||||||
std::cout << "WIFI" << std::endl;
|
|
||||||
curObs.wifi = data;
|
curObs.wifi = data;
|
||||||
|
//curObs.wifi = WiFiMeasurements::mix(curObs.wifi, data);
|
||||||
|
#ifdef PLOT_WIFI
|
||||||
plotWifi.add(Settings::WiFiModel::vg_eval.group(data));
|
plotWifi.add(Settings::WiFiModel::vg_eval.group(data));
|
||||||
plotWifi.plot();
|
plotWifi.plot();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onBarometer(const Timestamp ts, const BarometerData data) override {
|
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 {
|
virtual void onGPS(const Timestamp ts, const GPSData data) override {
|
||||||
@@ -300,12 +524,48 @@ private:
|
|||||||
return set.size();
|
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) */
|
/** perform a filter-update (called from a background-loop) */
|
||||||
void filterUpdate() {
|
void filterUpdate() {
|
||||||
|
|
||||||
++updateCount;
|
++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);
|
pef.showMarkers(true, true);
|
||||||
|
|
||||||
std::cout << "update" << std::endl;
|
std::cout << "update" << std::endl;
|
||||||
@@ -319,22 +579,23 @@ private:
|
|||||||
|
|
||||||
const Point3 curGT = groundTruthLive.get(lastTransition);
|
const Point3 curGT = groundTruthLive.get(lastTransition);
|
||||||
|
|
||||||
plotty.setCurEst(curEst.position.inMeter());
|
// start the error-over-time plot after some filter updates
|
||||||
plotty.setGroundTruth(curGT);
|
if (updateCount > 12) {
|
||||||
|
|
||||||
if (updateCount > 4) {
|
|
||||||
|
|
||||||
// error between ground-truth and estimation
|
// error between ground-truth and estimation
|
||||||
const float estRealErr = curEst.position.inMeter().getDistance(curGT);
|
const float estRealErr = curEst.position.inMeter().getDistance(curGT);
|
||||||
statsErr.add(estRealErr);
|
statsErr.add(estRealErr);
|
||||||
|
|
||||||
|
#ifdef PLOT_ERROR_FUNC
|
||||||
pef.clear();
|
pef.clear();
|
||||||
pef.add("", &statsErr);
|
pef.add("", &statsErr);
|
||||||
pef.plot();
|
#endif
|
||||||
|
|
||||||
|
#ifdef PLOT_ERROR_TIME
|
||||||
// timed error
|
// timed error
|
||||||
pet.addErr(lastTransition, estRealErr);
|
pet.addErr(lastTransition, estRealErr);
|
||||||
pet.addB(lastTransition, getNumFHWSAPs(curObs.wifi));
|
pet.addB(lastTransition, getNumFHWSAPs(curObs.wifi));
|
||||||
pet.plot();
|
#endif
|
||||||
|
|
||||||
// update estimated path
|
// update estimated path
|
||||||
const K::GnuplotPoint3 p3(curEst.position.x_cm, curEst.position.y_cm, curEst.position.z_cm);
|
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
|
// 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();
|
curCtrl.resetAfterTransition();
|
||||||
|
|
||||||
|
|||||||
98
pf/PF.h
Normal file → Executable file
98
pf/PF.h
Normal file → Executable file
@@ -98,7 +98,8 @@ struct MyObservation {
|
|||||||
|
|
||||||
// TODO: switch to a general activity enum/detector for barometer + accelerometer + ...?
|
// TODO: switch to a general activity enum/detector for barometer + accelerometer + ...?
|
||||||
/** detected activity */
|
/** detected activity */
|
||||||
ActivityButterPressure::Activity activity;
|
//ActivityButterPressure::Activity activity;
|
||||||
|
Activity activityNew = Activity::STANDING;
|
||||||
|
|
||||||
/** time of evaluation */
|
/** time of evaluation */
|
||||||
Timestamp currentTime;
|
Timestamp currentTime;
|
||||||
@@ -119,9 +120,9 @@ struct MyControl {
|
|||||||
|
|
||||||
// TODO: switch to a general activity enum/detector using barometer + accelerometer?
|
// TODO: switch to a general activity enum/detector using barometer + accelerometer?
|
||||||
/** currently detected activity */
|
/** 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 */
|
/** reset the control-data after each transition */
|
||||||
void resetAfterTransition() {
|
void resetAfterTransition() {
|
||||||
@@ -150,8 +151,10 @@ public:
|
|||||||
std::uniform_real_distribution<float> distHead(0, 2*M_PI);
|
std::uniform_real_distribution<float> distHead(0, 2*M_PI);
|
||||||
|
|
||||||
for (K::Particle<MyState>& p : particles) {
|
for (K::Particle<MyState>& p : particles) {
|
||||||
const int idx = distIdx(gen);
|
again:
|
||||||
const MyGridNode& node = (*grid)[idx];
|
const int idx = distIdx(gen);
|
||||||
|
const MyGridNode& node = (*grid)[idx];
|
||||||
|
if (node.getNumNeighbors() != 8) {goto again;}
|
||||||
p.state.position = node; // random position
|
p.state.position = node; // random position
|
||||||
p.state.heading.direction = Heading(distHead(gen)); // random heading
|
p.state.heading.direction = Heading(distHead(gen)); // random heading
|
||||||
p.weight = 1.0 / particles.size(); // equal weight
|
p.weight = 1.0 / particles.size(); // equal weight
|
||||||
@@ -174,7 +177,7 @@ public:
|
|||||||
WalkModuleFavorZ<MyGridNode, MyState> modFavorZ;
|
WalkModuleFavorZ<MyGridNode, MyState> modFavorZ;
|
||||||
WalkModuleNodeImportance<MyGridNode, MyState> modImportance;
|
WalkModuleNodeImportance<MyGridNode, MyState> modImportance;
|
||||||
WalkModuleFollowDestination<MyGridNode, MyState> modDestination;
|
WalkModuleFollowDestination<MyGridNode, MyState> modDestination;
|
||||||
WalkModuleActivityControl<MyGridNode, MyState, MyControl> modActivity;
|
//WalkModuleActivityControl<MyGridNode, MyState, MyControl> modActivity;
|
||||||
|
|
||||||
WalkModuleHeadingControl<MyGridNode, MyState, MyControl> modRelHead;
|
WalkModuleHeadingControl<MyGridNode, MyState, MyControl> modRelHead;
|
||||||
WalkModuleAbsoluteHeadingControl<MyGridNode, MyState, MyControl> modAbsHead;
|
WalkModuleAbsoluteHeadingControl<MyGridNode, MyState, MyControl> modAbsHead;
|
||||||
@@ -183,7 +186,11 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PFTrans(Grid<MyGridNode>* grid) : grid(grid), modRelHead(&ctrl, Settings::IMU::turnSigma), modAbsHead(&ctrl, Settings::IMU::absHeadSigma), modDestination(*grid), modActivity(&ctrl) {
|
PFTrans(Grid<MyGridNode>* grid) : grid(grid), modRelHead(&ctrl, Settings::IMU::turnSigma),
|
||||||
|
modAbsHead(&ctrl, Settings::IMU::absHeadSigma),
|
||||||
|
modDestination(*grid)
|
||||||
|
//,modActivity(&ctrl)
|
||||||
|
{
|
||||||
|
|
||||||
walker.addModule(&modRelHead);
|
walker.addModule(&modRelHead);
|
||||||
//walker.addModule(&modAbsHead);
|
//walker.addModule(&modAbsHead);
|
||||||
@@ -234,10 +241,9 @@ public:
|
|||||||
K::Particle<MyState>& p = particles[i];
|
K::Particle<MyState>& p = particles[i];
|
||||||
|
|
||||||
// first transitions: more variation as the state is unknown
|
// 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);
|
const MyGridNode* n = grid->getNodePtrFor(p.state.position);
|
||||||
std::normal_distribution<float> distTurn(0, 0.4);
|
|
||||||
|
|
||||||
for (int j = 0; j < 5; ++j) {
|
for (int j = 0; j < 5; ++j) {
|
||||||
std::uniform_int_distribution<int> distIdx(0, n->getNumNeighbors()-1);
|
std::uniform_int_distribution<int> distIdx(0, n->getNumNeighbors()-1);
|
||||||
@@ -246,9 +252,10 @@ public:
|
|||||||
}
|
}
|
||||||
p.state.position = *n;
|
p.state.position = *n;
|
||||||
|
|
||||||
if (numTrans < 50) {
|
if (numTrans < 70) {
|
||||||
p.state.heading.direction += distTurn(gen);
|
std::normal_distribution<float> distTurn(0, 0.3);
|
||||||
dist_m += 0.5;
|
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.state = walker.getDestination(*grid, p.state, dist_m, prob);
|
||||||
p.weight *= prob; // grid-walk-probability
|
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) {
|
if (p.weight != p.weight) {
|
||||||
throw Exception("nan");
|
throw Exception("nan");
|
||||||
}
|
}
|
||||||
@@ -320,14 +332,31 @@ public:
|
|||||||
|
|
||||||
double res = 0;
|
double res = 0;
|
||||||
|
|
||||||
if (angularDiff > Angle::degToRad(90)) {res = 0.05;}
|
if (angularDiff > Angle::degToRad(120)) {res = 0.30;}
|
||||||
else if (angularDiff > Angle::degToRad(45)) {res = 0.25;}
|
else {res = 0.70;}
|
||||||
else {res = 0.70;}
|
|
||||||
|
|
||||||
return res;
|
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;
|
WiFiQualityAnalyzer wqa;
|
||||||
|
|
||||||
double evaluation(std::vector<K::Particle<MyState>>& particles, const MyObservation& _observation) override {
|
double evaluation(std::vector<K::Particle<MyState>>& particles, const MyObservation& _observation) override {
|
||||||
@@ -343,7 +372,9 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
wqa.add(wifiObs);
|
wqa.add(wifiObs);
|
||||||
const float quality = wqa.getQuality();
|
float quality = wqa.getQuality();
|
||||||
|
std::cout << "wifi quality: " << quality << std::endl;
|
||||||
|
|
||||||
|
|
||||||
// GPS
|
// GPS
|
||||||
const GPSProbability gpsProb(em);
|
const GPSProbability gpsProb(em);
|
||||||
@@ -353,7 +384,7 @@ public:
|
|||||||
Assert::equal((int)particles.size(), Settings::numParticles, "number of particles does not match the settings!");
|
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
|
// use (0.9 * p) + (0.1 * (1-p)) for error cases
|
||||||
wiFiProbability.setUseError(false);
|
wiFiProbability.setUseError(true);
|
||||||
|
|
||||||
//#pragma omp parallel for num_threads(3)
|
//#pragma omp parallel for num_threads(3)
|
||||||
for (int i = 0; i < Settings::numParticles; ++i) {
|
for (int i = 0; i < Settings::numParticles; ++i) {
|
||||||
@@ -362,16 +393,15 @@ public:
|
|||||||
|
|
||||||
// WiFi free
|
// WiFi free
|
||||||
double pWiFi = wiFiProbability.getProbability(p.state.position.inMeter()+person, observation.currentTime, wifiObs);
|
double pWiFi = wiFiProbability.getProbability(p.state.position.inMeter()+person, observation.currentTime, wifiObs);
|
||||||
double pWiFiMod = Distribution::Exponential<double>::getProbability(0.20, -std::log(pWiFi));
|
//double pWiFiMod = Distribution::Exponential<double>::getProbability(0.20, -std::log(pWiFi));
|
||||||
double pWiFiVeto = wiFiProbability.getVeto(p.state.position.inMeter()+person, observation.currentTime, wifiObs);
|
//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
|
// WiFi grid
|
||||||
//const MyGridNode& node = grid->getNodeFor(p.state.position);
|
//const MyGridNode& node = grid->getNodeFor(p.state.position);
|
||||||
@@ -379,9 +409,18 @@ public:
|
|||||||
//const double pWiFi = wiFiProbability.getProbability(node, observation.currentTime, wifiObs);
|
//const double pWiFi = wiFiProbability.getProbability(node, observation.currentTime, wifiObs);
|
||||||
|
|
||||||
//const double pStair = 1;//getStairProb(p, observation.activity);
|
//const double pStair = 1;//getStairProb(p, observation.activity);
|
||||||
const double pGPS = gpsProb.getProbability(p.state.position.inMeter(), observation.gps);
|
double pGPS = gpsProb.getProbability(p.state.position.inMeter(), observation.gps);
|
||||||
const double pAbsHead = getAbsHead(p.state, observation);
|
double pAbsHead = getAbsHead(p.state, observation);
|
||||||
const double prob = pWiFi * pWiFiVeto;// * pAbsHead;
|
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?
|
//GPS ERROR?!?!?! does it work without disabling wifi when gps is disabled?
|
||||||
|
|
||||||
@@ -392,6 +431,11 @@ public:
|
|||||||
// TESTING
|
// TESTING
|
||||||
//p.weight = std::pow(p.weight, 0.5);
|
//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; // NOTE: keeps the weight returned by the transition step!
|
||||||
//p.weight = prob; // does NOT keep the weights returned by the transition step
|
//p.weight = prob; // does NOT keep the weights returned by the transition step
|
||||||
|
|
||||||
|
|||||||
5
plots/PlotErrFunc.h
Normal file → Executable file
5
plots/PlotErrFunc.h
Normal file → Executable file
@@ -49,6 +49,11 @@ class PlotErrFunc {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** empty ctor */
|
||||||
|
PlotErrFunc() {
|
||||||
|
setYRange(0, 90, 5);
|
||||||
|
}
|
||||||
|
|
||||||
/** ctor with x-axis label */
|
/** ctor with x-axis label */
|
||||||
PlotErrFunc(const std::string& xLabel, const std::string& yLabel) {
|
PlotErrFunc(const std::string& xLabel, const std::string& yLabel) {
|
||||||
gplot.getAxisX().setLabel(xLabel);
|
gplot.getAxisX().setLabel(xLabel);
|
||||||
|
|||||||
14
plots/PlotErrTime.h
Normal file → Executable file
14
plots/PlotErrTime.h
Normal file → Executable file
@@ -23,6 +23,11 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/** empty ctor */
|
||||||
|
PlotErrTime() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** ctor */
|
/** ctor */
|
||||||
PlotErrTime(const std::string& xLabel, const std::string& yLabel, const std::string& y2Label) {
|
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() {
|
void clear() {
|
||||||
for (int i = 0; i < 8; ++i) {lineErr[i].clear();}
|
for (int i = 0; i < 8; ++i) {lineErr[i].clear();}
|
||||||
lineB.clear();
|
lineB.clear();
|
||||||
|
|||||||
24
plots/PlotWiFiGroundProb.h
Normal file → Executable file
24
plots/PlotWiFiGroundProb.h
Normal file → Executable file
@@ -67,16 +67,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** plot the ground-probability for the given measurement */
|
/** plot the ground-probability for the given measurement */
|
||||||
void show(const WiFiObserverFree& prob, const WiFiMeasurements& _mes) {
|
void show(const WiFiObserverFree& prob, const WiFiMeasurements& mes, const Timestamp ts) {
|
||||||
|
|
||||||
VAPGrouper vap(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE);
|
|
||||||
const WiFiMeasurements mes = vap.group(_mes);
|
|
||||||
|
|
||||||
// determine min/max probability
|
// determine min/max probability
|
||||||
double min = +99999;
|
double min = +99999;
|
||||||
double max = -99999;
|
double max = -99999;
|
||||||
for (Entry& e : pos) {
|
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 < min) {min = p;}
|
||||||
if (p > max) {max = p;}
|
if (p > max) {max = p;}
|
||||||
}
|
}
|
||||||
@@ -84,8 +81,11 @@ public:
|
|||||||
|
|
||||||
// render
|
// render
|
||||||
for (Entry& e : pos) {
|
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);
|
||||||
const double f = (p-min) / diff * 255;
|
double f = (p-min) / diff * 255;
|
||||||
|
if (f < 0) {f = 0;}
|
||||||
|
if (f > 255) {f = 255;}
|
||||||
|
|
||||||
e.sum += p;
|
e.sum += p;
|
||||||
e.cnt++;
|
e.cnt++;
|
||||||
|
|
||||||
@@ -93,10 +93,14 @@ public:
|
|||||||
const K::GnuplotColor c = K::GnuplotColor::fromHSV(0, f, 255);
|
const K::GnuplotColor c = K::GnuplotColor::fromHSV(0, f, 255);
|
||||||
e.poly->getFill().setColor(c);
|
e.poly->getFill().setColor(c);
|
||||||
e.max = f;
|
e.max = f;
|
||||||
|
|
||||||
|
e.poly->setEnabled(f > 32);
|
||||||
//}
|
//}
|
||||||
if (f < 0.1) {
|
// if (f < 32) {
|
||||||
e.poly->setEnabled(false);
|
// e.poly->setEnabled(false);
|
||||||
}
|
// } else {
|
||||||
|
// e.poly->setEnabled(true);
|
||||||
|
// }
|
||||||
|
|
||||||
//plot.cpoints.add(K::GnuplotPoint3(pt.x, pt.y, pt.z), p);
|
//plot.cpoints.add(K::GnuplotPoint3(pt.x, pt.y, pt.z), p);
|
||||||
}
|
}
|
||||||
|
|||||||
0
plots/Plotty.h
Normal file → Executable file
0
plots/Plotty.h
Normal file → Executable file
2
tex/bare_conf.tex
Normal file → Executable file
2
tex/bare_conf.tex
Normal file → Executable file
@@ -81,6 +81,8 @@
|
|||||||
%\usepackage{ulem}
|
%\usepackage{ulem}
|
||||||
|
|
||||||
|
|
||||||
|
%\setcounter{figure}{0}
|
||||||
|
%\renewcommand{\thefigure}{A\arabic{section}.\arabic{figure}}
|
||||||
|
|
||||||
|
|
||||||
% replacement for the SI package
|
% replacement for the SI package
|
||||||
|
|||||||
0
tex/chapters/abstract.tex
Normal file → Executable file
0
tex/chapters/abstract.tex
Normal file → Executable file
0
tex/chapters/conclusion.tex
Normal file → Executable file
0
tex/chapters/conclusion.tex
Normal file → Executable file
97
tex/chapters/experiments.tex
Normal file → Executable file
97
tex/chapters/experiments.tex
Normal file → Executable file
@@ -41,13 +41,13 @@
|
|||||||
\centering
|
\centering
|
||||||
\input{gfx/all_fingerprints.tex}
|
\input{gfx/all_fingerprints.tex}
|
||||||
}
|
}
|
||||||
\label{fig:referenceMeasurements}
|
|
||||||
\caption{
|
\caption{
|
||||||
Locations of the 121 reference measurements.
|
Locations of the 121 reference measurements.
|
||||||
The size of each square denotes the number of permanently installed \docAPshort{}s
|
The size of each square denotes the number of permanently installed \docAPshort{}s
|
||||||
that are visible at this location,
|
that are visible at this location,
|
||||||
and ranges between 2 and 22 with an average of 9.
|
and ranges between 2 and 22 with an average of 9.
|
||||||
}
|
}
|
||||||
|
\label{fig:referenceMeasurements}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
% visible APs:
|
% visible APs:
|
||||||
@@ -56,12 +56,12 @@
|
|||||||
\begin{figure}[b]
|
\begin{figure}[b]
|
||||||
\centering
|
\centering
|
||||||
\input{gfx/compare-wifi-in-out.tex}
|
\input{gfx/compare-wifi-in-out.tex}
|
||||||
\label{fig:wifiIndoorOutdoor}
|
|
||||||
\caption{
|
\caption{
|
||||||
Measurable signal strengths of a testing \docAPshort{} (black dot).
|
Measurable signal strengths of a testing \docAPshort{} (black dot).
|
||||||
While the signal diminishes slowly along the corridor (upper rectangle)
|
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).
|
the metallised windows (dashed outline) attenuate the signal by over \SI{30}{\decibel} (lower rectangle).
|
||||||
}
|
}
|
||||||
|
\label{fig:wifiIndoorOutdoor}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
Figure \ref{fig:wifiIndoorOutdoor} depicts the to-be-expected issues by examining the signal strength
|
Figure \ref{fig:wifiIndoorOutdoor} depicts the to-be-expected issues by examining the signal strength
|
||||||
@@ -105,11 +105,11 @@
|
|||||||
\begin{figure}
|
\begin{figure}
|
||||||
\input{gfx/wifi_model_error_0_95.tex}
|
\input{gfx/wifi_model_error_0_95.tex}
|
||||||
%\input{gfx/wifi_model_error_95_100.tex}
|
%\input{gfx/wifi_model_error_95_100.tex}
|
||||||
\label{fig:wifiModelError}
|
|
||||||
\caption{
|
\caption{
|
||||||
Comparison between different optimization strategies by examining the error (in \decibel) at each reference measurement.
|
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.
|
The higher the number of variable parameters, the better the model resembles real world conditions.
|
||||||
}
|
}
|
||||||
|
\label{fig:wifiModelError}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
% statds:
|
% statds:
|
||||||
@@ -135,30 +135,77 @@
|
|||||||
|
|
||||||
As we try to minimize the system's setup time as much as possible, we need to determine
|
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.
|
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.
|
Depending on the chosen model and thus the number of to-be-optimized 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.
|
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]
|
\begin{figure}[b]
|
||||||
\input{gfx/wifi_model_error_num_fingerprints_method_5_0_90.tex}
|
\input{gfx/wifi_model_error_num_fingerprints_method_5_0_90.tex}
|
||||||
\input{gfx/wifi_model_error_num_fingerprints_method_5_90_100.tex}
|
\input{gfx/wifi_model_error_num_fingerprints_method_5_90_100.tex}
|
||||||
\label{fig:wifiNumFingerprints}%
|
|
||||||
\caption{%
|
\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}
|
\end{figure}
|
||||||
|
|
||||||
Figure \ref{fig:wifiNumFingerprints} depicts the impact of reducing the number of fingerprints
|
Figure \ref{fig:wifiNumFingerprints} depicts the impact of reducing the number of reference measurements
|
||||||
for the {\em \optPerRegion{}} strategy. Only using 60 of the 121 fingerprints yields only a slightly
|
during the optimization process for the {\em \optPerRegion{}} strategy.
|
||||||
increasing model error and still provides good results. While using only \SI{25}{\percent} of the reference
|
The error is determined by using the (absolute) difference between expected signal strength and
|
||||||
measurements increases the error rapidly, \SI{75}{\percent} of all considered errors are still better
|
the optimized model's corresponding prediction for all of the 121 reference measurements.
|
||||||
than using just empiric values without any 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
|
Additionally we examined the impact of skipping reference measurements for difficult locations
|
||||||
like aforementioned staircases, surrounded by concrete. While this slightly decreases the
|
like staircases, surrounded by steel-enforced concrete. While this slightly decreases the
|
||||||
estimation error for all other positions, the error within those locations is dramatically
|
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
|
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.
|
at location $\mPosVec$ returned from the to-be-examined prediction model.
|
||||||
For all comparisons we use a constant uncertainty $\sigma = $\SI{8}{\decibel}.
|
For all comparisons we use a constant uncertainty $\sigma = $\SI{8}{\decibel}.
|
||||||
|
|
||||||
The quality of the estimated location is determined by comparing the estimation
|
The quality of the estimated location is determined by using the Euclidean distance between estimation
|
||||||
$\mPosVec^*$ with the pedestrian's ground truth position at the time the scan $\mRssiVec$
|
$\mPosVec^*$ and the pedestrian's ground truth position at the time the scan $\mRssiVec$
|
||||||
has been received.
|
has been received.
|
||||||
|
|
||||||
|
|
||||||
@@ -226,18 +273,20 @@
|
|||||||
|
|
||||||
\begin{figure}[b]
|
\begin{figure}[b]
|
||||||
\input{gfx/modelPerformance_meter.tex}
|
\input{gfx/modelPerformance_meter.tex}
|
||||||
\label{fig:modelPerformance}
|
|
||||||
\caption{
|
\caption{
|
||||||
Error between ground truth and estimation using \refeq{eq:bestWiFiPos} depending
|
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}
|
\end{figure}
|
||||||
|
|
||||||
%To estimate the overall performance of the prediction models, we compare the position estimation
|
%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)
|
%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.
|
%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)
|
The position estimation for each \docWIFI{} measurement within the recorded walks (3756 scans in total)
|
||||||
is compared against its corresponding ground-truth, indicating the absolute 3D error.
|
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 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.
|
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.
|
However, as discussed earlier, the maximal estimation error might increase for some setups.
|
||||||
@@ -252,13 +301,13 @@
|
|||||||
|
|
||||||
\begin{figure}[t]
|
\begin{figure}[t]
|
||||||
\input{gfx/wifiMultimodality.tex}
|
\input{gfx/wifiMultimodality.tex}
|
||||||
\label{fig:wifiMultimodality}
|
|
||||||
\caption{
|
\caption{
|
||||||
Location probability \refeq{eq:bestWiFiPos} for three scans. Higher color intensities are more likely.
|
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).
|
Ideally, places near the ground truth (black) are highly highly probable (green).
|
||||||
Often, other locations are just as likely as the ground truth (blue),
|
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).
|
or the location with the highest probability does not match at all (red).
|
||||||
}
|
}
|
||||||
|
\label{fig:wifiMultimodality}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
Figure \ref{fig:wifiMultimodality} depicts aforementioned issues of multimodal (blue) or wrong (red) location
|
Figure \ref{fig:wifiMultimodality} depicts aforementioned issues of multimodal (blue) or wrong (red) location
|
||||||
@@ -318,13 +367,13 @@
|
|||||||
\begin{figure}
|
\begin{figure}
|
||||||
\input{gfx/wifiCompare_normalVsExp_cross.tex}
|
\input{gfx/wifiCompare_normalVsExp_cross.tex}
|
||||||
\input{gfx/wifiCompare_normalVsExp_meter.tex}
|
\input{gfx/wifiCompare_normalVsExp_meter.tex}
|
||||||
\label{fig:normalVsExponential}
|
|
||||||
\caption{
|
\caption{
|
||||||
Comparison between normal- (black) and exponential-distribution (red) for \refeq{eq:wifiProb}.
|
Comparison between normal- (black) and exponential-distribution (red) for \refeq{eq:wifiProb}.
|
||||||
While misclassifications are slightly reduced (upper chart),
|
While misclassifications are slightly reduced (upper chart),
|
||||||
the median error between ground-truth and estimation (lower chart) increases by
|
the median error between ground-truth and estimation (lower chart) increases by
|
||||||
about \SI{1}{\meter}.
|
about \SI{1}{\meter}.
|
||||||
}
|
}
|
||||||
|
\label{fig:normalVsExponential}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
tex/chapters/interoduction.tex
Normal file → Executable file
0
tex/chapters/interoduction.tex
Normal file → Executable file
0
tex/chapters/introduction.tex
Normal file → Executable file
0
tex/chapters/introduction.tex
Normal file → Executable file
0
tex/chapters/relatedwork.tex
Normal file → Executable file
0
tex/chapters/relatedwork.tex
Normal file → Executable file
0
tex/chapters/system.tex
Normal file → Executable file
0
tex/chapters/system.tex
Normal file → Executable file
14
tex/chapters/work.tex
Normal file → Executable file
14
tex/chapters/work.tex
Normal file → Executable file
@@ -100,12 +100,12 @@
|
|||||||
|
|
||||||
\begin{figure}[t!]
|
\begin{figure}[t!]
|
||||||
\input{gfx/wifiop_show_optfunc_params}
|
\input{gfx/wifiop_show_optfunc_params}
|
||||||
\label{fig:wifiOptFuncTXPEXP}
|
|
||||||
\caption{
|
\caption{
|
||||||
The average error (in \SI{}{\decibel}) between all reference measurements and corresponding model predictions
|
The average error (in \SI{}{\decibel}) between all reference measurements and corresponding model predictions
|
||||||
for one \docAPshort{} dependent on \docTXP{} \mTXP{} and \docEXP{} \mPLE{}
|
for one \docAPshort{} dependent on \docTXP{} \mTXP{} and \docEXP{} \mPLE{}
|
||||||
[known position $\mPosAPVec{}$, fixed \mWAF{}] denotes a convex function.
|
[known position $\mPosAPVec{}$, fixed \mWAF{}] denotes a convex function.
|
||||||
}
|
}
|
||||||
|
\label{fig:wifiOptFuncTXPEXP}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
For systems that demand a higher accuracy, one can choose a compromise between fingerprinting and
|
For systems that demand a higher accuracy, one can choose a compromise between fingerprinting and
|
||||||
@@ -138,12 +138,12 @@
|
|||||||
|
|
||||||
\begin{figure}[t!]
|
\begin{figure}[t!]
|
||||||
\input{gfx/wifiop_show_optfunc_pos_yz}
|
\input{gfx/wifiop_show_optfunc_pos_yz}
|
||||||
\label{fig:wifiOptFuncPosYZ}
|
|
||||||
\caption{
|
\caption{
|
||||||
The average error (in \SI{}{\decibel}) between reference measurements and model predictions
|
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{}]
|
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.
|
usually denotes a non-convex function with multiple [here: two] local minima.
|
||||||
}
|
}
|
||||||
|
\label{fig:wifiOptFuncPosYZ}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
Such functions demand for optimization algorithms, that are able to deal with non-convex functions,
|
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
|
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.
|
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}
|
\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
|
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
|
a very small delay (micro- to milliseconds). Such measurements may be grouped using some aggregate
|
||||||
function like average, median or maximum.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
tex/egbib.bib
Normal file → Executable file
0
tex/egbib.bib
Normal file → Executable file
2
tex/gfx/build.sh
Normal file → Executable file
2
tex/gfx/build.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
for file in *.gp
|
for file in *.gp
|
||||||
do
|
do
|
||||||
gnuplot $file;
|
gnuplot "$file";
|
||||||
done
|
done
|
||||||
|
|||||||
0
tex/make.sh
Normal file → Executable file
0
tex/make.sh
Normal file → Executable file
0
tex/misc/functions.tex
Normal file → Executable file
0
tex/misc/functions.tex
Normal file → Executable file
0
tex/misc/keywords.tex
Normal file → Executable file
0
tex/misc/keywords.tex
Normal file → Executable file
0
wifi/EvalWiFi.h
Normal file → Executable file
0
wifi/EvalWiFi.h
Normal file → Executable file
0
wifi/EvalWiFiConvex.h
Normal file → Executable file
0
wifi/EvalWiFiConvex.h
Normal file → Executable file
71
wifi/EvalWiFiGround.h
Normal file → Executable file
71
wifi/EvalWiFiGround.h
Normal file → Executable file
@@ -30,6 +30,7 @@
|
|||||||
#include "../plots/PlotErrTime.h"
|
#include "../plots/PlotErrTime.h"
|
||||||
#include "../plots/PlotErrFunc.h"
|
#include "../plots/PlotErrFunc.h"
|
||||||
#include "../plots/PlotWiFiGroundProb.h"
|
#include "../plots/PlotWiFiGroundProb.h"
|
||||||
|
#include <Indoor/debug/PlotWifiMeasurements.h>
|
||||||
//#include "../CSV.h"
|
//#include "../CSV.h"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@@ -46,6 +47,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
PlotWiFiGroundProb* groundProb;
|
PlotWiFiGroundProb* groundProb;
|
||||||
|
PlotWifiMeasurements plotWifi;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -55,25 +57,84 @@ public:
|
|||||||
obs = new WiFiObserverFree(8.0, *mdl);
|
obs = new WiFiObserverFree(8.0, *mdl);
|
||||||
groundProb = new PlotWiFiGroundProb(map, settings);
|
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<int> gtIndices) {
|
||||||
|
|
||||||
Offline::FileReader reader(walkFile);
|
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;
|
int cnt = 0;
|
||||||
|
|
||||||
for (const auto& entry : reader.getWiFiGroupedByTime()) {
|
WiFiMeasurements mes;
|
||||||
const WiFiMeasurements& mes = entry.data;
|
|
||||||
groundProb->show(*obs, mes);
|
//std::vector<int> indices = {260, 270,271,272, 280};
|
||||||
|
//std::vector<int> 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();
|
groundProb->plotMe();
|
||||||
|
|
||||||
|
|
||||||
//if (++cnt > 70) {break;}
|
//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->update();
|
||||||
groundProb->plotMe();
|
groundProb->plotMe();
|
||||||
int i = 0; (void) i;
|
int i = 0; (void) i;
|
||||||
|
|
||||||
|
sleep(1000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(const std::string walkFile, const int idx, const float hue) {
|
void add(const std::string walkFile, const int idx, const float hue) {
|
||||||
|
|||||||
48
wifi/EvalWiFiPathMethods.h
Normal file → Executable file
48
wifi/EvalWiFiPathMethods.h
Normal file → Executable file
@@ -242,7 +242,7 @@ public:
|
|||||||
|
|
||||||
// error calculation
|
// error calculation
|
||||||
auto funcOrig = [&] (const float* params) -> double { return errFuncOrig(params, mes); };
|
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);
|
// parameters (x,y,z);
|
||||||
float paramsOrig[3] = {0,0,0};
|
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<double>::getProbability(0, 4, errorAvg);
|
||||||
|
const double err = -prob;
|
||||||
|
return err;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double getVeto(const Point3& pos_m, const WiFiMeasurements& obs) const {
|
double getVeto(const Point3& pos_m, const WiFiMeasurements& obs) const {
|
||||||
|
|
||||||
|
|||||||
4
wifi/EvalWiFiPaths.h
Normal file → Executable file
4
wifi/EvalWiFiPaths.h
Normal file → Executable file
@@ -95,7 +95,9 @@ public:
|
|||||||
pef.getPlot().getKey().setPosition(K::GnuplotKey::Hor::RIGHT, K::GnuplotKey::Ver::BOTTOM);
|
pef.getPlot().getKey().setPosition(K::GnuplotKey::Hor::RIGHT, K::GnuplotKey::Ver::BOTTOM);
|
||||||
pef.getPlot().getKey().setWidthIncrement(7);
|
pef.getPlot().getKey().setWidthIncrement(7);
|
||||||
pef.getPlot().getAxisY().setLabelOffset(2.5, 0);
|
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
|
// MANUAL AXIS RANGE SETTINGS
|
||||||
pef.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0,25));
|
pef.getPlot().getAxisX().setRange(K::GnuplotAxis::Range(0,25));
|
||||||
|
|||||||
Reference in New Issue
Block a user