#ifndef WALKMODULEFOLLOWDESTINATION_H #define WALKMODULEFOLLOWDESTINATION_H #include "WalkModule.h" #include "WalkStateHeading.h" #include "../../../../nav/dijkstra/Dijkstra.h" #include "../../../../nav/dijkstra/DijkstraPath.h" #include "../../../../math/Distributions.h" #include "../../../../Assertions.h" /** * favor nodes that approach a known destination */ template class WalkModuleFollowDestination : public WalkModule { private: const Grid& grid; Dijkstra dijkstra; const DijkstraNode* dnDest; struct DijkstraAccess { const Grid& grid; DijkstraAccess(const Grid& grid) : grid(grid) {;} int getNumNeighbors(const Node& n) const {return n.getNumNeighbors();} const Node* getNeighbor(const Node& n, const int idx) const {return &grid.getNeighbor(n, idx);} float getWeightBetween(const Node& n1, const Node& n2) const { return n1.getDistanceInMeter(n2) / n2.getNavImportance(); } }; public: /** ctor WITHOUT known destination*/ WalkModuleFollowDestination(const Grid& grid) : grid(grid) { // ensure the template WalkState inherits from 'WalkStateFavorZ' //StaticAssert::AinheritsB(); } /** ctor WITH known destination*/ WalkModuleFollowDestination(const Grid& grid, const Node& destination) : grid(grid) { setDestination(destination); } /** set the desired destination node */ void setDestination(const Node& dest) { DijkstraAccess acc(grid); dijkstra.build(&dest, acc); dnDest = dijkstra.getNode(dest); } /** get the shortest path from the given start to the configured destination */ DijkstraPath getShortestPath(const Node& start) { const DijkstraNode* dnStart = dijkstra.getNode(start); const DijkstraPath path(dnStart, dnDest); return path; } virtual void updateBefore(WalkState& state, const Node& startNode) override { (void) state; (void) startNode; } 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; const DijkstraNode* dnCur = dijkstra.getNode(curNode); const DijkstraNode* dnPot = dijkstra.getNode(potentialNode); if (dnCur == nullptr) {return 1.0;} if (dnPot == nullptr) {return 1.0;} constexpr double kappa = 0.70; const float curDistToTarget = dnCur->cumWeight; const float potDistToTarget = dnPot->cumWeight; return (potDistToTarget < curDistToTarget) ? (kappa) : (1.0-kappa); } }; #endif // WALKMODULEFOLLOWDESTINATION_H