#include #include "filter/Structs.h" #include "filter/KLB.h" #include "Plotti.h" #include "filter/Logic.h" #include "Settings.h" #include #include #include //frank //const std::string mapDir = "/mnt/data/workspaces/IPIN2016/IPIN2016/competition/maps/"; //const std::string dataDir = "/mnt/data/workspaces/IPIN2016/IPIN2016/competition/src/data/"; //toni const std::string mapDir = "/home/toni/Documents/programme/localization/IndoorMap/maps/"; const std::string dataDir = "/home/toni/Documents/programme/localization/IPIN2017/code/data/"; const std::string errorDir = dataDir + "results/"; /** 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 BERKWERK = { mapDir + "SHL/SHL25.xml", { dataDir + "bergwerk/path1/nexus/vor/1454775984079.csv", dataDir + "bergwerk/path1/galaxy/vor/1454776168794.csv", dataDir + "bergwerk/path2/nexus/vor/1454779863041.csv", dataDir + "bergwerk/path2/galaxy/vor/1454780113404.csv", dataDir + "bergwerk/path3/nexus/vor/1454782562231.csv", dataDir + "bergwerk/path3/galaxy/vor/1454782896548.csv", dataDir + "bergwerk/path4/nexus/vor/1454776525797.csv", dataDir + "bergwerk/path4/galaxy/vor/1454779020844.csv" }, dataDir + "bergwerk/wifiParams.txt", 40, VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, mapDir + "SHL/grid25.dat" }; DataSetup IPIN2015 = { mapDir + "SHL/SHL_IPIN2015_gt.xml", { dataDir + "ipin2015/galaxy/Path0/1433581471902.csv", dataDir + "ipin2015/nexus/Path0/1433606195078.csv", dataDir + "ipin2015/galaxy/Path1/1433587749492.csv", dataDir + "ipin2015/nexus/Path1/1433606670723.csv", // wlan für 71 sekunden weg. verlaufen uns aufm klo. dataDir + "ipin2015/galaxy/Path2/1433581471902.csv", dataDir + "ipin2015/nexus/Path2/1433607251262.csv", dataDir + "eiszeit/path2/1479986737368.csv" }, dataDir + "bergwerk/wifiParams.txt", 40, VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, mapDir + "SHL/grid_IPIN2015_gt.dat" }; DataSetup IPIN2017 = { mapDir + "SHL39.xml", { dataDir + "ipin2017/nogps/i-building/path1/1489769326868.csv", dataDir + "ipin2017/nogps/i-building/path1/1489769510080.csv", dataDir + "ipin2017/nogps/i-building/path2/1489774173022.csv", dataDir + "ipin2017/nogps/i-building/path2/1489774361865.csv", dataDir + "ipin2017/nogps/i-building/path3/1489776812891.csv", dataDir + "ipin2017/nogps/i-building/path3/1489776979143.csv", dataDir + "ipin2017/nogps/all/path1/1490031549543.csv", dataDir + "ipin2017/nogps/all/path1/1490031883742.csv", dataDir + "ipin2017/nogps/all/path2/1490032575999.csv", dataDir + "ipin2017/nogps/all/path2/1490032861864.csv", dataDir + "ipin2017/nogps/all/path3/EMPTY.csv", dataDir + "ipin2017/nogps/all/path3/EMPTY.csv", }, mapDir + "wifi_fp_all.dat", 40, VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, mapDir + "grid_SHL39.dat" }; } data; //Floorplan::IndoorMap* MyState::map; K::Statistics run(DataSetup setup, int numFile, std::string folder, std::vector gtPath) { std::vector kld_data; std::vector quality_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"); 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(20); // 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); Importance::addImportance(grid); WiFiGridEstimator::estimate(grid, WiFiModel, Settings::smartphoneAboveGround); grid.write(onp); } else { grid.read(inp); } // 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); // init ctrl and observation MyControl ctrl; ctrl.resetAfterTransition(); MyObs obs; //init the mode filters std::vector> modes; //std::shared_ptr> init(new PFInitFixed(grid, GridPoint(1120.0f, 750.0f, 740.0f), 90.0f)); // mode 1 std::shared_ptr> initMode1(new PFInit(grid, 1)); //std::shared_ptr> initMode1(new PFInitFixed(grid, GridPoint(1120.0f, 750.0f, 740.0f), 90.0f, 1)); K::ParticleFilterMixing mode1(Settings::numParticles, initMode1, Settings::Mode1::modeProbability); mode1.setTransition(std::shared_ptr(new PFTrans(grid, &ctrl))); mode1.setEvaluation(std::shared_ptr(new PFEval(WiFiModel, beaconModel, grid))); mode1.setResampling(std::shared_ptr>(new K::ParticleFilterResamplingSimple())); mode1.setNEffThreshold(0.95); mode1.setEstimator(std::shared_ptr>(new K::ParticleFilterEstimationWeightedAverage())); modes.push_back(mode1); // mode 2 std::shared_ptr> initMode2(new PFInit(grid, 2)); //std::shared_ptr> initMode2(new PFInitFixed(grid, GridPoint(1120.0f, 750.0f, 740.0f), 90.0f, 2)); K::ParticleFilterMixing mode2(Settings::numParticles, initMode2, Settings::Mode2::modeProbability); mode2.setTransition(std::shared_ptr(new PFTransSimple(grid))); mode2.setEvaluation(std::shared_ptr(new PFEval(WiFiModel, beaconModel, grid))); mode2.setResampling(std::shared_ptr>(new K::ParticleFilterResamplingSimple())); mode2.setNEffThreshold(0.95); mode2.setEstimator(std::shared_ptr>(new K::ParticleFilterEstimationWeightedAverage())); modes.push_back(mode2); //init mixing Eigen::MatrixXd transitionProbabilityMatrix(2,2); transitionProbabilityMatrix << 1,0,0,1; K::InteractingMultipleModelParticleFilter IMMAPF(modes, transitionProbabilityMatrix); IMMAPF.setMixingSampler(std::unique_ptr>(new K::MixingSamplerDivergency())); IMMAPF.setJointEstimation(std::unique_ptr>(new K::JointEstimationPosteriorOnly())); //IMMAPF.setMarkovTransitionProbability(std::unique_ptr(new ModeProbabilityTransition(grid, Settings::Mixing::lambda))); IMMAPF.setMarkovTransitionProbability(std::unique_ptr(new ModeProbabilityTransitionNormal(Settings::Mixing::lambda))); Timestamp lastTimestamp = Timestamp::fromMS(0); StepDetection sd; TurnDetection td; MotionDetection md; ActivityButterPressure act; RelativePressure relBaro; relBaro.setCalibrationTimeframe( Timestamp::fromMS(5000) ); K::Statistics errorStats; //file writing for error data const long int t = static_cast(time(NULL)); const std::string evalDir = errorDir + "final_" + 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 kldFile; kldFile.open (evalDir + "/kld_" + std::to_string(numFile) + "_" + std::to_string(t) + ".csv"); std::ofstream wifiFile; wifiFile.open (evalDir + "/wifi_" + std::to_string(numFile) + "_" + std::to_string(t) + ".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]; td.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 obs.activity = act.add(ts, fr.getBarometer()[e.idx].data); //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); ctrl.motionDeltaAngle_rad = md.getMotionChangeInRad(); } if (ts.ms() - lastTimestamp.ms() > 500) { obs.currentTime = ts; MyState est; //update filter est = IMMAPF.update(&ctrl, obs); if(kld_data.empty()){ kld_data.push_back(0.0); } else{ kld_data.push_back(__KLD); } quality_data.push_back(__QUALITY); Point3 estPos = est.position.inMeter(); //current ground truth position Point3 gtPos = gtInterpolator.get(static_cast(ts.ms())); /** plotting stuff */ plot.pInterest.clear(); //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: "); //plot.setEst(estPos); //plot.setGT(gtPos); plot.addParticles1(IMMAPF.getModes()[0].getParticles()); plot.addParticles2(IMMAPF.getModes()[1].getParticles()); plot.addEstimationNode(estPos); //plot.addEstimationNodeSmoothed(IMMAPF.getModes()[1].getEstimation().position.inMeter()); //plot.gp << "set arrow 919 from " << tt.pos.x << "," << tt.pos.y << "," << tt.pos.z << " to "<< tt.pos.x << "," << tt.pos.y << "," << tt.pos.z+1 << "lw 3\n"; //plot.gp << "set label 1001 at screen 0.02, 0.98 'base:" << relBaro.getBaseAvg() << " sigma:" << relBaro.getSigma() << " cur:" << relBaro.getPressureRealtiveToStart() << " hPa " << -relBaro.getPressureRealtiveToStart()/0.10/4.0f << " floor'\n"; //int minutes = static_cast(ts.sec()) / 60; //plot.gp << "set label 1002 at screen 0.02, 0.94 'Time: " << minutes << ":" << static_cast(static_cast(ts.sec())%60) << "'\n"; //plot.gp << "set label 1003 at screen 0.02, 0.92 'KLD: " << ":" << kld_data.back() << "'\n"; //plot.gp << "set label 1004 at screen 0.90, 0.98 'act:" << obs.activity << "'\n"; //plot.gp << "set label 1011 at screen 0.90, 0.10 'Wifi Quality:" << __QUALITY << "'\n"; //plot.gp << "set label 1005 at screen 0.90, 0.08 'Prob. Mode1:" << IMMAPF.getModes()[0].getModePosteriorProbability() << "'\n"; //plot.gp << "set label 1006 at screen 0.90, 0.06 'Prob. Mode2:" << IMMAPF.getModes()[1].getModePosteriorProbability() << "'\n"; int ones = 0; int twos = 0; for(int i = 0; i < IMMAPF.getModes()[0].getParticles().size(); ++i){ int mode1 = IMMAPF.getModes()[0].getParticles()[i].state.curMode; int mode2 = IMMAPF.getModes()[1].getParticles()[i].state.curMode; if(mode1 == 1){ ++ones; } else { ++twos; } if(mode2 == 1){ ++ones; } else { ++twos; } } //plot.gp << "set label 1007 at screen 0.90, 0.04 'Part. Mode1:" << ones << "'\n"; //plot.gp << "set label 1008 at screen 0.90, 0.02 'Part. Mode2:" << twos << "'\n"; // error between GT and estimation float err_m = gtPos.getDistance(estPos); errorStats.add(err_m); errorFile << err_m << "\n"; kldFile << kld_data.back() << "\n"; wifiFile << __QUALITY << "\n"; plot.show(); usleep(10*10); lastTimestamp = ts; // reset control ctrl.resetAfterTransition(); } } errorFile.close(); kldFile.close(); wifiFile.close(); std::cout << "Statistical Analysis: " << std::endl; std::cout << "Median: " << errorStats.getMedian() << " Average: " << errorStats.getAvg() << " Std: " << errorStats.getStdDev() << std::endl; //Write the current plotti buffer into file std::ofstream plotFile; plotFile.open(evalDir + "/gnuplot_" + 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 kld K::Gnuplot gp; K::GnuplotPlot plotkld; K::GnuplotPlotElementLines lines; //save as screenshot for klb 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 << "klddistance.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(); //draw wifi quality K::Gnuplot gpQuality; K::GnuplotPlot plotquality; K::GnuplotPlotElementLines linesQuality; //save as screenshot for wifiquality std::string pathWifi = evalDir + "/image" + std::to_string(numFile) + "_" + std::to_string(t); gpQuality << "set terminal png size 1280,720\n"; gpQuality << "set output '" << pathWifi << "wifiquality.png'\n"; for(int i=0; i < quality_data.size()-1; ++i){ K::GnuplotPoint2 p1(i, quality_data[i]); K::GnuplotPoint2 p2(i+1, quality_data[i+1]); linesQuality.addSegment(p1, p2); } plotquality.add(&linesQuality); gpQuality.draw(plotquality); gpQuality.flush(); std::cout << "finished" << std::endl; sleep(1); return errorStats; } int main(int argc, char** argv) { //Testing files //run(data.BERKWERK, 6, "EVALBERGWERK"); // Nexus vor K::Statistics statsAVG; K::Statistics statsMedian; K::Statistics statsSTD; K::Statistics statsQuantil; K::Statistics tmp; for(int i = 0; i < 1; ++i){ // Settings::useKLB = false; // errorPair = run(data.IPIN2017, 1, "ipin2017", Settings::Paths_IPIN2017::path1); // run(data.IPIN2017, 0, "ipin2017", Settings::Paths_IPIN2017::path1); // errorPair = run(data.IPIN2017, 2, "ipin2017", Settings::Paths_IPIN2017::path2); // //run(data.IPIN2017, 3, "ipin2017", Settings::Paths_IPIN2017::path2); // run(data.IPIN2017, 5, "ipin2017", Settings::Paths_IPIN2017::path3); // //run(data.IPIN2017, 4, "ipin2017", Settings::Paths_IPIN2017::path3); tmp = run(data.IPIN2017, 4, "ipin2017", Settings::Paths_IPIN2017::path3); statsMedian.add(tmp.getMedian()); statsAVG.add(tmp.getAvg()); statsSTD.add(tmp.getStdDev()); statsQuantil.add(tmp.getQuantile(0.75)); tmp = run(data.IPIN2017, 5, "ipin2017", Settings::Paths_IPIN2017::path3); 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 + "/finalResults_Path3_AbsBaro.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 return 0; }