From 9e6d9f4ce7cf5635fa87e069a003366eaf1eb2f2 Mon Sep 17 00:00:00 2001 From: frank Date: Tue, 22 May 2018 11:45:35 +0200 Subject: [PATCH] added support for pillars some new helper methods/classes --- floorplan/v2/Floorplan.h | 7 +- floorplan/v2/FloorplanHelper.h | 24 ++++++ floorplan/v2/FloorplanReader.h | 3 +- floorplan/v2/FloorplanWriter.h | 1 + sensors/radio/WiFiMeasurements.h | 9 ++ sensors/radio/model/WiFiModelFactory.h | 2 + sensors/radio/model/WiFiModelFactoryImpl.h | 9 +- sensors/radio/model/WiFiModelLogDistCeiling.h | 4 + sensors/radio/model/WiFiModelPerFloor.h | 4 + .../radio/setup/WiFiOptimizerLogDistCeiling.h | 4 +- wifi/estimate/ray3/Cylinder.h | 82 +++++++++++++++++++ wifi/estimate/ray3/Mesh.h | 9 ++ wifi/estimate/ray3/ModelFactory.h | 36 ++++++++ 13 files changed, 185 insertions(+), 9 deletions(-) create mode 100644 wifi/estimate/ray3/Cylinder.h diff --git a/floorplan/v2/Floorplan.h b/floorplan/v2/Floorplan.h index 4e1f327..90edb51 100644 --- a/floorplan/v2/Floorplan.h +++ b/floorplan/v2/Floorplan.h @@ -165,6 +165,7 @@ namespace Floorplan { DRYWALL, GLASS, METAL, + METALLIZED_GLAS, _END, }; @@ -356,8 +357,10 @@ namespace Floorplan { struct FloorObstacleCircle : public FloorObstacle { Point2 center; float radius; - FloorObstacleCircle(const Material material, const Point2 center, const float radius) : FloorObstacle(material), center(center), radius(radius) {;} - FloorObstacleCircle(const Material material, const float cx, const float cy, const float radius) : FloorObstacle(material), center(cx,cy), radius(radius) {;} + float height = 0; // 0 = floor's height + FloorObstacleCircle(const Material material, const Point2 center, const float radius, const float height=0) : FloorObstacle(material), center(center), radius(radius), height(height) {;} + FloorObstacleCircle(const Material material, const float cx, const float cy, const float radius, const float height=0) : FloorObstacle(material), center(cx,cy), radius(radius), height(height) {;} + //float getHeight(const Floor* f) const {return (height > 0) ? (height) : (f->height);} }; /** door obstacle */ diff --git a/floorplan/v2/FloorplanHelper.h b/floorplan/v2/FloorplanHelper.h index 5a96f16..537d30b 100644 --- a/floorplan/v2/FloorplanHelper.h +++ b/floorplan/v2/FloorplanHelper.h @@ -29,6 +29,18 @@ public: return std::make_pair(nullptr, nullptr); } + /** get the AP for the given Name [if available] */ + static std::pair getAPByName(const Floorplan::IndoorMap* map, const std::string& name) { + for (Floorplan::Floor* f : map->floors) { + for (Floorplan::AccessPoint* ap : f->accesspoints) { + if (name == ap->name) { + return std::make_pair(ap, f); + } + } + } + return std::make_pair(nullptr, nullptr); + } + /** get all APs within the map */ static std::vector> getAPs(const Floorplan::IndoorMap* map) { std::vector> res; @@ -40,6 +52,18 @@ public: return res; } + /** get the Fingerprint-Loation for the given Name [if available] */ + static std::pair getFingerprintLocationByName(const Floorplan::IndoorMap* map, const std::string& name) { + for (Floorplan::Floor* f : map->floors) { + for (Floorplan::FingerprintLocation* fpl : f->fpLocations) { + if (name == fpl->name) { + return std::make_pair(fpl, f); + } + } + } + return std::make_pair(nullptr, nullptr); + } + /** get all ground-truth points within the map as hash-map: id->pos */ static std::unordered_map getGroundTruthPoints(const Floorplan::IndoorMap* map) { std::unordered_map res; diff --git a/floorplan/v2/FloorplanReader.h b/floorplan/v2/FloorplanReader.h index 3d16215..5c18ccf 100644 --- a/floorplan/v2/FloorplanReader.h +++ b/floorplan/v2/FloorplanReader.h @@ -412,7 +412,8 @@ namespace Floorplan { return new FloorObstacleCircle( parseMaterial(el->Attribute("material")), el->FloatAttribute("cx"), el->FloatAttribute("cy"), - el->FloatAttribute("radius") + el->FloatAttribute("radius"), + el->FloatAttribute("height") ); } diff --git a/floorplan/v2/FloorplanWriter.h b/floorplan/v2/FloorplanWriter.h index 931be34..1619c69 100644 --- a/floorplan/v2/FloorplanWriter.h +++ b/floorplan/v2/FloorplanWriter.h @@ -344,6 +344,7 @@ namespace Floorplan { obstacle->SetAttribute("cx", circle->center.x); obstacle->SetAttribute("cy", circle->center.y); obstacle->SetAttribute("radius", circle->radius); + obstacle->SetAttribute("height", circle->height); obstacles->InsertEndChild(obstacle); } diff --git a/sensors/radio/WiFiMeasurements.h b/sensors/radio/WiFiMeasurements.h index 412883a..18ce569 100644 --- a/sensors/radio/WiFiMeasurements.h +++ b/sensors/radio/WiFiMeasurements.h @@ -2,6 +2,7 @@ #define WIFIMEASUREMENTS_H #include +#include #include "WiFiMeasurement.h" @@ -42,6 +43,14 @@ struct WiFiMeasurements { } } + /** get the oldest timestamp among all contained measurements */ + Timestamp getOldestTS() const { + auto comp = [] (const WiFiMeasurement& m1, const WiFiMeasurement& m2) {return m1.getTimestamp() < m2.getTimestamp();}; + auto it = std::max_element(entries.begin(), entries.end(), comp); + if (it == entries.end()) {throw Exception("no element found");} + return it->getTimestamp(); + } + /** create a combination */ static WiFiMeasurements mix(const WiFiMeasurements& a, const WiFiMeasurements& b, float sec = 3) { diff --git a/sensors/radio/model/WiFiModelFactory.h b/sensors/radio/model/WiFiModelFactory.h index 6bcf94a..0027975 100644 --- a/sensors/radio/model/WiFiModelFactory.h +++ b/sensors/radio/model/WiFiModelFactory.h @@ -12,6 +12,8 @@ class WiFiModelFactory { private: + static constexpr const char* name = "WifiModelFac"; + Floorplan::IndoorMap* map; public: diff --git a/sensors/radio/model/WiFiModelFactoryImpl.h b/sensors/radio/model/WiFiModelFactoryImpl.h index d318146..1c7369b 100644 --- a/sensors/radio/model/WiFiModelFactoryImpl.h +++ b/sensors/radio/model/WiFiModelFactoryImpl.h @@ -7,6 +7,7 @@ #include "WiFiModelPerFloor.h" #include "WiFiModelPerBBox.h" + WiFiModel* WiFiModelFactory::loadXML(const std::string& file) { XMLDoc doc; @@ -25,10 +26,10 @@ WiFiModel* WiFiModelFactory::readFromXML(XMLDoc* doc, XMLElem* src) { WiFiModel* mdl = nullptr; // create an instance for the model - if (type == "WiFiModelLogDist") {mdl = new WiFiModelLogDist();} - else if (type == "WiFiModelLogDistCeiling") {mdl = new WiFiModelLogDistCeiling(map);} - else if (type == "WiFiModelPerFloor") {mdl = new WiFiModelPerFloor(map);} - else if (type == "WiFiModelPerBBox") {mdl = new WiFiModelPerBBox(map);} + if (type == "WiFiModelLogDist") {Log::add(name, "loading WiFiModelLogDist"); mdl = new WiFiModelLogDist();} + else if (type == "WiFiModelLogDistCeiling") {Log::add(name, "loading WiFiModelLogDistCeiling"); mdl = new WiFiModelLogDistCeiling(map);} + else if (type == "WiFiModelPerFloor") {Log::add(name, "loading WiFiModelPerFloor"); mdl = new WiFiModelPerFloor(map);} + else if (type == "WiFiModelPerBBox") {Log::add(name, "loading WiFiModelPerBBox"); mdl = new WiFiModelPerBBox(map);} else {throw Exception("invalid model type given: " + type);} // load the model from XML diff --git a/sensors/radio/model/WiFiModelLogDistCeiling.h b/sensors/radio/model/WiFiModelLogDistCeiling.h index bc40bd0..5552ef9 100644 --- a/sensors/radio/model/WiFiModelLogDistCeiling.h +++ b/sensors/radio/model/WiFiModelLogDistCeiling.h @@ -18,6 +18,8 @@ */ class WiFiModelLogDistCeiling : public WiFiModel { + static constexpr const char* name = "WifiModelLDC"; + public: /** parameters describing one AP to the model */ @@ -224,6 +226,8 @@ public: ceilings.addCeiling(atHeight_m); } + Log::add(name, "loaded " + std::to_string(accessPoints.size()) + " APs"); + } }; diff --git a/sensors/radio/model/WiFiModelPerFloor.h b/sensors/radio/model/WiFiModelPerFloor.h index 8d84b5f..5c9281c 100644 --- a/sensors/radio/model/WiFiModelPerFloor.h +++ b/sensors/radio/model/WiFiModelPerFloor.h @@ -14,6 +14,8 @@ */ class WiFiModelPerFloor : public WiFiModel { + static constexpr const char* name = "WiFiModelFlo"; + public: struct ModelForFloor { @@ -173,6 +175,8 @@ public: } + Log::add(name, "loaded " + std::to_string(models.size()) + " floor models"); + } void writeToXML(XMLDoc* doc, XMLElem* dst) override { diff --git a/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h b/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h index 837563a..63cdc5c 100644 --- a/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h +++ b/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h @@ -74,14 +74,14 @@ namespace WiFiOptimizer { float exp; float waf; - Point3 getPos() const {return Point3(x,y,z);} - /** ctor */ APParams() {;} /** ctor */ APParams(float x, float y, float z, float txp, float exp, float waf) : x(x), y(y), z(z), txp(txp), exp(exp), waf(waf) {;} + Point3 getPos() const {return Point3(x,y,z);} + std::string asString() const { std::stringstream ss; ss << "Pos:" << getPos().asString() << " TXP:" << txp << " EXP:" << exp << " WAF:" << waf; diff --git a/wifi/estimate/ray3/Cylinder.h b/wifi/estimate/ray3/Cylinder.h new file mode 100644 index 0000000..c8f08ca --- /dev/null +++ b/wifi/estimate/ray3/Cylinder.h @@ -0,0 +1,82 @@ +#ifndef CYLINDER_H +#define CYLINDER_H + + +#include "../../../math/Matrix4.h" +#include "Mesh.h" + +namespace Ray3D { + + /** walled cylinder */ + class Cylinder : public Mesh { + + public: + + /** ctor */ + Cylinder() { + ; + } + + /** get a transformed version */ + Cylinder transformed(const Matrix4& mat) const { + Cylinder res = *this; + res.transform(mat); + return res; + } + + /** build */ + void add(const float rOuter, const float h, bool topAndBottom) { + + const int tiles = 8; + const float deg_per_tile = 360.0f / tiles; + const float rad_per_tile = deg_per_tile / 180.0f * M_PI; + + for (int i = 0; i < tiles; ++i) { + + const float startRad = (i+0) * rad_per_tile; + const float endRad = (i+1) * rad_per_tile; + + const float xo0 = std::cos(startRad) * rOuter; + const float yo0 = std::sin(startRad) * rOuter; + const float xo1 = std::cos(endRad) * rOuter; + const float yo1 = std::sin(endRad) * rOuter; + const float cx = 0; + const float cy = 0; + + // outer + addQuad( + Point3(xo0, yo0, -h), + Point3(xo1, yo1, -h), + Point3(xo1, yo1, +h), + Point3(xo0, yo0, +h) + ); + + if (topAndBottom) { + + // top + addTriangle( + Point3(cx, cy, h), + Point3(xo0, yo0, h), + Point3(xo1, yo1, h) + ); + + // bottom + addTriangle( + Point3(cx, cy, -h), + Point3(xo1, yo1, -h), + Point3(xo0, yo0, -h) + ); + + } + + } + + } + + + + }; + +} + +#endif // CYLINDER_H diff --git a/wifi/estimate/ray3/Mesh.h b/wifi/estimate/ray3/Mesh.h index 1862f97..d5fc40e 100644 --- a/wifi/estimate/ray3/Mesh.h +++ b/wifi/estimate/ray3/Mesh.h @@ -28,6 +28,11 @@ namespace Ray3D { transform(mat); } + void translate(const Point3 pos) { + const Matrix4 mPos = Matrix4::getTranslation(pos.x, pos.y, pos.z); + transform(mPos); + } + void transform(const Matrix4& mat) { for (Triangle3& tria : trias) { @@ -53,6 +58,10 @@ namespace Ray3D { trias.push_back( Triangle3(p1,p3,p4) ); } + void addTriangle(Point3 p1, Point3 p2, Point3 p3) { + trias.push_back( Triangle3(p1,p2,p3) ); + } + }; } diff --git a/wifi/estimate/ray3/ModelFactory.h b/wifi/estimate/ray3/ModelFactory.h index 2f43454..fbd039c 100644 --- a/wifi/estimate/ray3/ModelFactory.h +++ b/wifi/estimate/ray3/ModelFactory.h @@ -8,6 +8,7 @@ #include "Obstacle3.h" #include "Cube.h" #include "Tube.h" +#include "Cylinder.h" #include "FloorplanMesh.h" #include "OBJPool.h" @@ -219,6 +220,14 @@ namespace Ray3D { } } + // handle circle obstacles + const Floorplan::FloorObstacleCircle* foc = dynamic_cast(fo); + if (foc) { + if (exportObstacles) { + res.push_back(getPillar(f, foc)); + } + } + // handle object obstacles const Floorplan::FloorObstacleObject* foo = dynamic_cast(fo); if (foo) { @@ -267,6 +276,27 @@ namespace Ray3D { return getWall(f, fol, aboveDoor); } + Obstacle3D getPillar(const Floorplan::Floor* f, const Floorplan::FloorObstacleCircle* foc) const { + + FloorPos fpos(f); + + // attributes + const float r = foc->radius; + const float h = (foc->height > 0) ? (foc->height) : (fpos.height); + const Point3 pos(foc->center.x, foc->center.y, fpos.z1 + h/2); + + // build + Cylinder cyl; + cyl.add(r, h/2, true); + cyl.translate(pos); + + // done + Obstacle3D res(getType(foc), foc->material); + res.triangles = cyl.getTriangles(); + return res; + + } + Obstacle3D getWall(const Floorplan::Floor* f, const Floorplan::FloorObstacleLine* fol, const Floorplan::FloorObstacleDoor* aboveDoor) const { FloorPos fpos(f); @@ -310,6 +340,7 @@ namespace Ray3D { Obstacle3D obs = OBJPool::get().getObject(name); obs = obs.rotated_deg( Point3(foo->rot.x, foo->rot.y, foo->rot.z) ); obs = obs.translated(foo->pos + Point3(0,0,fpos.z1)); + obs.type = Obstacle3D::Type::OBJECT; // std::vector trias; // for (const OBJReader::Face& face : reader.getData().faces) { @@ -642,6 +673,11 @@ namespace Ray3D { } } + static Obstacle3D::Type getType(const Floorplan::FloorObstacleCircle* c) { + (void) c; + return Obstacle3D::Type::WALL; + } + /** used to model ceiling thickness */ struct FloorPos { float fh;