From a20330562806a6d011d48a23619ba4bafa045507 Mon Sep 17 00:00:00 2001 From: FrankE Date: Mon, 29 Aug 2016 19:02:32 +0200 Subject: [PATCH] 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 --- Assertions.h | 8 +- floorplan/v2/Floorplan.h | 9 + grid/Grid.h | 18 +- grid/factory/v2/Importance.h | 161 ++++-------------- grid/factory/v2/Stairs.h | 38 ++++- grid/walk/v2/modules/WalkModuleFavorZ.h | 54 ++++++ .../v2/modules/WalkModuleHeadingControl.h | 4 +- .../v2/modules/WalkModuleNodeImportance.h | 4 +- main.cpp | 18 +- sensors/radio/WiFiGridEstimator.h | 6 +- sensors/radio/WiFiGridNode.h | 15 +- sensors/radio/WiFiProbabilityFree.h | 28 ++- sensors/radio/model/WiFiModel.h | 17 +- sensors/radio/model/WiFiModelLogDist.h | 54 +++++- sensors/radio/model/WiFiModelLogDistCeiling.h | 79 +++++++-- tests/grid/GridWalk2RelPressure.cpp | 2 +- tests/grid/TestGrid.cpp | 73 ++++++-- tests/grid/TestGridWalkV2.cpp | 40 ++--- tests/nav/dijkstra/TestDijkstra.cpp | 10 +- tests/sensors/pressure/TestBarometer.cpp | 4 +- .../radio/TestLogDistanceCeilingModel.cpp | 48 +++++- tests/sensors/radio/TestWiFiEval.cpp | 10 +- tests/sensors/radio/TestWiFiGrid.cpp | 56 ++++-- 23 files changed, 505 insertions(+), 251 deletions(-) create mode 100644 grid/walk/v2/modules/WalkModuleFavorZ.h diff --git a/Assertions.h b/Assertions.h index 116a9e1..f4b5d1c 100644 --- a/Assertions.h +++ b/Assertions.h @@ -2,6 +2,11 @@ #define ASSERTIONS_H #include "Exception.h" +#include + +// 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 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());} } } diff --git a/floorplan/v2/Floorplan.h b/floorplan/v2/Floorplan.h index b771b11..13c0f86 100644 --- a/floorplan/v2/Floorplan.h +++ b/floorplan/v2/Floorplan.h @@ -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 */ diff --git a/grid/Grid.h b/grid/Grid.h index 9a74e23..d41b29e 100755 --- a/grid/Grid.h +++ b/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 diff --git a/grid/factory/v2/Importance.h b/grid/factory/v2/Importance.h index 1af525a..24d0704 100644 --- a/grid/factory/v2/Importance.h +++ b/grid/factory/v2/Importance.h @@ -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 doors; + // create list of all stair-nodes + std::vector 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> knnArrDoors(doors); KNN>, 3> knnDoors(knnArrDoors); + // KNN for stairs + KNNArray> knnArrStairs(stairs); + KNN>, 3> knnStairs(knnArrStairs); + + // probability adjustments + Distribution::Normal avoidWalls(0.0, 0.35); Distribution::Normal favorDoors(0.0f, 0.5f); + Distribution::Normal 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 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 static bool isStaircase(Grid& 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 static bool isDoor( T& nSrc, std::vector 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 avoidWalls(0.0, 0.35); - - // favour walking near walls (likely) - //static Distribution::Normal stickToWalls(0.9, 0.7); - - // favour walking far away (likely) - //static Distribution::Normal 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 - ; - - - } - }; diff --git a/grid/factory/v2/Stairs.h b/grid/factory/v2/Stairs.h index cd2c930..9e139ae 100644 --- a/grid/factory/v2/Stairs.h +++ b/grid/factory/v2/Stairs.h @@ -8,7 +8,7 @@ #include "Helper.h" #include "../../../floorplan/v2/Floorplan.h" - +#include @@ -23,6 +23,10 @@ private: Helper helper; + std::ofstream outStairs; + std::ofstream outDelete; + + private: // struct Entry { @@ -68,10 +72,14 @@ public: /** ctor */ Stairs(Grid& 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 parts = stair->getParts(); const std::vector 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 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);} } diff --git a/grid/walk/v2/modules/WalkModuleFavorZ.h b/grid/walk/v2/modules/WalkModuleFavorZ.h new file mode 100644 index 0000000..87e319a --- /dev/null +++ b/grid/walk/v2/modules/WalkModuleFavorZ.h @@ -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 class WalkModuleFavorZ : public WalkModule { + +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 diff --git a/grid/walk/v2/modules/WalkModuleHeadingControl.h b/grid/walk/v2/modules/WalkModuleHeadingControl.h index c4995ac..8642121 100644 --- a/grid/walk/v2/modules/WalkModuleHeadingControl.h +++ b/grid/walk/v2/modules/WalkModuleHeadingControl.h @@ -26,14 +26,14 @@ private: public: /** ctor 3.0 should be OK! */ - WalkModuleHeadingControl(Control* ctrl) : dist(Distribution::VonMises(0.0f, 1.5).getLUT()), draw(dist.getDrawList()), ctrl(ctrl) { + WalkModuleHeadingControl(Control* ctrl) : dist(Distribution::VonMises(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; diff --git a/grid/walk/v2/modules/WalkModuleNodeImportance.h b/grid/walk/v2/modules/WalkModuleNodeImportance.h index 65c4545..d0abb2b 100644 --- a/grid/walk/v2/modules/WalkModuleNodeImportance.h +++ b/grid/walk/v2/modules/WalkModuleNodeImportance.h @@ -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; } diff --git a/main.cpp b/main.cpp index 82ea72a..51db809 100755 --- a/main.cpp +++ b/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(); diff --git a/sensors/radio/WiFiGridEstimator.h b/sensors/radio/WiFiGridEstimator.h index 3b28e47..3b117f8 100644 --- a/sensors/radio/WiFiGridEstimator.h +++ b/sensors/radio/WiFiGridEstimator.h @@ -43,13 +43,13 @@ public: * as nodes only provide a limited number of rssi-entries, * store only the strongest ones. */ - template static void estimate(Grid& grid, WiFiModel& mdl, const std::vector aps) { + template static void estimate(Grid& grid, WiFiModel& mdl, const std::vector 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)); diff --git a/sensors/radio/WiFiGridNode.h b/sensors/radio/WiFiGridNode.h index 44119a3..60472ac 100644 --- a/sensors/radio/WiFiGridNode.h +++ b/sensors/radio/WiFiGridNode.h @@ -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 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 */ diff --git a/sensors/radio/WiFiProbabilityFree.h b/sensors/radio/WiFiProbabilityFree.h index 090a5d8..1b9357b 100644 --- a/sensors/radio/WiFiProbabilityFree.h +++ b/sensors/radio/WiFiProbabilityFree.h @@ -8,8 +8,8 @@ #include /** - * 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 aps; + + /** the map's floorplan */ Floorplan::IndoorMap* map; + public: - WiFiObserverFree(const float sigma, WiFiModel& model, const std::vector& aps) : sigma(sigma), model(model) { - - for (const LocatedAccessPoint& ap : aps) { - this->aps.insert(std::pair(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 diff --git a/sensors/radio/model/WiFiModel.h b/sensors/radio/model/WiFiModel.h index 70a1a37..90df451 100644 --- a/sensors/radio/model/WiFiModel.h +++ b/sensors/radio/model/WiFiModel.h @@ -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; }; diff --git a/sensors/radio/model/WiFiModelLogDist.h b/sensors/radio/model/WiFiModelLogDist.h index 326405b..a86807f 100644 --- a/sensors/radio/model/WiFiModelLogDist.h +++ b/sensors/radio/model/WiFiModelLogDist.h @@ -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 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(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; + } }; diff --git a/sensors/radio/model/WiFiModelLogDistCeiling.h b/sensors/radio/model/WiFiModelLogDistCeiling.h index 090d190..7f0ba3c 100644 --- a/sensors/radio/model/WiFiModelLogDistCeiling.h +++ b/sensors/radio/model/WiFiModelLogDistCeiling.h @@ -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 accessPoints; /** position (height) of all ceilings (in meter) */ std::vector 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(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;} } diff --git a/tests/grid/GridWalk2RelPressure.cpp b/tests/grid/GridWalk2RelPressure.cpp index 43a6f34..6e6808a 100644 --- a/tests/grid/GridWalk2RelPressure.cpp +++ b/tests/grid/GridWalk2RelPressure.cpp @@ -39,7 +39,7 @@ struct MyState : public WalkState, public WalkStateRelativePressure { -TEST(GridWalk2RelPressure, walkHeading) { +TEST(GridWalk2RelPressure, LIVE_walkHeading) { Grid grid(20); diff --git a/tests/grid/TestGrid.cpp b/tests/grid/TestGrid.cpp index 312a57c..250df9c 100755 --- a/tests/grid/TestGrid.cpp +++ b/tests/grid/TestGrid.cpp @@ -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 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 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! } diff --git a/tests/grid/TestGridWalkV2.cpp b/tests/grid/TestGridWalkV2.cpp index 2a05cd5..bcbbb28 100644 --- a/tests/grid/TestGridWalkV2.cpp +++ b/tests/grid/TestGridWalkV2.cpp @@ -24,9 +24,10 @@ #include -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 grid(20); - GridFactory gf(grid); + Grid grid(20); + GridFactory 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 walker; - WalkModuleHeadingControl modHead(&ctrl); + GridWalker walker; + WalkModuleHeadingControl 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 grid(20); + Grid grid(20); std::ifstream inp("/tmp/grid.dat"); grid.read(inp); @@ -118,9 +120,9 @@ TEST(GgridWalk2, walkHeading) { // GridFactory fac(grid); // fac.addFloor(&floor); - GridWalker walker; - WalkModuleHeading wmHead; - WalkModuleFollowDestination wmDest(grid, grid.getNodeFor(GridPoint(7200,4800,400+340+340))); + GridWalker walker; + WalkModuleHeading wmHead; + WalkModuleFollowDestination 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)); } diff --git a/tests/nav/dijkstra/TestDijkstra.cpp b/tests/nav/dijkstra/TestDijkstra.cpp index 399e016..b68056a 100644 --- a/tests/nav/dijkstra/TestDijkstra.cpp +++ b/tests/nav/dijkstra/TestDijkstra.cpp @@ -59,7 +59,7 @@ void build(Grid& grid) { } } - std::set done; + //std::set done; for (int x = 0; x < size; x += gs) { for (int y = 0; y < size; y += gs) { @@ -69,17 +69,19 @@ void build(Grid& 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); } } diff --git a/tests/sensors/pressure/TestBarometer.cpp b/tests/sensors/pressure/TestBarometer.cpp index ea6d32a..5a79260 100644 --- a/tests/sensors/pressure/TestBarometer.cpp +++ b/tests/sensors/pressure/TestBarometer.cpp @@ -57,7 +57,7 @@ TEST(Barometer, relCalib) { #include -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; diff --git a/tests/sensors/radio/TestLogDistanceCeilingModel.cpp b/tests/sensors/radio/TestLogDistanceCeilingModel.cpp index 53e408f..ca56ec1 100644 --- a/tests/sensors/radio/TestLogDistanceCeilingModel.cpp +++ b/tests/sensors/radio/TestLogDistanceCeilingModel.cpp @@ -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 diff --git a/tests/sensors/radio/TestWiFiEval.cpp b/tests/sensors/radio/TestWiFiEval.cpp index 58f0177..ae61d09 100644 --- a/tests/sensors/radio/TestWiFiEval.cpp +++ b/tests/sensors/radio/TestWiFiEval.cpp @@ -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(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 diff --git a/tests/sensors/radio/TestWiFiGrid.cpp b/tests/sensors/radio/TestWiFiGrid.cpp index 49d0ed3..60ec5c6 100644 --- a/tests/sensors/radio/TestWiFiGrid.cpp +++ b/tests/sensors/radio/TestWiFiGrid.cpp @@ -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 grid(gs); + Grid 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 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 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 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