#include "main.h" #include "navMesh/mesh.h" #include "navMesh/filter.h" #include "Settings.h" #include "navMesh/meshPlotter.h" #include "Plotty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Stats::Statistics run(Settings::DataSetup setup, int numFile, std::string folder) { // reading file Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(setup.map); Offline::FileReader fr(setup.training[numFile]); WiFiFingerprints fingerprints(setup.fingerprints); std::ifstream inp(setup.wifiModel, std::ifstream::binary); //ground truth std::vector gtPath; for(int i = 0; i < setup.numGTPoints; ++i){gtPath.push_back(i);} Interpolator gtInterpolator = fr.getGroundTruthPath(map, gtPath); Stats::Statistics errorStats; //error file const long int t = static_cast(time(NULL)); const std::string evalDir = Settings::errorDir + folder; struct stat statStruct; stat(evalDir.c_str(), &statStruct); if(!S_ISDIR(statStruct.st_mode)){ if(mkdir(evalDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1){ Assert::doThrow("Eval folder couldn't be created!"); } } std::ofstream errorFile; errorFile.open (evalDir + "/" + std::to_string(numFile) + "_" + std::to_string(t) + ".csv"); // wifi WiFiModelLogDistCeiling WiFiModel(map); // with optimization if(Settings::WiFiModel::optimize){ if (!inp.good() || (inp.peek()&&0) || inp.eof()) { Assert::isFalse(fingerprints.getFingerprints().empty(), "no fingerprints available!"); WiFiOptimizer::LogDistCeiling opt(map, Settings::WiFiModel::vg_calib); for (const WiFiFingerprint& fp : fingerprints.getFingerprints()) { opt.addFingerprint(fp); } const WiFiOptimizer::LogDistCeiling::APParamsList res = opt.optimizeAll(opt.NONE); for (const WiFiOptimizer::LogDistCeiling::APParamsMAC& ap : res.get()) { const WiFiModelLogDistCeiling::APEntry entry(ap.params.getPos(), ap.params.txp, ap.params.exp, ap.params.waf); WiFiModel.addAP(ap.mac, entry); } WiFiModel.saveXML(setup.wifiModel); } else { WiFiModel.loadXML(setup.wifiModel); } } else { // without optimization WiFiModel.loadAPs(map, Settings::WiFiModel::TXP, Settings::WiFiModel::EXP, Settings::WiFiModel::WAF); Assert::isFalse(WiFiModel.getAllAPs().empty(), "no AccessPoints stored within the map.xml"); } // mesh NM::NavMeshSettings set; MyNavMesh mesh; MyNavMeshFactory fac(&mesh, set); fac.build(map); const Point3 srcPath0(26, 43, 7.5); const Point3 srcPath1(62, 38, 1.7); const Point3 srcPath2(62, 38, 1.8); const Point3 srcPath3(62, 38, 1.8); // add shortest-path to destination //const Point3 dst(51, 45, 1.7); //const Point3 dst(25, 45, 0); //NM::NavMeshDijkstra::stamp(mesh, dst); // debug show //MeshPlotter dbg; //dbg.addFloors(map); //dbg.addOutline(map); //dbg.addMesh(mesh); //dbg.addDijkstra(mesh); //dbg.draw(); Plotty plot(map); plot.buildFloorplan(); plot.setGroundTruth(gtPath); // particle-filter const int numParticles = 5000; //auto init = std::make_unique(&mesh, srcPath1); // known position auto init = std::make_unique(&mesh); // uniform distribution auto eval = std::make_unique(WiFiModel); auto trans = std::make_unique(mesh, WiFiModel); //auto resample = std::make_unique>(); //auto resample = std::make_unique>(); auto resample = std::make_unique>(); auto estimate = std::make_unique>(map, 0.2, Point2(1,1)); //auto estimate = std::make_unique>(); //auto estimate = std::make_unique>(); // setup MyFilter pf(numParticles, std::move(init)); pf.setEvaluation(std::move(eval)); pf.setTransition(std::move(trans)); pf.setResampling(std::move(resample)); pf.setEstimation(std::move(estimate)); pf.setNEffThreshold(0.85); // sensors MyControl ctrl; MyObservation obs; StepDetection sd; PoseDetection pd; TurnDetection td(&pd); RelativePressure relBaro; ActivityDetector act; relBaro.setCalibrationTimeframe( Timestamp::fromMS(5000) ); Timestamp lastTimestamp = Timestamp::fromMS(0); // parse each sensor-value within the offline data for (const Offline::Entry& e : fr.getEntries()) { const Timestamp ts = Timestamp::fromMS(e.ts); if (e.type == Offline::Sensor::WIFI) { obs.wifi = fr.getWiFiGroupedByTime()[e.idx].data; ctrl.wifi = fr.getWiFiGroupedByTime()[e.idx].data; } else if (e.type == Offline::Sensor::ACC) { if (sd.add(ts, fr.getAccelerometer()[e.idx].data)) { ++ctrl.numStepsSinceLastEval; } const Offline::TS& _acc = fr.getAccelerometer()[e.idx]; pd.addAccelerometer(ts, _acc.data); //simpleActivity walking / standing act.add(ts, fr.getAccelerometer()[e.idx].data); } else if (e.type == Offline::Sensor::GYRO) { const Offline::TS& _gyr = fr.getGyroscope()[e.idx]; const float delta_gyro = td.addGyroscope(ts, _gyr.data); ctrl.headingChangeSinceLastEval += delta_gyro; } else if (e.type == Offline::Sensor::BARO) { relBaro.add(ts, fr.getBarometer()[e.idx].data); obs.relativePressure = relBaro.getPressureRealtiveToStart(); obs.sigmaPressure = relBaro.getSigma(); //simpleActivity stairs up / down act.add(ts, fr.getBarometer()[e.idx].data); obs.activity = act.get(); } if (ctrl.numStepsSinceLastEval > 0) { obs.currentTime = ts; ctrl.currentTime = ts; // if(ctrl.numStepsSinceLastEval > 0){ // pf.updateTransitionOnly(&ctrl); // } MyState est = pf.update(&ctrl, obs); //pf.updateEvaluationOnly(obs); ctrl.afterEval(); Point3 gtPos = gtInterpolator.get(static_cast(ts.ms())) + Point3(0,0,0.1); lastTimestamp = ts; ctrl.lastEstimate = est.pos.pos; //plot //dbg.showParticles(pf.getParticles()); //dbg.setCurPos(est.pos.pos); //dbg.setGT(gtPos); //dbg.addEstimationNode(est.pos.pos); //dbg.addGroundTruthNode(gtPos); //dbg.setTimeInMinute(static_cast(ts.sec()) / 60, static_cast(static_cast(ts.sec())%60)); //dbg.draw(); plot.showParticles(pf.getParticles()); plot.setCurEst(est.pos.pos); plot.setGroundTruth(gtPos); plot.addEstimationNode(est.pos.pos); plot.setActivity((int) act.get()); //plot.plot(); // error calc float err_m = gtPos.getDistance(est.pos.pos); errorStats.add(err_m); errorFile << ts.ms() << " " << err_m << "\n"; //dbg.gp.setOutput("/tmp/123/" + std::to_string(i) + ".png"); //dbg.gp.setTerminal("pngcairo", K::GnuplotSize(60, 30)); } } // get someting on console std::cout << "Statistical Analysis Filtering: " << std::endl; std::cout << "Median: " << errorStats.getMedian() << " Average: " << errorStats.getAvg() << " Std: " << errorStats.getStdDev() << std::endl; // save the statistical data in file errorFile << "========================================================== \n"; errorFile << "Average of all statistical data: \n"; errorFile << "Median: " << errorStats.getMedian() << "\n"; errorFile << "Average: " << errorStats.getAvg() << "\n"; errorFile << "Standard Deviation: " << errorStats.getStdDev() << "\n"; errorFile << "75 Quantil: " << errorStats.getQuantile(0.75) << "\n"; errorFile.close(); /* plot in gp file */ std::ofstream plotFile; plotFile.open(evalDir + "/" + std::to_string(numFile) + "_" + std::to_string(t) + ".gp"); plot.saveToFile(plotFile); plotFile.close(); //save also a png image, just for a better overview plot.printOverview(evalDir + "/" + std::to_string(numFile) + "_" + std::to_string(t)); plot.plot(); return errorStats; } int main(int argc, char** argv) { Stats::Statistics statsAVG; Stats::Statistics statsMedian; Stats::Statistics statsSTD; Stats::Statistics statsQuantil; Stats::Statistics tmp; std::string evaluationName = "museum/Path3_Museum_KLD_SimpleDistance"; for(int i = 0; i < 100; ++i){ //TODO: in transition die distance über KLD noch einkommentieren als Test // for(int j = 0; j < Settings::data.Path0.training.size(); ++j){ // tmp = run(Settings::data.Path0, j, evaluationName); // statsMedian.add(tmp.getMedian()); // statsAVG.add(tmp.getAvg()); // statsSTD.add(tmp.getStdDev()); // statsQuantil.add(tmp.getQuantile(0.75)); // } // for(int j = 0; j < Settings::data.Path1.training.size(); ++j){ // tmp = run(Settings::data.Path1, j, evaluationName); // statsMedian.add(tmp.getMedian()); // statsAVG.add(tmp.getAvg()); // statsSTD.add(tmp.getStdDev()); // statsQuantil.add(tmp.getQuantile(0.75)); // } // for(int j = 0; j < Settings::data.Path2.training.size(); ++j){ // tmp = run(Settings::data.Path2, j, evaluationName); // statsMedian.add(tmp.getMedian()); // statsAVG.add(tmp.getAvg()); // statsSTD.add(tmp.getStdDev()); // statsQuantil.add(tmp.getQuantile(0.75)); // } for(int j = 0; j < Settings::data.Path3.training.size(); ++j){ tmp = run(Settings::data.Path3, j, evaluationName); statsMedian.add(tmp.getMedian()); statsAVG.add(tmp.getAvg()); statsSTD.add(tmp.getStdDev()); statsQuantil.add(tmp.getQuantile(0.75)); } std::cout << "Iteration " << i << " completed" << std::endl;; } std::cout << "==========================================================" << std::endl; std::cout << "Average of all statistical data: " << std::endl; std::cout << "Median: " << statsMedian.getAvg() << std::endl; std::cout << "Average: " << statsAVG.getAvg() << std::endl; std::cout << "Standard Deviation: " << statsSTD.getAvg() << std::endl; std::cout << "75 Quantil: " << statsQuantil.getAvg() << std::endl; std::cout << "==========================================================" << std::endl; //EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS std::ofstream finalStatisticFile; finalStatisticFile.open (Settings::errorDir + evaluationName + ".csv", std::ios_base::app); finalStatisticFile << "========================================================== \n"; finalStatisticFile << "Average of all statistical data: \n"; finalStatisticFile << "Median: " << statsMedian.getAvg() << "\n"; finalStatisticFile << "Average: " << statsAVG.getAvg() << "\n"; finalStatisticFile << "Standard Deviation: " << statsSTD.getAvg() << "\n"; finalStatisticFile << "75 Quantil: " << statsQuantil.getAvg() << "\n"; finalStatisticFile << "========================================================== \n"; finalStatisticFile.close(); //std::this_thread::sleep_for(std::chrono::seconds(60)); }