Basic Particle Filter
The BasicParticleFilter type is a flexible structure for building a particle filter. It simply contains functions that carry out each of the steps of a particle filter belief update.
The basic particle filtering step in ParticleFilters.jl is implemented in the update function, and consists of four steps:
- Preprocessing - before the prediction step, it may be useful to preprocess the belief, for example resampling if there are not enough distinct particles
- Prediction (or propagation) - each state particle is simulated forward one step in time
- Reweighting - an explicit measurement (observation) model is used to calculate a new weight
- Postprocessing - after the reweighting step, it may be useful to postprocess the belief, for example detecting particle degeneracy and sampling new particles that are consistent with the observation
In code, the update is written:
function update(up::BasicParticleFilter, b::AbstractParticleBelief, a, o)
    bb = up.preprocess(b, a, o, up.rng)
    particles = up.predict(bb, a, o, up.rng)
    weights = up.reweight(bb, a, particles, o)
    bp = WeightedParticleBelief(particles, weights)
    return up.postprocess(bp, a, o, b, bb, up.rng)
endIn the future, the steps in an update may change (for instance, the prediction and reweighting steps may be combined into a single function). However, we will maintain compatibility constructors so that code written for this 4-step process will continue to work.
A BasicParticleFilter is constructed by passing functions that implement each of the four steps. For example, a simple filter that adds Gaussian noise to each particle and reweights based on a Gaussian observation model is implemented in the following block. Note that there are no pre- or post-processing steps in this example.
using ParticleFilters, Distributions
preprocess(b, args...) = b
predict(b, a, o, rng) = particles(b) .+ a .+ randn(rng, n_particles(b))
reweight(b, a, particles, o) = weights(b) .* [pdf(Normal(p, 1.0), o) for p in particles]
postprocess(bp, args...) = bp
pf = BasicParticleFilter(preprocess, predict, reweight, postprocess)This filter can be used for an update as follows:
b = ParticleCollection([1.0, 2.0, 3.0])
a = 1.0
o = 2.0
bp = update(pf, b, a, o)In order to give access to additional information such as static dynamics parameters, consider using a callable object. For additional examples, and to re-use elements from the BootstrapFilter, see the BootstrapFilter source code.
Some building blocks for constructing a BasicParticleFilter are provided in the ParticleFilters module. For example, the BasicPredictor, BasicReweighter, POMDPPredictor, and POMDPReweighter are not exported, but can be used to construct the predict and reweight functions for a BasicParticleFilter. The check_particle_belief function can be used as a postprocessing step, and PostprocessChain can be used to chain multiple postprocessing steps together. A function (b, a, o, up.rng) -> ParticleCollection(low_variance_sample(b, 100, up.rng)) or NormalizedESSConditionalResampler can be used as a preprocessing step.
Reference
ParticleFilters.BasicParticleFilter — TypeBasicParticleFilter(preprocess, predict, reweight, postprocess; [rng], [initialize])Create a basic particle filter. See the Basic Particle Filter section of the ParticleFilters.jl documentation for more explanation.
Arguments
In the functions below, b is the belief at the beginning of the update, a is the action, and o is the observation. When present, particles is an AbstractVector of propagated particles, bp is the new belief after the prediciton and reweighting steps, and bb is the belief after the preprocessing step.
- preprocess::Function: Function to preprocess the belief before the prediction step. The function should have the signature- preprocess(b::AbstractParticleBelief, a, o, rng), and should return a new belief. The returned belief may be the same as- b(i.e. modified in place), or a new object.
- predict::Function: Function to propagate the particles forward in time. The function should have the signature- predict(b::AbstractParticleBelief, a, o, rng), and should return an- AbstractVectorof particles.
- reweight::Function: Function to reweight the particles based on the observation. The function should have the signature- reweight(b::AbstractParticleBelief, a, particles, o), and should return an- AbstractVectorof weights.
- postprocess::Function: Function to postprocess the belief after the update. The function should have the signature- postprocess(bp::WeightedParticleBelief, a, o, b, bb, rng), and should return a new belief. The returned belief may be the same as- bp(i.e. modified in place), or a new object.
Keyword Arguments
- rng::AbstractRNG=Random.default_rng(): Random number generator.
- initialize::Function=(d, rng)->d: Function to initialize the belief by creating a particle belief from a distribution. This can be safely ignored in many applications, but is important in POMDPs.jl. The function should have the signature- initialize(d, rng), and should return a new- AbstractParticleBeliefrepresenting distribution- d.