Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
GaussianFilters = "08d575fb-911d-541e-8431-6cfa767e7851"

[sources]
GaussianFilters = {path = ".."}
5 changes: 4 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using Documenter, GaussianFilters
# This function builds the documentation
makedocs(
modules = [GaussianFilters],
format = :html,
format = Documenter.HTML(),
sitename = "GaussianFilters",
pages = ["Introduction" => [
"Basics" => "index.md",
Expand All @@ -12,6 +12,9 @@ makedocs(
"User Documentation" => [
"Kalman-class Filters" => "kalman.md",
"GM-PHD Filter" => "gmphd.md"
],
"Integrations" => [
"POMDPs.jl" => "pomdps.md"
]
])

Expand Down
21 changes: 14 additions & 7 deletions docs/src/gmphd.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@ GaussianFilters.PHDFilter
Currently, the GM-PHD Filter must be run step-by-step. Similar to the Kalman-Class filters, this can be done with a single call to `update`, which wraps functions to `predict` the next state, perform a measurement update with `measure`, and `prune` the resulting mixture model of low-probability and sufficiently close mixtures.

```@docs
GaussianFilters.update
GaussianFilters.predict
GaussianFilters.measure
update(::PHDFilter, ::GaussianMixture, ::Vector{<:AbstractVector{<:Number}}, ::Real, ::Real, ::Integer)
predict(::PHDFilter, ::GaussianMixture)
measure(::PHDFilter, ::GaussianMixture, ::Vector{<:AbstractVector{<:Real}})
GaussianFilters.prune
```

The GM-PHD update internally evaluates a multivariate normal density:

```@docs
GaussianFilters.MvNormalPDF
```

Target locations can be extracted from a `GaussianMixture` state using `multiple_target_state_extraction`.

```@docs
Expand All @@ -44,8 +51,8 @@ GaussianFilters.multiple_target_state_extraction

## Examples

Full implementation examples can be found in the `notebooks` folder of the repo:

[GM-PHD Object Surveillance Example](https://github.com/sisl/GaussianFilters.jl/blob/master/notebooks/GMPHD_SurveillanceExample.ipynb)
Full implementation examples can be found in the [`examples/`](https://github.com/sisl/GaussianFilters.jl/tree/master/examples) directory of the repo:

[GM-PHD Aircraft Carrier Example](https://github.com/sisl/GaussianFilters.jl/blob/master/notebooks/GMPHD_AircraftCarrierExample.ipynb)
- [`gmphd_surveillance.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/gmphd_surveillance.jl) — Object Surveillance
- [`gmphd_aircraft_carrier.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/gmphd_aircraft_carrier.jl) — Aircraft Carrier scenario
- [`gmphd_tests.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/gmphd_tests.jl) — Visualization helpers
43 changes: 29 additions & 14 deletions docs/src/kalman.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The Kalman, Extended Kalman, and Unscented Kalman filters are used to estimate s

```@docs
GaussianFilters.GaussianBelief
GaussianFilters.AbstractFilter
```

## Building a Filter
Expand All @@ -17,6 +18,8 @@ In general, Kalman-class filters can be built with either linear or non-linear d
NOTE: There is no need to define Jacobians for non-linear models, since this package uses automatic forward differentiation to compute Jacobians in real time. Just make sure the models are forward differentiable in all possible belief locations.

```@docs
GaussianFilters.DynamicsModel
GaussianFilters.ObservationModel
GaussianFilters.LinearDynamicsModel
GaussianFilters.LinearObservationModel
GaussianFilters.NonlinearDynamicsModel
Expand All @@ -31,6 +34,13 @@ GaussianFilters.ExtendedKalmanFilter
GaussianFilters.UnscentedKalmanFilter
```

The UKF additionally exposes the sigma-point machinery used internally:

```@docs
GaussianFilters.unscented_transform
GaussianFilters.unscented_transform_inverse
```


## Simulating Data

Expand All @@ -43,11 +53,11 @@ GaussianFilters.simulate_step

In addition, the dynamics and observation models can be queried on a single state control input using the `predict` and `measure` methods respectively.

```@docs
predict(::LinearDynamicsModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
predict(::NonlinearDynamicsModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
measure(::LinearObservationModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
measure(::NonlinearObservationModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
```@docs
predict(::LinearDynamicsModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
predict(::NonlinearDynamicsModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
measure(::LinearObservationModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
measure(::NonlinearObservationModel, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
```

## Running a Filter
Expand All @@ -61,9 +71,13 @@ GaussianFilters.run_filter
Alternatively, you can make step-wise belief updates using the `update` function, which consists of a two-step process to a) `predict` the next state given a known action and b) make measurement-based belief updates with `measure`.

```@docs
GaussianFilters.update
GaussianFilters.predict
GaussianFilters.measure
update(::AbstractFilter, ::GaussianBelief, ::AbstractVector{<:Number}, ::AbstractVector{<:Number})
predict(::KalmanFilter, ::GaussianBelief, ::AbstractVector{<:Number})
predict(::ExtendedKalmanFilter, ::GaussianBelief, ::AbstractVector{<:Number})
predict(::UnscentedKalmanFilter, ::GaussianBelief, ::AbstractVector{<:Number})
measure(::KalmanFilter, ::GaussianBelief, ::AbstractVector{<:Number})
measure(::ExtendedKalmanFilter, ::GaussianBelief, ::AbstractVector{a}) where a<:Number
measure(::UnscentedKalmanFilter, ::GaussianBelief, ::AbstractVector{<:Number})
```


Expand All @@ -81,12 +95,13 @@ GaussianFilters.unpack
GaussianFilters.belief_ellipse
```

## Examples

Full implementation examples can be found in the `notebooks` folder of the repo:
For interoperability with the POMDPs.jl belief-updater interface, see the
[POMDPs.jl Integration](pomdps.md) page.

[Kalman Filter Example](https://github.com/sisl/GaussianFilters.jl/blob/master/notebooks/KF_2DMotionExample.ipynb)
## Examples

[Extended Kalman Filter Example](https://github.com/sisl/GaussianFilters.jl/blob/master/notebooks/EKF_SpinningSatelliteExample.ipynb)
Full implementation examples can be found in the [`examples/`](https://github.com/sisl/GaussianFilters.jl/tree/master/examples) directory of the repo:

[Unscented Kalman Filter Example](https://github.com/sisl/GaussianFilters.jl/blob/master/notebooks/UKF_NonholonomicRobot.ipynb)
- [`kf_2d_motion.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/kf_2d_motion.jl) — Kalman Filter
- [`ekf_spinning_satellite.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/ekf_spinning_satellite.jl) — Extended Kalman Filter
- [`ukf_nonholonomic_robot.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/ukf_nonholonomic_robot.jl) — Unscented Kalman Filter
83 changes: 83 additions & 0 deletions docs/src/pomdps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# POMDPs.jl Integration

```@meta
CurrentModule = GaussianFilters
```

GaussianFilters ships with a [POMDPs.jl](https://github.com/JuliaPOMDP/POMDPs.jl)
package extension that activates automatically when both packages are loaded.
The extension wires `AbstractFilter` into the POMDPs belief-updater interface
so that a Kalman, Extended Kalman, or Unscented Kalman filter can be used
directly as a `POMDPs.Updater` — including with simulators such as
`HistoryRecorder` and policy/planner code that expects the standard POMDPs
interface.

## Quick start

```julia
using GaussianFilters
using POMDPs
using POMDPTools

# 1. Build a filter as usual
dmodel = NonlinearDynamicsModel(f, W)
omodel = NonlinearObservationModel(h, V)
ekf = ExtendedKalmanFilter(dmodel, omodel)

# 2. Wrap it as a POMDPs.Updater
updater = pomdps_updater(ekf)

# 3. Pass it to any POMDPs.jl simulator
hist = simulate(HistoryRecorder(max_steps=60), pomdp, policy, updater)
```

The wrapper is needed because POMDPs.jl simulators dispatch on the abstract
type `POMDPs.Updater`, and `AbstractFilter` cannot subtype `POMDPs.Updater`
directly without making POMDPs.jl a hard dependency.

## Direct dispatch (without the wrapper)

For simpler use cases that don't need the full `POMDPs.simulate` machinery,
the extension also overloads `POMDPs.update` and `POMDPs.initialize_belief`
directly on `AbstractFilter`:

```julia
b1 = POMDPs.update(ekf, b0, action, observation)
```

This is convenient when integrating with code that calls `POMDPs.update`
generically but does not require the `<:Updater` subtype constraint.

## Initial beliefs from distributions

The extension supports initializing a `GaussianBelief` from any multivariate
normal distribution. This is useful when the initial state of a `POMDP` is
given as an `MvNormal`:

```julia
using Distributions
prior = MvNormal([0.0, 0.0], [1.0 0.0; 0.0 0.5])
b0 = POMDPs.initialize_belief(updater, prior)
```

## API

```@docs
GaussianFilters.pomdps_updater
```

## Examples

Two example scripts live in the
[`examples/`](https://github.com/sisl/GaussianFilters.jl/tree/master/examples)
directory:

- [`pomdps_integration.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/pomdps_integration.jl) —
a minimal demonstration of using a `KalmanFilter` through `POMDPs.update`.

- [`pendulum_ekf_ilqr.jl`](https://github.com/sisl/GaussianFilters.jl/blob/master/examples/pendulum_ekf_ilqr.jl) —
closed-loop stabilization of a noisy inverted pendulum observed only
through its angular velocity. Defines a `PendulumPOMDP`, an
`ILQRPolicy <: POMDPs.Policy` that runs iterative LQR on the belief
mean (certainty equivalent control), wraps the EKF with `pomdps_updater`,
and drives the whole closed loop through `POMDPs.simulate`.