This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/smc/merging/mixing/MixingSamplerDivergency.h
mail@toni-fetzer.de 8d37e94647 added stuff for bluetooth
worked on resampling methods
2019-06-05 18:09:15 +02:00

158 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef MIXINGSAMPLERDIVERGENCY_H
#define MIXINGSAMPLERDIVERGENCY_H
#include "MixingSampler.h"
#include <algorithm>
#include <random>
#include <eigen3/Eigen/Dense>
namespace SMC {
/**
* Using the direct sampling approach of Driessen and Boers in
* "Efficient particle filter for jump Markov nonlinear systems".
* as transition probability matrix for the markov chain we use
* a divergence based on JensenShannon divergence
*/
template <typename State, typename Control, typename Observation> class MixingSamplerDivergency
: public MixingSampler<State, Control, Observation> {
/** random number generator */
std::minstd_rand genNorm;
std::minstd_rand genPart;
/** copy of the modes with cumulative probabilities for easy drawing*/
std::vector<ParticleFilterMixing<State, Control, Observation>> copyModes;
public:
void mixAndSample(std::vector<ParticleFilterMixing<State, Control, Observation>>& modes, Eigen::MatrixXd transitionProbabilityMatrix) override{
genNorm.seed(std::chrono::system_clock::now().time_since_epoch().count());
genPart.seed(std::chrono::system_clock::now().time_since_epoch().count() + 233);
// set copyModes for later drawing
copyModes = modes;
// create cumulative particlesets for the copy
// Note: in most cases, the particles are already resampled within the filtering stage
// but in some cases they are not and therefore we need to draw cumulatively and not equally
for(ParticleFilterMixing<State, Control, Observation>& copyFilter : copyModes){
double cumWeight = 0;
std::vector<Particle<State>> copyParticles;
copyParticles = copyFilter.getParticles();
for(int i = 0; i < copyParticles.size(); ++i){
cumWeight += copyParticles[i].weight;
copyParticles[i].weight = cumWeight;
}
copyFilter.setParticles(copyParticles);
}
// calculate the new predicted mode prob P(m_t|Z_t-1) and P(m_t-1 | m_t, Z_t-1)
int m = 0; //this is m_t
for(ParticleFilterMixing<State, Control, Observation>& focusedFilter : modes){
// P(m_t|Z_t-1) = sum(P(m_t | m_t-1) P(m_t-1 | Z_t-1))
int i = 0; //this are all possible m_t-1
double predictedModeProbability = 0;
for(ParticleFilterMixing<State, Control, Observation>& filter : modes){
predictedModeProbability += transitionProbabilityMatrix(m,i) * filter.getModePosteriorProbability();
++i;
}
//Assert::isNotNull(predictedModeProbability, "predictedModeProbability is zero.. thats not possible!");
focusedFilter.setPredictedModeProbability(predictedModeProbability);
// cumulative sum of TransitionModeProbabilities for drawing modes from the perspective of ONE filter!
// this means, the transition mode probabilities are calculated for each filter NEW!
// calculate P(m_t-1 | m_t, Z_t-1) = P(m_t | m_t-1) * p(m_t-1 | Z_t-1) / P(m_t|Z_t-1)
double cumTransitionModeProbability = 0;
i = 0;
for(ParticleFilterMixing<State, Control, Observation>& filter : modes){
double prob = (transitionProbabilityMatrix(m,i) * filter.getModePosteriorProbability()) / focusedFilter.getPredictedModeProbability();
filter.setTransitionModeProbability(prob);
cumTransitionModeProbability += prob;
copyModes[i].setTransitionModeProbability(cumTransitionModeProbability);
//std::cout << "Draw Mode Probability from mode " << m << i << " : " << prob << std::endl;
++i;
}
// draw new modes and particles
// Note: in most cases, the particles are already resampled within the filtering stage
// but in some cases they are not and therefore we need to draw cumulatively and not equally
// todo: make the particle size dynamic depending on the kld or something else
// number of particles for this timestep
int numParticles = focusedFilter.getParticles().size();
std::vector<Particle<State>> newParticles;
newParticles.resize(numParticles);
double equalWeight = 1.0 / numParticles;
// draw modes cumulative
for(int k = 0; k < numParticles; ++k){
auto mode = drawMode(cumTransitionModeProbability);
newParticles[k] = drawParticle(mode);
newParticles[k].weight = equalWeight; //todo: why equal weight? i guess if the different filters have different representations of probability?
}
focusedFilter.setParticles(newParticles);
//iter
++m;
}
}
private:
/** draw a mode depending upon the transition mode probabilities */
ParticleFilterMixing<State, Control, Observation>& drawMode(const double cumTransitionModeProbabilities){
// generate random values between [0:cumWeight]
std::uniform_real_distribution<float> dist(0, cumTransitionModeProbabilities);
// draw a random value between [0:cumWeight]
const float rand = dist(genNorm);
// search comparator (cumWeight is ordered -> use binary search)
auto comp = [] (ParticleFilterMixing<State, Control, Observation>& filter, const float d) {return filter.getTransitionModeProbability() < d;};
auto it = std::lower_bound(copyModes.begin(), copyModes.end(), rand, comp);
return *it;
}
/** draw one particle according to its weight from the copy vector of a given mode */
const Particle<State>& drawParticle(ParticleFilterMixing<State, Control, Observation>& filter) {
//double weights = filter.getParticles().back().weight;
// generate random values between [0:cumWeight]
std::uniform_real_distribution<float> dist(0, filter.getParticles().back().weight);
// draw a random value between [0:cumWeight]
const float rand = dist(genPart);
// search comparator (cumWeight is ordered -> use binary search)
auto comp = [] (const Particle<State>& s, const float d) {return s.weight < d;};
auto it = std::lower_bound(filter.getParticles().begin(), filter.getParticles().end(), rand, comp);
return *it;
}
};
}
#endif // MIXINGSAMPLERDIVERGENCY_H