From 212573cba201459d154aac57e68b46d3a18a2ddb Mon Sep 17 00:00:00 2001 From: toni Date: Thu, 23 Mar 2017 19:50:33 +0100 Subject: [PATCH] added kld with parzen and nv distribution added new testfiles fixed plot fixed numerical errors --- code/Plotti.h | 73 ++++++++++++++++++ code/Settings.h | 48 +++++++++++- code/filter/Logic.h | 4 +- code/filter/Structs.h | 2 +- code/main.cpp | 172 +++++++++++++++++++++++------------------- 5 files changed, 215 insertions(+), 84 deletions(-) diff --git a/code/Plotti.h b/code/Plotti.h index a295350..6166b13 100644 --- a/code/Plotti.h +++ b/code/Plotti.h @@ -35,6 +35,10 @@ struct Plotti { K::GnuplotSplotElementPoints pAPs; K::GnuplotSplotElementPoints pInterest; K::GnuplotSplotElementPoints pParticles; + K::GnuplotSplotElementPoints pNormal1; + K::GnuplotSplotElementPoints pNormal2; + K::GnuplotSplotElementColorPoints pDistributation1; + K::GnuplotSplotElementColorPoints pDistributation2; K::GnuplotSplotElementColorPoints pColorPoints; K::GnuplotSplotElementLines gtPath; K::GnuplotSplotElementLines estPath; @@ -45,7 +49,11 @@ struct Plotti { splot.add(&pGrid); pGrid.setPointSize(0.25); pGrid.setColorHex("#888888"); splot.add(&pAPs); pAPs.setPointSize(0.7); splot.add(&pColorPoints); pColorPoints.setPointSize(0.6); + splot.add(&pDistributation1); pDistributation1.setPointSize(0.6); + splot.add(&pDistributation2); pDistributation2.setPointSize(0.6); splot.add(&pParticles); pParticles.setColorHex("#0000ff"); pParticles.setPointSize(0.4f); + splot.add(&pNormal1); pNormal1.setColorHex("#ff00ff"); pNormal1.setPointSize(0.4f); + splot.add(&pNormal2); pNormal2.setColorHex("#00aaff"); pNormal2.setPointSize(0.4f); splot.add(&pFloor); splot.add(&pOutline); pOutline.setColorHex("#999999"); splot.add(&pStairs); pStairs.setColorHex("#000000"); @@ -100,6 +108,71 @@ struct Plotti { estPathSmoothed.add(est); } + void debugDistribution1(std::vector> samples){ + + float min = +9999; + float max = -9999; + + pDistributation1.clear(); + for (int i = 0; i < samples.size(); ++i) { + //if (i % 10 != 0) {continue;} + + double prob = samples[i].weight; + if (prob < min) {min = prob;} + if (prob > max) {max = prob;} + + K::GnuplotPoint3 pos(samples[i].state.position.x_cm / 100.0f, samples[i].state.position.y_cm / 100.0f, samples[i].state.position.z_cm / 100.0f); + pDistributation1.add(pos, prob); + } + + if (min == max) {min -= 1;} + gp << "set cbrange [" << min << ":" << max << "]\n"; + } + + void debugDistribution2(std::vector> samples){ + + float min = +9999; + float max = -9999; + + pDistributation2.clear(); + for (int i = 0; i < samples.size(); ++i) { + if (i % 25 != 0) {continue;} + + double prob = samples[i].weight; + if (prob < min) {min = prob;} + if (prob > max) {max = prob;} + + K::GnuplotPoint3 pos(samples[i].state.position.x_cm / 100.0f, samples[i].state.position.y_cm / 100.0f, samples[i].state.position.z_cm / 100.0f); + pDistributation2.add(pos, prob); + } + + if (min == max) {min -= 1;} + gp << "set cbrange [" << min << ":" << max << "]\n"; + } + + void drawNormalN1(Distribution::NormalDistributionN normParticle){ + + pNormal1.clear(); + for (int i = 0; i < 100000; ++i) { + if (++i % 25 != 0) {continue;} + Eigen::VectorXd vec = normParticle.draw(); + K::GnuplotPoint3 pos(vec.x(), vec.y(), vec.z()); + pNormal1.add(pos); + } + + } + + void drawNormalN2(Distribution::NormalDistributionN normParticle){ + + pNormal2.clear(); + for (int i = 0; i < 100000; ++i) { + if (++i % 25 != 0) {continue;} + Eigen::VectorXd vec = normParticle.draw(); + K::GnuplotPoint3 pos(vec.x(), vec.y(), vec.z()); + pNormal2.add(pos); + } + } + void debugWiFi(WiFiModelLogDistCeiling& model, const WiFiMeasurements& scan, const Timestamp curTS, const float z) { WiFiObserverFree wiFiProbability(Settings::WiFiModel::sigma, model); diff --git a/code/Settings.h b/code/Settings.h index 8a270fb..6ee7a1f 100644 --- a/code/Settings.h +++ b/code/Settings.h @@ -7,7 +7,7 @@ namespace Settings { - const int numParticles = 10000; + const int numParticles = 5000; namespace IMU { const float turnSigma = 2.5; // 3.5 @@ -31,7 +31,7 @@ namespace Settings { const Timestamp updateEvery = Timestamp::fromMS(200); } - namespace WiFiModel { + namespace WiFiModel { constexpr float sigma = 8.0; /** if the wifi-signal-strengths are stored on the grid-nodes, this needs a grid rebuild! */ constexpr float TXP = -46; @@ -46,6 +46,21 @@ namespace Settings { const VAPGrouper vg_eval = VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE); } + namespace WiFiModelOptimized { + constexpr float sigma = 8.0; + /** if the wifi-signal-strengths are stored on the grid-nodes, this needs a grid rebuild! */ + constexpr float TXP = -64.5905; + constexpr float EXP = 1.25988; + constexpr float WAF = -2.47863; + + // how to perform VAP grouping. see + // - calibration in Controller.cpp + // - eval in Filter.h + // NOTE: maybe the UAH does not allow valid VAP grouping? delete the grid and rebuild without! + const VAPGrouper vg_calib = VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE); + const VAPGrouper vg_eval = VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE); + } + namespace BeaconModel { constexpr float sigma = 8.0; constexpr float TXP = -71; @@ -54,7 +69,7 @@ namespace Settings { } namespace MapView3D { - const int maxColorPoints = 10000; + const int maxColorPoints = 1000; constexpr int fps = 15; const Timestamp msPerFrame = Timestamp::fromMS(1000/fps); } @@ -64,6 +79,33 @@ namespace Settings { constexpr bool useMainThread = false; // perform filtering in the main thread } + namespace Paths_IPIN2015 { + // doing ground truth stuff for ipin 2015 + const std::vector path_0 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 1, 0}; + const std::vector path_1 = {29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 13, 14, 15, 16, 17, 18, 19, 2, 1, 0}; + const std::vector path_2 = {29, 28, 27, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 19, 18, 17, 16, 15, 14, 13, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; + } + + namespace Paths_Bergwerk { + // ipin 2016 (bergwerk) + const std::vector path1dbl = {29, 29, 28,27,26,255,25,24,23,22,21,20}; + const std::vector path2dbl = {19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 23, 7, 6}; + const std::vector path3dbl = {5, 5, 27, 26, 255, 25, 4, 3, 2, 215, 1, 0, 30, 31}; + const 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! + } + + namespace Paths_IPIN2017 { + const std::vector path1 = {0, 1, 2, 3, 4, 5, 6, 7, 700, 8, 9, 10}; + const std::vector path2 = {11, 12, 3, 2, 1, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 11}; + const std::vector path3 = {31, 32, 33, 34, 35, 36, 37, 38}; + } + + namespace PATHS_OTHER2017 { + const std::vector path1 = {40, 41, 42, 43, 44, 45, 1, 0, 46, 47, 48, 49, 50, 51, 52}; + const std::vector path2 = {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66}; + const std::vector path3 = {52, 51, 67, 68, 50, 49, 69, 70, 71, 72, 73, 74, 75, 76, 77, 73, 78, 79, 80, 81, 61, 82, 83, 84, 42, 41, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}; + } + } #endif // SETTINGS_H diff --git a/code/filter/Logic.h b/code/filter/Logic.h index 5e686ed..737afd4 100644 --- a/code/filter/Logic.h +++ b/code/filter/Logic.h @@ -190,13 +190,13 @@ struct PFEval : public K::ParticleFilterEvaluation { const double pWifi = getWIFI(observation, wifiObs, p.state.position); const double pBaroPressure = getBaroPressure(observation, p.state.relativePressure); - const double pBeacon = getBEACON(observation, p.state.position); + //const double pBeacon = getBEACON(observation, p.state.position); //small checks _assertNotNAN(pWifi, "Wifi prob is nan"); _assertNot0(pBaroPressure,"pBaroPressure is null"); - const double prob = pBaroPressure * pBeacon * pWifi; + const double prob = pBaroPressure * pWifi; p.weight = prob; sum += (prob); diff --git a/code/filter/Structs.h b/code/filter/Structs.h index b632edc..b79694d 100644 --- a/code/filter/Structs.h +++ b/code/filter/Structs.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,6 @@ struct MyState : public WalkState, public WalkStateHeading, public WalkStateSpre GridPoint positionOld; - MyState() : WalkState(GridPoint(0,0,0)), WalkStateHeading(Heading(0), 0), positionOld(0,0,0), relativePressure(0) {;} MyState(GridPoint pos) : WalkState(pos), WalkStateHeading(Heading(0), 0), positionOld(0,0,0), relativePressure(0) {;} diff --git a/code/main.cpp b/code/main.cpp index da4bc70..347b781 100755 --- a/code/main.cpp +++ b/code/main.cpp @@ -1,58 +1,19 @@ #include #include "filter/Structs.h" +#include "filter/KLB.h" #include "Plotti.h" - -#include - #include "filter/Logic.h" - -#include -#include - -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - #include "Settings.h" -#include -#include -#include - -#include -#include -#include -#include - -#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/russenJournal/russen/map/"; -const std::string dataDir = "/home/toni/Documents/programme/localization/russenJournal/russen/data/"; +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, ...) */ @@ -97,7 +58,7 @@ struct Data { dataDir + "ipin2015/galaxy/Path0/1433581471902.csv", dataDir + "ipin2015/nexus/Path0/1433606195078.csv", dataDir + "ipin2015/galaxy/Path1/1433587749492.csv", - dataDir + "ipin2015/nexus/Path1/1433606670723.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" @@ -109,6 +70,31 @@ struct Data { 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; @@ -116,6 +102,8 @@ Floorplan::IndoorMap* MyState::map; void run(DataSetup setup, int numFile, std::string folder) { + std::vector kld_data; + // load the floorplan Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(setup.map); MyState::map = map; @@ -126,7 +114,7 @@ void run(DataSetup setup, int numFile, std::string folder) { 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"); + //Assert::isFalse(beaconModel.getAllBeacons().empty(), "no Beacons stored within the map.xml"); // build the grid @@ -152,15 +140,12 @@ void run(DataSetup setup, int numFile, std::string folder) { WiFiGridEstimator::estimate(grid, WiFiModel, Settings::smartphoneAboveGround); // reading file - FileReader fr(setup.training[numFile]); - - // doing ground truth stuff - std::vector path_0 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 1, 0}; - std::vector path_1 = {29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 13, 14, 15, 16, 17, 18, 19, 2, 1, 0}; - std::vector path_2 = {29, 28, 27, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 19, 18, 17, 16, 15, 14, 13, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; - Interpolator gtInterpolator = fr.getGroundTruthPath(map, path_1); + Offline::FileReader fr(setup.training[numFile]); + //interpolator for ground truth + Interpolator gtInterpolator = fr.getGroundTruthPath(map, Settings::Paths_IPIN2017::path1); + //gnuplot plot Plotti plot; plot.addFloors(map); plot.addOutline(map); @@ -175,12 +160,12 @@ void run(DataSetup setup, int numFile, std::string folder) { MyObs obs; //random start position - //std::unique_ptr> init(new PFInit(grid)); std::move(init); + std::unique_ptr> init(new PFInit(grid)); std::move(init); //filter init //std::unique_ptr init = - //K::ParticleFilterHistory pf(numParticles, std::unique_ptr(new PFInit(grid))); - K::ParticleFilterHistory pf(Settings::numParticles, std::unique_ptr(new PFInitFixed(grid, GridPoint(1120.0f, 750.0f, 1080.0f), 90.0f))); + 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, 1080.0f), 90.0f))); pf.setTransition(std::unique_ptr(new PFTrans(grid, &ctrl))); pf.setEvaluation(std::unique_ptr(new PFEval(WiFiModel, beaconModel, grid))); @@ -212,41 +197,41 @@ void run(DataSetup setup, int numFile, std::string folder) { errorFile.open (errorDir + folder + "/error_" + std::to_string(numFile) + "_" + std::to_string(t) + ".csv"); // parse each sensor-value within the offline data - for (const FileReader::Entry& e : fr.getEntries()) { + for (const Offline::Entry& e : fr.getEntries()) { const Timestamp ts = Timestamp::fromMS(e.ts); - if (e.type == FileReader::Sensor::WIFI) { + if (e.type == Offline::Sensor::WIFI) { obs.wifi = fr.getWiFiGroupedByTime()[e.idx].data; - } else if (e.type == FileReader::Sensor::BEACON){ + } 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 == FileReader::Sensor::ACC) { + } else if (e.type == Offline::Sensor::ACC) { if (sd.add(ts, fr.getAccelerometer()[e.idx].data)) { ++ctrl.numStepsSinceLastTransition; } - const FileReader::TS& _acc = fr.getAccelerometer()[e.idx]; + const Offline::TS& _acc = fr.getAccelerometer()[e.idx]; td.addAccelerometer(ts, _acc.data); - } else if (e.type == FileReader::Sensor::GYRO) { - const FileReader::TS& _gyr = fr.getGyroscope()[e.idx]; + } 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 == FileReader::Sensor::BARO) { + } else if (e.type == Offline::Sensor::BARO) { relBaro.add(ts, fr.getBarometer()[e.idx].data); obs.relativePressure = relBaro.getPressureRealtiveToStart(); obs.sigmaPressure = relBaro.getSigma(); - } else if (e.type == FileReader::Sensor::LIN_ACC) { + } else if (e.type == Offline::Sensor::LIN_ACC) { md.addLinearAcceleration(ts, fr.getLinearAcceleration()[e.idx].data); - } else if (e.type == FileReader::Sensor::GRAVITY) { + } 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(); @@ -259,12 +244,15 @@ void run(DataSetup setup, int numFile, std::string folder) { MyState est = pf.update(&ctrl, obs); Point3 estPos = est.position.inMeter(); + //double kld = getKernelDensityProbability(pf, WiFiModel, obs, grid, ts, plot); + double kld = kldFromMultivariatNormal(pf, estPos, WiFiModel, obs, grid, ts, plot); + kld_data.push_back(kld); + //current ground truth position Point3 gtPos = gtInterpolator.get(static_cast(ts.ms())); /** plotting stuff */ - plot.pInterest.clear(); //turn angle plot @@ -275,27 +263,17 @@ void run(DataSetup setup, int numFile, std::string folder) { static float angleSumMotion = 0; angleSumMotion += ctrl.motionDeltaAngle_rad; plot.showAngle(2, angleSumMotion + M_PI, Point2(0.9, 0.8), "Motion: "); - //plot.debugWiFi(eval->model, obs.wifis, obs.curTS); - //plot.debugProb(grid, std::bind(&PFEval::getGPS, eval, std::placeholders::_1, std::placeholders::_2), obs); - //plot.debugProb(grid, std::bind(&PFEval::getWIFI, eval, std::placeholders::_1, std::placeholders::_2), obs); - //plot.debugProb(grid, std::bind(&PFEval::getALL, eval, std::placeholders::_1, std::placeholders::_2), obs); - plot.setEst(estPos); plot.setGT(gtPos); plot.addEstimationNode(estPos); plot.addParticles(pf.getParticles()); - plot.pColorPoints.clear(); - plot.debugWiFi(WiFiModel, obs.wifi, ts, 10.8f); //3 floor - plot.debugWiFi(WiFiModel, obs.wifi, ts, 7.4f); //2 floor - plot.debugWiFi(WiFiModel, obs.wifi, ts, 4.0f); //1 floor - plot.debugWiFi(WiFiModel, obs.wifi, ts, 0.0f); //0 floor - //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 1002 at screen 0.04, 0.94 'KLD: " << ":" << kld << "'\n"; //plot.gp << "set label 1002 at screen 0.98, 0.98 'act:" << ctrl.barometer.act << "'\n"; // error between GT and estimation @@ -311,6 +289,25 @@ void run(DataSetup setup, int numFile, std::string folder) { // reset control ctrl.resetAfterTransition(); + + //plot image files +// for(int i = 0; i < map->floors.size(); ++i){ +// plot.printSingleFloor("/home/toni/Documents/programme/localization/IPIN2017/code/eval/"+ folder + "/image" + std::to_string(numFile) + "_" + std::to_string(t++), i); +// plot.show(); +// usleep(10*10); +// } + +// plot.printSideView("/home/toni/Documents/programme/localization/IPIN2017/code/eval/"+ folder + "/image" + std::to_string(numFile) + "_" + std::to_string(t++), 90); +// plot.show(); + +// plot.printSideView("/home/toni/Documents/programme/localization/IPIN2017/code/eval/"+ folder + "/image" + std::to_string(numFile) + "_" + std::to_string(t++), 0); +// plot.show(); + +// plot.printOverview("/home/toni/Documents/programme/localization/IPIN2017/code/eval/"+ folder + "/image" + std::to_string(numFile) + "_" + std::to_string(t++)); +// plot.show(); + +// //reset to qt window +// plot.gp << "set terminal qt size 800,600\n"; } } @@ -341,7 +338,26 @@ void run(DataSetup setup, int numFile, std::string folder) { // plot.printOverview("/home/toni/Documents/programme/localization/IPIN2016/competition/eval/"+ folder + "/image" + std::to_string(numFile) + "_" + std::to_string(t)); // plot.show(); - sleep(1); + + //draw kld + K::Gnuplot gp; + K::GnuplotPlot plotkld; + K::GnuplotPlotElementLines lines; + + 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(); + + sleep(1000); } @@ -351,7 +367,7 @@ int main(int argc, char** argv) { //run(data.BERKWERK, 6, "EVALBERGWERK"); // Nexus vor //for(int i = 0; i < 5; ++i){ - run(data.IPIN2015, 3, "EVALIPIN2015"); // Nexus Path2 + run(data.IPIN2017, 0, "ipin2017"); // Nexus Path2 //} }