#ifndef KLB_H #define KLB_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include "Structs.h" #include "../Plotti.h" #include "Logic.h" #include "../Settings.h" double __KLD = 0.0; //todo function return the transition prob matrix for markov chain! //getKernelDensityProbability should work fine for first shot! nevertheless we need to do 2 kernel density estimations for both filters :( :( :( struct ModeProbabilityTransition : public K::MarkovTransitionProbability{ Grid& grid; const double lambda; ModeProbabilityTransition(Grid& grid, double lambda) : grid(grid), lambda(lambda) {;} virtual Eigen::MatrixXd update(std::vector>& modes) override { std::vector probsWifiV; std::vector probsParticleV; // mode[0] -> Posterior & mode[1] -> Wifi ---- i know what im doing :) for(MyNode node : grid.getNodes()){ double probParzenPosterior = calcKernelDensity(node, modes[0].getParticles()); probsParticleV.push_back(probParzenPosterior); double probParzenWifi = calcKernelDensity(node, modes[1].getParticles()); probsWifiV.push_back(probParzenWifi); } // make vectors Eigen::Map probsWifi(&probsWifiV[0], probsWifiV.size()); Eigen::Map probsParticle(&probsParticleV[0], probsParticleV.size()); // get kld double kld = Divergence::KullbackLeibler::getGeneralFromSamples(probsParticle, probsWifi, Divergence::LOGMODE::NATURALIS); // debugging global variable __KLD = kld; //exp. distribution double expKld = std::exp(-lambda * kld); //create the matrix Eigen::MatrixXd m(2,2); m << 1-expKld, expKld, 0, 1; return m; } double calcKernelDensity(const MyNode node, const std::vector> particles){ int size = particles.size(); double prob = 0; #pragma omp parallel for reduction(+:prob) num_threads(6) for(int i = 0; i < size; ++i){ double distance = particles[i].state.position.getDistanceInCM(node); prob += Distribution::Normal::getProbability(0, 100, distance) * particles[i].weight; } return prob; } }; struct ModeProbabilityTransitionNormal : public K::MarkovTransitionProbability{ const double lambda; //this is a hack! it is possible that the sigma of z is getting 0 and therefore the rank decreases to 2 and //no inverse matrix is possible Distribution::Uniform uniRand = Distribution::Uniform(-0.1, 0.1); /** ctor */ ModeProbabilityTransitionNormal(double lambda) : lambda(lambda) {;} virtual Eigen::MatrixXd update(std::vector>& modes) override { Assert::equal(modes[0].getParticles().size(), modes[1].getParticles().size(), "Particle.size() differs!"); // create eigen matrix for posterior and wifi Eigen::MatrixXd mParticle(modes[0].getParticles().size(), 3); Eigen::MatrixXd mWifi(modes[1].getParticles().size(), 3); #pragma omp parallel for num_threads(6) for(int i = 0; i < modes[0].getParticles().size(); ++i){ mParticle(i,0) = (modes[0].getParticles()[i].state.position.x_cm / 100.0) + uniRand.draw(); mParticle(i,1) = (modes[0].getParticles()[i].state.position.y_cm / 100.0) + uniRand.draw(); mParticle(i,2) = (modes[0].getParticles()[i].state.position.z_cm / 100.0) + uniRand.draw(); mWifi(i,0) = (modes[1].getParticles()[i].state.position.x_cm / 100.0) + uniRand.draw(); mWifi(i,1) = (modes[1].getParticles()[i].state.position.y_cm / 100.0) + uniRand.draw(); mWifi(i,2) = (modes[1].getParticles()[i].state.position.z_cm / 100.0) + uniRand.draw(); } // create normal distributions Eigen::VectorXd meanParticle(3); Point3 estParticle = modes[0].getEstimation().position.inMeter(); meanParticle << estParticle.x, estParticle.y, estParticle.z; Distribution::NormalDistributionN normParticle = Distribution::NormalDistributionN::getNormalNFromSamplesAndMean(mParticle, meanParticle); Eigen::VectorXd meanWifi(3); Point3 estWifi = modes[1].getEstimation().position.inMeter(); meanWifi << estWifi.x, estWifi.y, estWifi.z; Distribution::NormalDistributionN normWifi = Distribution::NormalDistributionN::getNormalNFromSamplesAndMean(mWifi, meanWifi); // get kld double kld = Divergence::KullbackLeibler::getMultivariateGauss(normParticle, normWifi); if(kld > 20){ std::cout << "STTTTTOOOOOOP" << std::endl; } // debugging global variable __KLD = kld; //exp. distribution double expKld = std::exp(-lambda * kld); Assert::isTrue(expKld < 1.0, "exp. distribution greater 1!"); //create the matrix Eigen::MatrixXd m(2,2); m << expKld, 1- expKld, 0, 1; return m; } }; #endif // KLB_H