#ifndef FILTER_H #define FILTER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "State.h" #include "Node.h" #include "../Settings.h" class PFInit : public K::ParticleFilterInitializer { private: Grid* grid; public: PFInit(Grid* grid) : grid(grid) { } virtual void initialize(std::vector>& particles) override { std::minstd_rand gen; std::uniform_int_distribution distIdx(0, grid->getNumNodes()-1); std::uniform_real_distribution distHead(0, 2*M_PI); for (K::Particle& p : particles) { const int idx = distIdx(gen); const MyGridNode& node = (*grid)[idx]; p.state.position = node; // random position p.state.heading.direction = Heading(distHead(gen)); // random heading } // // fix position + heading // for (K::Particle& p : particles) { // const int idx = 9000; // const MyGridNode& node = (*grid)[idx]; // p.state.position = node; // p.state.heading.direction = Heading(0); // } } }; class PFTrans : public K::ParticleFilterTransition { public: Grid* grid; GridWalker walker; WalkModuleFavorZ modFavorZ; WalkModuleHeadingControl modHeading; WalkModuleNodeImportance modImportance; WalkModuleButterActivity modBarometer; WalkModuleFollowDestination modDestination; std::minstd_rand gen; public: PFTrans(Grid* grid, MyControl* ctrl) : grid(grid), modHeading(ctrl, Settings::turnSigma), modDestination(*grid) { walker.addModule(&modFavorZ); walker.addModule(&modHeading); walker.addModule(&modImportance); walker.addModule(&modBarometer); walker.addModule(&modDestination); if (Settings::destination != GridPoint(0,0,0)) { modDestination.setDestination(grid->getNodeFor(Settings::destination)); } } void transition(std::vector>& particles, const MyControl* control) override { std::normal_distribution noise(0, Settings::stepSigma); for (K::Particle& p : particles) { const float dist_m = std::abs(control->numStepsSinceLastTransition * Settings::stepLength + noise(gen)); p.state = walker.getDestination(*grid, p.state, dist_m); } ((MyControl*)control)->resetAfterTransition(); } }; class PFEval : public K::ParticleFilterEvaluation { WiFiModelLogDistCeiling& wifiModel; WiFiObserverFree wiFiProbability; public: PFEval(WiFiModelLogDistCeiling& wifiModel) : wifiModel(wifiModel), wiFiProbability(Settings::wifiSigma, wifiModel) { } double evaluation(std::vector>& particles, const MyObservation& _observation) override { double sum = 0; // smartphone is 1.3 meter above ground const Point3 person(0,0,Settings::smartphoneAboveGround); // local copy!! observation might be changed async outside!! (will really produces crashes!) const MyObservation observation = _observation; for (K::Particle& p : particles) { const double pWiFi = wiFiProbability.getProbability(p.state.position.inMeter()+person, observation.currentTime, observation.wifi); const double pGPS = 1; const double prob = pWiFi * pGPS; p.weight = prob; sum += prob; } return sum; } }; #endif // FILTER_H