This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
IPIN2017/code/main.cpp
toni fdbd984584 change simple transition model
added klb transition models
added debugging output
2017-04-18 11:18:37 +02:00

435 lines
17 KiB
C++
Executable File

#include <iostream>
#include "filter/Structs.h"
#include "filter/KLB.h"
#include "Plotti.h"
#include "filter/Logic.h"
#include "Settings.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <KLib/math/filter/merging/InteractingMultipleModelParticleFilter.h>
//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<std::string> 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<int> gtPath) {
std::vector<double> 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<MyNode> 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<MyNode> 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<uint64_t, Point3> 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<K::ParticleFilterMixing<MyState, MyControl, MyObs>> modes;
//std::shared_ptr<K::ParticleFilterInitializer<MyState>> init(new PFInitFixed(grid, GridPoint(1120.0f, 750.0f, 740.0f), 90.0f));
// mode 1
std::shared_ptr<K::ParticleFilterInitializer<MyState>> initMode1(new PFInit(grid, 1));
K::ParticleFilterMixing<MyState, MyControl, MyObs> mode1(Settings::numParticles, initMode1, Settings::Mode1::modeProbability);
mode1.setTransition(std::shared_ptr<PFTrans>(new PFTrans(grid, &ctrl)));
mode1.setEvaluation(std::shared_ptr<PFEval>(new PFEval(WiFiModel, beaconModel, grid)));
mode1.setResampling(std::shared_ptr<K::ParticleFilterResamplingSimple<MyState>>(new K::ParticleFilterResamplingSimple<MyState>()));
mode1.setNEffThreshold(0.95);
mode1.setEstimator(std::shared_ptr<K::ParticleFilterEstimationWeightedAverage<MyState>>(new K::ParticleFilterEstimationWeightedAverage<MyState>()));
modes.push_back(mode1);
// mode 2
std::shared_ptr<K::ParticleFilterInitializer<MyState>> initMode2(new PFInit(grid, 2));
K::ParticleFilterMixing<MyState, MyControl, MyObs> mode2(Settings::numParticles, initMode2, Settings::Mode2::modeProbability);
mode2.setTransition(std::shared_ptr<PFTransSimple>(new PFTransSimple(grid)));
mode2.setEvaluation(std::shared_ptr<PFEval>(new PFEval(WiFiModel, beaconModel, grid)));
mode2.setResampling(std::shared_ptr<K::ParticleFilterResamplingSimple<MyState>>(new K::ParticleFilterResamplingSimple<MyState>()));
mode2.setNEffThreshold(0.95);
mode2.setEstimator(std::shared_ptr<K::ParticleFilterEstimationWeightedAverage<MyState>>(new K::ParticleFilterEstimationWeightedAverage<MyState>()));
modes.push_back(mode2);
//init mixing
Eigen::MatrixXd transitionProbabilityMatrix(2,2);
transitionProbabilityMatrix << 1,0,0,1;
K::InteractingMultipleModelParticleFilter<MyState, MyControl, MyObs> IMMAPF(modes, transitionProbabilityMatrix);
IMMAPF.setMixingSampler(std::unique_ptr<K::MixingSamplerDivergency<MyState, MyControl, MyObs>>(new K::MixingSamplerDivergency<MyState, MyControl, MyObs>()));
IMMAPF.setJointEstimation(std::unique_ptr<K::JointEstimationPosteriorOnly<MyState, MyControl, MyObs>>(new K::JointEstimationPosteriorOnly<MyState, MyControl, MyObs>()));
//IMMAPF.setMarkovTransitionProbability(std::unique_ptr<ModeProbabilityTransition>(new ModeProbabilityTransition(grid, Settings::Mixing::lambda)));
IMMAPF.setMarkovTransitionProbability(std::unique_ptr<ModeProbabilityTransitionNormal>(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<float> errorStats;
//file writing for error data
const long int t = static_cast<long int>(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<AccelerometerData>& _acc = fr.getAccelerometer()[e.idx];
td.addAccelerometer(ts, _acc.data);
} else if (e.type == Offline::Sensor::GYRO) {
const Offline::TS<GyroscopeData>& _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);
}
Point3 estPos = est.position.inMeter();
//current ground truth position
Point3 gtPos = gtInterpolator.get(static_cast<uint64_t>(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<int>(ts.sec()) / 60;
plot.gp << "set label 1002 at screen 0.02, 0.94 'Time: " << minutes << ":" << static_cast<int>(static_cast<int>(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 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";
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
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);
//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);
//}
}