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)
end
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.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 signaturepreprocess(b::AbstractParticleBelief, a, o, rng)
, and should return a new belief. The returned belief may be the same asb
(i.e. modified in place), or a new object.predict::Function
: Function to propagate the particles forward in time. The function should have the signaturepredict(b::AbstractParticleBelief, a, o, rng)
, and should return anAbstractVector
of particles.reweight::Function
: Function to reweight the particles based on the observation. The function should have the signaturereweight(b::AbstractParticleBelief, a, particles, o)
, and should return anAbstractVector
of weights.postprocess::Function
: Function to postprocess the belief after the update. The function should have the signaturepostprocess(bp::WeightedParticleBelief, a, o, b, bb, rng)
, and should return a new belief. The returned belief may be the same asbp
(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 signatureinitialize(d, rng)
, and should return a newAbstractParticleBelief
representing distributiond
.