#include #include "filter/Structs.h" #include "filter/KLB.h" #include "Plotti.h" #include "filter/Logic.h" #include "Settings.h" #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 + "SHL38.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_SHL38.dat" }; } data; Floorplan::IndoorMap* MyState::map; void 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"); 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); grid.write(onp); } else { grid.read(inp); } // add node-importance Importance::addImportance(grid); // 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); // init ctrl and observation MyControl ctrl; ctrl.resetAfterTransition(); MyObs obs; //random start position std::unique_ptr> init(new PFInit(grid)); std::move(init); //filter init //std::unique_ptr init = K::ParticleFilterHistory pf(Settings::numParticles, std::unique_ptr(new PFInit(grid))); //K::ParticleFilterHistory pf(Settings::numParticles, std::unique_ptr(new PFInitFixed(grid, GridPoint(1120.0f, 750.0f, 740.0f), 90.0f))); pf.setTransition(std::unique_ptr(new PFTrans(grid, &ctrl))); pf.setEvaluation(std::unique_ptr(new PFEval(WiFiModel, beaconModel, grid))); //resampling if(Settings::useKLB){ pf.setResampling(std::unique_ptr>(new K::ParticleFilterResamplingDivergence())); } else { //pf.setResampling(std::unique_ptr>(new K::ParticleFilterResamplingSimple())); pf.setResampling(std::unique_ptr>(new K::ParticleFilterResamplingPercent(0.4))); //pf.setResampling(std::unique_ptr>(new NodeResampling(*grid));); } pf.setNEffThreshold(0.95); //estimation //pf.setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationWeightedAverage())); //pf.setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationRegionalWeightedAverage())); pf.setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationOrderedWeightedAverage(0.5))); //pf.setEstimation(std::unique_ptr>(new K::ParticleFilterEstimationKernelDensity())); Timestamp lastTimestamp = Timestamp::fromMS(0); StepDetection sd; TurnDetection td; MotionDetection md; ActivityButterPressure act; RelativePressure relBaro; relBaro.setCalibrationTimeframe( Timestamp::fromMS(5000) ); K::Statistics errorStats; //calc wi-fi prob for every node and get mean vector WiFiObserverFree wiFiProbability(Settings::WiFiModel::sigma, WiFiModel); //file writing for error data const long int t = static_cast(time(NULL)); const std::string evalDir = errorDir + 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"); // 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); Eigen::Vector2f curVec = md.getCurrentMotionAxis(); ctrl.motionDeltaAngle_rad = md.getMotionChangeInRad(); } if (ts.ms() - lastTimestamp.ms() > 500) { obs.currentTime = ts; MyState est; if(Settings::useKLB){ const WiFiMeasurements wifiObs = Settings::WiFiModel::vg_eval.group(obs.wifi); std::vector allNodes = grid.getNodes(); std::vector> particleWifi; for(MyNode node : allNodes){ double prob = wiFiProbability.getProbability(node, ts, wifiObs); K::Particle tmp (MyState(GridPoint(node.x_cm, node.y_cm, node.z_cm)), prob); particleWifi.push_back(tmp); } if(kld_data.empty()){ kld_data.push_back(0.0); } double kld = 0.0; //set probability distributions. //std::function>&, MyState, std::vector>&)> kldFunc = getKernelDensityProbability; std::function>&, MyState, std::vector>&)> kldFunc = kldFromMultivariatNormal; //update filter est = pf.update(&ctrl, obs, particleWifi, kldFunc, kld); kld_data.push_back(kld); } else { est = pf.update(&ctrl, obs); } 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.addEstimationNode(estPos); plot.addParticles(pf.getParticles()); //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"; 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.98, 0.98 'act:" << obs.activity << "'\n"; // error between GT and estimation float err_m = gtPos.getDistance(estPos); errorStats.add(err_m); errorFile << err_m << "\n"; plot.show(); usleep(10*10); lastTimestamp = ts; // reset control ctrl.resetAfterTransition(); } } errorFile.close(); std::cout << "Statistical Analysis: " << std::endl; std::cout << "Median: " << errorStats.getMedian() << " Average: " << errorStats.getAvg() << std::endl; //Write the current plotti buffer into file std::ofstream plotFile; plotFile.open(errorDir + 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 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(); } std::cout << "finished" << std::endl; sleep(1); } int main(int argc, char** argv) { //Testing files //run(data.BERKWERK, 6, "EVALBERGWERK"); // Nexus vor //for(int i = 0; i < 5; ++i){ Settings::useKLB = false; //run(data.IPIN2017, 0, "ipin2017", Settings::Paths_IPIN2017::path1); run(data.IPIN2017, 1, "ipin2017", Settings::Paths_IPIN2017::path1); 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); Settings::useKLB = true; //run(data.IPIN2017, 0, "ipin2017", Settings::Paths_IPIN2017::path1); run(data.IPIN2017, 1, "ipin2017", Settings::Paths_IPIN2017::path1); 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); //} }