many changes and updates
- changed the wifi-estimation api - adjusted test-cases - worked on grid-bulding and grid-importance - new walking modules - fixed some minor issues
This commit is contained in:
@@ -2,6 +2,11 @@
|
||||
#define ASSERTIONS_H
|
||||
|
||||
#include "Exception.h"
|
||||
#include <sstream>
|
||||
|
||||
// for GTEST Testcases
|
||||
#define FRIEND_TEST(test_case_name, test_name)\
|
||||
friend class test_case_name##_##test_name##_Test
|
||||
|
||||
/**
|
||||
* this file provides assertion methods that may be enabled to trace
|
||||
@@ -62,7 +67,8 @@ namespace Assert {
|
||||
}
|
||||
|
||||
template <typename T, typename STR> static inline void isBetween(const T v, const T min, const T max, const STR err) {
|
||||
if (v < min || v > max) {doThrow(err);}
|
||||
std::stringstream ss; ss << "\n[" << min << ":" << max << "] but is " << v << "\n";
|
||||
if (v < min || v > max) {doThrow(err+ss.str());}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,15 @@ namespace Floorplan {
|
||||
Point3 p4;
|
||||
Quad3(const Point3 p1, const Point3 p2, const Point3 p3, const Point3 p4) : p1(p1), p2(p2), p3(p3), p4(p4) {;}
|
||||
Quad3 operator * (const float v) const {return Quad3(p1*v, p2*v, p3*v, p4*v);}
|
||||
const Point3& operator [] (const int idx) const {
|
||||
switch (idx) {
|
||||
case 0: return p1;
|
||||
case 1: return p2;
|
||||
case 2: return p3;
|
||||
case 3: return p4;
|
||||
default: throw Exception("out of bounds");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** additional type-info for obstacles */
|
||||
|
||||
18
grid/Grid.h
18
grid/Grid.h
@@ -221,13 +221,14 @@ public:
|
||||
Assert::isBetween((int32_t)p.y_cm, -max, +max, "y out of bounds");
|
||||
Assert::isBetween((int32_t)p.z_cm, -max, +max, "z out of bounds");
|
||||
|
||||
// shift by half of the allowed width of 20 bit to allow negative regions
|
||||
// shift by half of the allowed width of 20 bit to allow negative regions:
|
||||
// -> 19 bit positive and 19 bit negative
|
||||
const uint64_t center = 1 << 19;
|
||||
|
||||
// build
|
||||
const uint64_t x = std::round((p.x_cm+center) / (float)gridSize_cm);
|
||||
const uint64_t y = std::round((p.y_cm+center) / (float)gridSize_cm);
|
||||
const uint64_t z = std::round((p.z_cm+center) / (float)gridSize_cm * 5); // z is usually much lower and not always aligned -> allow more room for hashes
|
||||
const uint64_t x = center + (int64_t) std::round((p.x_cm) / (float)gridSize_cm);
|
||||
const uint64_t y = center + (int64_t) std::round((p.y_cm) / (float)gridSize_cm);
|
||||
const uint64_t z = center + (int64_t) std::round((p.z_cm) / (float)gridSize_cm * 5); // z is usually much lower and not always aligned -> allow more room for hashes
|
||||
|
||||
return (z << 40) | (y << 20) | (x << 0);
|
||||
|
||||
@@ -256,6 +257,11 @@ public:
|
||||
disconnectUniDir(n2, n1);
|
||||
}
|
||||
|
||||
/** remove the connection from n1 to n2 (not the other way round!) */
|
||||
void disconnectUniDir(const int idx1, const int idx2) {
|
||||
disconnectUniDir(nodes[idx1], nodes[idx2]);
|
||||
}
|
||||
|
||||
/** remove the connection from n1 to n2 (not the other way round!) */
|
||||
void disconnectUniDir(T& n1, T& n2) {
|
||||
for (int n = 0; n < n1._numNeighbors; ++n) {
|
||||
@@ -291,7 +297,11 @@ public:
|
||||
|
||||
// disconnect from all neighbors
|
||||
while (node._numNeighbors) {
|
||||
|
||||
// by removing one neighbor, all others are shifted to close the gap within the array
|
||||
// its therefor ok to always delete array index [0]
|
||||
disconnectBiDir(node._idx, node._neighbors[0]);
|
||||
|
||||
}
|
||||
|
||||
// remove from hash-list
|
||||
|
||||
@@ -54,166 +54,63 @@ public:
|
||||
// the number of neighbors to use
|
||||
static constexpr int numNeighbors = 12;
|
||||
|
||||
// create list of all doors
|
||||
// create list of all door-nodes
|
||||
std::vector<T> doors;
|
||||
|
||||
// create list of all stair-nodes
|
||||
std::vector<T> stairs;
|
||||
|
||||
// process each node
|
||||
for (T& n1 : g) {
|
||||
|
||||
// is the current node a door?
|
||||
//if (isDoor(n1, neighbors)) {doors.push_back(n1);} // OLD
|
||||
if (n1.getType() == GridNode::TYPE_DOOR) {doors.push_back(n1);} // NEW!
|
||||
|
||||
// favor stairs just like doors
|
||||
//if (isStaircase(g, n1)) {doors.push_back(n1);} // OLD
|
||||
if (n1.getType() == GridNode::TYPE_STAIR) {doors.push_back(n1);} // NEW
|
||||
switch(n1.getType()) {
|
||||
case GridNode::TYPE_DOOR: doors.push_back(n1); break;
|
||||
case GridNode::TYPE_STAIR: stairs.push_back(n1); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// KNN for doors
|
||||
KNNArray<std::vector<T>> knnArrDoors(doors);
|
||||
KNN<KNNArray<std::vector<T>>, 3> knnDoors(knnArrDoors);
|
||||
|
||||
// KNN for stairs
|
||||
KNNArray<std::vector<T>> knnArrStairs(stairs);
|
||||
KNN<KNNArray<std::vector<T>>, 3> knnStairs(knnArrStairs);
|
||||
|
||||
// probability adjustments
|
||||
Distribution::Normal<float> avoidWalls(0.0, 0.35);
|
||||
Distribution::Normal<float> favorDoors(0.0f, 0.5f);
|
||||
Distribution::Normal<float> favorStairs(0.0f, 3.5f);
|
||||
|
||||
|
||||
// process each node again
|
||||
for (T& n1 : g) {
|
||||
|
||||
// skip nodes on other than the requested floor-level
|
||||
//if (n1.z_cm != z_cm) {continue;}
|
||||
|
||||
// get the 10 nearest neighbors and their distance
|
||||
size_t indices[numNeighbors];
|
||||
float squaredDist[numNeighbors];
|
||||
float point[3] = {n1.x_cm, n1.y_cm, n1.z_cm};
|
||||
knn.get(point, numNeighbors, indices, squaredDist);
|
||||
|
||||
// get the neighbors
|
||||
std::vector<T*> neighbors;
|
||||
for (int i = 0; i < numNeighbors; ++i) {
|
||||
neighbors.push_back(&inv[indices[i]]);
|
||||
}
|
||||
|
||||
n1.navImportance = 1.0f;
|
||||
|
||||
//if (n1.getType() == GridNode::TYPE_FLOOR) {
|
||||
|
||||
// get the distance to the nearest door
|
||||
const float distToWall_m = Units::cmToM(std::sqrt(squaredDist[0]) + g.getGridSize_cm());
|
||||
// get the distance to the nearest wall
|
||||
const float distToWall_m = Units::cmToM(knn.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} ));
|
||||
|
||||
// get the distance to the nearest door
|
||||
const float distToDoor_m = Units::cmToM(knnDoors.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} ));
|
||||
|
||||
n1.navImportance =
|
||||
1 +
|
||||
getWallImportance( distToWall_m ) +
|
||||
favorDoors.getProbability(distToDoor_m) * 1.5f;
|
||||
// get the distance to the nearest stair
|
||||
const float distToStair_m = Units::cmToM(knnStairs.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} ));
|
||||
|
||||
const bool useNormal = (distToWall_m < distToDoor_m && distToWall_m < distToStair_m);
|
||||
|
||||
//}
|
||||
//addDoor(n1, neighbors);
|
||||
// final probability
|
||||
n1.navImportance = 1.0f;
|
||||
n1.navImportance += favorDoors.getProbability(distToDoor_m) * 1.25f;
|
||||
n1.navImportance += favorStairs.getProbability(distToStair_m) * 3.5f;
|
||||
|
||||
// importance for this node (based on the distance from the next door)
|
||||
//n1.navImportance += favorDoors.getProbability(dist_m) * 0.30;
|
||||
if (useNormal) {
|
||||
n1.navImportance -= avoidWalls.getProbability(distToWall_m);
|
||||
}
|
||||
|
||||
|
||||
//n1.navImportance = (dist_m < 0.2) ? (1) : (0.5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** is the given node connected to a staircase? */
|
||||
template <typename T> static bool isStaircase(Grid<T>& g, T& node) {
|
||||
|
||||
return node.getType() == GridNode::TYPE_STAIR;
|
||||
|
||||
// // if this node has a neighbor with a different z, this is a stair
|
||||
// for (T& neighbor : g.neighbors(node)) {
|
||||
// if (neighbor.z_cm != node.z_cm) {return true;}
|
||||
// }
|
||||
// return false;
|
||||
|
||||
}
|
||||
|
||||
// /** is the given node (and its inverted neighbors) a door? */
|
||||
// template <typename T> static bool isDoor( T& nSrc, std::vector<T*> neighbors ) {
|
||||
|
||||
// if (nSrc.getType() != GridNode::TYPE_FLOOR) {return false;}
|
||||
|
||||
// MiniMat2 m1;
|
||||
//// MiniMat2 m2;
|
||||
// Point3 center = nSrc;
|
||||
|
||||
// // calculate the centroid of the nSrc's nearest-neighbors
|
||||
// Point3 centroid(0,0,0);
|
||||
// for (const T* n : neighbors) {
|
||||
// centroid = centroid + (Point3)*n;
|
||||
// }
|
||||
// centroid /= neighbors.size();
|
||||
|
||||
// // if nSrc is too far from the centroid, this does not make sense
|
||||
// if ((centroid-center).length() > 40) {return false;}
|
||||
|
||||
// // build covariance of the nearest-neighbors
|
||||
// int used = 0;
|
||||
// for (const T* n : neighbors) {
|
||||
|
||||
// const Point3 d1 = (Point3)*n - centroid;
|
||||
// if (d1.length() > 100) {continue;} // radius search
|
||||
// m1.addSquared(d1.x, d1.y);
|
||||
|
||||
//// const Point3 d2 = (Point3)*n - center;
|
||||
//// if (d2.length() > 100) {continue;} // radius search
|
||||
//// m2.addSquared(d2.x, d2.y);
|
||||
|
||||
// ++used;
|
||||
|
||||
// }
|
||||
|
||||
// // we need at least two points for the covariance
|
||||
// if (used < 6) {return false;}
|
||||
|
||||
// // check eigenvalues
|
||||
// MiniMat2::EV ev1 = m1.getEigenvalues();
|
||||
//// MiniMat2::EV ev2 = m2.getEigenvalues();
|
||||
|
||||
// // ensure e1 > e2
|
||||
// if (ev1.e1 < ev1.e2) {std::swap(ev1.e1, ev1.e2);}
|
||||
//// if (ev2.e1 < ev2.e2) {std::swap(ev2.e1, ev2.e2);}
|
||||
|
||||
// // door?
|
||||
// const float ratio1 = (ev1.e2/ev1.e1);
|
||||
//// const float ratio2 = (ev2.e2/ev2.e1);
|
||||
//// const float ratio3 = std::max(ratio1, ratio2) / std::min(ratio1, ratio2);
|
||||
|
||||
// return (ratio1 < 0.30 && ratio1 > 0.05) ;
|
||||
|
||||
// }
|
||||
|
||||
/** get the importance of the given node depending on its nearest wall */
|
||||
static float getWallImportance(float dist_m) {
|
||||
|
||||
// avoid sticking too close to walls (unlikely)
|
||||
static Distribution::Normal<float> avoidWalls(0.0, 0.35);
|
||||
|
||||
// favour walking near walls (likely)
|
||||
//static Distribution::Normal<float> stickToWalls(0.9, 0.7);
|
||||
|
||||
// favour walking far away (likely)
|
||||
//static Distribution::Normal<float> farAway(2.2, 0.5);
|
||||
//if (dist_m > 2.0) {dist_m = 2.0;}
|
||||
|
||||
// overall importance
|
||||
// return - avoidWalls.getProbability(dist_m) * 0.30 // avoid walls
|
||||
// + stickToWalls.getProbability(dist_m) * 0.15 // walk near walls
|
||||
// + farAway.getProbability(dist_m) * 0.15 // walk in the middle
|
||||
return - avoidWalls.getProbability(dist_m) // avoid walls
|
||||
//+ stickToWalls.getProbability(dist_m) // walk near walls
|
||||
//+ farAway.getProbability(dist_m) // walk in the middle
|
||||
;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "Helper.h"
|
||||
#include "../../../floorplan/v2/Floorplan.h"
|
||||
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@ private:
|
||||
Helper<T> helper;
|
||||
|
||||
|
||||
std::ofstream outStairs;
|
||||
std::ofstream outDelete;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// struct Entry {
|
||||
@@ -68,10 +72,14 @@ public:
|
||||
|
||||
/** ctor */
|
||||
Stairs(Grid<T>& grid) : grid(grid), helper(grid) {
|
||||
;
|
||||
outStairs.open("/tmp/quads.dat");
|
||||
outDelete.open("/tmp/delete.dat");
|
||||
}
|
||||
|
||||
|
||||
~Stairs() {
|
||||
outStairs.close();
|
||||
outDelete.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -87,6 +95,7 @@ public:
|
||||
const std::vector<Floorplan::StairPart> parts = stair->getParts();
|
||||
const std::vector<Floorplan::Quad3> quads = Floorplan::getQuads(parts, floor);
|
||||
|
||||
|
||||
for (int i = 0; i < (int)parts.size(); ++i) {
|
||||
|
||||
//const Floorplan::StairPart& part = parts[i];
|
||||
@@ -97,6 +106,13 @@ public:
|
||||
const Point3 p3 = quad.p3;
|
||||
const Point3 p4 = quad.p4;
|
||||
|
||||
outStairs << p1.x << " " << p1.y << " " << p1.z << "\n";
|
||||
outStairs << p2.x << " " << p2.y << " " << p2.z << "\n";
|
||||
outStairs << p3.x << " " << p3.y << " " << p3.z << "\n";
|
||||
outStairs << p4.x << " " << p4.y << " " << p4.z << "\n";
|
||||
outStairs << p1.x << " " << p1.y << " " << p1.z << "\n\n\n";
|
||||
|
||||
|
||||
HelperPoly poly; poly.add(p1.xy()); poly.add(p2.xy()); poly.add(p3.xy()); poly.add(p4.xy());
|
||||
|
||||
const int x1 = helper.align(poly.bbox_cm.getMin().x); // ALIGNF?
|
||||
@@ -111,6 +127,9 @@ public:
|
||||
for (int y = y1; y <= y2; y+=gs_cm) {
|
||||
if (!poly.contains( Point2(x,y) )) {continue;}
|
||||
points.push_back(XYZ(x,y,-1));
|
||||
if (y < 500) {
|
||||
int i = 0; (void) i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +204,7 @@ public:
|
||||
// keep a list of all vertices below stairwells and remove them hereafter
|
||||
std::vector<T*> toDelete;
|
||||
|
||||
|
||||
// add all stair nodes or replace them with already existing ones
|
||||
for (Intermediate& iNode : stairNodes) {
|
||||
|
||||
@@ -192,7 +212,9 @@ public:
|
||||
const float minDiff = gs_cm * 0.49;
|
||||
|
||||
// nearer than maxDiff? -> delete as this one is unreachable below the stair
|
||||
const float maxDiff = 150;
|
||||
// to prevent errors (e.g. a platform at 1.0 meter) we use 0.98 meter as deleting threshold
|
||||
// otherwise we get problems in some places
|
||||
const float maxDiff = 98;
|
||||
|
||||
// distance between the stair node and the floor above / below
|
||||
const float zDiff1 = std::abs(iNode.node.z_cm - 100*floor->getStartingZ());
|
||||
@@ -223,11 +245,19 @@ public:
|
||||
// remove nodes directly below the stair
|
||||
} else if (zDiff1 < maxDiff) {
|
||||
T* n2 = (T*) grid.getNodePtrFor(GridPoint(iNode.node.x_cm, iNode.node.y_cm, 100*floor->getStartingZ()));
|
||||
outDelete << n2->x_cm << " " << n2->y_cm << " " << n2->z_cm << "\n";
|
||||
if (n2->y_cm < 500) {
|
||||
int i = 0; (void) i;
|
||||
}
|
||||
if (n2) {toDelete.push_back(n2);}
|
||||
|
||||
// remove nodes directly above the stair
|
||||
} else if (zDiff2 < maxDiff) {
|
||||
T* n2 = (T*) grid.getNodePtrFor(GridPoint(iNode.node.x_cm, iNode.node.y_cm, 100*floor->getEndingZ()));
|
||||
outDelete << n2->x_cm << " " << n2->y_cm << " " << n2->z_cm << "\n";
|
||||
if (n2->y_cm < 500) {
|
||||
int i = 0; (void) i;
|
||||
}
|
||||
if (n2) {toDelete.push_back(n2);}
|
||||
}
|
||||
|
||||
|
||||
54
grid/walk/v2/modules/WalkModuleFavorZ.h
Normal file
54
grid/walk/v2/modules/WalkModuleFavorZ.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef WALKMODULEFAVORZ_H
|
||||
#define WALKMODULEFAVORZ_H
|
||||
|
||||
#include "WalkModule.h"
|
||||
#include "WalkStateHeading.h"
|
||||
|
||||
#include "../../../../geo/Heading.h"
|
||||
#include "../../../../math/Distributions.h"
|
||||
|
||||
|
||||
/** favor z-transitions */
|
||||
template <typename Node, typename WalkState> class WalkModuleFavorZ : public WalkModule<Node, WalkState> {
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
WalkModuleFavorZ() {
|
||||
;
|
||||
}
|
||||
|
||||
virtual void updateBefore(WalkState& state) override {
|
||||
(void) state;
|
||||
}
|
||||
|
||||
virtual void updateAfter(WalkState& state, const Node& startNode, const Node& endNode) override {
|
||||
(void) state;
|
||||
(void) startNode;
|
||||
(void) endNode;
|
||||
|
||||
}
|
||||
|
||||
virtual void step(WalkState& state, const Node& curNode, const Node& nextNode) override {
|
||||
(void) state;
|
||||
(void) curNode;
|
||||
(void) nextNode;
|
||||
}
|
||||
|
||||
double getProbability(const WalkState& state, const Node& startNode, const Node& curNode, const Node& potentialNode) const override {
|
||||
|
||||
(void) state;
|
||||
(void) startNode;
|
||||
|
||||
if (curNode.z_cm != potentialNode.z_cm) {
|
||||
return 8;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // WALKMODULEFAVORZ_H
|
||||
@@ -26,14 +26,14 @@ private:
|
||||
public:
|
||||
|
||||
/** ctor 3.0 should be OK! */
|
||||
WalkModuleHeadingControl(Control* ctrl) : dist(Distribution::VonMises<double>(0.0f, 1.5).getLUT()), draw(dist.getDrawList()), ctrl(ctrl) {
|
||||
WalkModuleHeadingControl(Control* ctrl) : dist(Distribution::VonMises<double>(0.0f, 2.0).getLUT()), draw(dist.getDrawList()), ctrl(ctrl) {
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
virtual void updateBefore(WalkState& state) override {
|
||||
|
||||
const float var = draw.get() * 0.15;//0.05;
|
||||
const float var = draw.get() * 0.20;//0.05;
|
||||
//const float var = 0;
|
||||
state.startHeading += ctrl->turnAngle + var;
|
||||
|
||||
|
||||
@@ -44,8 +44,8 @@ public:
|
||||
(void) curNode;
|
||||
|
||||
const double prob = potentialNode.getNavImportance();
|
||||
return std::pow(prob, 10);
|
||||
//return prob;
|
||||
//return std::pow(prob, 10);
|
||||
return prob;
|
||||
|
||||
}
|
||||
|
||||
|
||||
18
main.cpp
18
main.cpp
@@ -15,7 +15,23 @@ int main(int argc, char** argv) {
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
::testing::GTEST_FLAG(filter) = "*huge*";
|
||||
|
||||
// skip all tests starting with LIVE_
|
||||
::testing::GTEST_FLAG(filter) = "-*.LIVE_*";
|
||||
|
||||
::testing::GTEST_FLAG(filter) = "*Grid.*";
|
||||
//::testing::GTEST_FLAG(filter) = "*Dijkstra.*";
|
||||
|
||||
//::testing::GTEST_FLAG(filter) = "*LogDistanceCeilingModel*";
|
||||
|
||||
|
||||
//::testing::GTEST_FLAG(filter) = "*Barometer*";
|
||||
//::testing::GTEST_FLAG(filter) = "*GridWalk2RelPressure*";
|
||||
|
||||
//::testing::GTEST_FLAG(filter) = "Heading*";
|
||||
//::testing::GTEST_FLAG(filter) = "*WiFiVAPGrouper*";
|
||||
//::testing::GTEST_FLAG(filter) = "*Offline*";
|
||||
|
||||
//::testing::GTEST_FLAG(filter) = "*Walk*";
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
|
||||
@@ -43,13 +43,13 @@ public:
|
||||
* as nodes only provide a limited number of rssi-entries,
|
||||
* store only the strongest ones.
|
||||
*/
|
||||
template <typename Node> static void estimate(Grid<Node>& grid, WiFiModel& mdl, const std::vector<LocatedAccessPoint> aps) {
|
||||
template <typename Node> static void estimate(Grid<Node>& grid, WiFiModel& mdl, const std::vector<AccessPoint> aps) {
|
||||
|
||||
// sanity checks
|
||||
Assert::isTrue(Node::getMapAPs().empty(), "there are already some processed APs available!");
|
||||
|
||||
// attach the access-points to the shared node-vector
|
||||
for (const LocatedAccessPoint& ap : aps) {
|
||||
for (const AccessPoint& ap : aps) {
|
||||
Node::getMapAPs().push_back(ap);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
for (int apIdx = 0; apIdx < (int) aps.size(); ++apIdx) {
|
||||
|
||||
// estimate the signal-strength
|
||||
const float rssi = mdl.getRSSI(aps[apIdx], n.inMeter());
|
||||
const float rssi = mdl.getRSSI(aps[apIdx].getMAC(), n.inMeter());
|
||||
|
||||
// keep it
|
||||
nodeAPs.push_back(WiFiGridNodeAP(apIdx, rssi));
|
||||
|
||||
@@ -12,7 +12,7 @@ struct WiFiGridNodeAP {
|
||||
|
||||
private:
|
||||
|
||||
static const int UNUSED_IDX = 255;
|
||||
static const uint8_t UNUSED_IDX = 255;
|
||||
|
||||
private:
|
||||
|
||||
@@ -25,10 +25,14 @@ private:
|
||||
public:
|
||||
|
||||
/** empty ctor */
|
||||
WiFiGridNodeAP() : idx(UNUSED_IDX), rssi(0) {;}
|
||||
WiFiGridNodeAP() : idx(UNUSED_IDX), rssi(0) {
|
||||
int i = 0; (void) i;
|
||||
}
|
||||
|
||||
/** ctor */
|
||||
WiFiGridNodeAP(const int idx, const float rssi) : idx(idx), rssi(stretch(rssi)) {;}
|
||||
WiFiGridNodeAP(const int idx, const float rssi) : idx(idx), rssi(stretch(rssi)) {
|
||||
int i = 0; (void) i;
|
||||
}
|
||||
|
||||
|
||||
/** is this entry valid/used? */
|
||||
@@ -70,13 +74,14 @@ private:
|
||||
*/
|
||||
template <int maxAccessPoints> struct WiFiGridNode {
|
||||
|
||||
|
||||
/** contains the 10 strongest APs measureable at this position */
|
||||
WiFiGridNodeAP strongestAPs[maxAccessPoints];
|
||||
|
||||
|
||||
/** ctor */
|
||||
WiFiGridNode() {;}
|
||||
explicit WiFiGridNode() : strongestAPs() {
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/** get the maximum number of APs each node is able to store */
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* compare WiFi-Measurements within LIVE (exact) predictions
|
||||
* just based on the distance to the access-point
|
||||
* compare WiFi-Measurements within predictions of a given model.
|
||||
* predictions are just based on the distance to the access-point.
|
||||
*/
|
||||
class WiFiObserverFree : public WiFiProbability {
|
||||
|
||||
@@ -19,17 +19,16 @@ private:
|
||||
|
||||
const float sigmaPerSecond = 1.5f;
|
||||
|
||||
/** the RSSI prediction model */
|
||||
WiFiModel& model;
|
||||
std::unordered_map<MACAddress, LocatedAccessPoint> aps;
|
||||
|
||||
/** the map's floorplan */
|
||||
Floorplan::IndoorMap* map;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
WiFiObserverFree(const float sigma, WiFiModel& model, const std::vector<LocatedAccessPoint>& aps) : sigma(sigma), model(model) {
|
||||
|
||||
for (const LocatedAccessPoint& ap : aps) {
|
||||
this->aps.insert(std::pair<MACAddress, LocatedAccessPoint>(ap.getMAC(), ap));
|
||||
}
|
||||
WiFiObserverFree(const float sigma, WiFiModel& model) : sigma(sigma), model(model) {
|
||||
|
||||
}
|
||||
|
||||
@@ -38,18 +37,17 @@ public:
|
||||
|
||||
double prob = 1.0;
|
||||
|
||||
// process each measured AP
|
||||
for (const WiFiMeasurement& entry : obs.entries) {
|
||||
|
||||
auto it = aps.find(entry.getAP().getMAC());
|
||||
// get the model's RSSI (if possible!)
|
||||
const float modelRSSI = model.getRSSI(entry.getAP().getMAC(), pos);
|
||||
|
||||
// AP is unknown
|
||||
if (it == aps.end()) {continue;}
|
||||
// NaN? -> AP not known to the model -> skip
|
||||
if (modelRSSI != modelRSSI) {continue;}
|
||||
|
||||
// get the AP
|
||||
const LocatedAccessPoint& ap = it->second;
|
||||
|
||||
// model and scan rssi
|
||||
const float modelRSSI = model.getRSSI(ap, pos);
|
||||
// the scan's RSSI
|
||||
const float scanRSSI = entry.getRSSI();
|
||||
|
||||
// the measurement's age
|
||||
|
||||
@@ -4,14 +4,25 @@
|
||||
#include "../LocatedAccessPoint.h"
|
||||
|
||||
/**
|
||||
* interface for signal-strength prediction models
|
||||
* 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 WiFiModel {
|
||||
|
||||
public:
|
||||
|
||||
/** get the given access-point's RSSI at the provided location */
|
||||
virtual float getRSSI(const LocatedAccessPoint& ap, const Point3 p) = 0;
|
||||
// /** get the given access-point's RSSI at the provided location */
|
||||
// virtual float getRSSI(const LocatedAccessPoint& ap, const Point3 p) = 0;
|
||||
|
||||
/**
|
||||
* get the RSSI expected at the given location (in meter)
|
||||
* for an AP identified by the given MAC.
|
||||
*
|
||||
* if the model can not predict the RSSI for an AP, it returns NaN!
|
||||
*/
|
||||
virtual float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -9,21 +9,63 @@
|
||||
*/
|
||||
class WiFiModelLogDist : public WiFiModel {
|
||||
|
||||
public:
|
||||
|
||||
/** parameters describing one AP 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:
|
||||
|
||||
float txp;
|
||||
float exp;
|
||||
/** map of all APs (and their parameters) known to the model */
|
||||
std::unordered_map<MACAddress, APEntry> accessPoints;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
WiFiModelLogDist(const float txp, const float exp) : txp(txp), exp(exp) {
|
||||
WiFiModelLogDist() {
|
||||
;
|
||||
}
|
||||
|
||||
/** get the given access-point's RSSI at the provided location */
|
||||
float getRSSI(const LocatedAccessPoint& ap, const Point3 p) override {
|
||||
return LogDistanceModel::distanceToRssi(txp, exp, ap.getDistance(p));
|
||||
/** make the given AP (and its parameters) known to the model */
|
||||
void addAP(const MACAddress& accessPoint, 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
|
||||
accessPoints.insert( std::pair<MACAddress, APEntry>(accessPoint, params) );
|
||||
|
||||
}
|
||||
|
||||
virtual float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const override {
|
||||
|
||||
// try to get the corresponding parameters
|
||||
const auto it = accessPoints.find(accessPoint);
|
||||
|
||||
// AP unknown? -> NAN
|
||||
if (it == accessPoints.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);
|
||||
|
||||
// done
|
||||
return rssiLOS;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "../../../floorplan/v2/Floorplan.h"
|
||||
|
||||
#include "../../../Assertions.h"
|
||||
#include "WiFiModel.h"
|
||||
#include "LogDistanceModel.h"
|
||||
|
||||
@@ -12,11 +13,26 @@
|
||||
*/
|
||||
class WiFiModelLogDistCeiling : public WiFiModel {
|
||||
|
||||
public:
|
||||
|
||||
/** parameters describing one AP 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)
|
||||
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:
|
||||
|
||||
float txp; // sending power (-40)
|
||||
float exp; // path-loss-exponent (~2.0 - 4.0)
|
||||
float waf; // attenuation per ceiling/floor (~-8.0)
|
||||
/** map of all APs (and their parameters) known to the model */
|
||||
std::unordered_map<MACAddress, APEntry> accessPoints;
|
||||
|
||||
/** position (height) of all ceilings (in meter) */
|
||||
std::vector<float> ceilingsAtHeight_m;
|
||||
@@ -24,9 +40,7 @@ private:
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
WiFiModelLogDistCeiling(const float txp, const float exp, const float waf, const Floorplan::IndoorMap* map) : txp(txp), exp(exp), waf(waf) {
|
||||
|
||||
Assert::isTrue(waf <= 0, "WAF must be a negative number!");
|
||||
WiFiModelLogDistCeiling(const Floorplan::IndoorMap* map) {
|
||||
|
||||
// position of all ceilings
|
||||
for (Floorplan::Floor* f : map->floors) {
|
||||
@@ -35,23 +49,56 @@ public:
|
||||
|
||||
}
|
||||
|
||||
/** get the given access-point's RSSI at the provided location */
|
||||
float getRSSI(const LocatedAccessPoint& ap, const Point3 p) override {
|
||||
const int numCeilings = numCeilingsBetween(ap.z, p.z);
|
||||
const float rssi = LogDistanceModel::distanceToRssi(txp, exp, ap.getDistance(p));
|
||||
return rssi + (numCeilings * waf);
|
||||
/** make the given AP (and its parameters) known to the model */
|
||||
void addAP(const MACAddress& accessPoint, 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]");
|
||||
|
||||
// add
|
||||
accessPoints.insert( std::pair<MACAddress, APEntry>(accessPoint, params) );
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const override {
|
||||
|
||||
// try to get the corresponding parameters
|
||||
const auto it = accessPoints.find(accessPoint);
|
||||
|
||||
// AP unknown? -> NAN
|
||||
if (it == accessPoints.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(LogDistanceCeilingModel, numCeilings);
|
||||
|
||||
/** get the number of ceilings between z1 and z2 */
|
||||
int numCeilingsBetween(const float z1, const float z2) const {
|
||||
int numCeilingsBetween(const Point3 pos1, const Point3 pos2) const {
|
||||
|
||||
int cnt = 0;
|
||||
const float zMin = std::min(z1, z2);
|
||||
const float zMax = std::max(z1, z2);
|
||||
const float zMin = std::min(pos1.z, pos2.z);
|
||||
const float zMax = std::max(pos1.z, pos2.z);
|
||||
|
||||
for (float z : ceilingsAtHeight_m) {
|
||||
for (const float z : ceilingsAtHeight_m) {
|
||||
if (zMin < z && zMax > z) {++cnt;}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ struct MyState : public WalkState, public WalkStateRelativePressure {
|
||||
|
||||
|
||||
|
||||
TEST(GridWalk2RelPressure, walkHeading) {
|
||||
TEST(GridWalk2RelPressure, LIVE_walkHeading) {
|
||||
|
||||
Grid<MyNode> grid(20);
|
||||
|
||||
|
||||
@@ -32,7 +32,9 @@ TEST(Grid, add) {
|
||||
ASSERT_THROW(grid.add(GP(10,10,10)), std::exception);
|
||||
ASSERT_THROW(grid.add(GP(10,20,20)), std::exception);
|
||||
ASSERT_THROW(grid.add(GP(20,10,20)), std::exception);
|
||||
ASSERT_THROW(grid.add(GP(20,20,10)), std::exception);
|
||||
//ASSERT_THROW(grid.add(GP(20,20,11)), std::exception); // unaligned z is OK
|
||||
|
||||
// aligned -> OK
|
||||
ASSERT_EQ(1, grid.add(GP(20,20,20)));
|
||||
|
||||
// access
|
||||
@@ -127,13 +129,64 @@ TEST(Grid, uid) {
|
||||
|
||||
Grid<GP> grid(20);
|
||||
|
||||
GP gp(20,40,60);
|
||||
uint64_t uid = grid.getUID(gp);
|
||||
GP gp1(+20, +40, +60);
|
||||
GP gp2(-20, -40, -60);
|
||||
|
||||
const uint64_t uid1 = grid.getUID(gp1);
|
||||
const uint64_t uid2 = grid.getUID(gp2);
|
||||
|
||||
// must be different
|
||||
ASSERT_NE(uid1, uid2);
|
||||
|
||||
const uint64_t center = 1 << 19;
|
||||
|
||||
const int mask = (1 << 20) - 1; // 20-bit mask
|
||||
ASSERT_EQ(3, uid >> 40 & mask); // x
|
||||
ASSERT_EQ(2, uid >> 20 & mask); // y
|
||||
ASSERT_EQ(1, uid >> 0 & mask); // z
|
||||
ASSERT_EQ(center+60/20*5, (uid1) >> 40 & mask); // z (z UID has a higher resolution: * 5
|
||||
ASSERT_EQ(center+40/20, (uid1) >> 20 & mask); // y
|
||||
ASSERT_EQ(center+20/20, (uid1) >> 0 & mask); // x
|
||||
|
||||
ASSERT_EQ(center-60/20*5, (uid2) >> 40 & mask); // z (z UID has a higher resolution: * 5
|
||||
ASSERT_EQ(center-40/20, (uid2) >> 20 & mask); // y
|
||||
ASSERT_EQ(center-20/20, (uid2) >> 0 & mask); // x
|
||||
|
||||
}
|
||||
|
||||
TEST(Grid, unconnect) {
|
||||
|
||||
Grid<GP> grid(1);
|
||||
|
||||
int idx1 = grid.add(GP(0,0,0));
|
||||
int idx2 = grid.add(GP(1,0,0));
|
||||
int idx3 = grid.add(GP(1,1,0));
|
||||
|
||||
grid.connectBiDir(idx1,idx2);
|
||||
grid.connectBiDir(idx2,idx3);
|
||||
grid.connectBiDir(idx3,idx1);
|
||||
|
||||
ASSERT_EQ(2, grid.getNumNeighbors(idx1));
|
||||
ASSERT_EQ(2, grid.getNumNeighbors(idx2));
|
||||
ASSERT_EQ(2, grid.getNumNeighbors(idx3));
|
||||
|
||||
grid.disconnectUniDir(idx1, idx2);
|
||||
ASSERT_EQ(1, grid.getNumNeighbors(idx1)); ASSERT_EQ(idx3, grid.getNeighbor(idx1,0).getIdx());
|
||||
ASSERT_EQ(2, grid.getNumNeighbors(idx2));
|
||||
grid.disconnectUniDir(idx2,idx1);
|
||||
ASSERT_EQ(1, grid.getNumNeighbors(idx1)); ASSERT_EQ(idx3, grid.getNeighbor(idx1,0).getIdx());
|
||||
ASSERT_EQ(1, grid.getNumNeighbors(idx2)); ASSERT_EQ(idx3, grid.getNeighbor(idx2,0).getIdx());
|
||||
|
||||
grid.disconnectUniDir(idx1, idx3);
|
||||
ASSERT_EQ(0, grid.getNumNeighbors(idx1));
|
||||
ASSERT_EQ(2, grid.getNumNeighbors(idx3));
|
||||
grid.disconnectUniDir(idx3, idx1);
|
||||
ASSERT_EQ(0, grid.getNumNeighbors(idx1));
|
||||
ASSERT_EQ(1, grid.getNumNeighbors(idx3)); ASSERT_EQ(idx2, grid.getNeighbor(idx3,0).getIdx());
|
||||
|
||||
grid.disconnectUniDir(idx2, idx3);
|
||||
ASSERT_EQ(0, grid.getNumNeighbors(idx2));
|
||||
ASSERT_EQ(1, grid.getNumNeighbors(idx3));
|
||||
grid.disconnectUniDir(idx3, idx2);
|
||||
ASSERT_EQ(0, grid.getNumNeighbors(idx2));
|
||||
ASSERT_EQ(0, grid.getNumNeighbors(idx3));
|
||||
|
||||
}
|
||||
|
||||
@@ -230,19 +283,19 @@ TEST(Grid, nearest) {
|
||||
|
||||
ASSERT_EQ(c1, grid.getNodeFor(GP(15,20,20)));
|
||||
ASSERT_EQ(c1, grid.getNodeFor(GP(20,15,20)));
|
||||
ASSERT_EQ(c1, grid.getNodeFor(GP(20,20,15)));
|
||||
//ASSERT_EQ(c1, grid.getNodeFor(GP(20,20,15))); // Z has a higher resolution!
|
||||
|
||||
ASSERT_EQ(c1, grid.getNodeFor(GP(25,20,20)));
|
||||
ASSERT_EQ(c1, grid.getNodeFor(GP(20,25,20)));
|
||||
ASSERT_EQ(c1, grid.getNodeFor(GP(20,20,25)));
|
||||
//ASSERT_EQ(c1, grid.getNodeFor(GP(20,20,25))); // Z has a higher resolution!
|
||||
|
||||
ASSERT_EQ(c2, grid.getNodeFor(GP(35,40,40)));
|
||||
ASSERT_EQ(c2, grid.getNodeFor(GP(40,35,40)));
|
||||
ASSERT_EQ(c2, grid.getNodeFor(GP(40,40,35)));
|
||||
//ASSERT_EQ(c2, grid.getNodeFor(GP(40,40,35))); // Z has a higher resolution!
|
||||
|
||||
ASSERT_EQ(c2, grid.getNodeFor(GP(45,40,40)));
|
||||
ASSERT_EQ(c2, grid.getNodeFor(GP(40,45,40)));
|
||||
ASSERT_EQ(c2, grid.getNodeFor(GP(40,40,45)));
|
||||
//ASSERT_EQ(c2, grid.getNodeFor(GP(40,40,45))); // Z has a higher resolution!
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@
|
||||
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||
|
||||
|
||||
struct MyNode : public GridPoint, public GridNode, public GridNodeImportance, public WiFiGridNode<10> {
|
||||
MyNode() {;}
|
||||
MyNode(const int x, const int y, const int z) : GridPoint(x,y,z) {;}
|
||||
// ENSURE UNIQUE CLASS NAME
|
||||
struct MyNode1239 : public GridPoint, public GridNode, public GridNodeImportance, public WiFiGridNode<10> {
|
||||
MyNode1239() {;}
|
||||
MyNode1239(const int x, const int y, const int z) : GridPoint(x,y,z) {;}
|
||||
static void staticDeserialize(std::istream& inp) {
|
||||
WiFiGridNode::staticDeserialize(inp);
|
||||
}
|
||||
@@ -36,16 +37,17 @@ struct MyNode : public GridPoint, public GridNode, public GridNodeImportance, pu
|
||||
}
|
||||
};
|
||||
|
||||
struct MyState : public WalkState, public WalkStateHeading {
|
||||
MyState(const GridPoint& pos, const Heading head) : WalkState(pos), WalkStateHeading(head) {;}
|
||||
// ENSURE UNIQUE CLASS NAME
|
||||
struct MyState23452 : public WalkState, public WalkStateHeading {
|
||||
MyState23452(const GridPoint& pos, const Heading head) : WalkState(pos), WalkStateHeading(head) {;}
|
||||
};
|
||||
|
||||
|
||||
TEST(GridWalk2, error) {
|
||||
TEST(GridWalk2, LIVE_error) {
|
||||
|
||||
|
||||
Grid<MyNode> grid(20);
|
||||
GridFactory<MyNode> gf(grid);
|
||||
Grid<MyNode1239> grid(20);
|
||||
GridFactory<MyNode1239> gf(grid);
|
||||
|
||||
Floorplan::Floor floor;
|
||||
Floorplan::FloorOutlinePolygon poly;
|
||||
@@ -61,13 +63,13 @@ TEST(GridWalk2, error) {
|
||||
float turnAngle = 0; // keep the angle as-is!
|
||||
} ctrl;
|
||||
|
||||
GridWalker<MyNode, MyState> walker;
|
||||
WalkModuleHeadingControl<MyNode, MyState, Control> modHead(&ctrl);
|
||||
GridWalker<MyNode1239, MyState23452> walker;
|
||||
WalkModuleHeadingControl<MyNode1239, MyState23452, Control> modHead(&ctrl);
|
||||
|
||||
walker.addModule(&modHead);
|
||||
|
||||
|
||||
MyState state(GridPoint(800,800,0), Heading(3.1415/2));
|
||||
MyState23452 state(GridPoint(800,800,0), Heading(3.1415/2));
|
||||
|
||||
K::Gnuplot gp;
|
||||
gp << "set xrange[0:5000]\n";
|
||||
@@ -98,9 +100,9 @@ TEST(GridWalk2, error) {
|
||||
}
|
||||
|
||||
|
||||
TEST(GgridWalk2, walkHeading) {
|
||||
TEST(GgridWalk2, LIVE_walkHeading) {
|
||||
|
||||
Grid<MyNode> grid(20);
|
||||
Grid<MyNode1239> grid(20);
|
||||
std::ifstream inp("/tmp/grid.dat");
|
||||
grid.read(inp);
|
||||
|
||||
@@ -118,9 +120,9 @@ TEST(GgridWalk2, walkHeading) {
|
||||
// GridFactory<MyNode> fac(grid);
|
||||
// fac.addFloor(&floor);
|
||||
|
||||
GridWalker<MyNode, MyState> walker;
|
||||
WalkModuleHeading<MyNode, MyState> wmHead;
|
||||
WalkModuleFollowDestination<MyNode, MyState> wmDest(grid, grid.getNodeFor(GridPoint(7200,4800,400+340+340)));
|
||||
GridWalker<MyNode1239, MyState23452> walker;
|
||||
WalkModuleHeading<MyNode1239, MyState23452> wmHead;
|
||||
WalkModuleFollowDestination<MyNode1239, MyState23452> wmDest(grid, grid.getNodeFor(GridPoint(7200,4800,400+340+340)));
|
||||
//walker.addModule(&wmHead);
|
||||
walker.addModule(&wmDest);
|
||||
|
||||
@@ -132,7 +134,7 @@ TEST(GgridWalk2, walkHeading) {
|
||||
K::GnuplotSplotElementPoints nodes; nodes.setPointSize(0.1); nodes.setColorHex("#888888"); splot.add(&nodes);
|
||||
K::GnuplotSplotElementPoints states; states.setPointSize(0.5); states.setColorHex("#0000ff"); splot.add(&states);
|
||||
|
||||
for (const MyNode& n : grid) {
|
||||
for (const MyNode1239& n : grid) {
|
||||
static int cnt = 0;
|
||||
if (++cnt % 5 == 0) {
|
||||
nodes.add(K::GnuplotPoint3(n.x_cm, n.y_cm, n.z_cm));
|
||||
@@ -143,8 +145,8 @@ TEST(GgridWalk2, walkHeading) {
|
||||
for (int j = 0; j < 500; ++j) {
|
||||
states.clear();
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
MyState start(points[i], Heading(0.0));
|
||||
MyState next = walker.getDestination(grid, start, 2.0);
|
||||
MyState23452 start(points[i], Heading(0.0));
|
||||
MyState23452 next = walker.getDestination(grid, start, 2.0);
|
||||
points[i] = next.startPos;
|
||||
states.add(K::GnuplotPoint3(points[i].x_cm, points[i].y_cm, points[i].z_cm));
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ void build(Grid<GP>& grid) {
|
||||
}
|
||||
}
|
||||
|
||||
std::set<int> done;
|
||||
//std::set<int> done;
|
||||
|
||||
for (int x = 0; x < size; x += gs) {
|
||||
for (int y = 0; y < size; y += gs) {
|
||||
@@ -69,17 +69,19 @@ void build(Grid<GP>& grid) {
|
||||
|
||||
for (int x1 = -gs; x1 <= +gs; x1 += gs) {
|
||||
for (int y1 = -gs; y1 <= +gs; y1 += gs) {
|
||||
if (x1 == 0 && y1 == 0) {continue;} // the node itself
|
||||
const GridPoint gp2(x+x1, y+y1, 0);
|
||||
if (grid.hasNodeFor(gp2)) {
|
||||
int idx2 = grid.getNodeFor(gp2).getIdx();
|
||||
if (done.find(idx2) != done.end()) {continue;}
|
||||
grid.connectBiDir(idx1, idx2);
|
||||
//if (done.find(idx2) != done.end()) {continue;}
|
||||
//grid.connectBiDir(idx1, idx2);
|
||||
grid.connectUniDir(idx1, idx2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
done.insert(idx1);
|
||||
//done.insert(idx1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ TEST(Barometer, relCalib) {
|
||||
|
||||
#include <fstream>
|
||||
|
||||
TEST(Barometer, tendence) {
|
||||
TEST(Barometer, LIVE_tendence) {
|
||||
|
||||
std::ifstream inp ("/tmp/baro1.dat");
|
||||
|
||||
@@ -81,7 +81,7 @@ TEST(Barometer, tendence) {
|
||||
|
||||
}
|
||||
|
||||
TEST(Barometer, tendence2) {
|
||||
TEST(Barometer, LIVE_tendence2) {
|
||||
|
||||
|
||||
const float timeframe = 5.0;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
TEST(LogDistanceCeilingModel, calc) {
|
||||
|
||||
// dummy floorplan
|
||||
Floorplan::Floor* f0 = new Floorplan::Floor(); f0->atHeight = 0;
|
||||
Floorplan::Floor* f1 = new Floorplan::Floor(); f1->atHeight = 3;
|
||||
Floorplan::Floor* f2 = new Floorplan::Floor(); f2->atHeight = 7;
|
||||
@@ -15,10 +16,16 @@ TEST(LogDistanceCeilingModel, calc) {
|
||||
map.floors.push_back(f1);
|
||||
map.floors.push_back(f2);
|
||||
|
||||
LocatedAccessPoint ap0("00:00:00:00:00:00", Point3(0,0,0));
|
||||
LocatedAccessPoint ap25("00:00:00:00:00:00", Point3(0,0,2.5));
|
||||
//LocatedAccessPoint ap0("00:00:00:00:00:00", Point3(0,0,0));
|
||||
//LocatedAccessPoint ap25("00:00:00:00:00:00", Point3(0,0,2.5));
|
||||
|
||||
WiFiModelLogDistCeiling model(-40, 1.0, -8.0, &map);
|
||||
WiFiModelLogDistCeiling model(&map);
|
||||
|
||||
const MACAddress ap0 = MACAddress("00:00:00:00:00:00");
|
||||
const MACAddress ap25 = MACAddress("00:00:00:00:00:01");
|
||||
|
||||
model.addAP(ap0, WiFiModelLogDistCeiling::APEntry( Point3(0,0,0), -40, 1.0, -8.0 ));
|
||||
model.addAP(ap25, WiFiModelLogDistCeiling::APEntry( Point3(0,0,2.5), -40, 1.0, -8.0 ));
|
||||
|
||||
|
||||
ASSERT_EQ(-40, model.getRSSI(ap0, Point3(1,0,0)));
|
||||
@@ -34,6 +41,41 @@ TEST(LogDistanceCeilingModel, calc) {
|
||||
|
||||
}
|
||||
|
||||
TEST(LogDistanceCeilingModel, numCeilings) {
|
||||
|
||||
// dummy floorplan
|
||||
Floorplan::Floor* f0 = new Floorplan::Floor(); f0->atHeight = 0;
|
||||
Floorplan::Floor* f1 = new Floorplan::Floor(); f1->atHeight = 3;
|
||||
Floorplan::Floor* f2 = new Floorplan::Floor(); f2->atHeight = 7;
|
||||
|
||||
Floorplan::IndoorMap map;
|
||||
map.floors.push_back(f0);
|
||||
map.floors.push_back(f1);
|
||||
map.floors.push_back(f2);
|
||||
|
||||
WiFiModelLogDistCeiling model(&map);
|
||||
|
||||
ASSERT_EQ(0, model.numCeilingsBetween(Point3(0,0,-1), Point3(0,0,0)) );
|
||||
ASSERT_EQ(0, model.numCeilingsBetween(Point3(0,0,0), Point3(0,0,-1)) );
|
||||
|
||||
ASSERT_EQ(0, model.numCeilingsBetween(Point3(0,0,0), Point3(0,0,1)) );
|
||||
ASSERT_EQ(0, model.numCeilingsBetween(Point3(0,0,1), Point3(0,0,0)) );
|
||||
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,-0.01), Point3(0,0,+0.01)) );
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,+0.01), Point3(0,0,-0.01)) );
|
||||
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,2.99), Point3(0,0,3.01)) );
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,3.01), Point3(0,0,2.99)) );
|
||||
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,6.99), Point3(0,0,7.01)) );
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,7.01), Point3(0,0,6.99)) );
|
||||
|
||||
ASSERT_EQ(0, model.numCeilingsBetween(Point3(0,0,7.00), Point3(0,0,99)) );
|
||||
|
||||
ASSERT_EQ(1, model.numCeilingsBetween(Point3(0,0,0), Point3(0,0,7)) );
|
||||
ASSERT_EQ(3, model.numCeilingsBetween(Point3(0,0,-1), Point3(0,0,8)) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -86,6 +86,7 @@ WiFiObservation groupVAP(const WiFiObservation& inp) {
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
struct WiFiEvalTestBase {
|
||||
|
||||
// all training files
|
||||
@@ -117,11 +118,9 @@ struct WiFiEvalTestBase {
|
||||
if (Floorplan::toUpperCase(ap->mac) == "00:04:96:6C:3A:A9") {continue;}
|
||||
if (Floorplan::toUpperCase(ap->mac) == "00:04:96:6B:DB:69") {continue;}
|
||||
|
||||
|
||||
|
||||
|
||||
aps.push_back(LocatedAccessPoint(*ap));
|
||||
apsMap.insert(std::pair<MACAddress, LocatedAccessPoint>(ap->mac, LocatedAccessPoint(*ap)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +141,8 @@ struct WiFiEvalTestBase {
|
||||
int cnt = 0;
|
||||
|
||||
// model
|
||||
WiFiModelLogDistCeiling model(params.txp, params.exp, params.waf, im);
|
||||
WiFiModelLogDistCeiling model(im);
|
||||
model.addAP();
|
||||
|
||||
VAPGrouper vg(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::AVERAGE);
|
||||
|
||||
@@ -422,6 +422,6 @@ TEST(aaiFiEval, getBestTXP_EXP) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
|
||||
#include "../../../grid/Grid.h"
|
||||
|
||||
struct MyNode : GridNode, GridPoint, WiFiGridNode<10> {
|
||||
// ensure the class-name is unique!
|
||||
struct TestNode190231 : public GridNode, public GridPoint, public WiFiGridNode<10> {
|
||||
|
||||
MyNode(const int x_cm, const int y_cm, const int z_cm) : GridPoint(x_cm, y_cm, z_cm) {;}
|
||||
TestNode190231(const int x_cm, const int y_cm, const int z_cm) : GridPoint(x_cm, y_cm, z_cm) {;}
|
||||
|
||||
};
|
||||
|
||||
@@ -42,30 +43,57 @@ TEST(WiFiGridNodeAP, rssiLimits) {
|
||||
|
||||
|
||||
|
||||
/** gnuplot debug dumps */
|
||||
TEST(WiFiGridNode, ctor) {
|
||||
|
||||
// ensure nodes are correctly empty initialized
|
||||
|
||||
WiFiGridNode<10> node;
|
||||
ASSERT_EQ(0, node.getNumVisibleAPs());
|
||||
|
||||
TestNode190231 node2(0,0,0);
|
||||
ASSERT_EQ(0, node2.getNumVisibleAPs());
|
||||
|
||||
}
|
||||
|
||||
|
||||
// gnuplot debug dumps
|
||||
TEST(WiFiGridModelLogDist, create) {
|
||||
|
||||
int gs = 20;
|
||||
Grid<MyNode> grid(gs);
|
||||
Grid<TestNode190231> grid(gs);
|
||||
|
||||
for (int x = 0; x < 2000; x += gs) {
|
||||
for (int y = 0; y < 2000; y += gs) {
|
||||
grid.add(MyNode(x,y,0));
|
||||
grid.add(TestNode190231(x,y,0));
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "GridNodeSize: " << sizeof(MyNode) << std::endl;
|
||||
std::cout << "GridNodeSize: " << sizeof(TestNode190231) << std::endl;
|
||||
|
||||
LocatedAccessPoint ap1("00:00:00:00:00:01", Point3( 0, 0,0));
|
||||
LocatedAccessPoint ap2("00:00:00:00:00:02", Point3(20, 0,0));
|
||||
LocatedAccessPoint ap3("00:00:00:00:00:03", Point3( 0,20,0));
|
||||
LocatedAccessPoint ap4("00:00:00:00:00:04", Point3(20,20,0));
|
||||
const MACAddress ap1 = MACAddress("00:00:00:00:00:01");
|
||||
const MACAddress ap2 = MACAddress("00:00:00:00:00:02");
|
||||
const MACAddress ap3 = MACAddress("00:00:00:00:00:03");
|
||||
const MACAddress ap4 = MACAddress("00:00:00:00:00:04");
|
||||
|
||||
std::vector<LocatedAccessPoint> aps = {ap1, ap2, ap3, ap4};
|
||||
// LocatedAccessPoint ap1, Point3( 0, 0,0));
|
||||
// LocatedAccessPoint ap2("00:00:00:00:00:02", Point3(20, 0,0));
|
||||
// LocatedAccessPoint ap3("00:00:00:00:00:03", Point3( 0,20,0));
|
||||
// LocatedAccessPoint ap4("00:00:00:00:00:04", Point3(20,20,0));
|
||||
// std::vector<LocatedAccessPoint> aps = {ap1, ap2, ap3, ap4};
|
||||
|
||||
// model not populated -> must be empty
|
||||
ASSERT_EQ(0, grid[0].getNumVisibleAPs());
|
||||
|
||||
WiFiModelLogDist model(-40, 1.5);
|
||||
WiFiModelLogDist model;
|
||||
model.addAP(ap1, WiFiModelLogDist::APEntry( Point3(0,0,0), -40, 1.5));
|
||||
model.addAP(ap2, WiFiModelLogDist::APEntry( Point3(20,0,0), -40, 1.5));
|
||||
model.addAP(ap3, WiFiModelLogDist::APEntry( Point3(0,20,0), -40, 1.5));
|
||||
model.addAP(ap4, WiFiModelLogDist::APEntry( Point3(20,20,0), -40, 1.5));
|
||||
|
||||
std::vector<AccessPoint> aps = {
|
||||
AccessPoint(ap1), AccessPoint(ap2), AccessPoint(ap3), AccessPoint(ap4)
|
||||
};
|
||||
|
||||
WiFiGridEstimator::estimate(grid, model, aps);
|
||||
|
||||
|
||||
@@ -90,13 +118,15 @@ TEST(WiFiGridModelLogDist, create) {
|
||||
obs.entries.push_back(WiFiMeasurement(MACAddress("00:00:00:00:00:04"), -55, ts));
|
||||
|
||||
WiFiObserverGrid observer(5.0f);
|
||||
const MyNode& gn = grid.getNodeFor(GridPoint(1000,1000,0));
|
||||
const TestNode190231& gn = grid.getNodeFor(GridPoint(1000,1000,0));
|
||||
const float p = observer.getProbability(gn, ts, obs);
|
||||
|
||||
observer.dump(grid, ts, obs, "/tmp/eval1.gp");
|
||||
std::cout << "see: /tmp/eval1.gp" << std::endl;
|
||||
|
||||
int i = 0; (void) i;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user