added tex

many changes/eval etc...
This commit is contained in:
2017-03-28 21:02:37 +02:00
parent 25e9b823eb
commit e718dc8cca
25 changed files with 4614 additions and 88 deletions

View File

@@ -58,7 +58,7 @@ ADD_DEFINITIONS(
-fstack-protector-all
-g3
-O0
-O0
-march=native
-DWITH_TESTS

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -47,6 +47,8 @@ public:
}
};
#endif // EVALDATA_H

View File

@@ -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();
}
};

View File

@@ -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
View 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
View File

@@ -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
View 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
View File

@@ -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

View File

@@ -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
View File

@@ -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
View 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
View 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}

View File

@@ -0,0 +1 @@
abstract

View File

@@ -0,0 +1 @@
conclusion

View 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

View File

@@ -0,0 +1 @@
abstract

View File

@@ -0,0 +1 @@
introduction

View File

@@ -0,0 +1,3 @@
relatedwork
\cite{Ebner-15}

2709
tex/egbib.bib Normal file

File diff suppressed because it is too large Load Diff

4
tex/gfx/build.sh Normal file
View File

@@ -0,0 +1,4 @@
for file in *.gp
do
gnuplot $file;
done

15
tex/make.sh Normal file
View 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
View 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
View 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}