#ifndef MYSMOOTHINGTRANSITION_H #define MYSMOOTHINGTRANSITION_H #include #include #include #include #include #include #include #include "../MyState.h" #include "../MyControl.h" #include "../../DijkstraMapper.h" #include "../../toni/barometric.h" #include #include static double smoothing_walk_mu = 0.7; static double smoothing_walk_sigma = 0.5; static double smoothing_heading_sigma = 15.0; static double smoothing_baro_sigma = 0.2; typedef std::pair my_key_type; class MySmoothingTransition : public K::BackwardFilterTransition { private: /** the created grid to draw transitions from */ Grid* grid; /** a simple normal distribution */ K::NormalDistribution distWalk; public: /** * ctor * @param choice the choice to use for randomly drawing nodes * @param fp the underlying floorplan */ MySmoothingTransition(Grid* grid) : grid(grid), distWalk(smoothing_walk_mu, smoothing_walk_sigma) { distWalk.setSeed(4321); } public: uint64_t ts = 0; uint64_t deltaMS = 0; /** set the current time in millisconds */ void setCurrentTime(const uint64_t ts) { if (this->ts == 0) { this->ts = ts; deltaMS = 0; } else { deltaMS = this->ts - ts; this->ts = ts; } } /** * smoothing transition starting at T with t, t-1,...0 * @param particles_new p_t (Forward Filter) * @param particles_old p_t+1 (Smoothed Particles from Step before) */ std::vector> transition(std::vector>const& particles_new, std::vector>const& particles_old ) override { // calculate alpha(m,n) = p(q_t+1(m) | q_t(n)) // this means, predict all possible states q_t+1 with all passible states q_t // e.g. p(q_490(1)|q_489(1));p(q_490(1)|q_489(2)) ... p(q_490(1)|q_489(N)) and // p(q_490(1)|q_489(1)); p(q_490(2)|q_489(1)) ... p(q_490(M)|q_489(1)) std::vector> predictionProbabilities; std::map shortestPathMap; AStar aStar; DijkstraMapper dm(*grid); omp_set_dynamic(0); // Explicitly disable dynamic teams omp_set_num_threads(7); #pragma omp parallel for shared(predictionProbabilities) for (int i = 0; i < particles_old.size(); ++i) { std::vector innerVector; auto p1 = &particles_old[i]; const MyGridNode* dst = grid->getNodePtrFor(GridPoint(p1->state.pCur.x, p1->state.pCur.y, p1->state.pCur.z)); for(int j = 0; j < particles_new.size(); ++j){ auto p2 = &particles_new[j]; const MyGridNode* src = grid->getNodePtrFor(GridPoint(p2->state.pCur.x, p2->state.pCur.y, p2->state.pCur.z)); double distDijkstra_m = 0; // check if this shortestPath was already calculated std::map::iterator it; it = shortestPathMap.find(my_key_type(dst, src)); if(it != shortestPathMap.end()){ distDijkstra_m = it->second; } else{ distDijkstra_m = aStar.get(src, dst, dm); if(distDijkstra_m != distDijkstra_m) {throw "detected NaN";} //save distance and nodes in lookup map #pragma omp critical shortestPathMap.insert(std::make_pair(my_key_type(dst, src), distDijkstra_m)); } const double distProb = distWalk.getProbability(distDijkstra_m * 0.01); //heading change prob double diffRad = Angle::getDiffRAD_2PI_PI(p2->state.walkState.heading.getRAD(), p1->state.walkState.heading.getRAD()); double diffDeg = Angle::radToDeg(diffRad); double angularChangeZeroToPi = std::fmod(std::abs(p1->state.angularHeadingChange), 360.0); const double headingProb = K::NormalDistribution::getProbability(angularChangeZeroToPi, smoothing_heading_sigma, diffDeg); //check how near we are to the measurement double floorProb = K::NormalDistribution::getProbability(p1->state.measurement_pressure, smoothing_baro_sigma, p2->state.hPa); //combine the probabilities double prob = distProb * floorProb * headingProb; innerVector.push_back(prob); //if(distance_m != distance_m) {throw "detected NaN";} //if(distProb != distProb) {throw "detected NaN";} //if(angle != angle) {throw "detected NaN";} //if(headingProb != headingProb) {throw "detected NaN";} //if(floorProb != floorProb) {throw "detected NaN";} //if(floorProb == 0) {throw "detected NaN";} //if(prob != prob) {throw "detected NaN";} //assert(prob != 0.0); } #pragma omp critical predictionProbabilities.push_back(innerVector); } return predictionProbabilities; } }; #endif // MYTRANSITION_H