From 1e8f4259a231bdff8f84c4f2fa946207ea7684af Mon Sep 17 00:00:00 2001 From: toni Date: Tue, 3 May 2016 11:17:08 +0200 Subject: [PATCH] activated interval smoothing for evaluation --- code/CMakeLists.txt | 2 +- code/CMakeLists.txt.user | 2 +- code/Settings.h | 6 +- code/eval/FixedLagEvalBase.h | 2 +- code/eval/SmoothingEval1.h | 101 ++++----- code/eval/SmoothingEvalBase.h | 205 +++++++++++++++--- code/main.cpp | 81 ++----- .../MySmoothingTransitionExperimental.h | 26 ++- tex/bare_conf.dvi | Bin 64548 -> 72672 bytes tex/chapters/experiments.tex | 2 +- 10 files changed, 272 insertions(+), 155 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 027e07a..52efa44 100755 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -67,7 +67,7 @@ ADD_DEFINITIONS( -O2 -DWITH_TESTS -DWITH_ASSERTIONS - + #-DUSE_FIXED_SEED ) endif() diff --git a/code/CMakeLists.txt.user b/code/CMakeLists.txt.user index 89c7d5d..8b9a790 100644 --- a/code/CMakeLists.txt.user +++ b/code/CMakeLists.txt.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/code/Settings.h b/code/Settings.h index 8d4c0ed..839c6a3 100644 --- a/code/Settings.h +++ b/code/Settings.h @@ -17,11 +17,11 @@ namespace MiscSettings { const int timeSteps = 500; - const int numParticles = 500; + const int numParticles = 2500; - const int numBSParticles = 50; + const int numBSParticles = 500; - const int lag = 15; + const int lag = 5; const int fixedLagGap = 1; diff --git a/code/eval/FixedLagEvalBase.h b/code/eval/FixedLagEvalBase.h index 675bf7d..c16f99f 100644 --- a/code/eval/FixedLagEvalBase.h +++ b/code/eval/FixedLagEvalBase.h @@ -457,7 +457,7 @@ public: // plot //vis.clearStates(); - vis.gp.setTerminal("png", K::GnuplotSize(1280 * 2.54, 720 * 2.54) ); + vis.gp.setTerminal("png", K::GnuplotSize(2560 * 2.54, 1440 * 2.54) ); vis.gp.setOutput("/tmp/" + runName + ".png"); vis.gp << "set view 60," << 40 << "\n"; //For fixed position diff --git a/code/eval/SmoothingEval1.h b/code/eval/SmoothingEval1.h index 519fc39..a779798 100644 --- a/code/eval/SmoothingEval1.h +++ b/code/eval/SmoothingEval1.h @@ -21,7 +21,7 @@ #include #include -class SmoothingEval1 : public FixedLagEvalBase { +class SmoothingEval1 : public SmoothingEvalBase { public: @@ -81,7 +81,7 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverageWithAngle())); @@ -112,13 +112,13 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverageWithAngle())); if(smoothing_resample) bf->setResampling( std::unique_ptr>(new K::ParticleFilterResamplingSimple()) ); - bf->setTransition(std::unique_ptr( new MySmoothingTransitionSimple) ); + bf->setTransition(std::unique_ptr( new MySmoothingTransitionExperimental) ); } // ============================================================ Dijkstra ============================================== // @@ -146,13 +146,13 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Dijkstra bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); if(smoothing_resample) bf->setResampling( std::unique_ptr>(new K::ParticleFilterResamplingSimple()) ); - bf->setTransition(std::unique_ptr( new MySmoothingTransitionExperimental) ); + bf->setTransition(std::unique_ptr( new MySmoothingTransition(&grid)) ); } @@ -175,7 +175,7 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -185,7 +185,7 @@ public: } void bergwerk_path1_nexus_simple() { - runName = "bergwerk_path1_nexus_simple_fixedlag"; + runName = "bergwerk_path1_nexus_simple_interval"; bergwerk_path1_nexus(); for (auto& n : grid) {n.imp = 1;} @@ -198,7 +198,7 @@ public: void bergwerk_path1_nexus_imp() { - runName = "bergwerk_path1_nexus_importance_fixedlag"; + runName = "bergwerk_path1_nexus_importance_interval"; bergwerk_path1_nexus(); GridWalkSimpleControl* walk = new GridWalkSimpleControl(); @@ -206,9 +206,9 @@ public: } - void bergwerk_path1_nexus_multi() { + void bergwerk_path1_nexus_multi(std::string name) { - runName = "bergwerk_path1_nexus_multi_fixedlag"; + runName = name; bergwerk_path1_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path1dbl.back()]) ); @@ -219,7 +219,7 @@ public: void bergwerk_path1_nexus_shortest() { - runName = "bergwerk_path1_nexus_shortest_fixedlag"; + runName = "bergwerk_path1_nexus_shortest_interval"; bergwerk_path1_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path1dbl.back()]) ); @@ -243,7 +243,7 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -254,7 +254,7 @@ public: void bergwerk_path2_nexus_simple() { - runName = "bergwerk_path2_nexus_simple_fixedlag"; + runName = "bergwerk_path2_nexus_simple_interval"; bergwerk_path2_nexus(); for (auto& n : grid) {n.imp = 1;} // remove importance @@ -266,7 +266,7 @@ public: void bergwerk_path2_nexus_imp() { - runName = "bergwerk_path2_nexus_importance_fixedlag"; + runName = "bergwerk_path2_nexus_importance_interval"; bergwerk_path2_nexus(); GridWalkSimpleControl* walk = new GridWalkSimpleControl(); @@ -274,9 +274,9 @@ public: } - void bergwerk_path2_nexus_multi() { + void bergwerk_path2_nexus_multi(std::string name) { - runName = "bergwerk_path2_nexus_multi_fixedlag"; + runName = name; bergwerk_path2_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path2dbl.back()]) ); @@ -287,7 +287,7 @@ public: void bergwerk_path2_nexus_shortest() { - runName = "bergwerk_path2_nexus_shortest_fixedlag"; + runName = "bergwerk_path2_nexus_shortest_interval"; bergwerk_path2_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path2dbl.back()]) ); @@ -312,7 +312,7 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -323,7 +323,7 @@ public: void bergwerk_path3_nexus_simple() { - runName = "bergwerk_path3_nexus_simple_fixedlag"; + runName = "bergwerk_path3_nexus_simple_interval"; bergwerk_path3_nexus(); for (auto& n : grid) {n.imp = 1;} // remove importance @@ -335,7 +335,7 @@ public: void bergwerk_path3_nexus_imp() { - runName = "bergwerk_path3_nexus_importance_fixedlag"; + runName = "bergwerk_path3_nexus_importance_interval"; bergwerk_path3_nexus(); GridWalkSimpleControl* walk = new GridWalkSimpleControl(); @@ -343,9 +343,9 @@ public: } - void bergwerk_path3_nexus_multi() { + void bergwerk_path3_nexus_multi(std::string name) { - runName = "bergwerk_path3_nexus_multi_fixedlag"; + runName = name; bergwerk_path3_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path3dbl.back()]) ); @@ -356,7 +356,7 @@ public: void bergwerk_path3_nexus_shortest() { - runName = "bergwerk_path3_nexus_shortest_fixedlag"; + runName = "bergwerk_path3_nexus_shortest_interval"; bergwerk_path3_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path3dbl.back()]) ); @@ -380,7 +380,7 @@ public: smoothing_baro_sigma = 0.05; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -391,7 +391,7 @@ public: void bergwerk_path4_nexus_simple() { - runName = "bergwerk_path4_nexus_simple_fixedlag"; + runName = "bergwerk_path4_nexus_simple_interval"; bergwerk_path4_nexus(); for (auto& n : grid) {n.imp = 1;} // remove importance @@ -403,7 +403,7 @@ public: void bergwerk_path4_nexus_imp() { - runName = "bergwerk_path4_nexus_importance_fixedlag"; + runName = "bergwerk_path4_nexus_importance_interval"; bergwerk_path4_nexus(); GridWalkSimpleControl* walk = new GridWalkSimpleControl(); @@ -411,9 +411,9 @@ public: } - void bergwerk_path4_nexus_multi() { + void bergwerk_path4_nexus_multi(std::string name) { - runName = "bergwerk_path4_nexus_multi_fixedlag"; + runName = name; bergwerk_path4_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path4dbl.back()]) ); @@ -424,7 +424,7 @@ public: void bergwerk_path4_nexus_shortest() { - runName = "bergwerk_path4_nexus_shortest_fixedlag"; + runName = "bergwerk_path4_nexus_shortest_interval"; bergwerk_path4_nexus(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path4dbl.back()]) ); @@ -449,7 +449,7 @@ public: smoothing_baro_sigma = 0.15; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -459,15 +459,15 @@ public: } void bergwerk_path1_galaxy_simple() { - runName = "bergwerk_path1_galaxy_simple_fixedlag"; + runName = "bergwerk_path1_galaxy_simple_interval"; bergwerk_path1_galaxy(); for (auto& n : grid) {n.imp = 1;} // remove importance GridWalkSimpleControl* walk = new GridWalkSimpleControl(); pf->setTransition( std::unique_ptr( new MyTransition(grid, *walk)) ); } - void bergwerk_path1_galaxy_multi() { - runName = "bergwerk_path1_galaxy_multi_fixedlag"; + void bergwerk_path1_galaxy_multi(std::string name) { + runName = name; bergwerk_path1_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path1dbl.back()]) ); GridWalkPathControl* walk = new GridWalkPathControl(grid, DijkstraMapper(grid), end); @@ -476,7 +476,7 @@ public: } void bergwerk_path1_galaxy_shortest() { - runName = "bergwerk_path1_galaxy_shortest_fixedlag"; + runName = "bergwerk_path1_galaxy_shortest_interval"; bergwerk_path1_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path1dbl.back()]) ); DebugShortestPath* walk = new DebugShortestPath(grid, DijkstraMapper(grid), end, this->floors); @@ -500,7 +500,7 @@ public: smoothing_baro_sigma = 0.15; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -510,15 +510,16 @@ public: } void bergwerk_path2_galaxy_simple() { - runName = "bergwerk_path2_galaxy_simple_fixedlag"; + runName = "bergwerk_path2_galaxy_simple_interval"; bergwerk_path2_galaxy(); for (auto& n : grid) {n.imp = 1;} // remove importance GridWalkSimpleControl* walk = new GridWalkSimpleControl(); pf->setTransition( std::unique_ptr( new MyTransition(grid, *walk)) ); } - void bergwerk_path2_galaxy_multi() { - runName = "bergwerk_path2_galaxy_multi_fixedlag"; + void bergwerk_path2_galaxy_multi(std::string name) { + //runName = "bergwerk_path2_galaxy_multi_interval"; + runName = name; bergwerk_path2_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path2dbl.back()]) ); GridWalkPathControl* walk = new GridWalkPathControl(grid, DijkstraMapper(grid), end); @@ -527,7 +528,7 @@ public: } void bergwerk_path2_galaxy_shortest() { - runName = "bergwerk_path2_galaxy_shortest_fixedlag"; + runName = "bergwerk_path2_galaxy_shortest_interval"; bergwerk_path2_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path2dbl.back()]) ); DebugShortestPath* walk = new DebugShortestPath(grid, DijkstraMapper(grid), end, this->floors); @@ -551,7 +552,7 @@ public: smoothing_baro_sigma = 0.15; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -561,15 +562,15 @@ public: } void bergwerk_path3_galaxy_simple() { - runName = "bergwerk_path3_galaxy_simple_fixedlag"; + runName = "bergwerk_path3_galaxy_simple_interval"; bergwerk_path3_galaxy(); for (auto& n : grid) {n.imp = 1;} // remove importance GridWalkSimpleControl* walk = new GridWalkSimpleControl(); pf->setTransition( std::unique_ptr( new MyTransition(grid, *walk)) ); } - void bergwerk_path3_galaxy_multi() { - runName = "bergwerk_path3_galaxy_multi_fixedlag"; + void bergwerk_path3_galaxy_multi(std::string name) { + runName = name; bergwerk_path3_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path3dbl.back()]) ); GridWalkPathControl* walk = new GridWalkPathControl(grid, DijkstraMapper(grid), end); @@ -578,7 +579,7 @@ public: } void bergwerk_path3_galaxy_shortest() { - runName = "bergwerk_path3_galaxy_shortest_fixedlag"; + runName = "bergwerk_path3_galaxy_shortest_interval"; bergwerk_path3_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path3dbl.back()]) ); DebugShortestPath* walk = new DebugShortestPath(grid, DijkstraMapper(grid), end, this->floors); @@ -604,7 +605,7 @@ public: smoothing_baro_sigma = 0.15; bool smoothing_resample = false; - smoothing_time_delay = 1; + //Smoothing using Simple Trans bf->setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); @@ -614,15 +615,15 @@ public: } void bergwerk_path4_galaxy_simple() { - runName = "bergwerk_path4_galaxy_simple_fixedlag"; + runName = "bergwerk_path4_galaxy_simple_interval"; bergwerk_path4_galaxy(); for (auto& n : grid) {n.imp = 1;} // remove importance GridWalkSimpleControl* walk = new GridWalkSimpleControl(); pf->setTransition( std::unique_ptr( new MyTransition(grid, *walk)) ); } - void bergwerk_path4_galaxy_multi() { - runName = "bergwerk_path4_galaxy_multi_fixedlag"; + void bergwerk_path4_galaxy_multi(std::string name) { + runName = name; bergwerk_path4_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path4dbl.back()]) ); GridWalkPathControl* walk = new GridWalkPathControl(grid, DijkstraMapper(grid), end); @@ -632,7 +633,7 @@ public: void bergwerk_path4_galaxy_shortest() { - runName = "bergwerk_path4_galaxy_shortest_fixedlag"; + runName = "bergwerk_path4_galaxy_shortest_interval"; bergwerk_path4_galaxy(); MyGridNode& end = (MyGridNode&)grid.getNodeFor( conv(floors.gtwp[path4dbl.back()]) ); DebugShortestPath* walk = new DebugShortestPath(grid, DijkstraMapper(grid), end, this->floors); diff --git a/code/eval/SmoothingEvalBase.h b/code/eval/SmoothingEvalBase.h index ef480ee..6387d46 100644 --- a/code/eval/SmoothingEvalBase.h +++ b/code/eval/SmoothingEvalBase.h @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include #include "GroundTruthWay.h" @@ -19,13 +22,16 @@ #include "../particles/MyInitializer.h" #include "../particles/smoothing/MySmoothingTransition.h" #include "../particles/smoothing/MySmoothingTransitionSimple.h" +#include "../particles/smoothing/MySmoothingTransitionExperimental.h" #include "../reader/SensorReader.h" #include "../reader/SensorReaderStep.h" #include "../reader/SensorReaderTurn.h" +#include "../reader/SensorReaderAccel.h" #include "../lukas/TurnObservation.h" #include "../lukas/StepObservation.h" +#include "../lukas/ActivityDetection.h" #include "../toni/BarometerSensorReader.h" @@ -33,8 +39,6 @@ #include "../frank/BeaconSensorReader.h" #include "../frank/OrientationSensorReader.h" -static int smoothing_time_delay = 0; -float stepSize = 0.71; class SmoothingEvalBase { @@ -71,6 +75,8 @@ protected: std::vector path4 = {29, 28, 27, 32, 33, 34, 35, 36, 10, 9, 8, 22, 37, 38, 39, 40, 41, 42, 43, 44}; std::vector path4dbl = {29, 29, 28, 27, 32, 33, 34, 35, 36, 10, 9, 8, 22, 37, 38, 39, 40, 41, 42, 43, 44}; // duplicate 1st waypoint! + float stepSize = 0.71; + public: SmoothingEvalBase() : grid(MiscSettings::gridSize_cm), floors(Helper::getFloors(grid)) { @@ -130,7 +136,7 @@ public: // sensor numbers const int s_wifi = 8; const int s_beacons = 9; const int s_barometer = 5; const int s_orientation = 6; - //const int s_linearAcceleration = 2; + const int s_accel = 0; std::list turn_observations; std::list step_observations; @@ -138,6 +144,8 @@ public: //Create an BarometerSensorReader BarometerSensorReader baroSensorReader; + // activity detection + ActivityDetection actDet; //Read all turn Observations while(srt->hasNext()) { @@ -186,8 +194,16 @@ public: K::Statistics statsFiltering; K::Statistics statsSmoothing; + K::Statistics statsDistFiltering; + K::Statistics statsDistSmoothing; int cnt = 0; + // error per update-step + std::vector errorsNorm; + std::vector errorsSmooth; + std::vector errorsDistNorm; + std::vector errorsDistSmooth; + //stats file std::ofstream statsout("/tmp/unsmoothed_" + runName + ".stats"); @@ -220,13 +236,21 @@ public: case s_barometer: { obs.barometer = baroSensorReader.readBarometer(se); + actDet.addBaro(baroSensorReader.getHPA(se)); break; } -// case s_linearAcceleration:{ -// baroSensorReader.readVerticalAcceleration(se); -// break; -// } + case s_accel: { + float acc[3]; + SensorReaderAccel sre; sre.read(se, acc); + actDet.addAccel(acc); + break; + } + + // case s_linearAcceleration:{ + // baroSensorReader.readVerticalAcceleration(se); + // break; + // } case s_orientation: { obs.orientation = OrientationSensorReader::read(se); @@ -251,6 +275,13 @@ public: } + // currently detected activity + // TODO: feed sensor values! + ctrl.currentActivitiy = actDet.getCurrentActivity(); + + // this is just for testing purposes + obs.currentActivity = actDet.getCurrentActivity(); + // time for a transition? if (se.ts - lastTransitionTS > MiscSettings::timeSteps) { @@ -266,16 +297,24 @@ public: const Point3 curEst = est.pCur; // error calculation. compare ground-truth to estimation - const int offset = 750; + const int offset = 0; const Point3 curGT = gtw.getPosAtTime(se.ts - offset); const Point3 diff = curEst - curGT; + pathEst.push_back(curEst); + const float err = diff.length(); + const float errDist = gtw.getMinDist(curEst); // minimum distance between estimation and ground-truth + + ++cnt; + // skip the first 24 scans due to uniform distribution start - if (++cnt > 24) { - pathEst.push_back(curEst); - const float err = diff.length(); + if (cnt > 35) { statsFiltering.add(err); - std::cout << statsFiltering.asString() << std::endl; + statsDistFiltering.add(errDist); + errorsNorm.push_back(err); + errorsDistNorm.push_back(errDist); + std::cout << "FilteringTime: " << se.ts << " " << statsFiltering.asString() << std::endl; + std::cout << "FilteringDist: " << se.ts << " " << statsDistFiltering.asString() << std::endl; //save the current estimation for later smoothing. pfHistory.push_back(pf->getNonResamplingParticles()); @@ -326,28 +365,37 @@ public: bf->reset(); MyState estBF; - int currentParticleSetToSmoothAtTimet = 0; - while(currentParticleSetToSmoothAtTimet != pfHistory.size() - 1){ + //iterate thru all particle sets from T to t (currentParticleSetToSmoothAtTimeT) + for(int i = pfHistory.size() - 1; i >= 0 ; i -= MiscSettings::fixedLagGap){ + //Set time + ((MySmoothingTransitionSimple*)bf->getTransition())->setCurrentTime(tsHistory[i]); + estBF = bf->update(pfHistory[i]); - //iterate thru all particle sets from T to t (currentParticleSetToSmoothAtTimeT) - for(int i = pfHistory.size() - 1; i >= currentParticleSetToSmoothAtTimet; i -= smoothing_time_delay){ - //Set time - ((MySmoothingTransitionSimple*)bf->getTransition())->setCurrentTime(tsHistory[i]); - estBF = bf->update(pfHistory[i]); - } + smoothedEst.push_back(estBF.pCur); + } - const Point3 curSmoothedEst = estBF.pCur; + std::reverse(smoothedEst.begin(), smoothedEst.end()); - smoothedEst.push_back(curSmoothedEst); + for(int t = 0; t < smoothedEst.size(); ++t){ + + const Point3 curSmoothedEst = smoothedEst[t]; // error calculation. compare ground-truth to estimation - const Point3 curGTSmoothed = gtw.getPosAtTime(tsHistory[currentParticleSetToSmoothAtTimet]); + const Point3 curGTSmoothed = gtw.getPosAtTime(tsHistory[t]); const Point3 diffSmoothed = curSmoothedEst - curGTSmoothed; + const float errSmoothed = diffSmoothed.length(); + const float errDistSmoothed = gtw.getMinDist(curSmoothedEst); // minimum distance between smoothed-estimation and ground-truth + statsSmoothing.add(errSmoothed); - std::cout << statsSmoothing.asString() << std::endl; + statsDistSmoothing.add(errDistSmoothed); + errorsSmooth.push_back(errSmoothed); + errorsDistSmooth.push_back(errDistSmoothed); + + std::cout << "SmoothingTime: " << tsHistory[(tsHistory.size() - 1) - MiscSettings::lag] << " " << statsSmoothing.asString() << std::endl; + std::cout << "SmoothingDist: " << tsHistory[(tsHistory.size() - 1) - MiscSettings::lag] << " " << statsDistSmoothing.asString() << std::endl; // plot @@ -356,7 +404,7 @@ public: const K::Particle& p = bf->getbackwardParticles().back()[j]; vis.addState(p.state.walkState); } - vis.setTimestamp(tsHistory[currentParticleSetToSmoothAtTimet]); + vis.setTimestamp(tsHistory[t]); vis.addGroundTruth(gtw); vis.addEstPath(smoothedEst); vis.setEstAndShould(curSmoothedEst, curGTSmoothed); @@ -365,6 +413,7 @@ public: vis.gp << "set label 112 'baro: " << obs.barometer->hpa << "' at screen 0.1,0.2\n"; } vis.gp << "set label 111 '" <getbackwardParticles().back().size(); j+=15) { + const K::Particle& p = bf->getbackwardParticles().back()[j]; + vis.addState(p.state.walkState); + } + //vis.setTimestamp(se.ts); + vis.setFilteringMedian(statsFiltering.getMedian()); + vis.setSmoothingMedian(statsSmoothing.getMedian()); + vis.addGroundTruth(gtw); + vis.addEstPath(pathEst); + vis.addSmoothPath(smoothedEst); + //vis.setEstAndShould(curEst, curGT); + //vis.setEstAndShould2(curSmoothedEst, curGTSmoothed); + + if (obs.barometer != nullptr) { + vis.gp << "set label 112 'baro: " << obs.barometer->hpa << "' at screen 0.1,0.2\n"; + } + vis.gp << "set label 111 '" <> predictionProbabilities; omp_set_dynamic(0); // Explicitly disable dynamic teams - omp_set_num_threads(4); + omp_set_num_threads(7); #pragma omp parallel for shared(predictionProbabilities) for (int i = 0; i < particles_old.size(); ++i) { std::vector innerVector; @@ -79,38 +79,53 @@ public: const double distance_m = p2->state.pCur.getDistance(p1->state.pCur) / 100.0; - double muDistance = 1.0; + double muDistance = 0.8; double sigmaDistance = 0.5; + double muFloor = 0.0; + double sigmaFloor = 0.1; switch (p2->state.currentActivity) { case Activity::ELEVATOR: muDistance = 0.0; sigmaDistance = 0.3; + + muFloor = 0.6; + sigmaFloor = 0.25; break; case Activity::STAIRS_DOWN: muDistance = 0.5; sigmaDistance = 0.3; + + muFloor = 0.3; break; case Activity::STAIRS_UP: muDistance = 0.4; sigmaDistance = 0.2; + + muFloor = -0.3; break; case Activity::STANDING: muDistance = 0.0; sigmaDistance = 0.2; + + muFloor = 0.0; break; case Activity::WALKING: - muDistance = 1.0; + muDistance = 0.8; sigmaDistance = 0.5; + + muFloor = 0.0; break; default: - muDistance = 1.0; + muDistance = 0.8; sigmaDistance = 0.5; + + muFloor = 0.0; break; } @@ -125,7 +140,8 @@ public: //check how near we are to the measurement - const double floorProb = K::NormalDistribution::getProbability(p1->state.measurement_pressure, smoothing_baro_sigma, p2->state.hPa); + double diffZ = (p2->state.pCur.z - p1->state.pCur.z) / 100.0; + const double floorProb = K::NormalDistribution::getProbability(muFloor, sigmaFloor, diffZ); //combine the probabilities diff --git a/tex/bare_conf.dvi b/tex/bare_conf.dvi index c214b59f52161638c2f305e88687b5df31d6fe03..f1611cc59bbaa828b45aa129ab3e827e19f6066b 100644 GIT binary patch delta 20020 zcmb7M33wD$wobabfk48($s&sj35Jjaki|g>gvcVu59&Z``+{WOi|md zbI(1?f0o;uPb>TX=xrL-bzD*Lm`TMGOUB%rm6eq(4m^Ls)&<4hWYhci>KnfLsV)?) zvAj&SSYTEcu*5+V6{y*Oxze8Q3G0`Ftw&nRmo5zuXd@Y}~N5utc66t(dOlf3O{UDH=T=|*j#Gj5$` zb(mBVH|j-P7p5LwjoX?q6aHk-VH~qZ)L|46)WR|P+#Ed$)=yK7uN5Gmk(iEu>!yBxuc?@xq~6nvCUn_uiOl#6$kDmiD~6 z&V30&;t~zUF~ve<{@W_%oWytRP}Hv*7zCn+MRmrlPQ)dX(?0zllI21&-16!F6^fd1 zO%2$3wY@T7#_fa&t_Vm44;_s|Rswbm^KeEBsBsljd@ZXI3zSw~J)}kH^JdagUOgO9 zqxAxEWQM9jVF;6E+LD=~I$=N#3>#{}k^v%D(}!@;8Q2v+%a^QjMU}YeOCFnwwZc)& zFhImLe=r(amC#Iw2O=5JVqv|WIOr~rYFggn*|}@9z^JfVllB(R!dwKOhaeCJq;|DX z!?wG&^fb*@#d`5QEo`eXNw4Y;y6j}lvb-awpTq5?m`&O{vK$kN2*`B^f;nHPC4!qOd=jC^Zu?vZ!>ks-C_QNcdTTa5wC-LNk~+!?Zk8Pl?Am59yuq zOg-HuPSP%j1D$*O9%}CQSRe6o=dnu92fK*kE=#(kl?VTd<+GFr-xt5_Qe0pMLp4D` zCek&=hU(w2Z&SUclx~e`TEK+PrIgZb;%JwlNgS)1cJEEdg)rrppb)l8n+X#DRvvlO z)S%zcPuTP$kEjNOMUd_vu7NcV>aiHjik>ye!s=c9nq39)sWpon*3FDszKQ}v^TTM0 zdQCN8x+3B?x!tA+DOvcqW@xZ7j!c0}=hcX&#Vy~`YhgZ2O&Hp$M96TBuW#wQ;y`Y% zY|(Nu_eD=1@oGcrhy9!JG0#WeMszct_Iz|)?CLgj25f{Duwm9%0nV{CJg(Kzzl&HG zu1|OL?+k<>S41g%lL?m;ua9Xk^&JDRi80-y6FaTg2%Z}nyp{Bh3HS&&PH1R7Y8IDFyHdY7sNqgwQels7VLx+!XHJraqh@P?@iEfj5R z&dJJZs0x{;Kd50nFMm-@m}$@DF9l$Q=7#*ixG4ZJY)Gr9Rii_rP+?I6FcQ#2G-23y z4FW|Y=|%wG0Z$6WoxdF^$~Rx^Ju~3WjbiD5!D4T9W72b|Xva){Fzq=sI)Y&}rq@;z z=lEbdp;c){SOXq{efJz1yCijXS)pnqBA@_oLHMJMn~7vh)KbzRem*2KF<^fBj7(k{)08%eKVaSBS*rZ9qubOa;YUAcyOp=BRgu0SNx0EGyLhaE% zhfoWfJ#ob~eUqfTcnCAFlpAh~>d{eGVgbz%mJ7&C3qzfh8*VR8K!J2dm~6QGIzd0E z%9;?XlIv?RQZNA)rO+aphzY6U-%?4^QLtqr3L_mkOlHW>Z92evcP%Bu} zxFxT1eM72yR@PLtUL!&*Wp5uwD)2OW`!X=ww~2vS&?ZeG%qn2F6EOe?Fb?<*cjFF9 z0ZDB(+Vbpt1ja34n4t|XWvy=7m)rycpYrT{ltGug2w6wAOsKdv(bVF!j0ToXk7SICbov;HjHu;V{Cr$b zdlt9yx7H9ocdZ~6AzV+KiY5PdO9S;;(qSrl7z~L)_!UbTb{70iE5ox`h)mddEHL~q z^f3U5wCAV>IUF6FTn#?~C~CsnR102CN8B>NGiiCZ^wXn2@muVXY3wUMFD(P>28R zaO{mL_B@4RUipGlhi|?%6Yy4$0a$ulcm|y9@^S?huoe#E&c!Vg2JTR(o$$#O)Ug+$f&Da)J;;SLSxO4<-PC-lntHhDFI= zdw1TH^$0FC?=0WcGGf@n*@HbFb}Ru5ex_>~tUY{{4C%->dOqwVz8rpjGUI@QP=(H?x z;))w@xVB^FhSwi4CLAeAD}6TY0KYAz&qH}I5h9c{;oBWZ104r`u4{rz3Wv$&vbeaB zqeGv_C%2t2u*&|BfjFmt!aFmDkOB67SAk0M0{Pe#sw64iHIj`cVWgvXQGn)#3L?M8 z(6nerz^ABIV2j3!&a1{iq3Eb8EnbH^7-R3-W!1p?uuqLDOw(@+5-)*>C|bxi=oh5f zW>|09y{8Uefps$CCgB`dBYpjWITYdAAQ7JsT`nG$9G-08m1{l6idw!CHtYpnr@-8I z;&-b78DXx-z94+|$3so9YBr1nn3Le(iJrn|g18dKg0WM8M8Gcr6q%SuT3LCgMz6tI zL*&TbuUwa`5HgIGz{*lq-qp_fnT56kDus$5>~M`5HrsG=K!dVE%Pe0*74stPYw-Kw zPyBE!8Z)NNAQKD1gcl*^{#uA)!`Brs97)|E^#-BrWEhWF-WkcN`m}e(&BU{sXo#ap zmH7=V&}~zPj?m2On50@VaDaNy4`(bx2gdR?J>kTqWI@#^;y=wudz+rD3e|v3;qdyy zHFYq{^{KPhZbG2Z^gWy($fOs^bQhA;$#B~lmf^bPu@9Ph1Yxy(hz%n`W?ozNfkxB) z&4u&`tFEoqG@Tev9wM$XHiy3^r49p)Ys@8f%b2}hZFz61#|P8io7SGQ$mFM_hqm*z zq8bo-)ALc?ZksyDH1tGG(76<5l;TjVN5l1&_w#Ou58!`+EYjZ3ySIDQOvVs`6kyQL zS5}g{LP$wiJZu9Is0cpEz8fSP&VZoM^8LB9v#tO)5g0;}3CTp?pC2qs`Cdx6=!J|{ zJLb@^O5EpMNv0xZ<*mz&=Hu7>hFFru`?09wWdFqW{-YQ#sBvH@F= z+v)SPo5tWTjS5A9lQ7q{>;WC3U2l<6vQM+0LdpatA^Yd0rOD+`15f`M`udl$>NFuy z0j(i)i%$SbvQM)ohh*CjBIINU62;r}03i~o6;VW%Jhp;)N13SD17)t*#jc|m4RQ;0 zv}JZ93>uTLu9DZ3gmBXsWIsTU<+*i>)XS9T*2fw3P}JkO^=Jjm0j#EGJE^%e?z4T1 z=!hn0M4~7}40MI5-2y6me^`P!hDKF{sz|gFVGTC!dvH*GLy*`AO#&x2JJomXy z#+BqSKWd4PL8;Nza7y`T8|kdXFytYGTBY0M7c%gKp2=WmvY9fB?~u&O3Pm9VynrB( z4He~ZFRzG_@YJQ1%cq}{g=5KWlXM7jHJDp>7$EbJp%|nK?VU4LQ>`=0r`Psy363;D1fDx zo~K26=>;}(^e}Se3_qZt)tCp5VNS9uAdB&E61u(iFe#1AND^xW2qtkXhBw^=v!&c~ zuVb9k%00iPh^SpW=!S!kN4QVM;0NYFZV^4nN&&~a7!P_2#jt$+J*1Mp{@F>XlkK2| z6MFzu^#9#Lwos(l4vlT5!*vO@QGElUGc8b~S>CeAG8{>H%Pt3OF-A1~=6VwmHz_TP z6wH%QN5zbgZiEEhP1^ER*!Qvr;53bZ^ED8Q%7Sth=@GIbWQWqqS!h4UV;K`7o%y*Y zWcQxczc3+EPutlJOIddb+m0l1C!DSc6YwcaDeFeIHy@(TR{0KLPcj~OU@3HwKoGR> zp9ug`7z{Sg)kL8It~#0s`UDWq?!C~&0Z>Ip|DddNC!>6n;mBSj=8YWTZJzP|jiiR> z@4tR$n;K5KJO(wyU#W(Nt{2Cui#rWyp1>D{I(TIAt1mumc)2olcG~@VG&IRl24A%U zx&yfm=#;V9;Z!QK=EhQS`em&h&>)ut27jYPy-|z5M3J=lK}2;BcR$K7%$VZn%@1cmG#f4r!O2C9R2+biLk=?OZkC1Tpv9ht;9j0~m4qA3iZ;cdtt z!NuVairDmvpF?$ANBMj{_M3iT&X%rs zy}@~GQ8rx;aQF1teD|-@=kYPWqJodBDz4_^j*3}He1KyewqD;i1sN`}ldeKEmhyf7 z8;R0vEv(1j{+5=E0T}iDP+WnOJ>AZrJJ?O!9lIP%rASG&eCPe_W<%PFia-LeU*zBc zMFNQ=s-(ZLrZkQlBB2_fBXWDEA&;S^Fhg$bk^Fqh_f8|{_aq25f$(8SeD7Wa#ldPJ zLy!E1PH{33w6tX0a?5+)yZAh6KhgncNhH9KAd{&<1E87sfQMie36N1Tk4%y~4`(P! z2RW|*FOiqGyrXkDWWrle1^_Oo6%DdLBOpX)i%hLL5f)d4s$Bq`zo2Q*{mqN6DzJbM z@D-|2phSxT0>@B7%$?aEQnPaAJ;?5~oVu#FC&#M8plPqQTJ*TOSH3$7j^~ir1tbOp zrf4V;4j_X9jDn(6+-_NT^8@-g$RWdR){c2mw%TSS%zP=t7G+Ry)d25F-Y8x=s+pkY@hqP1j1$(}%r>&Sfr z+wAPJkg85|U?a(dAe>pL#bMQuUW-#PoHFlZbH!ARQ~P9cbyP9%7}*|Y3NyG;OBNA@ zzyRmrv-72wD)4rrl{^3I_FgKVy%hdBD<{2F5AssD$X@FEbG?-3*ce%|I5w8dEKIC3 zIg^-Z*m@P$TYf>R{Xa;R3v({Lmh$uim_N+;)9;g8ft8$-#1V5%D^EX29)?^Je_(A$ zi_oO8CZRa08MH1`$*$5+lA*2+&-xcDfWpuqu>KiWa?+mlTj6m`U5oO&?Mfen@!oOrY8Ww5Wzh$;1Ry5iXp< zIS6=BTP0*6Kp*lHkEYp%$uer%_viyKPE<yYY3T z*1a2d`H@$vVE~DxB?JNzDS`p2Lt@^EBZ0|f#soG363xvD&S(@IQmO>m`d2bSbDY(qU&fq~9rl6+kyk z|9&7wU5`AA&_e(#{rfRxsO1(ygem<>{*Q`ml13*7v6ikn@ZTAf6Fwj`YI#c|PM}A* zz1qUGw=~QbXdyW_B2yzGnF-Bp3e5>3V2zydxC91GV)JhKZXXgyLrB_p`}vYAaFLJ# z=%etQV>ufpJ_^=G3sZR94OzG+3kzJgfwIdK(O62sKZxIT$^Q|^jO+>H)jn+lc}KI7 z>>hC7b(C>dCQ%^s8dws`yW&3ydLy;Lkzd-oVjtBKP3BcS(h1V)gzIe-@=!=s5on`= zi+ z+9aiv(xy!`G!O`^1kkt|^;9emVn^z5K+6^-NQu4(=X*$TP_gQHB-N0*^uqJSyd@=_ zx|OeD4How-nWBKhV)v4(_&D&IEBUBhGd24m@$NNO;qL|4j#h?_xvgcyqWG zl%DUGwKOmPFx%VQ^ZhB}hU*>}g@2T>ZA2wQX1i&*d<#Cql7LZRClv$ChHIki`aVhD z!o@SFI@i!3j?Oh38yixcfB#u?cJl0tb)nqG)WCn~+A4J%MG%naJkw=f7C#fJYE1R3 zxuTWAG(bJ8!$tjwf9(qtsSX!WIgtp6qKSp%)KBHRQ86fLJn5=be%ZW&REOQ~;bT^Z zJx_(EYAObW62T-8j?1iwwB$vp4sYJIEqi;Z#DjoNq z2PmHIxPJi68X*F55(diT=zBRZe)|AP5Wd%#>h_n7tq?jI^_=hHH8dokSP^%JMq^4TgRPG@%s$7{{BSAOv+8kx@*Vc)Y(B# zXhuZhk+hO^ce_rLdDMDASpXTxrj)Gv%81izWX}kK%cur*0-gXYk!>xJ5aUZ~Wm$uT zFvL8kkF`ip^Gr{GVost_Sr^ZWBb_NQRWLnq_QH#k-Lg(IGh9hU&)~DKVl~p=%)XbyqrznJ|Ti&XE zJiF7trlk$3X)iR3TZ6+pb=wf)a8djrSlFrC${sSL{wz3?KXplH0UvJ($q@RT&{9Wzz4l-~RpM`IO@dNHqdiD9XWlzMLt@N6Grsch8xku?$FkK8>Rp43Kqorb1 z%;P!vx_HifQt3PGKSeOU)${L1TLvcjXM6tm$Ch!cr+Qob0}@_`uqs7rgvaL+ZMVCLdTllet`(0f*4N zg2VFt&(?F|gga!#_GFWr}1!N-$HIf0qCOarH$yJZgk=G@w#^nCdzasRC)p8QzL?pts7 zc$>T7UkmS;mksan=$#|w`8#)Bp6%Vz^Dn;>z3+Y;Qur5Jym<#p|Z?BWu=4aoVv?iqm-wQrw~q^1S5NgT(%Z z(OtLXW*0XP`*a_^f9lF^_�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 delta 12884 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