added tex
many changes/eval etc...
This commit is contained in:
@@ -58,7 +58,7 @@ ADD_DEFINITIONS(
|
||||
-fstack-protector-all
|
||||
|
||||
-g3
|
||||
-O0
|
||||
-O0
|
||||
-march=native
|
||||
|
||||
-DWITH_TESTS
|
||||
|
||||
22
EvalApOpt.h
22
EvalApOpt.h
@@ -27,6 +27,7 @@
|
||||
#include "Structs.h"
|
||||
#include "Plotty.h"
|
||||
#include "CSV.h"
|
||||
#include "Helper.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -48,7 +49,7 @@ void plot(const K::SimpleHistogram& h) {
|
||||
class EvalApOpt {
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
WiFiFingerprints* calib;
|
||||
WiFiFingerprints calib;
|
||||
VAPGrouper* vap;
|
||||
WiFiOptimizer::LogDistCeiling* opt;
|
||||
Floorplan::Ceilings ceilings;
|
||||
@@ -63,13 +64,19 @@ public:
|
||||
map = Floorplan::Reader::readFromFile(mapFile);
|
||||
|
||||
// load fingerprints
|
||||
calib = new WiFiFingerprints(fpFile);
|
||||
calib = WiFiFingerprints(fpFile);
|
||||
|
||||
|
||||
calib = LeHelper::removeOutdoor(calib);
|
||||
calib = LeHelper::removeStaircases(calib);
|
||||
LeHelper::plot(map, calib);
|
||||
|
||||
|
||||
// how to handle VAPs
|
||||
vap = new VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE);
|
||||
|
||||
// the optimizer
|
||||
opt = new WiFiOptimizer::LogDistCeiling(map, *vap, *calib, WiFiOptimizer::LogDistCeiling::Mode::MEDIUM);
|
||||
opt = new WiFiOptimizer::LogDistCeiling(map, *vap, calib, WiFiOptimizer::LogDistCeiling::Mode::MEDIUM);
|
||||
|
||||
// some ceiling calculations
|
||||
ceilings = Floorplan::Ceilings(map);
|
||||
@@ -115,6 +122,7 @@ public:
|
||||
continue;
|
||||
}
|
||||
|
||||
plot(result);
|
||||
|
||||
results.push_back(result);
|
||||
dumpStats(result);
|
||||
@@ -135,8 +143,10 @@ public:
|
||||
}
|
||||
|
||||
// average error
|
||||
std::cout << "OVERALL RESULT: " << std::endl;
|
||||
std::cout << "error signed: " << statsSigned.asString() << std::endl;
|
||||
std::cout << "error unsigned: " << statsAbs.asString() << std::endl;
|
||||
std::cout << "--------------------------------------------------------" << std::endl;
|
||||
|
||||
// all APs known to the map but invisible during fingerprinting [should not happen]
|
||||
std::unordered_set<MACAddress> mapUnseen = mapAPs;
|
||||
@@ -212,7 +222,9 @@ public:
|
||||
// }
|
||||
// }
|
||||
|
||||
plot.plot();
|
||||
if (1 == 0) {
|
||||
plot.plot();
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -224,7 +236,7 @@ public:
|
||||
optStats.mac = mac;
|
||||
|
||||
const WiFiOptimizer::LogDistCeiling::APParams params = opt->optimize(mac, optStats.opt);
|
||||
const std::vector<WiFiFingerprint> fps = calib->getFingerprintsFor(vap->getBaseMAC(mac));
|
||||
const std::vector<WiFiFingerprint> fps = calib.getFingerprintsFor(vap->getBaseMAC(mac));
|
||||
|
||||
optStats.params = params;
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
#include "Indoor/floorplan/v2/FloorplanCeilings.h"
|
||||
|
||||
#include "Indoor/sensors/radio/model/WiFiModelLogDistCeiling.h"
|
||||
#include "Helper.h"
|
||||
|
||||
using APAtFloor = std::pair<Floorplan::AccessPoint*, Floorplan::Floor*>;
|
||||
|
||||
|
||||
/**
|
||||
* compare different optimzation levels
|
||||
* fixed ap pos / fixed params
|
||||
@@ -29,8 +31,9 @@ class EvalCompareOpt {
|
||||
|
||||
protected:
|
||||
|
||||
int power = 1;
|
||||
Floorplan::IndoorMap* map;
|
||||
WiFiFingerprints* calib;
|
||||
WiFiFingerprints calib;
|
||||
VAPGrouper* vap;
|
||||
Floorplan::Ceilings ceilings;
|
||||
std::vector<APAtFloor> mapAPs;
|
||||
@@ -38,13 +41,26 @@ protected:
|
||||
|
||||
|
||||
/** ctor with map and fingerprints */
|
||||
EvalCompareOpt(const std::string& mapFile, const std::string& fpFile) {
|
||||
EvalCompareOpt(const std::string& mapFile, const std::string& fpFile, const bool ignoreStaircases, const bool ignoreOutdoor) {
|
||||
|
||||
// load floorplan
|
||||
map = Floorplan::Reader::readFromFile(mapFile);
|
||||
|
||||
// how to group VAPs
|
||||
vap = new VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE);
|
||||
|
||||
// load fingerprints
|
||||
calib = new WiFiFingerprints(fpFile);
|
||||
calib = WiFiFingerprints(fpFile);
|
||||
|
||||
LeHelper::removeNonFHWS(calib);
|
||||
if (ignoreOutdoor) {calib = LeHelper::removeOutdoor(calib);}
|
||||
if (ignoreStaircases) {calib = LeHelper::removeStaircases(calib);}
|
||||
//LeHelper::plot(map, calib);
|
||||
WiFiFingerprints calib2 = calib;
|
||||
for (WiFiFingerprint& fp : calib2.getFingerprints()) {
|
||||
fp.measurements = vap->group(fp.measurements);
|
||||
}
|
||||
LeHelper::plot(map, calib2);
|
||||
|
||||
// some ceiling calculations
|
||||
ceilings = Floorplan::Ceilings(map);
|
||||
@@ -52,12 +68,9 @@ protected:
|
||||
// all APs within the map
|
||||
mapAPs = FloorplanHelper::getAPs(map);
|
||||
|
||||
// how to group VAPs
|
||||
vap = new VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE);
|
||||
|
||||
// used to aggreagate fingerprints
|
||||
base = new WiFiOptimizer::Base(*vap);
|
||||
base->addFingerprints(*calib);
|
||||
base->addFingerprints(calib);
|
||||
|
||||
}
|
||||
|
||||
@@ -121,8 +134,8 @@ protected:
|
||||
const float diff = std::abs(rssiModel - reading.rssi);
|
||||
|
||||
// adjust
|
||||
stats.add(std::abs(diff));
|
||||
dstAbs.add(std::abs(diff));
|
||||
stats.add(std::pow(std::abs(diff), power));
|
||||
dstAbs.add(std::pow(std::abs(diff), power));
|
||||
|
||||
}
|
||||
|
||||
@@ -135,6 +148,8 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** fixed ap pos, fixed ap params */
|
||||
class EvalCompareOptAllFixed : public EvalCompareOpt {
|
||||
|
||||
@@ -147,8 +162,9 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
EvalCompareOptAllFixed(const std::string& mapFile, const std::string& fpFile) : EvalCompareOpt(mapFile, fpFile) {
|
||||
|
||||
EvalCompareOptAllFixed(const std::string& mapFile, const std::string& fpFile, const bool ignoreStaircases, const bool ignoreOutdoor) :
|
||||
EvalCompareOpt(mapFile, fpFile, ignoreStaircases, ignoreOutdoor) {
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,28 +198,38 @@ public:
|
||||
}
|
||||
|
||||
/** calculate error for fixed positions and fixed constants */
|
||||
void fixedPosFixedParamsForAll() {
|
||||
K::Statistics<float> fixedPosFixedParamsForAll() {
|
||||
|
||||
// fire
|
||||
K::Statistics<float> stats = getStatsAll(txp, exp, waf);
|
||||
std::cout << "----------------------------------------------------" << std::endl;
|
||||
std::cout << "AP POS FROM MAP, FIXED TXP/EXP/WAF FOR ALL APS" << std::endl;
|
||||
std::cout << getStatsAll(txp, exp, waf).asString() << std::endl;
|
||||
std::cout << stats.asString() << std::endl;
|
||||
std::cout << std::endl;
|
||||
return stats;
|
||||
|
||||
}
|
||||
|
||||
/** calculate error for fixed positions and optimized constants, but the same 3 for all APs */
|
||||
void fixedPosOptParamsForAll() {
|
||||
K::Statistics<float> fixedPosOptParamsForAll() {
|
||||
|
||||
auto func = [&] (const float* params) {
|
||||
return getStatsAll(params[0], params[1], params[2]).getAvg();
|
||||
};
|
||||
|
||||
auto callback = [&] (const int run, const int iteration, const float , const float* ) {
|
||||
const int percent = ((run*40+iteration)*100) / (40*11);
|
||||
if (iteration == 0) {
|
||||
std::cout << percent << "," << std::flush;
|
||||
}
|
||||
};
|
||||
|
||||
// use simplex
|
||||
float params[3] = {-40, 2, -8};
|
||||
K::NumOptAlgoDownhillSimplex<float> opt(3);
|
||||
opt.setMaxIterations(50);
|
||||
opt.setMaxIterations(40);
|
||||
opt.setNumRestarts(10);
|
||||
opt.setCallback(callback);
|
||||
opt.calculateOptimum(func, params);
|
||||
|
||||
// use genetic
|
||||
@@ -215,16 +241,18 @@ public:
|
||||
// opt.setMutation(0.25);
|
||||
// opt.calculateOptimum(func, params);
|
||||
|
||||
K::Statistics<float> stats = getStatsAll(params[0], params[1], params[2]);
|
||||
std::cout << "----------------------------------------------------" << std::endl;
|
||||
std::cout << "AP POS FROM MAP, OPTIMIZING TXP/EXP/WAF: THE SAME FOR ALL APS" << std::endl;
|
||||
std::cout << "params: " << params[0] << "," << params[1] << "," << params[2] << std::endl;
|
||||
std::cout << getStatsAll(params[0], params[1], params[2]).asString() << std::endl;
|
||||
std::cout << stats.asString() << std::endl;
|
||||
std::cout << std::endl;
|
||||
return stats;
|
||||
|
||||
}
|
||||
|
||||
/** calculate error for fixed positions and optimized constants, each AP on its own */
|
||||
void fixedPosOptParamsForEach() {
|
||||
K::Statistics<float> fixedPosOptParamsForEach() {
|
||||
|
||||
K::Statistics<float> _dstAbs;
|
||||
|
||||
@@ -263,7 +291,7 @@ public:
|
||||
analyzeErrorForAP(mac, pos, params[0], params[1], params[2], tmp);
|
||||
|
||||
// adjust global error with the resulting params
|
||||
std::cout << "--" << mac.asString() << " params: " << params[0] << "," << params[1] << "," << params[2] << " err: " << tmp.getAvg() << std::endl;
|
||||
std::cout << "--" << mac.asString() << " params: " << params[0] << ",\t" << params[1] << ",\t" << params[2] << "\terr: " << tmp.getAvg() << std::endl;
|
||||
analyzeErrorForAP(mac, pos, params[0], params[1], params[2], _dstAbs);
|
||||
|
||||
}
|
||||
@@ -272,14 +300,19 @@ public:
|
||||
std::cout << "AP POS FROM MAP, OPTIMIZING TXP/EXP/WAF INDIVIDUALLY FOR EACH AP" << std::endl;
|
||||
std::cout << _dstAbs.asString() << std::endl;
|
||||
std::cout << std::endl;
|
||||
return _dstAbs;
|
||||
|
||||
}
|
||||
|
||||
/** calculate error for fixed positions and optimized constants, each AP on its own */
|
||||
void optPosOptParamsForEach() {
|
||||
K::Statistics<float> optPosOptParamsForEach() {
|
||||
|
||||
K::Statistics<float> _dstAbs;
|
||||
|
||||
std::cout << "NOTE" << std::endl;
|
||||
std::cout << "INCREASE ITERATIONS!" << std::endl;
|
||||
std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
|
||||
|
||||
// construct vector containing each AP within the map + add fixed parameters
|
||||
for (const APAtFloor& mapAP : mapAPs) {
|
||||
|
||||
@@ -312,9 +345,10 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
K::NumOptAlgoRangeRandom<float> opt(valRegion);
|
||||
opt.setPopulationSize(500);
|
||||
opt.setNumIerations(150);
|
||||
opt.setPopulationSize(100);
|
||||
opt.setNumIerations(40);
|
||||
opt.calculateOptimum(func, params);
|
||||
|
||||
// local stats
|
||||
@@ -322,7 +356,7 @@ public:
|
||||
analyzeErrorForAP(mac, Point3(params[0], params[1], params[2]), params[3], params[4], params[5], tmp);
|
||||
|
||||
// adjust global error with the resulting params
|
||||
std::cout << "--" << mac.asString() << " params: " << params[0] << "," << params[1] << "," << params[2] << "," << params[3] << "," << params[4] << "," << params[5] << " err: " << tmp.getAvg() << std::endl;
|
||||
std::cout << "--" << mac.asString() << " params: " << params[0] << ",\t" << params[1] << ",\t" << params[2] << ",\t" << params[3] << ",\t" << params[4] << ",\t" << params[5] << "\terr: " << tmp.getAvg() << std::endl;
|
||||
analyzeErrorForAP(mac, Point3(params[0], params[1], params[2]), params[3], params[4], params[5], _dstAbs);
|
||||
|
||||
}
|
||||
@@ -331,6 +365,7 @@ public:
|
||||
std::cout << "OPTIMIZING POS/TXP/EXP/WAF INDIVIDUALLY FOR EACH AP" << std::endl;
|
||||
std::cout << _dstAbs.asString() << std::endl;
|
||||
std::cout << std::endl;
|
||||
return _dstAbs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // EVALDATA_H
|
||||
|
||||
250
EvalWalk.h
250
EvalWalk.h
@@ -1,6 +1,16 @@
|
||||
#ifndef EVALWALK_H
|
||||
#define EVALWALK_H
|
||||
|
||||
#include <KLib/math/filter/particles/ParticleFilter.h>
|
||||
#include <KLib/math/filter/particles/ParticleFilterEvaluation.h>
|
||||
#include <KLib/math/filter/particles/ParticleFilterInitializer.h>
|
||||
#include <KLib/math/filter/particles/ParticleFilterTransition.h>
|
||||
#include <KLib/math/filter/particles/estimation/ParticleFilterEstimationWeightedAverage.h>
|
||||
#include <KLib/math/filter/particles/resampling/ParticleFilterResamplingSimple.h>
|
||||
#include <KLib/math/filter/particles/resampling/ParticleFilterResamplingPercent.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "Indoor/sensors/radio/setup/WiFiOptimizer.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiFingerprint.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiFingerprints.h"
|
||||
@@ -9,6 +19,8 @@
|
||||
#include "Indoor/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h"
|
||||
|
||||
#include "Indoor/sensors/radio/VAPGrouper.h"
|
||||
#include "Indoor/sensors/imu/StepDetection.h"
|
||||
#include "Indoor/sensors/imu/TurnDetection.h"
|
||||
|
||||
#include "Indoor/floorplan/v2/Floorplan.h"
|
||||
#include "Indoor/floorplan/v2/FloorplanReader.h"
|
||||
@@ -19,16 +31,250 @@
|
||||
|
||||
#include "Indoor/sensors/offline/FileReader.h"
|
||||
#include "Helper.h"
|
||||
#include "pf/PF.h"
|
||||
|
||||
class EvalWalk {
|
||||
#include <Indoor/sensors/offline/FileReader.h>
|
||||
#include <Indoor/sensors/offline/Listener.h>
|
||||
|
||||
class EvalWalk : public Offline::Listener {
|
||||
|
||||
Grid<MyGridNode>* grid;
|
||||
K::ParticleFilter<MyState, MyControl, MyObservation>* pf;
|
||||
|
||||
std::string runName;
|
||||
WiFiModelLogDistCeiling wifiModel;
|
||||
|
||||
Plotty plotty;
|
||||
|
||||
Offline::FileReader reader;
|
||||
|
||||
Timestamp lastTransition;
|
||||
|
||||
MyObservation curObs;
|
||||
MyControl curCtrl;
|
||||
MyState curEst;
|
||||
|
||||
StepDetection stepDetect;
|
||||
TurnDetection turnDetect;
|
||||
|
||||
std::vector<Point3> groundTruth;
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
|
||||
public:
|
||||
|
||||
EvalWalk() {
|
||||
EvalWalk(Floorplan::IndoorMap* map) : wifiModel(map), plotty(map), map(map) {
|
||||
|
||||
const std::string saveFile = Settings::pathData + "/grid.dat";
|
||||
grid = new Grid<MyGridNode>(Settings::Grid::gridSize_cm);
|
||||
|
||||
plotty.buildFloorplan();
|
||||
|
||||
// deserialize grid
|
||||
std::ifstream inp(saveFile, std::ofstream::binary);
|
||||
if (inp) {
|
||||
grid->read(inp);
|
||||
inp.close();
|
||||
} else {
|
||||
// build the grid
|
||||
GridFactory<MyGridNode> gf(*grid);
|
||||
gf.build(map);
|
||||
std::ofstream out(saveFile, std::ofstream::binary);
|
||||
grid->write(out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
pf = new K::ParticleFilter<MyState, MyControl, MyObservation>( Settings::numParticles, std::unique_ptr<PFInit>(new PFInit(grid)) );
|
||||
|
||||
// TODO: flexible model
|
||||
wifiModel.loadAPs(map, Settings::WiFiModel::TXP, Settings::WiFiModel::EXP, Settings::WiFiModel::WAF, false);
|
||||
std::unique_ptr<PFEval> eval = std::unique_ptr<PFEval>( new PFEval(grid, wifiModel) );
|
||||
pf->setEvaluation( std::move(eval) );
|
||||
|
||||
// resampling step?
|
||||
pf->setNEffThreshold(0.5);
|
||||
//pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingSimple<MyState>>(new K::ParticleFilterResamplingSimple<MyState>()) );
|
||||
pf->setResampling( std::unique_ptr<K::ParticleFilterResamplingPercent<MyState>>(new K::ParticleFilterResamplingPercent<MyState>(0.10)) );
|
||||
|
||||
// state estimation step
|
||||
pf->setEstimation( std::unique_ptr<K::ParticleFilterEstimationWeightedAverage<MyState>>(new K::ParticleFilterEstimationWeightedAverage<MyState>()));
|
||||
//pf->setEstimation( std::unique_ptr<K::ParticleFilterEstimationRegionalWeightedAverage<MyState>>(new K::ParticleFilterEstimationRegionalWeightedAverage<MyState>()));
|
||||
//pf->setEstimation( std::unique_ptr<K::ParticleFilterEstimationOrderedWeightedAverage<MyState>>(new K::ParticleFilterEstimationOrderedWeightedAverage<MyState>(0.50f)));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void walk1() {
|
||||
|
||||
runName = "path2_forward_simple";
|
||||
std::string path = Settings::path1a;
|
||||
groundTruth = FloorplanHelper::getGroundTruth(map, Settings::GroundTruth::path1);
|
||||
|
||||
//GridWalkSimpleControl<MyGridNode>* walk = new GridWalkSimpleControl<MyGridNode>();
|
||||
pf->setTransition( std::unique_ptr<PFTrans>( new PFTrans(grid)) );
|
||||
|
||||
reader.open(path, this);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void onGyroscope(const Timestamp ts, const GyroscopeData data) override {
|
||||
|
||||
const float delta_rad = turnDetect.addGyroscope(ts, data);
|
||||
curCtrl.turnSinceLastTransition_rad += delta_rad;
|
||||
|
||||
}
|
||||
|
||||
virtual void onAccelerometer(const Timestamp ts, const AccelerometerData data) override {
|
||||
turnDetect.addAccelerometer(ts, data);
|
||||
const bool step = stepDetect.add(ts, data);
|
||||
if (step) {
|
||||
++curCtrl.numStepsSinceLastTransition;
|
||||
}
|
||||
gotSensorData(ts);
|
||||
}
|
||||
|
||||
virtual void onGravity(const Timestamp ts, const GravityData data) override {
|
||||
;
|
||||
}
|
||||
|
||||
virtual void onWiFi(const Timestamp ts, const WiFiMeasurements data) override {
|
||||
std::cout << "WIFI" << std::endl;
|
||||
curObs.wifi = data;
|
||||
}
|
||||
|
||||
virtual void onBarometer(const Timestamp ts, const BarometerData data) override {
|
||||
;
|
||||
}
|
||||
|
||||
virtual void onGPS(const Timestamp ts, const GPSData data) override {
|
||||
curObs.gps = data;
|
||||
}
|
||||
|
||||
virtual void onCompass(const Timestamp ts, const CompassData data) override {
|
||||
const float newAzimuth = - data.azimuth + M_PI/2; // oriented towards north for our map
|
||||
curCtrl.compass_azimuth = curCtrl.compass_azimuth * 0.99 + newAzimuth * 0.01;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/** called when any sensor has received new data */
|
||||
void gotSensorData(const Timestamp ts) {
|
||||
curObs.currentTime = ts;
|
||||
filterUpdateIfNeeded();
|
||||
}
|
||||
|
||||
/** check whether its time for a filter update, and if so, execute the update and return true */
|
||||
bool filterUpdateIfNeeded() {
|
||||
|
||||
static float avgSum = 0;
|
||||
static int avgCount = 0;
|
||||
|
||||
// fixed update rate based on incoming sensor data
|
||||
// allows working with live data and faster for offline data
|
||||
const Timestamp diff = curObs.currentTime - lastTransition;
|
||||
if (diff >= Settings::Filter::updateEvery) {
|
||||
|
||||
// as the difference is slightly above the 500ms, calculate the error and incorporate it into the next one
|
||||
const Timestamp err = diff - Settings::Filter::updateEvery;
|
||||
lastTransition = curObs.currentTime - err;
|
||||
|
||||
const Timestamp ts1 = Timestamp::fromUnixTime();
|
||||
filterUpdate();
|
||||
const Timestamp ts2 = Timestamp::fromUnixTime();
|
||||
const Timestamp tsDiff = ts2-ts1;
|
||||
|
||||
//const QString filterTime = QString::number(tsDiff.ms());
|
||||
//avgSum += tsDiff.ms(); ++avgCount;
|
||||
//Log::add("xxx", "ts:" + std::to_string(curObs.currentTime.ms()) + " avg:" + std::to_string(avgSum/avgCount));
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** perform a filter-update (called from a background-loop) */
|
||||
void filterUpdate() {
|
||||
|
||||
std::cout << "update" << std::endl;
|
||||
|
||||
MyControl ctrlCopy = curCtrl;
|
||||
static float absHead = M_PI/2; absHead += ctrlCopy.turnSinceLastTransition_rad;
|
||||
|
||||
//lastEst = curEst;
|
||||
curEst = pf->update(&curCtrl, curObs);
|
||||
//Log::add("Nav", "cur est: " + curEst.position.asString());
|
||||
|
||||
// inform listeners about the new estimation
|
||||
// for (NavControllerListener* l : listeners) {l->onNewEstimation(curEst.position.inMeter());}
|
||||
|
||||
// update estimated path
|
||||
//estPath.push_back(curEst.position.inMeter());
|
||||
|
||||
// PFTrans* trans = (PFTrans*)pf->getTransition();
|
||||
|
||||
|
||||
|
||||
const K::GnuplotPoint3 p3(curEst.position.x_cm, curEst.position.y_cm, curEst.position.z_cm);
|
||||
plotty.pathEst.add(p3/100);
|
||||
|
||||
plotty.particles.clear();
|
||||
for (const auto p : pf->getParticles()) {
|
||||
const K::GnuplotPoint3 p3(p.state.position.x_cm, p.state.position.y_cm, p.state.position.z_cm);
|
||||
plotty.particles.add(p3/100);
|
||||
}
|
||||
|
||||
// GT
|
||||
plotty.pathReal.clear();
|
||||
for (const Point3 pt : groundTruth) {
|
||||
plotty.pathReal.add(K::GnuplotPoint3(pt.x, pt.y, pt.z));
|
||||
}
|
||||
|
||||
std::string title =
|
||||
" time " + std::to_string(curObs.currentTime.sec()) +
|
||||
" steps: " + std::to_string(ctrlCopy.numStepsSinceLastTransition) +
|
||||
" turn: " + std::to_string(ctrlCopy.turnSinceLastTransition_rad);
|
||||
plotty.setTitle(title);
|
||||
|
||||
{
|
||||
Point2 cen(0.1, 0.9);
|
||||
Point2 dir(std::cos(absHead), std::sin(absHead));
|
||||
Point2 arr = cen + dir * 0.1;
|
||||
plotty.gp << "set arrow 1 from screen " << cen.x << "," << cen.y << " to screen " << arr.x << "," << arr.y << "\n";
|
||||
dir = Point2(std::cos(ctrlCopy.compass_azimuth), std::sin(ctrlCopy.compass_azimuth));
|
||||
arr = cen + dir * 0.05;
|
||||
plotty.gp << "set arrow 2 from screen " << cen.x << "," << cen.y << " to screen " << arr.x << "," << arr.y << "\n";
|
||||
}
|
||||
|
||||
|
||||
// plot
|
||||
plotty.plot();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(30));
|
||||
|
||||
curCtrl.resetAfterTransition();
|
||||
|
||||
// const MyGridNode* node = grid->getNodePtrFor(curEst.position);
|
||||
// if (node) {
|
||||
// try {
|
||||
// pathToDest = trans->modDestination.getShortestPath(*node);
|
||||
// } catch (...) {;}
|
||||
// }
|
||||
// mainController->getMapView()->showGridImportance();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -127,11 +127,6 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
/** is the given mac one of a FHWS ap? */
|
||||
bool isFHWS_AP(const MACAddress& mac) {
|
||||
return mac.asString().substr(0,5) == "D8:84";
|
||||
}
|
||||
|
||||
void run() {
|
||||
|
||||
Plotty* plot = new Plotty(map);
|
||||
@@ -168,7 +163,7 @@ private:
|
||||
for (const WiFiMeasurement& m : mes.entries) {
|
||||
|
||||
// skip non-FHWS APs
|
||||
if (!isFHWS_AP(m.getAP().getMAC())) {continue;}
|
||||
if (!LeHelper::isFHWS_AP(m.getAP().getMAC())) {continue;}
|
||||
|
||||
// get model's rssi for the given location
|
||||
const float rssi_model = wiModel->getRSSI(m.getAP().getMAC(), pos_m);
|
||||
@@ -219,7 +214,7 @@ private:
|
||||
|
||||
// draw a smoothed version of th epath
|
||||
plot->pathEst.clear();
|
||||
for (const Point3 p : path.getAverage(1)) {
|
||||
for (const Point3 p : path.getAverage(2)) {
|
||||
const K::GnuplotPoint3 gp3(p.x, p.y, p.z);
|
||||
plot->pathEst.add(gp3);
|
||||
}
|
||||
|
||||
153
EvalWiFiSigStrength.h
Normal file
153
EvalWiFiSigStrength.h
Normal file
@@ -0,0 +1,153 @@
|
||||
#ifndef EVALWIFISIGSTRENGTH_H
|
||||
#define EVALWIFISIGSTRENGTH_H
|
||||
|
||||
|
||||
#include "Indoor/sensors/radio/setup/WiFiOptimizer.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiFingerprint.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiFingerprints.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiOptimizer.h"
|
||||
|
||||
#include "Indoor/sensors/radio/VAPGrouper.h"
|
||||
#include "Indoor/sensors/offline/FileReader.h"
|
||||
|
||||
#include "Indoor/floorplan/v2/Floorplan.h"
|
||||
#include "Indoor/floorplan/v2/FloorplanReader.h"
|
||||
#include "Indoor/floorplan/v2/FloorplanHelper.h"
|
||||
#include "Indoor/floorplan/v2/FloorplanCeilings.h"
|
||||
|
||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementPoints.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementColorPoints.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementLines.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotPlotElementHistogram.h>
|
||||
|
||||
#include <KLib/math/statistics/Statistics.h>
|
||||
|
||||
#include "Structs.h"
|
||||
#include "Plotty.h"
|
||||
#include "CSV.h"
|
||||
#include "Helper.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
/**
|
||||
* read path
|
||||
* fetch wifi
|
||||
* use given model to estimate the most likely location
|
||||
* -> WIFI ONLY
|
||||
*/
|
||||
class EvalWiFiSigStrength {
|
||||
|
||||
private:
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
BBox3 mapBBox;
|
||||
|
||||
WiFiFingerprints calib;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with map and fingerprints */
|
||||
EvalWiFiSigStrength(const std::string& mapFile, const std::string& fpFile) {
|
||||
|
||||
// load floorplan
|
||||
map = Floorplan::Reader::readFromFile(mapFile);
|
||||
|
||||
// estimate bbox
|
||||
mapBBox = FloorplanHelper::getBBox(map);
|
||||
|
||||
// load fingerprints
|
||||
calib = WiFiFingerprints(fpFile);
|
||||
|
||||
// remove some stuff
|
||||
LeHelper::removeNonFHWS(calib);
|
||||
|
||||
}
|
||||
|
||||
float scale(const float val, const float min, const float max) {
|
||||
return (val - min) / (max-min);
|
||||
}
|
||||
|
||||
|
||||
void forAP_avg(Plotty* p, const MACAddress& mac) {
|
||||
|
||||
VAPGrouper vap(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE);
|
||||
|
||||
// get AP/floor
|
||||
std::pair<Floorplan::AccessPoint*, Floorplan::Floor*> _ap = FloorplanHelper::getAP(map, mac);
|
||||
const Floorplan::Floor* floor = _ap.second;
|
||||
const Floorplan::AccessPoint* ap = _ap.first;
|
||||
|
||||
// copy
|
||||
WiFiFingerprints calib = this->calib;
|
||||
for (WiFiFingerprint& fp : calib.getFingerprints()) {
|
||||
fp.measurements = vap.group(fp.measurements);
|
||||
}
|
||||
|
||||
// plot
|
||||
|
||||
|
||||
std::cout << ap->mac << std::endl;
|
||||
|
||||
const Point3 apPos3 = ap->getPos(floor);
|
||||
K::GnuplotPoint3 apPos(apPos3.x, apPos3.y, apPos3.z);
|
||||
p->points.add(apPos);
|
||||
|
||||
// process every fingerprint location
|
||||
for (const WiFiFingerprint& fp : calib.getFingerprints()) {
|
||||
|
||||
// either 0 entries [ap not seen here] or 1 entry due to vap grouping [ap seen here]
|
||||
std::vector<WiFiMeasurement> mes = fp.getAllForMAC(mac);
|
||||
|
||||
if (!mes.empty()) {
|
||||
|
||||
const float rssi = mes.front().getRSSI();
|
||||
const float s = scale(rssi, -100, -40);
|
||||
const Color c = Color::fromHSV(s*100, 255, 255);
|
||||
|
||||
// fingerprint onto the floor
|
||||
p->addFloorRect(fp.pos_m - Point3(0,0,1.3), 1, c);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void perAP_avg() {
|
||||
|
||||
std::vector<std::pair<Floorplan::AccessPoint*, Floorplan::Floor*>> aps = FloorplanHelper::getAPs(map);
|
||||
|
||||
for (const auto& it : aps) {
|
||||
|
||||
const Floorplan::Floor* floor = it.second;
|
||||
const Floorplan::AccessPoint* ap = it.first;
|
||||
const MACAddress mac(ap->mac);
|
||||
|
||||
Plotty* p = new Plotty(map);
|
||||
p->setTitle(ap->mac);
|
||||
p->buildFloorplan();
|
||||
forAP_avg(p, mac);
|
||||
|
||||
p->plot();
|
||||
|
||||
int i = 0; (void) i;
|
||||
|
||||
// MACs:
|
||||
// d8:84:66:4a:23:d0 <<<< BEST
|
||||
// d8:84:66:4a:25:c0
|
||||
// d8:84:66:4a:4c:60
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // EVALWIFISIGSTRENGTH_H
|
||||
112
Helper.h
112
Helper.h
@@ -3,6 +3,10 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <Indoor/geo/EarthPos.h>
|
||||
#include <Indoor/sensors/radio/setup/WiFiFingerprints.h>
|
||||
#include <Indoor/floorplan/v2/Floorplan.h>
|
||||
|
||||
#include "Plotty.h"
|
||||
|
||||
class LeHelper {
|
||||
|
||||
@@ -24,6 +28,114 @@ public:
|
||||
|
||||
}
|
||||
|
||||
/** remove all outdoor fingerprints */
|
||||
static WiFiFingerprints removeOutdoor(const WiFiFingerprints& inp) {
|
||||
|
||||
WiFiFingerprints res;
|
||||
|
||||
for (const WiFiFingerprint& fp : inp.getFingerprints()) {
|
||||
const Point3 pos = fp.pos_m;
|
||||
|
||||
// garden
|
||||
if (pos == Point3(21, 12, 1.3)) {continue;}
|
||||
if (pos == Point3(21, 27, 1.3)) {continue;}
|
||||
if (pos == Point3(39, 12, 1.3)) {continue;}
|
||||
if (pos == Point3(39, 27, 1.3)) {continue;}
|
||||
if (pos == Point3(67, 12, 1.3)) {continue;}
|
||||
if (pos == Point3(67, 27, 1.3)) {continue;}
|
||||
if (pos == Point3(88, 12, 1.3)) {continue;}
|
||||
if (pos == Point3(88, 27, 1.3)) {continue;}
|
||||
|
||||
// front door
|
||||
if (pos == Point3(94, 43, 4+1.3)) {continue;}
|
||||
if (pos == Point3(110, 43, 4+1.3)) {continue;}
|
||||
if (pos == Point3(94, 55, 4+1.3)) {continue;}
|
||||
if (pos == Point3(110, 55, 4+1.3)) {continue;}
|
||||
if (pos == Point3(67.2, 55, 4+1.3)) {continue;}
|
||||
|
||||
res.add(fp);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static WiFiFingerprints removeStaircases(const WiFiFingerprints& inp) {
|
||||
|
||||
WiFiFingerprints res;
|
||||
|
||||
for (const WiFiFingerprint& fp : inp.getFingerprints()) {
|
||||
const Point3 pos = fp.pos_m;
|
||||
|
||||
// floor 0
|
||||
if (pos == Point3(67.2, 48.5, 1.3)) {continue;}
|
||||
if (pos == Point3(11.2, 48.3, 1.3)) {continue;}
|
||||
if (pos == Point3(16.5, 11.9, 1.3)) {continue;}
|
||||
if (pos == Point3(57.4, 2.6, 1.3)) {continue;}
|
||||
if (pos == Point3(57.4, -3.2, 3.0)) {continue;}
|
||||
|
||||
// floor 1
|
||||
if (pos == Point3(67.2, 48.3, 4+1.3)) {continue;}
|
||||
if (pos == Point3(11.4, 48.3, 4+1.3)) {continue;}
|
||||
if (pos == Point3(16.1, 11.9, 4+1.3)) {continue;}
|
||||
if (pos == Point3(57.4, 2.4, 4+1.3)) {continue;}
|
||||
|
||||
// floor 2
|
||||
if (pos == Point3(67.0, 48.5, 3.4+4+1.3)) {continue;}
|
||||
if (pos == Point3(11.6, 48.5, 3.4+4+1.3)) {continue;}
|
||||
if (pos == Point3(16.3, 11.9, 3.4+4+1.3)) {continue;}
|
||||
|
||||
// floor 3
|
||||
if (pos == Point3(67.0, 48.3, 3.4+3.4+4+1.3)) {continue;}
|
||||
if (pos == Point3(11.4, 48.5, 3.4+3.4+4+1.3)) {continue;}
|
||||
if (pos == Point3(16.3, 11.9, 3.4+3.4+4+1.3)) {continue;}
|
||||
|
||||
res.add(fp);
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void plot(const Floorplan::IndoorMap* map, const WiFiFingerprints& inp, const std::string& title = "Fingerprints") {
|
||||
|
||||
Plotty* p = new Plotty(map);
|
||||
p->setTitle(title);
|
||||
p->buildFloorplan();
|
||||
p->cpoints.clear();
|
||||
for (const WiFiFingerprint& fp : inp.getFingerprints()) {
|
||||
const K::GnuplotPoint3 gp(fp.pos_m.x, fp.pos_m.y, fp.pos_m.z);
|
||||
//p->cpoints.add(gp, 1);
|
||||
const float size = fp.measurements.entries.size() / 10.0 * 1.0;
|
||||
p->addFloorRect(fp.pos_m, size, Color::fromRGB(255,0,0));
|
||||
p->addLabel(std::to_string(fp.measurements.entries.size()), fp.pos_m+Point3(1,1,1));
|
||||
}
|
||||
p->plot();
|
||||
|
||||
}
|
||||
|
||||
/** is the given mac one of a FHWS ap? */
|
||||
static inline bool isFHWS_AP(const MACAddress& mac) {
|
||||
return mac.asString().substr(0,5) == "D8:84";
|
||||
}
|
||||
|
||||
/** remove all non-FHWS APs from the calibration */
|
||||
static inline void removeNonFHWS(WiFiFingerprints& calib) {
|
||||
int removed = 0;
|
||||
for (WiFiFingerprint& fp : calib.getFingerprints()) {
|
||||
for (size_t i = 0; i < fp.measurements.entries.size(); ++i) {
|
||||
const WiFiMeasurement& m = fp.measurements.entries[i];
|
||||
if (!isFHWS_AP(m.getAP().getMAC())) {
|
||||
fp.measurements.entries.erase(fp.measurements.entries.begin() + i);
|
||||
--i;
|
||||
++removed;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "removed " << removed << " entries" <<std::endl;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // HELPER_H
|
||||
|
||||
92
PlotErrFunc.h
Normal file
92
PlotErrFunc.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef PLOTERRFUNC_H
|
||||
#define PLOTERRFUNC_H
|
||||
|
||||
#include <KLib/math/statistics/Statistics.h>
|
||||
|
||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||
|
||||
|
||||
class PlotErrFunc {
|
||||
|
||||
|
||||
|
||||
struct Entry {
|
||||
std::string name;
|
||||
K::Statistics<float> stats;
|
||||
Entry(const std::string& name, const K::Statistics<float>& stats) : name(name), stats(stats) {;}
|
||||
};
|
||||
|
||||
std::vector<Entry> entries;
|
||||
|
||||
K::Gnuplot gp;
|
||||
K::GnuplotPlot gplot;
|
||||
|
||||
//std::vector<std::string> colors = {"#000000", "#ff0000", "#00bb00", "#0000ff"};
|
||||
std::vector<std::string> colors = {"#000000", "#999999", "#0000ff", "#9999ff"};
|
||||
|
||||
std::string codeFile;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with x-axis label */
|
||||
PlotErrFunc(const std::string& xLabel, const std::string& yLabel) {
|
||||
gplot.setLabelX(xLabel);
|
||||
gplot.setLabelY(yLabel);
|
||||
}
|
||||
|
||||
/** add one curve */
|
||||
void add(const std::string name, const K::Statistics<float> stats) {
|
||||
entries.push_back(Entry(name, stats));
|
||||
}
|
||||
|
||||
K::Gnuplot& getGP() {
|
||||
return gp;
|
||||
}
|
||||
|
||||
void writeCodeTo(const std::string& file) {
|
||||
this->codeFile = file;
|
||||
}
|
||||
|
||||
/** plot all curves */
|
||||
void plot() {
|
||||
|
||||
gp << "set grid\n";
|
||||
|
||||
for (size_t i = 0; i < entries.size(); ++i) {
|
||||
|
||||
const Entry e = entries[i];
|
||||
|
||||
K::GnuplotPlotElementLines* line = new K::GnuplotPlotElementLines();
|
||||
line->setTitle(e.name);
|
||||
line->setColorHex(colors[i]);
|
||||
line->setLineWidth(2);
|
||||
gplot.add(line);
|
||||
|
||||
// 0 - 80%
|
||||
for (int i = 0; i <= 85; i+= 5) {
|
||||
const float q = i / 100.0f;
|
||||
const float y = e.stats.getQuantile(q);
|
||||
K::GnuplotPoint2 gp(y, q*100);
|
||||
line->add(gp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gp.draw(gplot);
|
||||
|
||||
if (codeFile != "") {
|
||||
std::ofstream out(codeFile);
|
||||
out << gp.getBuffer();
|
||||
out.close();
|
||||
}
|
||||
|
||||
gp.flush();
|
||||
gp.close();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // PLOTERRFUNC_H
|
||||
288
Plotty.h
288
Plotty.h
@@ -12,22 +12,108 @@
|
||||
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotPlotElementHistogram.h>
|
||||
|
||||
struct Color {
|
||||
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
|
||||
Color() : r(0), g(0), b(0) {
|
||||
;
|
||||
}
|
||||
|
||||
static Color fromRGB(const uint8_t r, const uint8_t g, const uint8_t b) {
|
||||
Color c; c.setRGB(r,g,b);
|
||||
return c;
|
||||
}
|
||||
|
||||
static Color fromHSV(const uint8_t h, const uint8_t s, const uint8_t v) {
|
||||
Color c; c.setHSV(h,s,v);
|
||||
return c;
|
||||
}
|
||||
|
||||
void setRGB(const uint8_t r, const uint8_t g, const uint8_t b) {
|
||||
this->r = r;
|
||||
this->g = g;
|
||||
this->b = b;
|
||||
}
|
||||
|
||||
void setHSV(const uint8_t h, const uint8_t s, const uint8_t v) {
|
||||
|
||||
uint8_t region, remainder, p, q, t;
|
||||
|
||||
region = h / 43;
|
||||
remainder = (h - (region * 43)) * 6;
|
||||
|
||||
p = (v * (255 - s)) >> 8;
|
||||
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
||||
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
||||
|
||||
switch (region) {
|
||||
case 0:
|
||||
r = v; g = t; b = p;
|
||||
break;
|
||||
case 1:
|
||||
r = q; g = v; b = p;
|
||||
break;
|
||||
case 2:
|
||||
r = p; g = v; b = t;
|
||||
break;
|
||||
case 3:
|
||||
r = p; g = q; b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = t; g = p; b = v;
|
||||
break;
|
||||
default:
|
||||
r = v; g = p; b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string toHEX() const {
|
||||
char buf[8];
|
||||
sprintf(buf, "#%02x%02x%02x", r, g, b);
|
||||
std::string color(buf);
|
||||
return color;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Plotty {
|
||||
|
||||
public:
|
||||
|
||||
Floorplan::IndoorMap* map;
|
||||
const Floorplan::IndoorMap* map;
|
||||
K::Gnuplot gp;
|
||||
K::GnuplotSplot splot;
|
||||
K::GnuplotSplotElementPoints points;
|
||||
K::GnuplotSplotElementColorPoints cpoints;
|
||||
|
||||
K::GnuplotSplotElementLines pathReal;
|
||||
K::GnuplotSplotElementLines pathEst;
|
||||
K::GnuplotSplotElementLines mapOutline;
|
||||
K::GnuplotSplotElementPoints particles;
|
||||
|
||||
K::GnuplotSplotElementLines mapOutlineGlass;
|
||||
K::GnuplotSplotElementLines mapOutlineDrywall;
|
||||
K::GnuplotSplotElementLines mapOutlineConcrete;
|
||||
|
||||
std::string codeFile;
|
||||
|
||||
struct Settings {
|
||||
std::vector<int> floors = {};
|
||||
bool stairs = true;
|
||||
bool obstacles = true;
|
||||
bool outline = true;
|
||||
float minZ = -9999;
|
||||
float maxZ = +9999;
|
||||
} settings;
|
||||
|
||||
public:
|
||||
|
||||
Plotty(Floorplan::IndoorMap* map) : map(map) {
|
||||
Plotty(const Floorplan::IndoorMap* map) : map(map) {
|
||||
|
||||
//gp << "set view equal xy\n";
|
||||
|
||||
@@ -37,37 +123,17 @@ public:
|
||||
gp << "g(x) = 0\n";
|
||||
gp << "b(x) = (x > 0) ? 0 : (-x/2)\n";
|
||||
gp << "set palette model RGB functions r(gray),g(gray),b(gray)\n";
|
||||
gp << "set ticslevel 0\n";
|
||||
|
||||
// draw floorplan
|
||||
mapOutline.setColorHex("#888888");
|
||||
splot.add(&mapOutline);
|
||||
for (Floorplan::Floor* floor : map->floors) {
|
||||
for (Floorplan::FloorObstacle* obs : floor->obstacles) {
|
||||
Floorplan::FloorObstacleLine* line = dynamic_cast<Floorplan::FloorObstacleLine*>(obs);
|
||||
if (line) {
|
||||
const K::GnuplotPoint3 p1(line->from.x, line->from.y, floor->atHeight);
|
||||
const K::GnuplotPoint3 p2(line->to.x, line->to.y, floor->atHeight);
|
||||
mapOutline.addSegment(p1, p2);
|
||||
}
|
||||
}
|
||||
for (Floorplan::Stair* s : floor->stairs) {
|
||||
for (const Floorplan::StairPart& sp : s->getParts()) {
|
||||
const K::GnuplotPoint3 p1(sp.start.x, sp.start.y, sp.start.z + floor->atHeight);
|
||||
const K::GnuplotPoint3 p2(sp.end.x, sp.end.y, sp.end.z + floor->atHeight);
|
||||
mapOutline.addSegment(p1, p2);
|
||||
}
|
||||
}
|
||||
for (Floorplan::FloorOutlinePolygon* poly : floor->outline) {
|
||||
gp << "set object polygon from ";
|
||||
for (size_t i = 0; i < poly->poly.points.size(); ++i) {
|
||||
if (i > 0) {gp << " to ";}
|
||||
const Point2 pt = poly->poly.points[i];
|
||||
gp << pt.x << "," << pt.y << "," << floor->atHeight << " ";
|
||||
}
|
||||
gp << " fs solid fc rgb " << ( poly->outdoor ? "'#ddffdd'" : "'#dddddd'");
|
||||
gp << "\n";
|
||||
}
|
||||
}
|
||||
// how to draw the floorplan
|
||||
mapOutlineConcrete.setColorHex("#888888"); mapOutlineConcrete.setLineWidth(2);
|
||||
mapOutlineDrywall.setColorHex("#888888");
|
||||
mapOutlineGlass.setColorHex("#888888"); mapOutlineGlass.setDashType(2);
|
||||
splot.add(&mapOutlineConcrete);
|
||||
splot.add(&mapOutlineDrywall);
|
||||
splot.add(&mapOutlineGlass);
|
||||
|
||||
splot.add(&particles); particles.setPointSize(0.33); particles.setColorHex("#0000ff");
|
||||
|
||||
splot.add(&pathReal); pathReal.setLineWidth(2); pathReal.setColorHex("#0000ff");
|
||||
splot.add(&pathEst);
|
||||
@@ -117,6 +183,64 @@ public:
|
||||
gp << "set label '" << txt << "' at " << pos.x << "," << pos.y << "," << pos.z << "\n";
|
||||
}
|
||||
|
||||
void addRectangle(const Point3 p1, const Point3 p2, const Color c, bool front = false, bool fill = true) {
|
||||
std::vector<Point3> points = {
|
||||
Point3(p1.x, p1.y, p1.z),
|
||||
Point3(p2.x, p1.y, p1.z),
|
||||
Point3(p2.x, p2.y, p1.z),
|
||||
Point3(p1.x, p2.y, p1.z),
|
||||
Point3(p1.x, p1.y, p1.z),
|
||||
};
|
||||
addPolygon(points, c.toHEX(), front, fill);
|
||||
}
|
||||
|
||||
void addPolygon(const std::vector<Point3>& points, const std::string& color, bool front = false, bool fill = true) {
|
||||
|
||||
for (const Point3 p : points) {
|
||||
if (p.z < settings.minZ) {return;}
|
||||
if (p.z > settings.maxZ) {return;}
|
||||
}
|
||||
|
||||
gp << "set object polygon from ";
|
||||
for (size_t i = 0; i < points.size(); ++i) {
|
||||
const Point3 p = points[i];
|
||||
if (i > 0) {gp << " to ";}
|
||||
gp << p.x << "," << p.y << "," << p.z << " ";
|
||||
}
|
||||
gp << (front ? "front" : "");
|
||||
if (fill) {gp << " fs solid ";} else {gp << " fs transparent ";}
|
||||
gp << " fc rgb " << "'" << color << "'";
|
||||
gp << "\n";
|
||||
|
||||
}
|
||||
|
||||
void setZRange(const float min, const float max) {
|
||||
gp << "set zrange [" << min << ":" << max << "]\n";
|
||||
}
|
||||
|
||||
|
||||
void addFloorRect(const Point3 pos_m, const float size, Color c) {
|
||||
|
||||
const Point3 p1 = pos_m + Point3(-size, -size, 0);
|
||||
const Point3 p2 = pos_m + Point3(+size, -size, 0);
|
||||
const Point3 p3 = pos_m + Point3(+size, +size, 0);
|
||||
const Point3 p4 = pos_m + Point3(-size, +size, 0);
|
||||
|
||||
std::vector<Point3> points = {p1,p2,p3,p4,p1};
|
||||
|
||||
addPolygon(points, c.toHEX());
|
||||
|
||||
// gp << "set object polygon from ";
|
||||
// for (size_t i = 0; i < points.size(); ++i) {
|
||||
// const Point3 p = points[i];
|
||||
// if (i > 0) {gp << " to ";}
|
||||
// gp << p.x << "," << p.y << "," << p.z << " ";
|
||||
// }
|
||||
// gp << "front fs solid fc rgb " << "'" << c.toHEX() << "'";
|
||||
// gp << "\n";
|
||||
|
||||
}
|
||||
|
||||
void setTitle(const std::string& title) {
|
||||
gp << "set title '" << title << "'\n";
|
||||
}
|
||||
@@ -129,11 +253,109 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void equalXY() {
|
||||
gp << "set view equal xy\n";
|
||||
}
|
||||
|
||||
void setView(const float degX, const float degY) {
|
||||
gp << "set view " << degX << "," << degY << "\n";
|
||||
}
|
||||
|
||||
void setScale(const float x, const float y) {
|
||||
gp << "set multiplot layout 1,1 scale " << x << "," << y << "\n";
|
||||
}
|
||||
|
||||
void writeCodeTo(const std::string& file) {
|
||||
this->codeFile = file;
|
||||
}
|
||||
|
||||
void noFrame() {
|
||||
gp << "unset border\n";
|
||||
gp << "unset xtics\n";
|
||||
gp << "unset ytics\n";
|
||||
gp << "unset ztics\n";
|
||||
}
|
||||
|
||||
void writeEpsTex(const std::string file, K::GnuplotSize size = K::GnuplotSize(8.5, 5.1)) {
|
||||
gp.setTerminal("epslatex", size);
|
||||
gp.setOutput(file);
|
||||
}
|
||||
|
||||
void plot() {
|
||||
gp.draw(splot);
|
||||
gp << "unset multiplot\n"; // scaling
|
||||
if (codeFile != "") {
|
||||
std::ofstream out(codeFile);
|
||||
out << gp.getBuffer();
|
||||
out.close();
|
||||
}
|
||||
gp.flush();
|
||||
}
|
||||
|
||||
|
||||
void buildFloorplan() {
|
||||
|
||||
std::vector<Floorplan::Floor*> floors;
|
||||
|
||||
// only some floors??
|
||||
if (settings.floors.empty()) {
|
||||
floors = map->floors;
|
||||
} else {
|
||||
for (int i : settings.floors) {
|
||||
floors.push_back(map->floors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Floorplan::Floor* floor : floors) {
|
||||
|
||||
// plot obstacles
|
||||
if (settings.obstacles) {
|
||||
for (Floorplan::FloorObstacle* obs : floor->obstacles) {
|
||||
Floorplan::FloorObstacleLine* line = dynamic_cast<Floorplan::FloorObstacleLine*>(obs);
|
||||
if (line) {
|
||||
const K::GnuplotPoint3 p1(line->from.x, line->from.y, floor->atHeight);
|
||||
const K::GnuplotPoint3 p2(line->to.x, line->to.y, floor->atHeight);
|
||||
switch(line->material) {
|
||||
case Floorplan::Material::CONCRETE: mapOutlineConcrete.addSegment(p1, p2); break;
|
||||
case Floorplan::Material::GLASS: mapOutlineGlass.addSegment(p1, p2); break;
|
||||
case Floorplan::Material::UNKNOWN:
|
||||
case Floorplan::Material::DRYWALL: mapOutlineDrywall.addSegment(p1, p2); break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// plot the floor's outline
|
||||
if (settings.outline) {
|
||||
for (Floorplan::FloorOutlinePolygon* poly : floor->outline) {
|
||||
gp << "set object polygon from ";
|
||||
for (size_t i = 0; i < poly->poly.points.size() + 1; ++i) {
|
||||
if (i > 0) {gp << " to ";}
|
||||
const Point2 pt = poly->poly.points[i % poly->poly.points.size()]; // ensures closing the polygon
|
||||
gp << pt.x << "," << pt.y << "," << floor->atHeight << " ";
|
||||
}
|
||||
gp << " fs solid fc rgb " << ( poly->outdoor ? "'#bbeebb'" : "'#dddddd'");
|
||||
gp << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// plot the stairs as polygon
|
||||
if (settings.stairs) {
|
||||
for (Floorplan::Stair* s : floor->stairs) {
|
||||
std::vector<Floorplan::Quad3> quads = Floorplan::getQuads(s->getParts(), floor);
|
||||
for (const Floorplan::Quad3& q : quads) {
|
||||
addPolygon({q.p1, q.p2, q.p3, q.p4, q.p1}, "#c0c0c0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // PLOTTY_H
|
||||
|
||||
47
Settings.h
47
Settings.h
@@ -6,6 +6,7 @@
|
||||
|
||||
namespace Settings {
|
||||
|
||||
const std::string pathData = "/apps/android/workspace/OTHER2017/data/";
|
||||
const std::string pathWalks = "/apps/android/workspace/OTHER2017/data/";
|
||||
|
||||
const std::string path1a = pathWalks + "path1/1490208103510.csv";
|
||||
@@ -18,6 +19,52 @@ namespace Settings {
|
||||
const std::string fMap = "/apps/android/workspace/IndoorMap/maps/SHL37.xml";
|
||||
const std::string fCalib = "/apps/android/workspace/OTHER2017/data/wifi_fp_all.dat";
|
||||
|
||||
const std::string fPathGFX = "/apps/android/workspace/OTHER2017/tex/gfx/";
|
||||
|
||||
int numParticles = 5000;
|
||||
|
||||
float smartphoneAboveGround = 1.3;
|
||||
|
||||
namespace IMU {
|
||||
const float turnSigma = 1.5 + 1.5;//1.5;
|
||||
const float stepLength = 0.80;
|
||||
const float stepSigma = 0.40;
|
||||
}
|
||||
|
||||
namespace Grid {
|
||||
constexpr int gridSize_cm = 20;
|
||||
}
|
||||
|
||||
namespace Filter {
|
||||
const Timestamp updateEvery = Timestamp::fromMS(500);
|
||||
}
|
||||
|
||||
|
||||
// //const GridPoint destination = GridPoint(70*100, 35*100, 0*100); // use destination
|
||||
// const GridPoint destination = GridPoint(0,0,0); // do not use destination
|
||||
|
||||
// namespace SensorDebug {
|
||||
// const Timestamp updateEvery = Timestamp::fromMS(200);
|
||||
// }
|
||||
|
||||
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 = -44;
|
||||
constexpr float EXP = 2.5;
|
||||
constexpr float WAF = -8.0;
|
||||
// constexpr float TXP = -64.5896;
|
||||
// constexpr float EXP = 1.25986;
|
||||
// constexpr float WAF = -2.47467;
|
||||
|
||||
// how to perform VAP grouping
|
||||
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 GroundTruth {
|
||||
|
||||
// IPIN2017 [toni]
|
||||
|
||||
178
main.cpp
178
main.cpp
@@ -1,3 +1,5 @@
|
||||
#define BREAK raise(SIGTRAP);
|
||||
|
||||
#include "Indoor/sensors/radio/setup/WiFiOptimizer.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiFingerprint.h"
|
||||
#include "Indoor/sensors/radio/setup/WiFiFingerprints.h"
|
||||
@@ -10,6 +12,7 @@
|
||||
#include "Indoor/floorplan/v2/FloorplanHelper.h"
|
||||
|
||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementPoints.h>
|
||||
#include <KLib/misc/gnuplot/GnuplotSplotElementLines.h>
|
||||
@@ -22,11 +25,102 @@
|
||||
#include "EvalWalk.h"
|
||||
#include "EvalData.h"
|
||||
#include "EvalWiFi.h"
|
||||
#include "EvalWiFiSigStrength.h"
|
||||
|
||||
#include "PlotErrFunc.h"
|
||||
|
||||
// build plots for the paper
|
||||
void paperOutputs() {
|
||||
|
||||
Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);
|
||||
|
||||
if (1==1){
|
||||
EvalWiFiSigStrength sig(Settings::fMap, Settings::fCalib);
|
||||
Plotty* p = new Plotty(map);
|
||||
p->writeCodeTo(Settings::fPathGFX + "compare-wifi-in-out.gp");
|
||||
p->writeEpsTex(Settings::fPathGFX + "compare-wifi-in-out.tex");
|
||||
p->settings.floors = {0};
|
||||
p->settings.maxZ = 1;
|
||||
p->buildFloorplan();
|
||||
sig.forAP_avg(p, MACAddress("d8:84:66:4a:23:d0"));
|
||||
p->equalXY();
|
||||
p->setView(0,0);
|
||||
p->setScale(3.1, 3.1);
|
||||
p->addRectangle(Point3(62, 24, 0), Point3(72, 34, 0), Color::fromRGB(0,0,0), false, false);
|
||||
p->noFrame();
|
||||
p->plot();
|
||||
delete p;
|
||||
}
|
||||
|
||||
if (1==1) {
|
||||
|
||||
const bool ignoreStaircases = false;
|
||||
const bool ignoreOutdoor = false;
|
||||
EvalCompareOptAllFixed allFixed(Settings::fMap, Settings::fCalib, ignoreStaircases, ignoreOutdoor);
|
||||
|
||||
K::Statistics<float> s1 = allFixed.fixedPosFixedParamsForAll(); //BREAK;
|
||||
K::Statistics<float> s2 = allFixed.fixedPosOptParamsForAll(); //BREAK;
|
||||
K::Statistics<float> s3 = allFixed.fixedPosOptParamsForEach(); //BREAK;
|
||||
K::Statistics<float> s4 = allFixed.optPosOptParamsForEach(); //BREAK;
|
||||
|
||||
PlotErrFunc pef("\\small{error (dB)}", "\\small{fingerprints (\\%)}");
|
||||
pef.add("\\small{empiric}", s1);
|
||||
pef.add("\\small{real pos, opt params}", s2);
|
||||
pef.add("\\small{real pos, opt params [per AP]}", s3);
|
||||
pef.add("\\small{opt pos, opt params [per AP]}", s4);
|
||||
|
||||
pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.5, 5));
|
||||
pef.getGP().setOutput(Settings::fPathGFX + "wifi-opt-error-hist-methods.tex");
|
||||
pef.writeCodeTo(Settings::fPathGFX + "wifi-opt-error-hist-methods.gp");
|
||||
pef.getGP() << "set key right bottom width -4 samplen 0.5\n";
|
||||
pef.getGP() << "set rmargin 0.4\n";
|
||||
pef.getGP() << "set tmargin 0.4\n";
|
||||
pef.plot();
|
||||
|
||||
}
|
||||
|
||||
// error histogram all pos, all params, between in/out/stair, in/out, in/stair, in
|
||||
if(1==1){
|
||||
EvalCompareOptAllFixed e1(Settings::fMap, Settings::fCalib, false, false);
|
||||
EvalCompareOptAllFixed e2(Settings::fMap, Settings::fCalib, true, false);
|
||||
EvalCompareOptAllFixed e3(Settings::fMap, Settings::fCalib, false, true);
|
||||
EvalCompareOptAllFixed e4(Settings::fMap, Settings::fCalib, true, true);
|
||||
|
||||
K::Statistics<float> s1 = e1.optPosOptParamsForEach();
|
||||
K::Statistics<float> s2 = e2.optPosOptParamsForEach();
|
||||
K::Statistics<float> s3 = e3.optPosOptParamsForEach();
|
||||
K::Statistics<float> s4 = e4.optPosOptParamsForEach();
|
||||
|
||||
PlotErrFunc pef("\\small{error (dB)}", "\\small{fingerprints (\\%)}");
|
||||
pef.add("\\small{floor + stairs + out}", s1);
|
||||
pef.add("\\small{floor + out}", s2);
|
||||
pef.add("\\small{floor + stairs}", s3);
|
||||
pef.add("\\small{floor}", s4);
|
||||
|
||||
pef.getGP().setTerminal("epslatex", K::GnuplotSize(8.5, 5));
|
||||
pef.getGP().setOutput(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.tex");
|
||||
pef.writeCodeTo(Settings::fPathGFX + "wifi-opt-error-hist-stair-outdoor.gp");
|
||||
pef.getGP() << "set key right bottom width -3\n";
|
||||
pef.getGP() << "set rmargin 0.4\n";
|
||||
pef.getGP() << "set tmargin 0.4\n";
|
||||
pef.plot();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define BREAK raise(SIGTRAP);
|
||||
|
||||
int main(void) {
|
||||
|
||||
// paperOutputs(); return 0;
|
||||
|
||||
if (1 == 1) {
|
||||
Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile(Settings::fMap);;
|
||||
EvalWalk walk(map);
|
||||
walk.walk1();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// test gps within data files
|
||||
if (1 == 0) {
|
||||
EvalData::dumpGPSforPath(Settings::path1a); BREAK;
|
||||
@@ -35,35 +129,83 @@ int main(void) {
|
||||
EvalData::dumpGPSforPath(Settings::path2b); BREAK;
|
||||
}
|
||||
|
||||
// test wifi within data files
|
||||
if (1 == 1) {
|
||||
//EvalWiFi ew1(Settings::fMap, Settings::path2a, Settings::GroundTruth::path2);
|
||||
EvalWiFi ew1(Settings::fMap, Settings::path2a, Settings::GroundTruth::path1);
|
||||
//ew1.fixedParams(-40, 2.5, -8); BREAK;
|
||||
ew1.fixedParams(-64.5905, 1.25988, -2.47863); BREAK;
|
||||
// eval average signal-strength per AP
|
||||
if (1 == 0) {
|
||||
|
||||
EvalWiFiSigStrength ewss(Settings::fMap, Settings::fCalib);
|
||||
ewss.perAP_avg();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// test wifi within data files
|
||||
if (1 == 0) {
|
||||
//EvalWiFi ew1(Settings::fMap, Settings::path2a, Settings::GroundTruth::path2);
|
||||
EvalWiFi ew1(Settings::fMap, Settings::path2a, Settings::GroundTruth::path2);
|
||||
//ew1.fixedParams(-40, 2.5, -8); BREAK;
|
||||
//ew1.fixedParams(-64.5905, 1.25988, -2.47863); BREAK;
|
||||
ew1.fixedParams(-59.4903,1.52411,-3.25077); BREAK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// run walking
|
||||
|
||||
|
||||
// run earthmapping
|
||||
//testMapEarthReg(fMap);
|
||||
|
||||
// EvalApOpt eval(fMap, fCalib);
|
||||
// eval.optAll();
|
||||
|
||||
|
||||
// run evaluation
|
||||
if (1 == 0) {
|
||||
EvalCompareOptAllFixed allFixed(Settings::fMap, Settings::fCalib);
|
||||
allFixed.fixedPosFixedParamsForAll();
|
||||
allFixed.fixedPosOptParamsForAll();
|
||||
allFixed.fixedPosOptParamsForEach();
|
||||
allFixed.optPosOptParamsForEach();
|
||||
EvalApOpt eval(Settings::fMap, Settings::fCalib);
|
||||
eval.optAll();
|
||||
}
|
||||
|
||||
|
||||
// compare wifi opt methods
|
||||
if (1 == 1) {
|
||||
|
||||
const bool ignoreStaircases = false;
|
||||
const bool ignoreOutdoor = false;
|
||||
EvalCompareOptAllFixed allFixed(Settings::fMap, Settings::fCalib, ignoreStaircases, ignoreOutdoor);
|
||||
|
||||
K::Statistics<float> s1 = allFixed.fixedPosFixedParamsForAll(); //BREAK;
|
||||
K::Statistics<float> s2 = allFixed.fixedPosOptParamsForAll(); //BREAK;
|
||||
K::Statistics<float> s3 = allFixed.fixedPosOptParamsForEach(); //BREAK;
|
||||
K::Statistics<float> s4 = allFixed.optPosOptParamsForEach(); //BREAK;
|
||||
|
||||
PlotErrFunc pef("error (dB)", "fingerprints (%)");
|
||||
pef.add("empiric", s1);
|
||||
pef.add("real pos, opt params [same for all]", s2);
|
||||
pef.add("real pos, opt params [for each]", s3);
|
||||
pef.add("opt pos, opt params [for each]", s4);
|
||||
pef.plot();
|
||||
|
||||
}
|
||||
|
||||
// compare leaving out fingerprints
|
||||
if (1 == 0) {
|
||||
|
||||
EvalCompareOptAllFixed e1(Settings::fMap, Settings::fCalib, false, false);
|
||||
EvalCompareOptAllFixed e2(Settings::fMap, Settings::fCalib, true, false);
|
||||
EvalCompareOptAllFixed e3(Settings::fMap, Settings::fCalib, false, true);
|
||||
EvalCompareOptAllFixed e4(Settings::fMap, Settings::fCalib, true, true);
|
||||
|
||||
K::Statistics<float> s1 = e1.optPosOptParamsForEach();
|
||||
K::Statistics<float> s2 = e2.optPosOptParamsForEach();
|
||||
K::Statistics<float> s3 = e3.optPosOptParamsForEach();
|
||||
K::Statistics<float> s4 = e4.optPosOptParamsForEach();
|
||||
|
||||
PlotErrFunc pef("error (dB)", "fingerprints (%)");
|
||||
pef.add("floor + stairs + out", s1);
|
||||
pef.add("floor + out", s2);
|
||||
pef.add("floor + stairs", s3);
|
||||
pef.add("floor", s4);
|
||||
pef.plot();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Floorplan::IndoorMap* map = Floorplan::Reader::readFromFile("/apps/android/workspace/OTHER2017/data/SHL33a.xml");
|
||||
|
||||
|
||||
328
pf/PF.h
Normal file
328
pf/PF.h
Normal file
@@ -0,0 +1,328 @@
|
||||
#ifndef PF_H
|
||||
#define PF_H
|
||||
|
||||
#include <KLib/math/filter/particles/ParticleFilter.h>
|
||||
|
||||
#include <KLib/math/filter/particles/estimation/ParticleFilterEstimationWeightedAverage.h>
|
||||
#include <KLib/math/filter/particles/estimation/ParticleFilterEstimationOrderedWeightedAverage.h>
|
||||
|
||||
#include <KLib/math/filter/particles/resampling/ParticleFilterResamplingSimple.h>
|
||||
#include <KLib/math/filter/particles/resampling/ParticleFilterResamplingPercent.h>
|
||||
|
||||
#include <Indoor/sensors/radio/WiFiProbabilityFree.h>
|
||||
#include <Indoor/sensors/radio/model/WiFiModelLogDistCeiling.h>
|
||||
#include <Indoor/sensors/radio/WiFiProbabilityFree.h>
|
||||
#include <Indoor/sensors/radio/WiFiProbabilityGrid.h>
|
||||
#include <Indoor/sensors/gps/GPSData.h>
|
||||
|
||||
#include <Indoor/grid/walk/v2/GridWalker.h>
|
||||
#include <Indoor/grid/walk/v2/modules/WalkModuleHeadingControl.h>
|
||||
#include <Indoor/grid/walk/v2/modules/WalkModuleNodeImportance.h>
|
||||
#include <Indoor/grid/walk/v2/modules/WalkModuleFavorZ.h>
|
||||
#include <Indoor/grid/walk/v2/modules/WalkModuleActivityControl.h>
|
||||
#include <Indoor/grid/walk/v2/modules/WalkModuleFollowDestination.h>
|
||||
|
||||
#include "../Settings.h"
|
||||
|
||||
struct MyGridNode : public GridNode, public GridPoint {//, public WiFiGridNode<30> {
|
||||
|
||||
float navImportance;
|
||||
float getNavImportance() const { return navImportance; }
|
||||
|
||||
float walkImportance;
|
||||
float getWalkImportance() const { return walkImportance; }
|
||||
|
||||
|
||||
/** empty ctor */
|
||||
MyGridNode() : GridPoint(-1, -1, -1) {;}
|
||||
|
||||
/** ctor */
|
||||
MyGridNode(const int x_cm, const int y_cm, const int z_cm) : GridPoint(x_cm, y_cm, z_cm) {;}
|
||||
|
||||
|
||||
static void staticDeserialize(std::istream& inp) {
|
||||
//WiFiGridNode::staticDeserialize(inp);
|
||||
}
|
||||
|
||||
static void staticSerialize(std::ostream& out) {
|
||||
//WiFiGridNode::staticSerialize(out);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct MyState : public WalkState, public WalkStateFavorZ, public WalkStateHeading {
|
||||
|
||||
|
||||
/** ctor */
|
||||
MyState(const int x_cm, const int y_cm, const int z_cm) : WalkState(GridPoint(x_cm, y_cm, z_cm)), WalkStateHeading(Heading(0), 0) {
|
||||
;
|
||||
}
|
||||
|
||||
MyState() : WalkState(GridPoint()), WalkStateHeading(Heading(0), 0) {
|
||||
;
|
||||
}
|
||||
|
||||
MyState& operator += (const MyState& o) {
|
||||
position += o.position;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyState& operator /= (const float val) {
|
||||
position /= val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyState operator * (const float val) const {
|
||||
MyState copy = *this;
|
||||
copy.position = copy.position * val;
|
||||
return copy;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** observed sensor data */
|
||||
struct MyObservation {
|
||||
|
||||
/** wifi measurements */
|
||||
WiFiMeasurements wifi;
|
||||
|
||||
/** gps measurements */
|
||||
GPSData gps;
|
||||
|
||||
// TODO: switch to a general activity enum/detector for barometer + accelerometer + ...?
|
||||
/** detected activity */
|
||||
ActivityButterPressure::Activity activity;
|
||||
|
||||
/** time of evaluation */
|
||||
Timestamp currentTime;
|
||||
|
||||
};
|
||||
|
||||
/** (observed) control data */
|
||||
struct MyControl {
|
||||
|
||||
/** turn angle (in radians) since the last transition */
|
||||
float turnSinceLastTransition_rad = 0;
|
||||
|
||||
/** number of steps since the last transition */
|
||||
int numStepsSinceLastTransition = 0;
|
||||
|
||||
/** absolute heading in radians */
|
||||
float compass_azimuth = 0;
|
||||
|
||||
// TODO: switch to a general activity enum/detector using barometer + accelerometer?
|
||||
/** currently detected activity */
|
||||
ActivityButterPressure::Activity activity;
|
||||
|
||||
/** reset the control-data after each transition */
|
||||
void resetAfterTransition() {
|
||||
turnSinceLastTransition_rad = 0;
|
||||
numStepsSinceLastTransition = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class PFInit : public K::ParticleFilterInitializer<MyState> {
|
||||
|
||||
private:
|
||||
|
||||
Grid<MyGridNode>* grid;
|
||||
|
||||
public:
|
||||
|
||||
PFInit(Grid<MyGridNode>* grid) : grid(grid) {
|
||||
|
||||
}
|
||||
|
||||
virtual void initialize(std::vector<K::Particle<MyState>>& particles) override {
|
||||
|
||||
std::minstd_rand gen;
|
||||
std::uniform_int_distribution<int> distIdx(0, grid->getNumNodes()-1);
|
||||
std::uniform_real_distribution<float> distHead(0, 2*M_PI);
|
||||
|
||||
for (K::Particle<MyState>& p : particles) {
|
||||
const int idx = distIdx(gen);
|
||||
const MyGridNode& node = (*grid)[idx];
|
||||
p.state.position = node; // random position
|
||||
p.state.heading.direction = Heading(distHead(gen)); // random heading
|
||||
p.weight = 1.0 / particles.size(); // equal weight
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class PFTrans : public K::ParticleFilterTransition<MyState, MyControl> {
|
||||
|
||||
public:
|
||||
|
||||
/** local, static control-data COPY */
|
||||
MyControl ctrl;
|
||||
|
||||
Grid<MyGridNode>* grid;
|
||||
GridWalker<MyGridNode, MyState> walker;
|
||||
|
||||
WalkModuleFavorZ<MyGridNode, MyState> modFavorZ;
|
||||
WalkModuleHeadingControl<MyGridNode, MyState, MyControl> modHeading;
|
||||
WalkModuleNodeImportance<MyGridNode, MyState> modImportance;
|
||||
WalkModuleFollowDestination<MyGridNode, MyState> modDestination;
|
||||
WalkModuleActivityControl<MyGridNode, MyState, MyControl> modActivity;
|
||||
|
||||
std::minstd_rand gen;
|
||||
|
||||
public:
|
||||
|
||||
PFTrans(Grid<MyGridNode>* grid) : grid(grid), modHeading(&ctrl, Settings::IMU::turnSigma), modDestination(*grid), modActivity(&ctrl) {
|
||||
|
||||
//walker.addModule(&modFavorZ);
|
||||
walker.addModule(&modHeading);
|
||||
//walker.addModule(&modImportance);
|
||||
//walker.addModule(&modActivity);
|
||||
|
||||
// if (Settings::destination != GridPoint(0,0,0)) {
|
||||
// //walker.addModule(&modDestination);
|
||||
// modDestination.setDestination(grid->getNodeFor(Settings::destination));
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void transition(std::vector<K::Particle<MyState>>& particles, const MyControl* _ctrl) override {
|
||||
|
||||
// local copy!! observation might be changed async outside!! (will really produces crashes!)
|
||||
this->ctrl = *_ctrl;
|
||||
((MyControl*)_ctrl)->resetAfterTransition();
|
||||
|
||||
std::normal_distribution<float> noise(0, Settings::IMU::stepSigma);
|
||||
|
||||
// sanity check
|
||||
Assert::equal((int)particles.size(), Settings::numParticles, "number of particles does not match the settings!");
|
||||
|
||||
//for (K::Particle<MyState>& p : particles) {
|
||||
//#pragma omp parallel for num_threads(3)
|
||||
for (int i = 0; i < Settings::numParticles; ++i) {
|
||||
|
||||
//#pragma omp atomic
|
||||
const float dist_m = std::abs(ctrl.numStepsSinceLastTransition * Settings::IMU::stepLength + noise(gen));
|
||||
|
||||
K::Particle<MyState>& p = particles[i];
|
||||
|
||||
double prob;
|
||||
p.state = walker.getDestination(*grid, p.state, dist_m, prob);
|
||||
//p.weight *= prob;//(prob > 0.01) ? (1.0) : (0.15);
|
||||
//p.weight = (prob > 0.01) ? (1.0) : (0.15);
|
||||
//p.weight = prob;
|
||||
//p.weight = 1.0; // reset
|
||||
//p.weight = std::pow(p.weight, 0.1); // make all particles a little more equal [less strict]
|
||||
//p.weight *= std::pow(prob, 0.1); // add grid-walk-probability
|
||||
p.weight = prob; // grid-walk-probability
|
||||
if (p.weight != p.weight) {throw Exception("nan");}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class PFEval : public K::ParticleFilterEvaluation<MyState, MyObservation> {
|
||||
|
||||
Grid<MyGridNode>* grid;
|
||||
|
||||
WiFiModelLogDistCeiling& wifiModel;
|
||||
|
||||
|
||||
WiFiObserverFree wiFiProbability; // free-calculation
|
||||
//WiFiObserverGrid<MyGridNode> wiFiProbability; // grid-calculation
|
||||
|
||||
// smartphone is 1.3 meter above ground
|
||||
const Point3 person = Point3(0,0,Settings::smartphoneAboveGround);
|
||||
|
||||
public:
|
||||
|
||||
PFEval(Grid<MyGridNode>* grid, WiFiModelLogDistCeiling& wifiModel) :
|
||||
grid(grid), wifiModel(wifiModel),
|
||||
|
||||
wiFiProbability(Settings::WiFiModel::sigma, wifiModel) { // WiFi free
|
||||
//wiFiProbability(Settings::WiFiModel::sigma) { // WiFi grid
|
||||
|
||||
|
||||
}
|
||||
|
||||
double getStairProb(const K::Particle<MyState>& p, const ActivityButterPressure::Activity act) {
|
||||
|
||||
const float kappa = 0.75;
|
||||
|
||||
const MyGridNode& gn = grid->getNodeFor(p.state.position);
|
||||
switch (act) {
|
||||
|
||||
case ActivityButterPressure::Activity::STAY:
|
||||
if (gn.getType() == GridNode::TYPE_FLOOR) {return kappa;}
|
||||
if (gn.getType() == GridNode::TYPE_DOOR) {return kappa;}
|
||||
{return 1-kappa;}
|
||||
|
||||
case ActivityButterPressure::Activity::UP:
|
||||
case ActivityButterPressure::Activity::DOWN:
|
||||
if (gn.getType() == GridNode::TYPE_STAIR) {return kappa;}
|
||||
if (gn.getType() == GridNode::TYPE_ELEVATOR) {return kappa;}
|
||||
{return 1-kappa;}
|
||||
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
|
||||
}
|
||||
|
||||
double evaluation(std::vector<K::Particle<MyState>>& particles, const MyObservation& _observation) override {
|
||||
|
||||
double sum = 0;
|
||||
|
||||
// local copy!! observation might be changed async outside!! (will really produces crashes!)
|
||||
const MyObservation observation = _observation;
|
||||
|
||||
// vap-grouping
|
||||
const int numAP1 = observation.wifi.entries.size();
|
||||
const WiFiMeasurements wifiObs = Settings::WiFiModel::vg_eval.group(_observation.wifi);
|
||||
const int numAP2 = wifiObs.entries.size();
|
||||
|
||||
Log::add("Filter", "VAP: " + std::to_string(numAP1) + " -> " + std::to_string(numAP2));
|
||||
|
||||
// sanity check
|
||||
Assert::equal((int)particles.size(), Settings::numParticles, "number of particles does not match the settings!");
|
||||
|
||||
//#pragma omp parallel for num_threads(3)
|
||||
for (int i = 0; i < Settings::numParticles; ++i) {
|
||||
|
||||
K::Particle<MyState>& p = particles[i];
|
||||
|
||||
// WiFi free
|
||||
const double pWiFi = wiFiProbability.getProbability(p.state.position.inMeter()+person, observation.currentTime, wifiObs);
|
||||
|
||||
// WiFi grid
|
||||
//const MyGridNode& node = grid->getNodeFor(p.state.position);
|
||||
//const double pWiFi = wiFiProbability.getProbability(node, observation.currentTime, wifiObs);
|
||||
|
||||
|
||||
//Log::add("xxx", std::to_string(observation.currentTime.ms()) + "_" + std::to_string(wifiObs.entries[0].ts.ms()));
|
||||
|
||||
const double pStair = 1;//getStairProb(p, observation.activity);
|
||||
const double pGPS = 1;
|
||||
const double prob = pWiFi * pGPS * pStair;
|
||||
|
||||
p.weight *= prob; // NOTE: keeps the weight returned by the transition step!
|
||||
//p.weight = prob; // does NOT keep the weights returned by the transition step
|
||||
if (p.weight != p.weight) {throw Exception("nan");}
|
||||
|
||||
#pragma omp atomic
|
||||
sum += p.weight;
|
||||
|
||||
}
|
||||
|
||||
return sum;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // PF_H
|
||||
222
tex/bare_conf.tex
Normal file
222
tex/bare_conf.tex
Normal file
@@ -0,0 +1,222 @@
|
||||
|
||||
%% bare_conf.tex
|
||||
%% V1.4b
|
||||
%% 2015/08/26
|
||||
%% by Michael Shell
|
||||
%% See:
|
||||
%% http://www.michaelshell.org/
|
||||
%% for current contact information.
|
||||
%%
|
||||
%% This is a skeleton file demonstrating the use of IEEEtran.cls
|
||||
%% (requires IEEEtran.cls version 1.8b or later) with an IEEE
|
||||
%% conference paper.
|
||||
%%
|
||||
%% Support sites:
|
||||
%% http://www.michaelshell.org/tex/ieeetran/
|
||||
%% http://www.ctan.org/pkg/ieeetran
|
||||
%% and
|
||||
%% http://www.ieee.org/
|
||||
|
||||
%%*************************************************************************
|
||||
%% Legal Notice:
|
||||
%% This code is offered as-is without any warranty either expressed or
|
||||
%% implied; without even the implied warranty of MERCHANTABILITY or
|
||||
%% FITNESS FOR A PARTICULAR PURPOSE!
|
||||
%% User assumes all risk.
|
||||
%% In no event shall the IEEE or any contributor to this code be liable for
|
||||
%% any damages or losses, including, but not limited to, incidental,
|
||||
%% consequential, or any other damages, resulting from the use or misuse
|
||||
%% of any information contained here.
|
||||
%%
|
||||
%% All comments are the opinions of their respective authors and are not
|
||||
%% necessarily endorsed by the IEEE.
|
||||
%%
|
||||
%% This work is distributed under the LaTeX Project Public License (LPPL)
|
||||
%% ( http://www.latex-project.org/ ) version 1.3, and may be freely used,
|
||||
%% distributed and modified. A copy of the LPPL, version 1.3, is included
|
||||
%% in the base LaTeX documentation of all distributions of LaTeX released
|
||||
%% 2003/12/01 or later.
|
||||
%% Retain all contribution notices and credits.
|
||||
%% ** Modified files should be clearly indicated as such, including **
|
||||
%% ** renaming them and changing author support contact information. **
|
||||
%%*************************************************************************
|
||||
|
||||
|
||||
% *** Authors should verify (and, if needed, correct) their LaTeX system ***
|
||||
% *** with the testflow diagnostic prior to trusting their LaTeX platform ***
|
||||
% *** with production work. The IEEE's font choices and paper sizes can ***
|
||||
% *** trigger bugs that do not appear when using other class files. *** ***
|
||||
% The testflow support page is at:
|
||||
% http://www.michaelshell.org/tex/testflow/
|
||||
|
||||
|
||||
|
||||
\documentclass[conference]{IEEEtran}
|
||||
% Some Computer Society conferences also require the compsoc mode option,
|
||||
% but others use the standard conference format.
|
||||
%
|
||||
% If IEEEtran.cls has not been installed into the LaTeX system files,
|
||||
% manually specify the path to it like:
|
||||
% \documentclass[conference]{../sty/IEEEtran}
|
||||
|
||||
|
||||
% needed packages
|
||||
|
||||
\usepackage{color, colortbl}
|
||||
%\usepackage[table]{xcolor}
|
||||
\usepackage{cite}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{amsfonts}
|
||||
|
||||
\usepackage[cmex10]{amsmath}
|
||||
|
||||
\interdisplaylinepenalty=2500
|
||||
\usepackage{algorithmic}
|
||||
\usepackage{array}
|
||||
\usepackage{mdwmath}
|
||||
\usepackage{mdwtab}
|
||||
\usepackage{eqparbox}
|
||||
|
||||
\usepackage{epstopdf}
|
||||
%\usepackage{ulem}
|
||||
|
||||
|
||||
|
||||
|
||||
% replacement for the SI package
|
||||
\newcommand{\SI}[2]{\ensuremath{#1}\text{\,#2}}
|
||||
\newcommand{\SIrange}[3]{\ensuremath{#1} to \ensuremath{#2}\text{\,#3}}
|
||||
|
||||
% units for the SI package
|
||||
\newcommand{\centimeter}{cm}
|
||||
\newcommand{\meter}{m}
|
||||
\newcommand{\per}{/}
|
||||
\newcommand{\milli}{m}
|
||||
\newcommand{\second}{s}
|
||||
\newcommand{\giga}{G}
|
||||
\newcommand{\hertz}{Hz}
|
||||
\newcommand{\dBm}{dBm}
|
||||
\newcommand{\percent}{\%}
|
||||
\newcommand{\decibel}{dB}
|
||||
\newcommand{\dB}{dB}
|
||||
\newcommand{\hpa}{hPa}
|
||||
\newcommand{\degree}{\ensuremath{^{\circ}}}
|
||||
|
||||
% missing math operators
|
||||
\DeclareMathOperator*{\argmin}{arg\,min}
|
||||
\DeclareMathOperator*{\argmax}{arg\,max}
|
||||
|
||||
|
||||
% vector and matrix typesetting
|
||||
\renewcommand{\vec}[1]{\boldsymbol{#1}} % italic and greek symbols
|
||||
\newcommand{\mat}[1]{\vec{#1}} % the same as vec
|
||||
|
||||
|
||||
%other macros
|
||||
\newcommand{\noStep}{\overline{\text{step}}}
|
||||
|
||||
|
||||
% gfx include folder
|
||||
\graphicspath{ {gfx/baro/},{gfx/graph/},{gfx/paths/},{gfx/eval/},{gfx/},{gfx/grid/}}
|
||||
|
||||
|
||||
% correct bad hyphenation here
|
||||
\hyphenation{op-tical net-works semi-conduc-tor}
|
||||
|
||||
|
||||
% input stuff
|
||||
\input{misc/keywords}
|
||||
\input{misc/functions}
|
||||
|
||||
|
||||
\begin{document}
|
||||
%
|
||||
% paper title
|
||||
% Titles are generally capitalized except for words such as a, an, and, as,
|
||||
% at, but, by, for, in, nor, of, on, or, the, to and up, which are usually
|
||||
% not capitalized unless they are the first or last word of the title.
|
||||
% Linebreaks \\ can be used within to get better formatting as desired.
|
||||
% Do not put math or special symbols in the title.
|
||||
\title{minimizing system setup times }
|
||||
|
||||
|
||||
% author names and affiliations
|
||||
% use a multiple column layout for up to three different
|
||||
% affiliations
|
||||
\author{
|
||||
|
||||
\IEEEauthorblockN{Frank Ebner, Toni Fetzer and Frank Deinzer}%
|
||||
\IEEEauthorblockA{%
|
||||
Faculty of Computer Science and Business Information Systems\\
|
||||
University of Applied Sciences W\"urzburg-Schweinfurt\\
|
||||
W\"urzburg, Germany\\
|
||||
\{frank.ebner, toni.fetzer, frank.deinzer\}@fhws.de\\
|
||||
}
|
||||
\and
|
||||
|
||||
\IEEEauthorblockN{Marcin Grzegorzek}
|
||||
\IEEEauthorblockA{%
|
||||
Pattern Recognition Group \\
|
||||
University of Siegen\\
|
||||
Siegen, Germany\\
|
||||
\{marcin.grzegorzek\}@uni-siegen.de
|
||||
}%
|
||||
}
|
||||
|
||||
% conference papers do not typically use \thanks and this command
|
||||
% is locked out in conference mode. If really needed, such as for
|
||||
% the acknowledgment of grants, issue a \IEEEoverridecommandlockouts
|
||||
% after \documentclass
|
||||
|
||||
% use for special paper notices
|
||||
%\IEEEspecialpapernotice{(Invited Paper)}
|
||||
|
||||
|
||||
% make the title area
|
||||
\maketitle
|
||||
|
||||
% As a general rule, do not put math, special symbols or citations
|
||||
% in the abstract
|
||||
\input{chapters/abstract}
|
||||
|
||||
|
||||
% For peer review papers, you can put extra information on the cover
|
||||
% page as needed:
|
||||
% \ifCLASSOPTIONpeerreview
|
||||
% \begin{center} \bfseries EDICS Category: 3-BBND \end{center}
|
||||
% \fi
|
||||
%
|
||||
% For peerreview papers, this IEEEtran command inserts a page break and
|
||||
% creates the second title. It will be ignored for other modes.
|
||||
\IEEEpeerreviewmaketitle
|
||||
|
||||
|
||||
\input{chapters/introduction}
|
||||
|
||||
\input{chapters/relatedwork}
|
||||
|
||||
\input{chapters/experiments}
|
||||
|
||||
\input{chapters/conclusion}
|
||||
|
||||
|
||||
% conference papers do not normally have an appendix
|
||||
|
||||
% use section* for acknowledgment
|
||||
%\section*{Acknowledgment}
|
||||
|
||||
%The authors would like to thank...
|
||||
|
||||
% balancing
|
||||
%\IEEEtriggeratref{8}
|
||||
% The "triggered" command can be changed if desired:
|
||||
%\IEEEtriggercmd{\enlargethispage{-5in}}
|
||||
|
||||
|
||||
% references section
|
||||
\bibliographystyle{IEEEtran}
|
||||
\bibliography{IEEEabrv,egbib}
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
1
tex/chapters/abstract.tex
Normal file
1
tex/chapters/abstract.tex
Normal file
@@ -0,0 +1 @@
|
||||
abstract
|
||||
1
tex/chapters/conclusion.tex
Normal file
1
tex/chapters/conclusion.tex
Normal file
@@ -0,0 +1 @@
|
||||
conclusion
|
||||
15
tex/chapters/experiments.tex
Normal file
15
tex/chapters/experiments.tex
Normal file
@@ -0,0 +1,15 @@
|
||||
experiments
|
||||
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
|
||||
\input{gfx/compare-wifi-in-out.tex}
|
||||
starker einfluss der glasscheiben.. 3 meter nach dem AP ist nur noch sehr wenig uebrig
|
||||
|
||||
|
||||
\input{gfx/wifi-opt-error-hist-methods.tex}
|
||||
|
||||
\input{gfx/wifi-opt-error-hist-stair-outdoor.tex}
|
||||
outdoor hat insgesamt nicht all zu viel einfluss, da die meisten APs
|
||||
an den outdoor punkten kaum gesehen werden. auf einzelne APs kann
|
||||
der einfluss jedoch recht groß sein, siehe den fingerprint plot von
|
||||
dem einen ausgewählten AP
|
||||
1
tex/chapters/interoduction.tex
Normal file
1
tex/chapters/interoduction.tex
Normal file
@@ -0,0 +1 @@
|
||||
abstract
|
||||
1
tex/chapters/introduction.tex
Normal file
1
tex/chapters/introduction.tex
Normal file
@@ -0,0 +1 @@
|
||||
introduction
|
||||
3
tex/chapters/relatedwork.tex
Normal file
3
tex/chapters/relatedwork.tex
Normal file
@@ -0,0 +1,3 @@
|
||||
relatedwork
|
||||
|
||||
\cite{Ebner-15}
|
||||
2709
tex/egbib.bib
Normal file
2709
tex/egbib.bib
Normal file
File diff suppressed because it is too large
Load Diff
4
tex/gfx/build.sh
Normal file
4
tex/gfx/build.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
for file in *.gp
|
||||
do
|
||||
gnuplot $file;
|
||||
done
|
||||
15
tex/make.sh
Normal file
15
tex/make.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
#PATH=$PATH:/mnt/data/texlive/bin/x86_64-linux/
|
||||
PATH=$PATH:/mnt/vm/programme/texlive/bin/x86_64-linux/
|
||||
|
||||
latex bare_conf.tex
|
||||
bibtex bare_conf
|
||||
latex bare_conf.tex
|
||||
latex bare_conf.tex
|
||||
|
||||
dvips bare_conf.dvi
|
||||
|
||||
ps2pdf14 bare_conf.ps
|
||||
|
||||
okular bare_conf.pdf&
|
||||
137
tex/misc/functions.tex
Normal file
137
tex/misc/functions.tex
Normal file
@@ -0,0 +1,137 @@
|
||||
|
||||
\newcommand{\mAvgSquaredError}{\ensuremath{\overline{e}}}
|
||||
|
||||
\newcommand{\mLogDistGamma}{\ensuremath{\gamma}}
|
||||
\newcommand{\mLogDistTX}{TX}
|
||||
|
||||
\newcommand{\mDongle}[1]{\ensuremath{D_{#1}}}
|
||||
%\newcommand{\mDongle}{d} % dongle
|
||||
\newcommand{\mBeacon}[1]{\ensuremath{B_{#1}}} % beacon
|
||||
|
||||
\newcommand{\mRssi}{\ensuremath{s}} % client's signal-strength measurement
|
||||
\newcommand{\mMdlRSSI}{\ensuremath{\varsigma}} % model's signal-strength
|
||||
|
||||
\newcommand{\mPosAP}{\varrho} % char for access point position vector
|
||||
\newcommand{\mPos}{\rho} % char for positions
|
||||
|
||||
|
||||
\newcommand{\mPosVec}{\vec{\mPos}} % position vector
|
||||
\newcommand{\mRssiVec}{\vec{s}} % client signal strength measurements
|
||||
|
||||
\newcommand{\mState}{q} % state variable
|
||||
\newcommand{\mStateVec}{\vec{q}} % state vector variable
|
||||
\newcommand{\mObs}{o} % observation variable
|
||||
\newcommand{\mObsVec}{\vec{o}} % observation vector variable
|
||||
\newcommand{\mObsWifi}{\vec{o}_{\text{wifi}}} % wifi observation
|
||||
|
||||
\newcommand{\mProb}{p} % char for probability
|
||||
|
||||
\newcommand{\mMovingAvgWithSize}[1]{\ensuremath{\text{avg}_{#1}}}
|
||||
|
||||
\newcommand{\mPressure}{\rho}
|
||||
\newcommand{\mObsPressure}{\mPressure_\text{rel}} % symbol for observation pressure
|
||||
\newcommand{\mStatePressure}{\hat{\mPressure}_\text{rel}} % symbol for state pressure
|
||||
|
||||
\newcommand{\mHeading}{\theta}
|
||||
\newcommand{\mObsHeading}{\Delta\mHeading} % symbol used for the observation heading
|
||||
\newcommand{\mStateHeading}{\mHeading} % symbol used for the state heading
|
||||
|
||||
\newcommand{\mSteps}{n_\text{steps}}
|
||||
\newcommand{\mObsSteps}{\mSteps}
|
||||
|
||||
\newcommand{\mNN}{\text{nn}}
|
||||
\newcommand{\mKNN}{\text{knn}}
|
||||
\newcommand{\fPos}[1]{\textbf{pos}(#1)}
|
||||
\newcommand{\fDistance}[2]{\delta(#1, #2)}
|
||||
\newcommand{\fWA}[1]{\text{wall}(#1)}
|
||||
\newcommand{\fDD}[1]{\text{door}(#1)}
|
||||
\newcommand{\fImp}[1]{\text{imp}(#1)}
|
||||
\newcommand{\fNN}[2]{\text{nn}(#1, #2)}
|
||||
\newcommand{\fLength}[2]{\text{d}(#1, #2)}
|
||||
|
||||
%\newcommand{\mTarget}{\dot{v}}
|
||||
\newcommand{\mVertexA}{v_i}
|
||||
\newcommand{\mVertexB}{v_j}
|
||||
\newcommand{\mEdgeAB}{e_{i,j}}
|
||||
\newcommand{\mVertexDest}{v_\text{dest}}
|
||||
|
||||
\newcommand{\mUsePath}{\kappa}
|
||||
|
||||
\newcommand{\mStepSize}{s_\text{step}}
|
||||
|
||||
%\newcommand{\docIBeacon}{iBeacon}
|
||||
|
||||
% for equation references
|
||||
\newcommand{\refeq}[1]{eq. \eqref{#1}}
|
||||
|
||||
% add todo notes
|
||||
\newcommand{\todo}[1]{%
|
||||
\noindent%
|
||||
\fcolorbox{black}{yellow}{%
|
||||
\parbox[position]{0.45\textwidth}{%
|
||||
\footnotesize%
|
||||
{\bf TODO} #1%
|
||||
}%
|
||||
}%
|
||||
}
|
||||
|
||||
%\newcommand{\commentByFrank}[1]{}
|
||||
%\newcommand{\commentByToni}[1]{}
|
||||
|
||||
%comments
|
||||
\newcommand{\commentByFrank}[1]{%
|
||||
\noindent%
|
||||
\fcolorbox{black}{cyan}{%
|
||||
\parbox[position]{0.45\textwidth}{%
|
||||
\footnotesize%
|
||||
{\bf Frank:} #1%
|
||||
}%
|
||||
}%
|
||||
}
|
||||
\newcommand{\commentByLukas}[1]{%
|
||||
\noindent%
|
||||
\fcolorbox{black}{green}{%
|
||||
\parbox[position]{0.45\textwidth}{%
|
||||
\footnotesize%
|
||||
{\bf Lukas:} #1%
|
||||
}%
|
||||
}%
|
||||
}
|
||||
\newcommand{\commentByToni}[1]{%
|
||||
\noindent%
|
||||
\fcolorbox{black}{red}{%
|
||||
\parbox[position]{0.45\textwidth}{%
|
||||
\footnotesize%
|
||||
{\bf Toni:} #1%
|
||||
}%
|
||||
}%
|
||||
}
|
||||
|
||||
\newcommand{\docRSSI}{RSSI}
|
||||
\newcommand{\docTX}{TX}
|
||||
\newcommand{\docLogDist}{log-distance}
|
||||
|
||||
%\newcommand{\docAP}{access-point}
|
||||
%\newcommand{\docAPs}{access-points}
|
||||
|
||||
|
||||
|
||||
|
||||
\newcommand{\R}{\mathbb{R}}
|
||||
\newcommand{\N}{\mathbb{N}}
|
||||
|
||||
\newcommand{\mPLE}{\ensuremath{\gamma}} % path-loss exponent
|
||||
\newcommand{\mTXP}{\ensuremath{P_0}} % tx-power
|
||||
\newcommand{\mWAF}{\ensuremath{\beta}} % wall attenuation factor
|
||||
|
||||
\newcommand{\mMdlDist}{\ensuremath{d}} % distance used within propagation models
|
||||
|
||||
%\newcommand{\mGraph}{\ensuremath{G}}
|
||||
%\newcommand{\mVertices}{\ensuremath{V}}
|
||||
%\newcommand{\mVertex}{\ensuremath{v}}
|
||||
%\newcommand{\mVertexB}{\ensuremath{w}}
|
||||
%\newcommand{\mEdges}{\ensuremath{E}}
|
||||
%\newcommand{\mEdge}{\ensuremath{e}}
|
||||
|
||||
|
||||
|
||||
31
tex/misc/keywords.tex
Normal file
31
tex/misc/keywords.tex
Normal file
@@ -0,0 +1,31 @@
|
||||
% keyword macros
|
||||
\newcommand{\docIBeacon}{iBeacon}
|
||||
|
||||
% wifi naming
|
||||
\newcommand{\wifiRSSI}{RSSI}
|
||||
\newcommand{\wifiTxPower}{TX-Power}
|
||||
\newcommand{\wifiPathLossExp}{PathLoss}
|
||||
|
||||
\newcommand{\wifiPropLogScale}{Log-Scale}
|
||||
\newcommand{\wifiPropLogScaleWalls}{Log-Scale-Walls}
|
||||
\newcommand{\docLogDistance}{log-distance}
|
||||
\newcommand{\docLogDistanceWalls}{wall-attenuation-factor}
|
||||
|
||||
|
||||
% misc
|
||||
\newcommand{\docTxPower}{TX-Power}
|
||||
\newcommand{\docPathLossExp}{PathLoss}
|
||||
\newcommand{\docPathLoss}{Pathloss}
|
||||
|
||||
\newcommand{\docsAP}{AP}
|
||||
\newcommand{\docAPshort}{AP}
|
||||
\newcommand{\docAP}{access-point}
|
||||
\newcommand{\docAPs}{access-points}
|
||||
|
||||
\newcommand{\docWIFI}{Wi\hbox{-}Fi}
|
||||
\newcommand{\docBeacon}{\Gls{Beacon}}
|
||||
\newcommand{\docBeacons}{\Glspl{Beacon}}
|
||||
|
||||
\newcommand{\docsRSSI}{RSSI}
|
||||
|
||||
\newcommand{\docDSimplex}{downhill-simplex}
|
||||
Reference in New Issue
Block a user