added beacon stuff similiar architecture then wifi \n added activity percentage stuff \n added testcases
This commit is contained in:
46
sensors/beacon/model/BeaconModel.h
Normal file
46
sensors/beacon/model/BeaconModel.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef BEACONMODEL_H
|
||||
#define BEACONMODEL_H
|
||||
|
||||
#include "../Beacon.h"
|
||||
#include "../BeaconMeasurement.h"
|
||||
#include "../../../geo/Point3.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* interface for signal-strength prediction models.
|
||||
*
|
||||
* the model is passed a MAC-address of an AP in question, and a position.
|
||||
* hereafter the model returns the RSSI for this AP at the questioned location.
|
||||
*/
|
||||
class BeaconModel {
|
||||
|
||||
public:
|
||||
|
||||
// /** get the given access-point's RSSI at the provided location */
|
||||
// virtual float getRSSI(const LocatedAccessPoint& ap, const Point3 p) = 0;
|
||||
|
||||
/** get a list of all APs known to the model */
|
||||
virtual std::vector<Beacon> getAllBeacons() const = 0;
|
||||
|
||||
/**
|
||||
* update the beacons signal strength using the current measurement
|
||||
* this could happen if the txp is not updated within the floorplan
|
||||
*
|
||||
* be careful and don't use fantasy values, this could ruin your localitions
|
||||
* completely
|
||||
*/
|
||||
virtual void updateBeacon(const BeaconMeasurement beacon) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* get the RSSI expected at the given location (in meter)
|
||||
* for an beacon identified by the given MAC.
|
||||
*
|
||||
* if the model can not predict the RSSI for an beacon, it returns NaN!
|
||||
*/
|
||||
virtual float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif // BEACONMODEL_H
|
||||
92
sensors/beacon/model/BeaconModelLogDist.h
Normal file
92
sensors/beacon/model/BeaconModelLogDist.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef BEACONMODELLOGDIST_H
|
||||
#define BEACONMODELLOGDIST_H
|
||||
|
||||
#include "BeaconModel.h"
|
||||
#include "../../radio/model/LogDistanceModel.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* signal-strength estimation using log-distance model
|
||||
*/
|
||||
class BeaconModelLogDist : public BeaconModel {
|
||||
|
||||
public:
|
||||
|
||||
/** parameters describing one beacons to the model */
|
||||
struct APEntry {
|
||||
|
||||
Point3 position_m; // the AP's position (in meter)
|
||||
float txp; // sending power (-40)
|
||||
float exp; // path-loss-exponent (~2.0 - 4.0)
|
||||
|
||||
/** ctor */
|
||||
APEntry(const Point3 position_m, const float txp, const float exp) :
|
||||
position_m(position_m), txp(txp), exp(exp) {;}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** map of all beacons (and their parameters) known to the model */
|
||||
std::unordered_map<MACAddress, APEntry> beacons;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
BeaconModelLogDist() {
|
||||
;
|
||||
}
|
||||
|
||||
/** get a list of all beacons known to the model */
|
||||
std::vector<Beacon> getAllBeacons() const {
|
||||
std::vector<Beacon> aps;
|
||||
for (const auto it : beacons) {aps.push_back(Beacon(it.first));}
|
||||
return aps;
|
||||
}
|
||||
|
||||
/** make the given beacon (and its parameters) known to the model */
|
||||
void addAP(const MACAddress& beacon, const APEntry& params) {
|
||||
|
||||
// sanity check
|
||||
Assert::isBetween(params.txp, -50.0f, -30.0f, "TXP out of bounds [-90:-30]");
|
||||
Assert::isBetween(params.exp, 1.0f, 4.0f, "EXP out of bounds [1:4]");
|
||||
|
||||
// add
|
||||
beacons.insert( std::pair<MACAddress, APEntry>(beacon, params) );
|
||||
|
||||
}
|
||||
|
||||
void updateBeacon(const BeaconMeasurement beacon) override{
|
||||
// try to get the corresponding parameters
|
||||
const auto it = beacons.find(MACAddress(beacon.getBeacon().getMAC()));
|
||||
|
||||
// beacon unknown? -> NAN
|
||||
if (it == beacons.end()) {return;}
|
||||
|
||||
it->second.txp = beacon.getBeacon().getTXP();
|
||||
}
|
||||
|
||||
virtual float getRSSI(const MACAddress& beacon, const Point3 position_m) const override {
|
||||
|
||||
// try to get the corresponding parameters
|
||||
const auto it = beacons.find(beacon);
|
||||
|
||||
// AP unknown? -> NAN
|
||||
if (it == beacons.end()) {return NAN;}
|
||||
|
||||
// the beacons' parameters
|
||||
const APEntry& params = it->second;
|
||||
|
||||
// free-space (line-of-sight) RSSI
|
||||
const float distance_m = position_m.getDistance(params.position_m);
|
||||
const float rssiLOS = LogDistanceModel::distanceToRssi(params.txp, params.exp, distance_m);
|
||||
|
||||
// done
|
||||
return rssiLOS;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // BEACONMODELLOGDIST_H
|
||||
208
sensors/beacon/model/BeaconModelLogDistCeiling.h
Normal file
208
sensors/beacon/model/BeaconModelLogDistCeiling.h
Normal file
@@ -0,0 +1,208 @@
|
||||
#ifndef BEACONMODELLOGDISTCEILING_H
|
||||
#define BEACONMODELLOGDISTCEILING_H
|
||||
|
||||
#include "../../../floorplan/v2/Floorplan.h"
|
||||
|
||||
#include "../../../Assertions.h"
|
||||
#include "BeaconModel.h"
|
||||
#include "../../radio/model/LogDistanceModel.h"
|
||||
#include "../BeaconMeasurement.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* signal-strength estimation using log-distance model
|
||||
* including ceilings between beacon and position
|
||||
*/
|
||||
class BeaconModelLogDistCeiling : public BeaconModel {
|
||||
|
||||
public:
|
||||
|
||||
/** parameters describing one beacon to the model */
|
||||
struct APEntry {
|
||||
|
||||
Point3 position_m; // the beacon's position (in meter)
|
||||
float txp; // sending power (-40)
|
||||
float exp; // path-loss-exponent (~2.0 - 4.0)
|
||||
float waf; // attenuation per ceiling/floor (~-8.0)
|
||||
|
||||
/** ctor */
|
||||
APEntry(const Point3 position_m, const float txp, const float exp, const float waf) :
|
||||
position_m(position_m), txp(txp), exp(exp), waf(waf) {;}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** map of all beacons (and their parameters) known to the model */
|
||||
std::unordered_map<MACAddress, APEntry> beacons;
|
||||
|
||||
/** position (height) of all ceilings (in meter) */
|
||||
std::vector<float> ceilingsAtHeight_m;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor with floorplan (needed for ceiling position) */
|
||||
BeaconModelLogDistCeiling(const Floorplan::IndoorMap* map) {
|
||||
|
||||
// sanity checks
|
||||
Assert::isTrue(map->floors.size() >= 1, "map has no floors?!");
|
||||
|
||||
// position of all ceilings
|
||||
for (Floorplan::Floor* f : map->floors) {
|
||||
ceilingsAtHeight_m.push_back(f->atHeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** get a list of all beacons known to the model */
|
||||
std::vector<Beacon> getAllBeacons() const {
|
||||
std::vector<Beacon> aps;
|
||||
for (const auto it : beacons) {aps.push_back(Beacon(it.first));}
|
||||
return aps;
|
||||
}
|
||||
|
||||
/** load beacon information from the floorplan. use the given fixed TXP/EXP/WAF for all APs */
|
||||
void loadBeaconsFromMap(const Floorplan::IndoorMap* map, const float txp = -40.0f, const float exp = 2.5f, const float waf = -8.0f) {
|
||||
|
||||
for (const Floorplan::Floor* floor : map->floors) {
|
||||
for (const Floorplan::Beacon* beacon : floor->beacons) {
|
||||
APEntry ape(beacon->getPos(floor), txp, exp, waf);
|
||||
addBeacon(MACAddress(beacon->mac), ape);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** load beacon information from a vector. use the given fixed TXP/EXP/WAF for all APs */
|
||||
void loadBeaconsFromVector(const Floorplan::IndoorMap* map, const float txp = -40.0f, const float exp = 2.5f, const float waf = -8.0f) {
|
||||
|
||||
for (const Floorplan::Floor* floor : map->floors) {
|
||||
for (const Floorplan::Beacon* beacon : floor->beacons) {
|
||||
APEntry ape(beacon->getPos(floor), txp, exp, waf);
|
||||
addBeacon(MACAddress(beacon->mac), ape);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** make the given beacon (and its parameters) known to the model */
|
||||
void addBeacon(const MACAddress& beacon, const APEntry& params) {
|
||||
|
||||
// sanity check
|
||||
Assert::isBetween(params.waf, -99.0f, 0.0f, "WAF out of bounds [-99:0]");
|
||||
Assert::isBetween(params.txp, -50.0f, -30.0f, "TXP out of bounds [-50:-30]");
|
||||
Assert::isBetween(params.exp, 1.0f, 4.0f, "EXP out of bounds [1:4]");
|
||||
|
||||
Assert::equal(beacons.find(beacon), beacons.end(), "AccessPoint already present!");
|
||||
|
||||
// add
|
||||
beacons.insert( std::pair<MACAddress, APEntry>(beacon, params) );
|
||||
|
||||
}
|
||||
|
||||
void updateBeacon(const BeaconMeasurement beacon) override {
|
||||
// try to get the corresponding parameters
|
||||
auto it = beacons.find(MACAddress(beacon.getBeacon().getMAC()));
|
||||
|
||||
// beacon unknown? -> NAN
|
||||
if (it == beacons.end()) {return;}
|
||||
|
||||
|
||||
// TODO: Check if this works as expected
|
||||
it->second.txp = beacon.getBeacon().getTXP();
|
||||
}
|
||||
|
||||
/** remove all added APs */
|
||||
void clear() {
|
||||
beacons.clear();
|
||||
}
|
||||
|
||||
float getRSSI(const MACAddress& beacon, const Point3 position_m) const override {
|
||||
|
||||
// try to get the corresponding parameters
|
||||
const auto it = beacons.find(beacon);
|
||||
|
||||
// beacon unknown? -> NAN
|
||||
if (it == beacons.end()) {return NAN;}
|
||||
|
||||
// the access-points' parameters
|
||||
const APEntry& params = it->second;
|
||||
|
||||
// free-space (line-of-sight) RSSI
|
||||
const float distance_m = position_m.getDistance(params.position_m);
|
||||
const float rssiLOS = LogDistanceModel::distanceToRssi(params.txp, params.exp, distance_m);
|
||||
|
||||
// WAF loss (params.waf is a negative value!) -> WAF loss is also a negative value
|
||||
const float wafLoss = params.waf * numCeilingsBetween(position_m, params.position_m);
|
||||
|
||||
// combine
|
||||
return rssiLOS + wafLoss;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
FRIEND_TEST(LogDistanceCeilingModelBeacon, numCeilings);
|
||||
FRIEND_TEST(LogDistanceCeilingModelBeacon, numCeilingsFloat);
|
||||
|
||||
|
||||
/** get the number of ceilings between z1 and z2 */
|
||||
float numCeilingsBetweenFloat(const Point3 pos1, const Point3 pos2) const {
|
||||
|
||||
|
||||
const float zMin = std::min(pos1.z, pos2.z);
|
||||
const float zMax = std::max(pos1.z, pos2.z);
|
||||
|
||||
float cnt = 0;
|
||||
|
||||
for (const float z : ceilingsAtHeight_m) {
|
||||
if (zMin < z && zMax > z) {
|
||||
const float dmax = zMax - z;
|
||||
cnt += (dmax > 1) ? (1) : (dmax);
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
|
||||
}
|
||||
|
||||
/** get the number of ceilings between z1 and z2 */
|
||||
int numCeilingsBetween(const Point3 pos1, const Point3 pos2) const {
|
||||
|
||||
int cnt = 0;
|
||||
const float zMin = std::min(pos1.z, pos2.z);
|
||||
const float zMax = std::max(pos1.z, pos2.z);
|
||||
|
||||
#ifdef WITH_ASSERTIONS
|
||||
|
||||
static int numNear = 0;
|
||||
static int numFar = 0;
|
||||
for (const float z : ceilingsAtHeight_m) {
|
||||
const float diff = std::min( std::abs(z-zMin), std::abs(z-zMax) );
|
||||
if (diff < 0.1) {++numNear;} else {++numFar;}
|
||||
}
|
||||
if ((numNear + numFar) > 150000) {
|
||||
Assert::isTrue(numNear < numFar*0.1,
|
||||
"many requests to the WiFiModel address nodes (very) near to a ground! \
|
||||
due to rounding issues, determining the number of floors between AP and point-in-question is NOT possible! \
|
||||
expect very wrong outputs! \
|
||||
consider adding the person's height to the questioned positions: p += Point3(0,0,1.3) "
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (const float z : ceilingsAtHeight_m) {
|
||||
if (zMin < z && zMax > z) {++cnt;}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // WIFIMODELLOGDISTCEILING_H
|
||||
Reference in New Issue
Block a user