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:

  1. Preprocessing - before the prediction step, it may be useful to preprocess the belief, for example resampling if there are not enough distinct particles
  2. Prediction (or propagation) - each state particle is simulated forward one step in time
  3. Reweighting - an explicit measurement (observation) model is used to calculate a new weight
  4. 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)
end
Note

In 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.BasicParticleFilterType
BasicParticleFilter(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 AbstractVector of 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 AbstractVector of 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 AbstractParticleBelief representing distribution d.
source