#ifndef MAINTONI_H #define MAINTONI_H #include #include "filter/Structs.h" #include "filter/KLB.h" #include "Plotti.h" #include "filter/Logic.h" #include "Settings.h" #include #include #include #include #include #include #include #include "navMesh/main.h" #define D_TONI 1 #define D_FRANK 2 #define USE_DATA D_FRANK #if (USE_DATA == D_FRANK) //const std::string mapDir = "/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/"; //const std::string dataDir = "/mnt/data/workspaces/IPIN2016/IPIN2016/competition/src/data/"; const std::string mapDir = "/apps/museum/maps/"; const std::string dataDir = "/apps/museum/data/"; const std::string errorDir = dataDir + "results/"; #elif (USE_DATA == D_TONI) const std::string mapDir = "/home/toni/Documents/programme/localization/IndoorMap/maps/"; //const std::string dataDir = "/home/toni/Documents/programme/localization/DynLag/code/data/"; const std::string dataDir = "/home/toni/Documents/programme/localization/museum/measurements/shl/"; //const std::string dataDir = "/home/toni/Documents/programme/localization/museum/measurements/motionAxisTest/"; const std::string errorDir = dataDir + "results/"; #endif /** describes one dataset (map, training, parameter-estimation, ...) */ struct DataSetup { std::string map; std::vector training; std::string wifiParams; int minWifiOccurences; VAPGrouper::Mode vapMode; std::string grid; }; /** all configured datasets */ struct Data { DataSetup SecondFloorOnly = { mapDir + "SHL_Stock_2_01.xml", { dataDir + "Path1_1.csv", dataDir + "Path2_1.csv", dataDir + "Path3_1.csv", }, mapDir + "wifi_fp_all.dat", 40, VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, mapDir + "grid_Stock_2_01.dat" }; DataSetup FloorOneToThree = { mapDir + "SHL_Stock_1-3_03.xml", { dataDir + "Path4_0.csv", dataDir + "Path5_0.csv", dataDir + "Path6_0.csv", }, mapDir + "wifi_fp_all.dat", 40, VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, mapDir + "grid_Stock_1-3_03.dat" }; DataSetup MotionAxisTest = { mapDir + "SHL40_noElevator.xml", { dataDir + "Path0_0.csv" }, mapDir + "wifi_fp_all.dat", 40, VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, mapDir + "grid_SHL40_noElevator.dat" }; } data; Floorplan::IndoorMap* MyState::map; Stats::Statistics run(DataSetup setup, int numFile, std::string folder, std::vector gtPath) { std::vector kld_data; // load the floorplan Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(setup.map); MyState::map = map; WiFiModelLogDistCeiling WiFiModel(map); WiFiModel.loadAPs(map, Settings::WiFiModel::TXP, Settings::WiFiModel::EXP, Settings::WiFiModel::WAF); Assert::isFalse(WiFiModel.getAllAPs().empty(), "no AccessPoints stored within the map.xml"); //Wi-Fi model new // WiFiModelFactory factory(map); // WiFiModel* wifimodel= factory.loadXML("/home/toni/Documents/programme/localization/data/wifi/model/eachOptParPos_multimodel.xml"); // Assert::isFalse(wifimodel->getAllAPs().empty(), "no AccessPoints stored within the map.xml"); BeaconModelLogDistCeiling beaconModel(map); beaconModel.loadBeaconsFromMap(map, Settings::BeaconModel::TXP, Settings::BeaconModel::EXP, Settings::BeaconModel::WAF); //Assert::isFalse(beaconModel.getAllBeacons().empty(), "no Beacons stored within the map.xml"); // build the grid std::ifstream inp(setup.grid, std::ifstream::binary); Grid grid(Settings::Grid::gridSize_cm); // grid.dat empty? -> build one and save it if (!inp.good() || (inp.peek()&&0) || inp.eof()) { std::ofstream onp; onp.open(setup.grid); GridFactory factory(grid); factory.build(map); // add node-importance Importance::addImportance(grid); grid.write(onp); } else { grid.read(inp); } // stamp WiFi signal-strengths onto the grid WiFiGridEstimator::estimate(grid, WiFiModel, Settings::smartphoneAboveGround); // reading file Offline::FileReader fr(setup.training[numFile]); //interpolator for ground truth Interpolator gtInterpolator = fr.getGroundTruthPath(map, gtPath); //gnuplot plot Plotti plot; plot.addFloors(map); plot.addOutline(map); plot.addStairs(map); plot.gp << "set autoscale xy\n"; //plot.addGrid(grid); plot.splot.getView().setEnabled(false); // init ctrl and observation MyControl ctrl; ctrl.resetAfterTransition(); MyObs obs; //History of all estimated particles. Used for smoothing SMC::ForwardFilterHistory pfHistory; //filter init SMC::ParticleFilterHistory pf(Settings::numParticles, std::unique_ptr(new PFInit(grid))); //SMC::ParticleFilterHistory pf(Settings::numParticles, std::unique_ptr(new PFInitFixed(grid, GridPoint(55.5f * 100.0, 43.7f * 100.0, 740.0f), 180.0f))); pf.setTransition(std::unique_ptr(new PFTrans(grid, &ctrl))); //pf.setTransition(std::unique_ptr(new PFTransKLDSampling(grid, &ctrl))); //pf.setTransition(std::unique_ptr(new PFTransSimple(grid))); pf.setEvaluation(std::unique_ptr(new PFEval(WiFiModel, beaconModel, grid))); //resampling if(Settings::useKLB){ pf.setResampling(std::unique_ptr>(new SMC::ParticleFilterResamplingDivergence())); } else { pf.setResampling(std::unique_ptr>(new SMC::ParticleFilterResamplingSimple())); //pf.setResampling(std::unique_ptr>(new SMC::ParticleFilterResamplingPercent(0.4))); //pf.setResampling(std::unique_ptr>(new NodeResampling(*grid));); //pf.setResampling(std::unique_ptr>(new SMC::ParticleFilterResamplingKLD())); } pf.setNEffThreshold(0.95); //estimation pf.setEstimation(std::unique_ptr>(new SMC::ParticleFilterEstimationWeightedAverage())); //pf.setEstimation(std::unique_ptr>(new SMC::ParticleFilterEstimationRegionalWeightedAverage())); //pf.setEstimation(std::unique_ptr>(new SMC::ParticleFilterEstimationOrderedWeightedAverage(0.5))); //pf.setEstimation(std::unique_ptr>(new SMC::ParticleFilterEstimationKernelDensity())); /** Smoothing Init */ SMC::FastKDESmoothing bf(Settings::numParticles, map, Settings::Grid::gridSize_cm, Settings::KDE::bandwidth); if(Settings::Smoothing::activated){ //create the backward smoothing filter bf.setSampler( std::unique_ptr>(new SMC::CumulativeSampler())); bool smoothing_resample = false; //bf->setNEffThreshold(1.0); if(smoothing_resample) bf.setResampling( std::unique_ptr>(new SMC::ParticleFilterResamplingSimple()) ); //bf.setTransition(std::unique_ptr( new BFTrans) ); bf.setTransition(std::unique_ptr(new PFTrans(grid, &ctrl))); //Smoothing estimation bf.setEstimation(std::unique_ptr>(new SMC::ParticleFilterEstimationWeightedAverage())); //bf->setEstimation( std::unique_ptr>(new SMC::ParticleFilterEstimationRegionalWeightedAverage())); //bf->setEstimation( std::unique_ptr>(new SMC::ParticleFilterEstimationOrderedWeightedAverage(0.50f))); } Timestamp lastTimestamp = Timestamp::fromMS(0); StepDetection sd; PoseDetection pd; TurnDetection td(&pd); MotionDetection md; ActivityButterPressure act; //ActivityDetector act; RelativePressure relBaro; relBaro.setCalibrationTimeframe( Timestamp::fromMS(5000) ); Stats::Statistics errorStats; Stats::Statistics errorStatsSmoothing; //file writing for error data const long int t = static_cast(time(NULL)); const std::string evalDir = errorDir + folder + std::to_string(t); 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"); std::ofstream errorFileSmoothing; errorFileSmoothing.open (evalDir + "/" + std::to_string(numFile) + "_" + std::to_string(t) + "_Smoothing.csv"); // 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; } else if (e.type == Offline::Sensor::BEACON){ obs.beacons.entries.push_back(fr.getBeacons()[e.idx].data); // remove to old beacon measurements obs.beacons.removeOld(ts); } else if (e.type == Offline::Sensor::ACC) { if (sd.add(ts, fr.getAccelerometer()[e.idx].data)) { ++ctrl.numStepsSinceLastTransition; } const Offline::TS& _acc = fr.getAccelerometer()[e.idx]; pd.addAccelerometer(ts, _acc.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.turnSinceLastTransition_rad += 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(); //activity recognition act.add(ts, fr.getBarometer()[e.idx].data); obs.activity = act.get(); //activity for transition } else if (e.type == Offline::Sensor::LIN_ACC) { md.addLinearAcceleration(ts, fr.getLinearAcceleration()[e.idx].data); } else if (e.type == Offline::Sensor::GRAVITY) { md.addGravity(ts, fr.getGravity()[e.idx].data); Eigen::Vector2f curVec = md.getCurrentMotionAxis(); ctrl.motionDeltaAngle_rad = md.getMotionChangeInRad(); } if (ts.ms() - lastTimestamp.ms() > 500) { /** filtering stuff */ obs.currentTime = ts; MyState est = pf.update(&ctrl, obs); Point3 estPos = est.position.inMeter(); Point3 gtPos = gtInterpolator.get(static_cast(ts.ms())); /** plotting stuff */ plot.pInterest.clear(); plot.setEst(estPos); plot.setGT(gtPos); //plot.addEstimationNode(estPos); //plot.addParticles(pf.getParticles()); /** error calculation stuff */ float err_m = gtPos.getDistance(estPos); errorStats.add(err_m); errorFile << err_m << "\n"; /** smoothing stuff */ if(Settings::Smoothing::activated){ // add everything from the forward step to the history pfHistory.add(ts, pf.getNonResamplingParticles(), ctrl, obs); //backward filtering //((BFTrans*)bf.getTransition())->setCurrentTime(tsHistory[(tsHistory.size() - 1) - i]); MyState estBF = bf.update(pfHistory, Settings::Smoothing::lag); // get ground truth position at lag time Point3 estPosSmoothing = estBF.position.inMeter(); Point3 gtPosSmoothed; if(pfHistory.size() <= Settings::Smoothing::lag){ gtPosSmoothed = gtInterpolator.get(static_cast(pfHistory.getFirstTimestamp().ms())); } else { gtPosSmoothed = gtInterpolator.get(static_cast(pfHistory.getTimestamp(Settings::Smoothing::lag).ms())); } //plot plot.addEstimationNodeSmoothed(estPosSmoothing); plot.addParticles(bf.getbackwardParticles().back()); if(Settings::Smoothing::lag >= pfHistory.size()){ // error between GT and smoothing float errSmoothing_m = gtPosSmoothed.getDistance(estPosSmoothing); errorStatsSmoothing.add(errSmoothing_m); errorFileSmoothing << errSmoothing_m << "\n"; } } //plot misc plot.setTimeInMinute(static_cast(ts.sec()) / 60, static_cast(static_cast(ts.sec())%60)); if(Settings::useKLB){ plot.gp << "set label 1002 at screen 0.04, 0.94 'KLD: " << ":" << kld_data.back() << "'\n"; } plot.gp << "set label 1002 at screen 0.95, 0.98 'act:" << static_cast(obs.activity) << "'\n"; //draw gyro angle and motion angle //turn angle plot static float angleSumTurn = 0; angleSumTurn += ctrl.turnSinceLastTransition_rad; plot.showAngle(1, angleSumTurn + M_PI, Point2(0.9, 0.9), "Turn: "); //motion angle plot static float angleSumMotion = 0; angleSumMotion += ctrl.motionDeltaAngle_rad; plot.showAngle(2, angleSumMotion + M_PI, Point2(0.9, 0.8), "Motion: "); /** Draw everything */ plot.show(); usleep(10*10); lastTimestamp = ts; // reset control ctrl.resetAfterTransition(); } } errorFile.close(); std::cout << "Statistical Analysis Filtering: " << std::endl; std::cout << "Median: " << errorStats.getMedian() << " Average: " << errorStats.getAvg() << " Std: " << errorStats.getStdDev() << std::endl; std::cout << "Statistical Analysis Smoothing: " << std::endl; std::cout << "Median: " << errorStatsSmoothing.getMedian() << " Average: " << errorStatsSmoothing.getAvg() << " Std: " << errorStatsSmoothing.getStdDev() << std::endl; //Write the current plotti buffer into file std::ofstream plotFile; plotFile.open(evalDir + "/plot_" + std::to_string(numFile) + "_" + std::to_string(t) + ".gp"); plot.saveToFile(plotFile); plotFile.close(); for(int i = 0; i < map->floors.size(); ++i){ plot.printSingleFloor(evalDir + "/image" + std::to_string(numFile) + "_" + std::to_string(t), i); plot.show(); usleep(10*10); } plot.printSideView(evalDir + "/image" + std::to_string(numFile) + "_" + std::to_string(t), 90); plot.show(); plot.printSideView(evalDir + "/image" + std::to_string(numFile) + "_" + std::to_string(t), 0); plot.show(); plot.printOverview(evalDir + "/image" + std::to_string(numFile) + "_" + std::to_string(t)); plot.show(); /** Draw KLB */ K::Gnuplot gp; K::GnuplotPlot plotkld; K::GnuplotPlotElementLines lines; if(Settings::useKLB){ std::string path = evalDir + "/image" + std::to_string(numFile) + "_" + std::to_string(t); gp << "set terminal png size 1280,720\n"; gp << "set output '" << path << "_shennendistance.png'\n"; for(int i=0; i < kld_data.size()-1; ++i){ K::GnuplotPoint2 p1(i, kld_data[i]); K::GnuplotPoint2 p2(i+1, kld_data[i+1]); lines.addSegment(p1, p2); } plotkld.add(&lines); gp.draw(plotkld); gp.flush(); plot.splot.getView().setEnabled(false); } std::cout << "finished" << std::endl; sleep(1); return errorStats; } int main(int argc, char** argv) { Stats::Statistics statsAVG; Stats::Statistics statsMedian; Stats::Statistics statsSTD; Stats::Statistics statsQuantil; Stats::Statistics tmp; for(int i = 0; i < 10; ++i){ tmp = run(data.SecondFloorOnly, 0, "KDE-Smoothing-Test", Settings::Path_DongleTest::path1); statsMedian.add(tmp.getMedian()); statsAVG.add(tmp.getAvg()); statsSTD.add(tmp.getStdDev()); statsQuantil.add(tmp.getQuantile(0.75)); // tmp = run(data.MotionAxisTest, 0, "Motion-Axis-Test", Settings::Path_DongleTest::path1); // 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 (errorDir + "/tmp.csv"); 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.close(); //EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS EDIT THIS } #endif // MAINTONI_H