#ifndef MYSMOOTHINGTRANSITIONSIMPLE_H #define MYSMOOTHINGTRANSITIONSIMPLE_H #include #include #include #include #include #include "../MyState.h" #include "../MyControl.h" #include "../../Helper.h" #include "../../toni/barometric.h" class MySmoothingTransitionSimple : public K::BackwardFilterTransition { private: /** a simple normal distribution */ K::NormalDistribution distWalk; public: /** * ctor * @param choice the choice to use for randomly drawing nodes * @param fp the underlying floorplan */ MySmoothingTransitionSimple() : 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; omp_set_dynamic(0); // Explicitly disable dynamic teams omp_set_num_threads(6); #pragma omp parallel for shared(predictionProbabilities) for (int i = 0; i < particles_old.size(); ++i) { std::vector innerVector; auto p1 = &particles_old[i]; for(int j = 0; j < particles_new.size(); ++j){ auto p2 = &particles_new[j]; //distance can be pretty big here const double distance_m = p2->state.pCur.getDistance(p1->state.pCur) / 100.0; //get distance walked and getProb using the walking model const double distProb = distWalk.getProbability(distance_m); //get proba for heading change 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 * headingProb * floorProb; innerVector.push_back(prob); //error checks if(distance_m != distance_m) {throw "detected NaN";} if(distProb != distProb) {throw "detected NaN";} if(headingProb != headingProb) {throw "detected NaN";} if(floorProb != floorProb) {throw "detected NaN";} if(floorProb == 0) {throw "detected zero prob in floorprob";} if(prob != prob) {throw "detected NaN";} //if(prob == 0) {throw "detected zero prob in smoothing transition";} } #pragma omp critical predictionProbabilities.push_back(innerVector); } return predictionProbabilities; } }; #endif // MYTRANSITIONSIMPLE_H