diff --git a/Assertions.h b/Assertions.h new file mode 100644 index 0000000..7e4e814 --- /dev/null +++ b/Assertions.h @@ -0,0 +1,60 @@ +#ifndef ASSERTIONS_H +#define ASSERTIONS_H + +#include "Exception.h" + +/** + * this file provides assertion methods that may be enabled to trace + * coding errors efficiently during debug or disabled to speed up the + * code execution for the release build + * + * compile with -DWITH_ASSERTIONS + */ +namespace Assert { + + + static inline void doThrow(const char* err) { + #ifdef WITH_ASSERTIONS + std::string str = "in: "; + str += __PRETTY_FUNCTION__; + str += " error: "; + str += err; + throw Exception(err); + #endif + } + + template static inline void equal(const T v1, const T v2, const char* err) { + if (v1 != v2) {doThrow(err);} + } + + template static inline void isTrue(const T v, const char* err) { + if (!v) {doThrow(err);} + } + + template static inline void isFalse(const T v, const char* err) { + if (v) {doThrow(err);} + } + + template static inline void isNull(const T v, const char* err) { + if (v != nullptr) {doThrow(err);} + } + + template static inline void isNotNull(const T v, const char* err) { + if (v == nullptr) {doThrow(err);} + } + + template static inline void isNotNaN(const T v, const char* err) { + if (v != v) {doThrow(err);} + } + + template static inline void isNot0(const T v, const char* err) { + if (v == 0) {doThrow(err);} + } + + template static inline void isBetween(const T v, const T min, const T max, const char* err) { + if (v < min || v > max) {doThrow(err);} + } + +} + +#endif // ASSERTIONS_H diff --git a/floorplan/PlatformStair.h b/floorplan/PlatformStair.h index f74fefe..fdfc8ac 100644 --- a/floorplan/PlatformStair.h +++ b/floorplan/PlatformStair.h @@ -1,17 +1,32 @@ #ifndef PLATFORMSTAIR_H #define PLATFORMSTAIR_H -#include "Stair.h"; +#include "Stair.h" -class PlatformStair { +struct PlatformStair { + /** stair to the platform */ Stair s1; + /** platform in the center */ BBox2 platform; + /** stair from the platform */ Stair s2; + PlatformStair() : s1(), platform(), s2() {;} + +// PlatformStair(const Line2& startEdge, const Line2& endEdge, const int w2, const int w2) { +// s1.start = startEdge; +// s2.start = endEdge; +// Point2 edgeDir = startEdge.p2 - startEdge.p1; +// Point2 perp(edgeDir.y, -edgeDir.x); + +// platform.add(startEdge.p1 + perp); +// plat +// } + }; #endif // PLATFORMSTAIR_H diff --git a/floorplan/Stair.h b/floorplan/Stair.h index b446d67..505de8b 100644 --- a/floorplan/Stair.h +++ b/floorplan/Stair.h @@ -13,6 +13,13 @@ struct Stair { /** the direction to move all the starting points to */ Point2 dir; + + /** empty ctor */ + Stair() : start(), dir() {;} + + /** ctor with starting edge and stair-direction */ + Stair(const Line2& start, const Point2& dir) : start(start), dir(dir) {;} + }; #endif // STAIR_H diff --git a/geo/Angle.h b/geo/Angle.h index ee3da1c..25e5fc1 100755 --- a/geo/Angle.h +++ b/geo/Angle.h @@ -2,7 +2,7 @@ #define ANGLE_H #include -#include +#include "../Assertions.h" struct Angle { @@ -11,7 +11,7 @@ public: /** get the radians from (x1,y1) to (x2,y2) between 0 (to-the-right) and <2_PI */ static float getRAD_2PI(const float x1, const float y1, const float x2, const float y2) { - _assertFalse( (x1==x2)&&(y1==y2), "(x1,y1) must not equal (x2,y2)!!"); + Assert::isFalse( (x1==x2)&&(y1==y2), "(x1,y1) must not equal (x2,y2)!!"); const float tmp = std::atan2(y2-y1, x2-x1); return (tmp < 0) ? (tmp + 2*M_PI) : (tmp); } @@ -27,8 +27,8 @@ public: * - as a change-in-direction between [0:PI] */ static float getDiffRAD_2PI_PI(const float r1, const float r2) { - _assertBetween(r1, 0, (float)(2*M_PI), "r1 out of bounds"); - _assertBetween(r2, 0, (float)(2*M_PI), "r2 out of bounds"); + Assert::isBetween(r1, 0.0f, (float)(2*M_PI), "r1 out of bounds"); + Assert::isBetween(r2, 0.0f, (float)(2*M_PI), "r2 out of bounds"); float tmp = std::abs(r1-r2); return (tmp <= M_PI) ? (tmp) : (2*M_PI-tmp); } diff --git a/geo/BBox2.h b/geo/BBox2.h index 35d7535..568e74f 100644 --- a/geo/BBox2.h +++ b/geo/BBox2.h @@ -19,8 +19,12 @@ protected: public: + /** empty ctor */ BBox2() : p1(MAX,MAX), p2(MIN,MIN) {;} + /** ctor */ + BBox2(const Point2& p1, const Point2& p2) : p1(p1), p2(p2) {;} + /** adjust the bounding-box by adding this point */ void add(const Point2& p) { diff --git a/geo/Heading.h b/geo/Heading.h index 404a24a..965d6b2 100644 --- a/geo/Heading.h +++ b/geo/Heading.h @@ -19,12 +19,12 @@ public: /** ctor with radians */ Heading(const float rad) : rad(rad) { - _assertBetween(rad, 0, _2PI, "radians out of bounds"); + Assert::isBetween(rad, 0.0f, (float)_2PI, "radians out of bounds"); } /** ctor from(x1,y1) to(x2,y2) */ Heading(const float x1, const float y1, const float x2, const float y2) : rad(Angle::getRAD_2PI(x1,y1,x2,y2)) { - _assertBetween(rad, 0, _2PI, "radians out of bounds"); + Assert::isBetween(rad, 0.0f, (float)_2PI, "radians out of bounds"); } /** angular difference [0:PI] */ @@ -34,7 +34,7 @@ public: /** update the angle but ensure we stay within [0:2PI] */ Heading& operator += (const float _rad) { - _assertBetween(_rad, -_2PI*0.99, +_2PI*0.99, "radians out of bounds"); + Assert::isBetween(_rad, float(-_2PI*0.99), float(+_2PI*0.99), "radians out of bounds"); rad += _rad; if (rad >= _2PI) {rad -= _2PI;} else if (rad < 0) {rad += _2PI;} diff --git a/geo/Point3.h b/geo/Point3.h index cf24e0a..2c731d3 100644 --- a/geo/Point3.h +++ b/geo/Point3.h @@ -1,7 +1,7 @@ #ifndef POINT3_H #define POINT3_H -#include +#include "../Assertions.h" #include /** @@ -37,7 +37,7 @@ struct Point3 { /** read-only array access */ float operator [] (const int idx) const { - _assertBetween(idx, 0, 2, "index out of bounds"); + Assert::isBetween(idx, 0, 2, "index out of bounds"); if (0 == idx) {return x;} if (1 == idx) {return y;} return z; diff --git a/grid/Grid.h b/grid/Grid.h index 6f68c9b..354cbd8 100755 --- a/grid/Grid.h +++ b/grid/Grid.h @@ -9,7 +9,7 @@ #include "GridPoint.h" #include "GridNode.h" -#include +#include "../Assertions.h" #include "../geo/BBox3.h" #include "../misc/Debug.h" @@ -95,7 +95,7 @@ public: void connectUniDir(T& n1, const T& n2) { n1._neighbors[n1._numNeighbors] = n2._idx; ++n1._numNeighbors; - _assertBetween(n1._numNeighbors, 0, 10, "number of neighbors out of bounds!"); + Assert::isBetween(n1._numNeighbors, 0, 10, "number of neighbors out of bounds!"); } /** @@ -188,13 +188,13 @@ public: /** array access */ T& operator [] (const int idx) { - _assertBetween(idx, 0, getNumNodes()-1, "index out of bounds"); + Assert::isBetween(idx, 0, getNumNodes()-1, "index out of bounds"); return nodes[idx]; } /** const array access */ const T& operator [] (const int idx) const { - _assertBetween(idx, 0, getNumNodes()-1, "index out of bounds"); + Assert::isBetween(idx, 0, getNumNodes()-1, "index out of bounds"); return nodes[idx]; } diff --git a/grid/GridPoint.h b/grid/GridPoint.h index f920e8d..fe862c2 100755 --- a/grid/GridPoint.h +++ b/grid/GridPoint.h @@ -4,7 +4,7 @@ #include #include "../geo/Point3.h" -#include +#include "../Assertions.h" struct GridPoint { @@ -46,7 +46,7 @@ struct GridPoint { /** read-only array access */ float operator [] (const int idx) const { - _assertBetween(idx, 0, 2, "index out of bounds"); + Assert::isBetween(idx, 0, 2, "index out of bounds"); if (0 == idx) {return x_cm;} if (1 == idx) {return y_cm;} {return z_cm;} diff --git a/grid/factory/GridFactory.h b/grid/factory/GridFactory.h index ca91ae9..276cc2f 100755 --- a/grid/factory/GridFactory.h +++ b/grid/factory/GridFactory.h @@ -6,6 +6,7 @@ #include "../../floorplan/Floor.h" #include "../../floorplan/Stairs.h" +#include "../../floorplan/PlatformStair.h" #include "../../geo/Units.h" #include "../GridNodeBBox.h" @@ -57,40 +58,32 @@ public: } + /** connect all neighboring nodes part of the given index-vector */ + void connectAdjacent(const std::vector& indices) { + + for (const int idx : indices) { + + // connect the node with its neighbors + connectAdjacent(grid[idx]); + + } + + } + /** connect all neighboring nodes located on the given height-plane */ void connectAdjacent(const float z_cm) { Log::add(name, "connecting all adjacent nodes at height " + std::to_string(z_cm), false); Log::tick(); - const int gridSize_cm = grid.getGridSize_cm(); - // connect adjacent grid-points for (T& n1 : grid) { // not the floor we are looking for? -> skip (ugly.. slow(er)) if (n1.z_cm != z_cm) {continue;} - // square around each point - for (int x = -gridSize_cm; x <= gridSize_cm; x += gridSize_cm) { - for (int y = -gridSize_cm; y <= gridSize_cm; y += gridSize_cm) { - - // skip the center (node itself) - if ((x == y) && (x == 0)) {continue;} - - // position of the potential neighbor - const int ox = n1.x_cm + x; - const int oy = n1.y_cm + y; - const GridPoint p(ox, oy, n1.z_cm); - - // does the grid contain the potential neighbor? - const T* n2 = grid.getNodePtrFor(p); - if (n2 != nullptr) { - grid.connectUniDir(n1, *n2); // UNI-dir connection as EACH node is processed! - } - - } - } + // connect the node with its neighbors + connectAdjacent(n1); } @@ -98,54 +91,124 @@ public: } + /** connect the given node with its neighbors */ + void connectAdjacent(T& n1) { + + const int gridSize_cm = grid.getGridSize_cm(); + + // square around the node + for (int x = -gridSize_cm; x <= gridSize_cm; x += gridSize_cm) { + for (int y = -gridSize_cm; y <= gridSize_cm; y += gridSize_cm) { + + // skip the center (node itself) + if ((x == y) && (x == 0)) {continue;} + + // position of the potential neighbor + const int ox = n1.x_cm + x; + const int oy = n1.y_cm + y; + const GridPoint p(ox, oy, n1.z_cm); + + // does the grid contain the potential neighbor? + const T* n2 = grid.getNodePtrFor(p); + if (n2 != nullptr) { + grid.connectUniDir(n1, *n2); // UNI-dir connection as EACH node is processed! + } + + } + } + + } + + + /** shrink the given bbox to be grid-aligned */ + BBox2 shrinkAlign(const BBox2& bb) { + const float gridSize_cm = grid.getGridSize_cm(); + Point2 p1 = bb.getMin(); + Point2 p2 = bb.getMax(); + p1.x = std::ceil(p1.x/gridSize_cm)*gridSize_cm; + p1.y = std::ceil(p1.y/gridSize_cm)*gridSize_cm; + p2.x = std::floor(p2.x/gridSize_cm)*gridSize_cm; + p2.y = std::floor(p2.y/gridSize_cm)*gridSize_cm; + BBox2 res; res.add(p1); res.add(p2); return res; + } + + /** add a new platform-stair between the two given floors */ + void buildPlatformStair(const PlatformStair& s, const float z1_cm, const float z2_cm) { + + const float zCenter_cm = (z2_cm + z1_cm) / 2; + std::vector indices; + + // add the platform in the middle + BBox2 bb = shrinkAlign(s.platform); + const int gridSize_cm = grid.getGridSize_cm(); + for (int x_cm = bb.getMin().x; x_cm <= bb.getMax().x; x_cm += gridSize_cm) { + for (int y_cm = bb.getMin().y; y_cm <= bb.getMax().y; y_cm += gridSize_cm) { + int idx = grid.add(T(x_cm, y_cm, zCenter_cm)); + indices.push_back(idx); + } + } + + // connect the plattform in the middle + connectAdjacent(indices); + + // TODO: interconnect (x-y) the stair lines??? + buildStair(s.s1, z1_cm, zCenter_cm); + buildStair(s.s2, z2_cm, zCenter_cm); + + } void addStairs(const Stairs& stairs, const float z1_cm, const float z2_cm) { Log::add(name, "adding stairs between " + std::to_string(z1_cm) + " and " + std::to_string(z2_cm), false); Log::tick(); - for (const Stair& s : stairs) { - - // potential starting-point for the stair - for (T& n : grid) { - - // node lies on the stair's starting edge? - if (n.z_cm == z1_cm && grid.getBBox(n).intersects(s.start)) { - - // construct end-point by using the stair's direction - const Point3 end = Point3(n.x_cm, n.y_cm, z2_cm) + Point3(s.dir.x, s.dir.y, 0); - GridPoint gp(end.x, end.y, end.z); - - // does such and end-point exist within the grap? -> construct stair - if (grid.hasNodeFor(gp)) { - T& n2 = (T&) grid.getNodeFor(gp); - - buildStair(n, n2); - - } - - } - } - - } + for (const Stair& s : stairs) { buildStair(s, z1_cm, z2_cm); } Log::tock(); } - /** build a stair (z-transition) from n1 to n2 */ - void buildStair(T& n1, T& n2) { + void buildStair(const Stair& s, const float z1_cm, const float z2_cm) { + + // potential starting-point for the stair + for (T& n : grid) { + + // node lies on the stair's starting edge? + if (n.z_cm == z1_cm && grid.getBBox(n).intersects(s.start)) { + + // construct end-point by using the stair's direction + const Point3 end = Point3(n.x_cm, n.y_cm, z2_cm) + Point3(s.dir.x, s.dir.y, 0); + GridPoint gp(end.x, end.y, end.z); + + // does such and end-point exist within the grid? -> construct stair-line + if (grid.hasNodeFor(gp)) { + T& n2 = (T&) grid.getNodeFor(gp); + buildStairLine(n, n2); + } + + } + } + + } + + /** build a stair (z-transition) from n1 to n2 */ + void buildStairLine(T& _n1, T& _n2) { + + const int gridSize_cm = grid.getGridSize_cm(); + + // local copies, needed for std::swap to work + T n1 = _n1; T n2 = _n2; + + // ensure we work from lower to upper levels + if (n2.z_cm < n1.z_cm) { std::swap(n1, n2); } - //TODO: ensure n1 is below n2 const float zDiff = n2.z_cm - n1.z_cm; const float xDiff = n2.x_cm - n1.x_cm; const float yDiff = n2.y_cm - n1.y_cm; - int idx1 = n1.getIdx(); - int idx2 = -1; - const int idx3 = n2.getIdx(); - - const int gridSize_cm = grid.getGridSize_cm(); + int idx1 = n1.getIdx(); // starting node + int idx2 = -1; // next node + const int idx3 = n2.getIdx(); // final node // move upards in gridSize steps for (int _z = gridSize_cm; _z < zDiff; _z+= gridSize_cm) { @@ -170,9 +233,8 @@ public: } // add the last segment - if (idx2 != -1) { - grid.connectBiDir(idx2, idx3); - } + Assert::isTrue(idx2 != -1, "strange stair issue?!"); + grid.connectBiDir(idx2, idx3); } diff --git a/grid/factory/GridImportance.h b/grid/factory/GridImportance.h index 887cb0e..80551e9 100644 --- a/grid/factory/GridImportance.h +++ b/grid/factory/GridImportance.h @@ -11,7 +11,7 @@ #include "../../nav/dijkstra/Dijkstra.h" #include "../../nav/dijkstra/DijkstraPath.h" -#include +#include "../../math/Distributions.h" @@ -69,7 +69,7 @@ public: n1.imp = 1.0f; - n1.imp += getWallImportance(n1, Units::cmToM(std::sqrt(squaredDist[0])) ); + n1.imp += getWallImportance( Units::cmToM(std::sqrt(squaredDist[0])) ); //addDoor(n1, neighbors); // is the current node a door? @@ -86,7 +86,7 @@ public: // process each node again for (T& n1 : g) { - static K::NormalDistribution favorDoors(0.0, 1.0); + static Distribution::Normal favorDoors(0.0f, 1.0f); // get the distance to the nearest door const float dist_m = Units::cmToM(knnDoors.getNearestDistance( {n1.x_cm, n1.y_cm, n1.z_cm} )); @@ -141,7 +141,7 @@ public: //T& node = g[idx]; const float dist_cm = knn.getNearestDistance( {n.x_cm, n.y_cm, n.z_cm} ); const float dist_m = Units::cmToM(dist_cm); - n.impPath = 1.0 + K::NormalDistribution::getProbability(0, 1.0, dist_m) * 0.8; + n.impPath = 1.0 + Distribution::Normal::getProbability(0, 1.0, dist_m) * 0.8; } @@ -191,16 +191,16 @@ public: } /** get the importance of the given node depending on its nearest wall */ - template float getWallImportance(T& nSrc, float dist_m) { + float getWallImportance(float dist_m) { // avoid sticking too close to walls (unlikely) - static K::NormalDistribution avoidWalls(0.0, 0.4); + static Distribution::Normal avoidWalls(0.0, 0.4); // favour walking near walls (likely) - static K::NormalDistribution sticToWalls(0.9, 0.5); + static Distribution::Normal sticToWalls(0.9, 0.5); // favour walking far away (likely) - static K::NormalDistribution farAway(2.2, 0.5); + static Distribution::Normal farAway(2.2, 0.5); if (dist_m > 2.0) {dist_m = 2.0;} // overall importance diff --git a/grid/walk/GridWalkHelper.h b/grid/walk/GridWalkHelper.h index 3ae0144..26825f8 100644 --- a/grid/walk/GridWalkHelper.h +++ b/grid/walk/GridWalkHelper.h @@ -40,7 +40,7 @@ public: */ template static GridWalkState retryOrInvert(Walker& w, const int numRetries, Grid& grid, GridWalkState start, float distance_m) { - _assertTrue(distance_m >= 0, "distance must not be negative!"); + Assert::isTrue(distance_m >= 0, "distance must not be negative!"); GridWalkState res; diff --git a/grid/walk/GridWalkLightAtTheEndOfTheTunnel.h b/grid/walk/GridWalkLightAtTheEndOfTheTunnel.h index 96cbb3b..ed07181 100644 --- a/grid/walk/GridWalkLightAtTheEndOfTheTunnel.h +++ b/grid/walk/GridWalkLightAtTheEndOfTheTunnel.h @@ -5,7 +5,7 @@ #include "../Grid.h" #include "../../math/DrawList.h" -#include +#include "../../math/Distributions.h" #include "../../nav/dijkstra/Dijkstra.h" @@ -84,7 +84,7 @@ private: const float diff = cur.heading.getDiffHalfRAD(potentialHeading); // probability for this direction change? - double prob = K::NormalDistribution::getProbability(0, HEADING_DIFF_SIGMA, diff); + double prob = Distribution::Normal::getProbability(0, HEADING_DIFF_SIGMA, diff); // perfer locations reaching the target const double shortening = cur.node->distToTarget - neighbor.distToTarget; diff --git a/grid/walk/GridWalkPushForward.h b/grid/walk/GridWalkPushForward.h index 80b9ec4..42eab20 100644 --- a/grid/walk/GridWalkPushForward.h +++ b/grid/walk/GridWalkPushForward.h @@ -8,9 +8,6 @@ #include "../Grid.h" #include "../../math/DrawList.h" -#include -#include - #include "../../nav/dijkstra/Dijkstra.h" #include "GridWalkState.h" @@ -70,7 +67,7 @@ private: const float diffRad = potentialHeading.getDiffHalfRAD(cur.heading); // weight this change - const float prob1 = K::NormalDistribution::getProbability(0, HEADING_ALLOWED_SIGMA, diffRad); + const float prob1 = Distribution::Normal::getProbability(0, HEADING_ALLOWED_SIGMA, diffRad); // distance from average? and previous distance from average diff --git a/grid/walk/GridWalkRandomHeadingUpdate.h b/grid/walk/GridWalkRandomHeadingUpdate.h index 8ba30a0..6c5a3f3 100644 --- a/grid/walk/GridWalkRandomHeadingUpdate.h +++ b/grid/walk/GridWalkRandomHeadingUpdate.h @@ -4,8 +4,6 @@ #include "../../geo/Heading.h" #include "../Grid.h" -#include - #include "../../nav/dijkstra/Dijkstra.h" #include "GridWalkState.h" diff --git a/grid/walk/GridWalkRandomHeadingUpdateAdv.h b/grid/walk/GridWalkRandomHeadingUpdateAdv.h index 9baaf45..d96afa4 100644 --- a/grid/walk/GridWalkRandomHeadingUpdateAdv.h +++ b/grid/walk/GridWalkRandomHeadingUpdateAdv.h @@ -6,9 +6,7 @@ #include "../Grid.h" #include "../../math/DrawList.h" -#include -#include - +#include "../../math/Distributions.h" #include "../../nav/dijkstra/Dijkstra.h" #include "GridWalkState.h" @@ -55,11 +53,7 @@ public: private: - // https://de.wikipedia.org/wiki/Logistische_Verteilung - /** alpha = move the center, beta = slope */ - const float logisticDist(const float x, const float alpha, const float beta) { - return 1 / (1 + std::exp( -((x-alpha)/beta) ) ); - } + // NOTE: allocate >>ONCE<::getProbability(0, Angle::degToRad(40), diffRad); // add the node's importance factor into the calculation - const float prob2 = logisticDist(neighbor.imp, 1.0, 0.05); + const float prob2 = Distribution::Logistic::getCDF(neighbor.imp, 1.0, 0.05); //const float prob2 = std::pow(neighbor.imp, 10); // final importance diff --git a/grid/walk/GridWalkWeighted.h b/grid/walk/GridWalkWeighted.h index 7c12a1b..252130a 100644 --- a/grid/walk/GridWalkWeighted.h +++ b/grid/walk/GridWalkWeighted.h @@ -5,7 +5,7 @@ #include "../Grid.h" #include "../../math/DrawList.h" -#include +#include "../../math/Distributions.h" /** * perform walks on the grid based on some sort of weighting @@ -87,7 +87,7 @@ private: const float diff = cur.heading.getDiffHalfRAD(potentialHeading); // probability for this direction change? - double prob = K::NormalDistribution::getProbability(0, HEADING_DIFF_SIGMA, diff); + double prob = Distribution::Normal::getProbability(0, HEADING_DIFF_SIGMA, diff); // perfer locations reaching the target const double shortening = cur.node->distToTarget - neighbor.distToTarget; diff --git a/math/Distributions.h b/math/Distributions.h new file mode 100644 index 0000000..cb9f0ab --- /dev/null +++ b/math/Distributions.h @@ -0,0 +1,8 @@ +#ifndef DISTRIBUTIONS_H +#define DISTRIBUTIONS_H + +#include "distribution/Normal.h" +#include "distribution/Exponential.h" +#include "distribution/Logistic.h" + +#endif // DISTRIBUTIONS_H diff --git a/math/DrawList.h b/math/DrawList.h index 8b29072..a9d3b36 100644 --- a/math/DrawList.h +++ b/math/DrawList.h @@ -4,7 +4,7 @@ #include #include -#include +#include "../Assertions.h" /** * add elements of a certain probability @@ -72,7 +72,7 @@ public: const auto tmp = std::lower_bound(elements.begin(), elements.end(), rndVal); // sanity check - _assertFalse(tmp == elements.end(), "draw() did not find a valid element"); + Assert::isFalse(tmp == elements.end(), "draw() did not find a valid element"); // done return (*tmp).element; diff --git a/math/distribution/Exponential.h b/math/distribution/Exponential.h new file mode 100644 index 0000000..8af34d6 --- /dev/null +++ b/math/distribution/Exponential.h @@ -0,0 +1,4 @@ +#ifndef EXPONENTIAL_H +#define EXPONENTIAL_H + +#endif // EXPONENTIAL_H diff --git a/math/distribution/Exponential.h.autosave b/math/distribution/Exponential.h.autosave new file mode 100644 index 0000000..534f0e9 --- /dev/null +++ b/math/distribution/Exponential.h.autosave @@ -0,0 +1,54 @@ +#ifndef EXPONENTIAL_H +#define EXPONENTIAL_H + +#include +#include + +namespace Distribution { + + template class Exponential { + + private: + + T lambda; + + std::minstd_rand gen; + std::exponential_distribution dist; + + public: + + /** ctor */ + Exponential(const T lambda) : lambda(lambda), gen(1234), dist(lambda) { + ; + } + + + /** get probability for the given value */ + T getProbability(const T val) const { + return lambda * std::exp(-lambda * val); + } + + /** get a normally distributed random number */ + T draw() { + return dist(gen); + } + + /** set the seed to use */ + void setSeed(const long seed) { + gen.seed(seed); + } + + + /** get the probability for the given value */ + static double getProbability(const double lambda, const double val) { + return lambda * std::exp(-lambda * val); + } + + }; + + + }; + +} + +#endif // EXPONENTIAL_H diff --git a/math/distribution/Logistic.h b/math/distribution/Logistic.h new file mode 100644 index 0000000..957699b --- /dev/null +++ b/math/distribution/Logistic.h @@ -0,0 +1,22 @@ +#ifndef LOGISTIC_H +#define LOGISTIC_H + + +namespace Distribution { + + // https://de.wikipedia.org/wiki/Logistische_Verteilung + template class Logistic { + + public: + + /** alpha = move the center, beta = slope */ + static T getCDF(const T x, const T alpha, const T beta) { + return 1 / (1 + std::exp( -((x-alpha)/beta) ) ); + } + + + }; + +} + +#endif // LOGISTIC_H diff --git a/math/distribution/Normal.h b/math/distribution/Normal.h new file mode 100644 index 0000000..4f12a41 --- /dev/null +++ b/math/distribution/Normal.h @@ -0,0 +1,57 @@ +#ifndef NORMAL_H +#define NORMAL_H + +#include +#include + +namespace Distribution { + + /** normal distribution */ + template class Normal { + + private: + + const T mu; + const T sigma; + const T _a; + + std::minstd_rand gen; + std::normal_distribution dist; + + public: + + /** ctor */ + Normal(const T mu, const T sigma) : + mu(mu), sigma(sigma), _a(1.0 / (sigma * std::sqrt(2.0 * M_PI))), gen(1234), dist(mu,sigma) { + + } + + /** get probability for the given value */ + T getProbability(const T val) const { + const T b = -0.5 * ((val-mu)/sigma) * ((val-mu)/sigma); + return _a * std::exp(b); + } + + /** get a normally distributed random number */ + T draw() { + return dist(gen); + } + + /** set the seed to use */ + void setSeed(const long seed) { + gen.seed(seed); + } + + + /** get the probability for the given value */ + static T getProbability(const T mu, const T sigma, const T val) { + const T a = 1.0 / (sigma * std::sqrt(2.0 * M_PI)); + const T b = -0.5 * ((val-mu)/sigma) * ((val-mu)/sigma); + return a * std::exp(b); + } + + }; + +} + +#endif // NORMAL_H diff --git a/nav/dijkstra/Dijkstra.h b/nav/dijkstra/Dijkstra.h index 56fb040..9a79cc7 100644 --- a/nav/dijkstra/Dijkstra.h +++ b/nav/dijkstra/Dijkstra.h @@ -13,7 +13,7 @@ #include "../../misc/Time.h" #include "../../Defines.h" -#include +#include "../../Assertions.h" template class Dijkstra { @@ -32,6 +32,7 @@ public: // NOTE: end is currently ignored! // runs until all nodes were evaluated + (void) end; Log::add("Dijkstra", "calculating dijkstra from " + (std::string)start + " to ALL OTHER nodes", false); Log::tick(); @@ -89,7 +90,7 @@ public: // get the distance-weight to the neighbor const float weight = acc.getWeightBetween(*dnSrc->element, *dst); - _assertTrue(weight >= 0, "edge-weight must not be negative!"); + Assert::isTrue(weight >= 0, "edge-weight must not be negative!"); // update the weight to the destination? const float potentialWeight = dnSrc->cumWeight + weight; diff --git a/tests/grid/TestGrid.cpp b/tests/grid/TestGrid.cpp index c1b00d4..14c14bc 100755 --- a/tests/grid/TestGrid.cpp +++ b/tests/grid/TestGrid.cpp @@ -176,7 +176,7 @@ TEST(Grid, neighborIter) { grid.connectBiDir(idx1, idx5); int i = 0; - for (GP& node : grid.neighbors(idx1)) {++i;} + for (GP& node : grid.neighbors(idx1)) { (void) node; ++i; } ASSERT_EQ(4, i); } diff --git a/tests/grid/TestWalk.cpp b/tests/grid/TestWalk.cpp index 31d372c..8670d63 100644 --- a/tests/grid/TestWalk.cpp +++ b/tests/grid/TestWalk.cpp @@ -12,7 +12,8 @@ #include "../../grid/walk/GridWalkWeighted.h" #include "../../grid/walk/GridWalkLightAtTheEndOfTheTunnel.h" -TEST(Walk, DISABLED_plot) { +TEST(Walk, plot) { +//TEST(Walk, DISABLED_plot) { Grid g(20); GridFactory gf(g); @@ -25,12 +26,24 @@ TEST(Walk, DISABLED_plot) { Floor f2 = fpf.getFloor("2"); Stairs s1_2 = fpf.getStairs("1_2"); + + // build the grid gf.addFloor(f1, 20); if (use3D) { gf.addFloor(f2, 340); gf.addStairs(s1_2, 20, 340); } + + + + //TODO: write as something simpler? e.g. as box with rotation?? + PlatformStair pStair; + pStair.platform = BBox2(Point2(200, 200), Point2(400,500)); + pStair.s1 = Stair(Line2( 600,200, 600,350 ), Point2(-200,0)); + pStair.s2 = Stair(Line2( 600,400, 600,500 ), Point2(-250,0)); + //gf.buildPlatformStair(pStair, 20, 340); + gf.removeIsolated(); // calculate node importance based on the floorplan (walls, ...) @@ -95,7 +108,10 @@ TEST(Walk, DISABLED_plot) { } Plot p; + + // show the grid //p.build(g); + p.addFloor(f1, 20); if (use3D) { p.addFloor(f2, 340);