From 32fe436510436eb620edb637137a5a66915a56bd Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sat, 21 Dec 2024 09:28:43 +0000 Subject: [PATCH] build based on ec95e71 --- dev/.documenter-siteinfo.json | 2 +- .../{307702a0.svg => 8d916370.svg} | 60 +- .../{bfc60acd.svg => ac409e6f.svg} | 112 +-- .../{8c81adda.svg => b5045006.svg} | 68 +- .../{59e85a4f.svg => dbe90c0d.svg} | 64 +- .../{c6b6935d.svg => df5b83a3.svg} | 64 +- .../{1797bee1.svg => ee8991d8.svg} | 64 +- dev/adaptive_kalmanfilter/index.html | 8 +- dev/api/index.html | 22 +- dev/beetle_example/04bb4f6c.png | Bin 77111 -> 0 bytes dev/beetle_example/0c78f876.png | Bin 0 -> 81319 bytes dev/beetle_example/18eca807.png | Bin 0 -> 55912 bytes dev/beetle_example/3079f958.svg | 46 ++ dev/beetle_example/3551aa42.png | Bin 71877 -> 0 bytes dev/beetle_example/3da61457.png | Bin 0 -> 50359 bytes dev/beetle_example/6cda41b0.svg | 48 ++ dev/beetle_example/7d56539f.png | Bin 83160 -> 0 bytes .../{c17cca23.svg => 831112a0.svg} | 82 +- dev/beetle_example/9887f561.svg | 50 -- dev/beetle_example/e74a81d4.svg | 46 -- dev/beetle_example/index.html | 10 +- dev/beetle_example_imm/1f6e463e.svg | 46 -- dev/beetle_example_imm/4396de8a.png | Bin 66735 -> 0 bytes dev/beetle_example_imm/5525986c.svg | 46 ++ dev/beetle_example_imm/68a796f9.png | Bin 0 -> 64059 bytes dev/beetle_example_imm/index.html | 16 +- dev/benchmark/index.html | 2 +- dev/dae/index.html | 2 +- dev/discretization/index.html | 2 +- dev/distributions/index.html | 2 +- dev/fault_detection/index.html | 2 +- dev/index-33d29abe.png | Bin 0 -> 24024 bytes dev/index-388f16d4.png | Bin 25026 -> 0 bytes dev/index-4b9768e5.png | Bin 0 -> 53222 bytes dev/index-4cc3cda1.svg | 54 ++ dev/index-62cb66c7.png | Bin 0 -> 48600 bytes dev/index-6ac96477.png | Bin 53267 -> 0 bytes dev/index-80b9d4e0.png | Bin 49313 -> 0 bytes dev/index-894e6729.svg | 52 -- dev/index-8fbe54cb.svg | 82 ++ dev/index-96104843.svg | 92 --- dev/index-b37be692.png | Bin 63170 -> 0 bytes dev/index-e6146f98.png | Bin 0 -> 74802 bytes dev/index.html | 54 +- dev/measurement_models/index.html | 4 +- .../{0c9f13e1.svg => 34a9b0f3.svg} | 754 +++++++++--------- dev/neural_network/index.html | 4 +- dev/noisetuning/index.html | 2 +- dev/parameter_estimation/0ce988d8.svg | 301 ------- dev/parameter_estimation/0d315cae.svg | 248 ------ dev/parameter_estimation/1fbc1cbb.svg | 248 ++++++ dev/parameter_estimation/23dbe7cf.svg | 245 ++++++ dev/parameter_estimation/24f69092.svg | 41 + dev/parameter_estimation/43f4c869.svg | 257 ------ dev/parameter_estimation/5afd5f48.svg | 44 - dev/parameter_estimation/99d67e60.svg | 44 + .../{c5d789ad.svg => b3acc360.svg} | 140 ++-- dev/parameter_estimation/b61366d9.svg | 304 +++++++ .../{b91de95b.svg => b69d40b1.svg} | 148 ++-- dev/parameter_estimation/c319f8f0.svg | 41 - .../{175e5dc8.svg => d91b6330.svg} | 689 ++++++++-------- dev/parameter_estimation/index.html | 20 +- dev/search_index.js | 2 +- 63 files changed, 2359 insertions(+), 2375 deletions(-) rename dev/adaptive_kalmanfilter/{307702a0.svg => 8d916370.svg} (86%) rename dev/adaptive_kalmanfilter/{bfc60acd.svg => ac409e6f.svg} (86%) rename dev/adaptive_kalmanfilter/{8c81adda.svg => b5045006.svg} (88%) rename dev/adaptive_kalmanfilter/{59e85a4f.svg => dbe90c0d.svg} (87%) rename dev/adaptive_kalmanfilter/{c6b6935d.svg => df5b83a3.svg} (87%) rename dev/adaptive_kalmanfilter/{1797bee1.svg => ee8991d8.svg} (87%) delete mode 100644 dev/beetle_example/04bb4f6c.png create mode 100644 dev/beetle_example/0c78f876.png create mode 100644 dev/beetle_example/18eca807.png create mode 100644 dev/beetle_example/3079f958.svg delete mode 100644 dev/beetle_example/3551aa42.png create mode 100644 dev/beetle_example/3da61457.png create mode 100644 dev/beetle_example/6cda41b0.svg delete mode 100644 dev/beetle_example/7d56539f.png rename dev/beetle_example/{c17cca23.svg => 831112a0.svg} (88%) delete mode 100644 dev/beetle_example/9887f561.svg delete mode 100644 dev/beetle_example/e74a81d4.svg delete mode 100644 dev/beetle_example_imm/1f6e463e.svg delete mode 100644 dev/beetle_example_imm/4396de8a.png create mode 100644 dev/beetle_example_imm/5525986c.svg create mode 100644 dev/beetle_example_imm/68a796f9.png create mode 100644 dev/index-33d29abe.png delete mode 100644 dev/index-388f16d4.png create mode 100644 dev/index-4b9768e5.png create mode 100644 dev/index-4cc3cda1.svg create mode 100644 dev/index-62cb66c7.png delete mode 100644 dev/index-6ac96477.png delete mode 100644 dev/index-80b9d4e0.png delete mode 100644 dev/index-894e6729.svg create mode 100644 dev/index-8fbe54cb.svg delete mode 100644 dev/index-96104843.svg delete mode 100644 dev/index-b37be692.png create mode 100644 dev/index-e6146f98.png rename dev/neural_network/{0c9f13e1.svg => 34a9b0f3.svg} (96%) delete mode 100644 dev/parameter_estimation/0ce988d8.svg delete mode 100644 dev/parameter_estimation/0d315cae.svg create mode 100644 dev/parameter_estimation/1fbc1cbb.svg create mode 100644 dev/parameter_estimation/23dbe7cf.svg create mode 100644 dev/parameter_estimation/24f69092.svg delete mode 100644 dev/parameter_estimation/43f4c869.svg delete mode 100644 dev/parameter_estimation/5afd5f48.svg create mode 100644 dev/parameter_estimation/99d67e60.svg rename dev/parameter_estimation/{c5d789ad.svg => b3acc360.svg} (93%) create mode 100644 dev/parameter_estimation/b61366d9.svg rename dev/parameter_estimation/{b91de95b.svg => b69d40b1.svg} (93%) delete mode 100644 dev/parameter_estimation/c319f8f0.svg rename dev/parameter_estimation/{175e5dc8.svg => d91b6330.svg} (66%) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 8282950e..5009c5f1 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-21T07:27:33","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-21T09:28:19","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/adaptive_kalmanfilter/307702a0.svg b/dev/adaptive_kalmanfilter/8d916370.svg similarity index 86% rename from dev/adaptive_kalmanfilter/307702a0.svg rename to dev/adaptive_kalmanfilter/8d916370.svg index 6f9754b8..62fd0b63 100644 --- a/dev/adaptive_kalmanfilter/307702a0.svg +++ b/dev/adaptive_kalmanfilter/8d916370.svg @@ -1,44 +1,44 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/adaptive_kalmanfilter/bfc60acd.svg b/dev/adaptive_kalmanfilter/ac409e6f.svg similarity index 86% rename from dev/adaptive_kalmanfilter/bfc60acd.svg rename to dev/adaptive_kalmanfilter/ac409e6f.svg index 30786956..0bc14ccf 100644 --- a/dev/adaptive_kalmanfilter/bfc60acd.svg +++ b/dev/adaptive_kalmanfilter/ac409e6f.svg @@ -1,74 +1,74 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/adaptive_kalmanfilter/8c81adda.svg b/dev/adaptive_kalmanfilter/b5045006.svg similarity index 88% rename from dev/adaptive_kalmanfilter/8c81adda.svg rename to dev/adaptive_kalmanfilter/b5045006.svg index 58aa53b5..2861f9f5 100644 --- a/dev/adaptive_kalmanfilter/8c81adda.svg +++ b/dev/adaptive_kalmanfilter/b5045006.svg @@ -1,48 +1,48 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/adaptive_kalmanfilter/59e85a4f.svg b/dev/adaptive_kalmanfilter/dbe90c0d.svg similarity index 87% rename from dev/adaptive_kalmanfilter/59e85a4f.svg rename to dev/adaptive_kalmanfilter/dbe90c0d.svg index 5de94659..4dd619e6 100644 --- a/dev/adaptive_kalmanfilter/59e85a4f.svg +++ b/dev/adaptive_kalmanfilter/dbe90c0d.svg @@ -1,46 +1,46 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/adaptive_kalmanfilter/c6b6935d.svg b/dev/adaptive_kalmanfilter/df5b83a3.svg similarity index 87% rename from dev/adaptive_kalmanfilter/c6b6935d.svg rename to dev/adaptive_kalmanfilter/df5b83a3.svg index 1c462fe5..21b7d423 100644 --- a/dev/adaptive_kalmanfilter/c6b6935d.svg +++ b/dev/adaptive_kalmanfilter/df5b83a3.svg @@ -1,46 +1,46 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/adaptive_kalmanfilter/1797bee1.svg b/dev/adaptive_kalmanfilter/ee8991d8.svg similarity index 87% rename from dev/adaptive_kalmanfilter/1797bee1.svg rename to dev/adaptive_kalmanfilter/ee8991d8.svg index a837ed59..f83c9c38 100644 --- a/dev/adaptive_kalmanfilter/1797bee1.svg +++ b/dev/adaptive_kalmanfilter/ee8991d8.svg @@ -1,46 +1,46 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/adaptive_kalmanfilter/index.html b/dev/adaptive_kalmanfilter/index.html index 04066783..1b46d8d9 100644 --- a/dev/adaptive_kalmanfilter/index.html +++ b/dev/adaptive_kalmanfilter/index.html @@ -9,7 +9,7 @@ x = [zeros(50); 0:100] T = length(x) Y = x + randn(T) -plot([Y x], lab=["Measurement" "True state to be tracked"], c=[1 :purple])Example block output

Simple Kalman filtering

We will use a Kalman filter to perform the filtering. The model is a double integrator, i.e., a constant-acceleration model. The state vector is thus $x = [p, v]^T$, where $p$ is the position and $v$ is the velocity. When designing a Kalman filter, we need to specify the noise covariances $R_1$ and $R_2$. While it's often easy to measure the covariance of the measurement noise, $R_2$, it can be quite difficult to know ahead of time what the dynamics noise covariance, $R_1$, should be. In this example, we will use an adaptive filter, where we will increase the dynamics noise covariance if the filter prediction error is too large. However, we first run the filter twice, once with a large $R_1$ and once with a small $R_1$ to illustrate the difference.

y = [[y] for y in Y] # create a vector of vectors for the KF
+plot([Y x], lab=["Measurement" "True state to be tracked"], c=[1 :purple])
Example block output

Simple Kalman filtering

We will use a Kalman filter to perform the filtering. The model is a double integrator, i.e., a constant-acceleration model. The state vector is thus $x = [p, v]^T$, where $p$ is the position and $v$ is the velocity. When designing a Kalman filter, we need to specify the noise covariances $R_1$ and $R_2$. While it's often easy to measure the covariance of the measurement noise, $R_2$, it can be quite difficult to know ahead of time what the dynamics noise covariance, $R_1$, should be. In this example, we will use an adaptive filter, where we will increase the dynamics noise covariance if the filter prediction error is too large. However, we first run the filter twice, once with a large $R_1$ and once with a small $R_1$ to illustrate the difference.

y = [[y] for y in Y] # create a vector of vectors for the KF
 u = fill([], T) # No inputs in this example :(
 
 # Define the model
@@ -38,7 +38,7 @@
     Yh = reduce(hcat, yh)
     plot!(Yh', lab="Estimate \$σ_w\$ = $σw")
 end
-fig
Example block output

When $R_1$ is small (controlled by $σ_w$), we get a nice and smooth filter estimate, but this estimate clearly lags behind the true state. When $R_1$ is large, the filter estimate is much more responsive, but it also has a lot of noise.

Adaptive noise covariance

Below, we will implement an adaptive filter, where we keep the dynamics noise covariance low by default, but increase it if the filter prediction error is too large. We will use a Z-score to determine if the prediction error is too large. The Z-score is defined as the number of standard deviations the prediction error is away from the estimated mean. This time around we use separate correct! and predict! calls, so that we can access the prediction error as well as the prior covariance of the prediction error, $S$. $S$ (or the Cholesky factor $Sᵪ$) will be used to compute the Z-score.

σw = 1e-5 # Set the covariance to a low value by default
+fig
Example block output

When $R_1$ is small (controlled by $σ_w$), we get a nice and smooth filter estimate, but this estimate clearly lags behind the true state. When $R_1$ is large, the filter estimate is much more responsive, but it also has a lot of noise.

Adaptive noise covariance

Below, we will implement an adaptive filter, where we keep the dynamics noise covariance low by default, but increase it if the filter prediction error is too large. We will use a Z-score to determine if the prediction error is too large. The Z-score is defined as the number of standard deviations the prediction error is away from the estimated mean. This time around we use separate correct! and predict! calls, so that we can access the prediction error as well as the prior covariance of the prediction error, $S$. $S$ (or the Cholesky factor $Sᵪ$) will be used to compute the Z-score.

σw = 1e-5 # Set the covariance to a low value by default
 R1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts]
 kf = KalmanFilter(A, B, C, D, R1, R2)
 measure = LowLevelParticleFilters.measurement(kf)
@@ -64,7 +64,7 @@
 end
 
 Yh = reduce(hcat, yh)
-plot([Y Yh'], lab=["Measurement" "Adaptive estimate"])
Example block output

Not too bad! This time the filter estimate is much more responsive during the transition, but exhibits favorable noise properties during the stationary phases. We can also plot the prediction error and the Z-score to see how the filter adapts to the dynamics noise covariance.

plot([es σs], lab=["Prediction error" "Z-score"])
Example block output

Notice how the prediction errors, that should ideally be centered around zero, remain predominantly negative for a long time interval after the transition. This can be attributed to an overshoot in the velocity state of the estimator, but the rapid decrease of the covariance after the transition makes the filter slow at correcting its overshoot. If we want, we could mitigate this and make the adaptation even more sophisticated by letting the covariance remain large for a while after a transition in operating mode has been detected. Below, we implement a simple version of this, where we use a multiplier $σ_{wt}$ that defaults to 1, but is increase to a very large value of 1000 if a transition is detected. When no transition is detected, $σ_{wt}$ is decreased exponentially back down to 1.

σw  = 1e-5 # Set the covariance to a low value by default
+plot([Y Yh'], lab=["Measurement" "Adaptive estimate"])
Example block output

Not too bad! This time the filter estimate is much more responsive during the transition, but exhibits favorable noise properties during the stationary phases. We can also plot the prediction error and the Z-score to see how the filter adapts to the dynamics noise covariance.

plot([es σs], lab=["Prediction error" "Z-score"])
Example block output

Notice how the prediction errors, that should ideally be centered around zero, remain predominantly negative for a long time interval after the transition. This can be attributed to an overshoot in the velocity state of the estimator, but the rapid decrease of the covariance after the transition makes the filter slow at correcting its overshoot. If we want, we could mitigate this and make the adaptation even more sophisticated by letting the covariance remain large for a while after a transition in operating mode has been detected. Below, we implement a simple version of this, where we use a multiplier $σ_{wt}$ that defaults to 1, but is increase to a very large value of 1000 if a transition is detected. When no transition is detected, $σ_{wt}$ is decreased exponentially back down to 1.

σw  = 1e-5 # Set the covariance to a low value by default
 σwt = 1.0
 R1  = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts]
 kf  = KalmanFilter(A, B, C, D, R1, R2)
@@ -94,4 +94,4 @@
 end
 
 Yh = reduce(hcat, yh)
-plot([Y Yh'], lab=["Measurement" "Adaptive estimate"])
Example block output
plot([es σs σwts], lab=["Prediction error" "Z-score" "\$σ_{wt}\$ multiplier"], layout=2, sp=[1 1 2])
Example block output

This time, the prediction errors look more like white noise centered around zero after the initial transient caused by the transition.

Summary

This tutorial demonstrated simple Kalman filtering for a double integrator without control inputs. We saw how the filtering estimate could be improved by playing around with the covariance matrices of the estimator, helping it catch up to fast changes in the behavior of the system without sacrificing steady-state noise properties.

In this case, we handled the modification of $R_1$ outside of the filter, implementing our own filtering loop. Some applications get away with instead providing time-varying matrices in the form of a 3-dimension array, where the third dimension corresponds to time, or instead of providing a matrix, providing a function $R_1(x, u, p, t)$ allows the matrix to be a function of state, input, parameters and time. These options apply to all matrices in the filter, including the dynamics matrices, $A,B,C,D$.

Lastly, we mention the ability of the KalmanFilter to act like a recursive least-squares estimator, by setting the "forgetting factor $α>1$ when creating the KalmanFilter. $α>1$ will cause the filter will exhibit exponential forgetting similar to an RLS estimator, in addition to the covariance inflation due to R1. It is thus possible to get a RLS-like algorithm by setting $R_1 = 0, R_2 = 1/α$ and $α > 1$.

Disturbance modeling and noise tuning

See this notebook for a blog post about disturbance modeling and noise tuning using LowLevelParticleFilter.jl

+plot([Y Yh'], lab=["Measurement" "Adaptive estimate"])Example block output
plot([es σs σwts], lab=["Prediction error" "Z-score" "\$σ_{wt}\$ multiplier"], layout=2, sp=[1 1 2])
Example block output

This time, the prediction errors look more like white noise centered around zero after the initial transient caused by the transition.

Summary

This tutorial demonstrated simple Kalman filtering for a double integrator without control inputs. We saw how the filtering estimate could be improved by playing around with the covariance matrices of the estimator, helping it catch up to fast changes in the behavior of the system without sacrificing steady-state noise properties.

In this case, we handled the modification of $R_1$ outside of the filter, implementing our own filtering loop. Some applications get away with instead providing time-varying matrices in the form of a 3-dimension array, where the third dimension corresponds to time, or instead of providing a matrix, providing a function $R_1(x, u, p, t)$ allows the matrix to be a function of state, input, parameters and time. These options apply to all matrices in the filter, including the dynamics matrices, $A,B,C,D$.

Lastly, we mention the ability of the KalmanFilter to act like a recursive least-squares estimator, by setting the "forgetting factor $α>1$ when creating the KalmanFilter. $α>1$ will cause the filter will exhibit exponential forgetting similar to an RLS estimator, in addition to the covariance inflation due to R1. It is thus possible to get a RLS-like algorithm by setting $R_1 = 0, R_2 = 1/α$ and $α > 1$.

Disturbance modeling and noise tuning

See this notebook for a blog post about disturbance modeling and noise tuning using LowLevelParticleFilter.jl

diff --git a/dev/api/index.html b/dev/api/index.html index b42b483c..eb08bae6 100644 --- a/dev/api/index.html +++ b/dev/api/index.html @@ -1,13 +1,13 @@ -API · LowLevelParticleFilters Documentation

Exported functions and types

Index

LowLevelParticleFilters.AdvancedParticleFilterMethod
AdvancedParticleFilter(N::Integer, dynamics::Function, measurement::Function, measurement_likelihood, dynamics_density, initial_density; p = NullParameters(), threads = false, kwargs...)

This type represents a standard particle filter but affords extra flexibility compared to the ParticleFilter type, e.g., non-additive noise in the dynamics and measurement functions.

See the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#AdvancedParticleFilter-1

Arguments:

  • N: Number of particles
  • dynamics: A discrete-time dynamics function (x, u, p, t, noise=false) -> x⁺. It's important that the noise argument defaults to false.
  • measurement: A measurement function (x, u, p, t, noise=false) -> y. It's important that the noise argument defaults to false.
  • measurement_likelihood: A function (x, u, y, p, t)->logl to evaluate the log-likelihood of a measurement.
  • dynamics_density: This field is not used by the advanced filter and can be set to nothing.
  • initial_density: The distribution of the initial state.
  • threads: use threads to propagate particles in parallel. Only activate this if your dynamics is thread-safe. SeeToDee.SimpleColloc is not thread-safe by default due to the use of internal caches, but SeeToDee.Rk4 is.

Extended help

Multiple measurement models

The measurement_likelihood function is used to evaluate the likelihood of a measurement. If you have multiple sensors and want to perform individual correct! steps for each, call correct!(..., g = custom_likelihood_function).

source
LowLevelParticleFilters.CompositeMeasurementModelMethod
CompositeMeasurementModel(model1, model2, ...)

A composite measurement model that combines multiple measurement models. This model acts as all component models concatenated. The tuple returned from correct! will be

  • ll: The sum of the log-likelihood of all component models
  • e: The concatenated innovation vector
  • S: A vector of the innovation covariance matrices of the component models
  • Sᵪ: A vector of the Cholesky factorizations of the innovation covariance matrices of the component models
  • K: A vector of the Kalman gains of the component models

If all sensors operate on at the same rate, and all measurement models are of the same type, it's more efficient to use a single measurement model with a vector-valued measurement function.

Fields:

  • models: A tuple of measurement models
source
LowLevelParticleFilters.EKFMeasurementModelMethod
EKFMeasurementModel{IPM}(measurement, R2, ny, Cjac, cache = nothing)

A measurement model for the Extended Kalman Filter.

Arguments:

  • IPM: A boolean indicating if the measurement function is inplace
  • measurement: The measurement function y = h(x, u, p, t)
  • R2: The measurement noise covariance matrix
  • ny: The number of measurement variables
  • Cjac: The Jacobian of the measurement function Cjac(x, u, p, t). If none is provided, ForwardDiff will be used.
source
LowLevelParticleFilters.ExtendedKalmanFilterType
ExtendedKalmanFilter(kf, dynamics, measurement; Ajac, Cjac)
+API · LowLevelParticleFilters Documentation

Exported functions and types

Index

LowLevelParticleFilters.AdvancedParticleFilterMethod
AdvancedParticleFilter(N::Integer, dynamics::Function, measurement::Function, measurement_likelihood, dynamics_density, initial_density; p = NullParameters(), threads = false, kwargs...)

This type represents a standard particle filter but affords extra flexibility compared to the ParticleFilter type, e.g., non-additive noise in the dynamics and measurement functions.

See the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#AdvancedParticleFilter-1

Arguments:

  • N: Number of particles
  • dynamics: A discrete-time dynamics function (x, u, p, t, noise=false) -> x⁺. It's important that the noise argument defaults to false.
  • measurement: A measurement function (x, u, p, t, noise=false) -> y. It's important that the noise argument defaults to false.
  • measurement_likelihood: A function (x, u, y, p, t)->logl to evaluate the log-likelihood of a measurement.
  • dynamics_density: This field is not used by the advanced filter and can be set to nothing.
  • initial_density: The distribution of the initial state.
  • threads: use threads to propagate particles in parallel. Only activate this if your dynamics is thread-safe. SeeToDee.SimpleColloc is not thread-safe by default due to the use of internal caches, but SeeToDee.Rk4 is.

Extended help

Multiple measurement models

The measurement_likelihood function is used to evaluate the likelihood of a measurement. If you have multiple sensors and want to perform individual correct! steps for each, call correct!(..., g = custom_likelihood_function).

source
LowLevelParticleFilters.CompositeMeasurementModelMethod
CompositeMeasurementModel(model1, model2, ...)

A composite measurement model that combines multiple measurement models. This model acts as all component models concatenated. The tuple returned from correct! will be

  • ll: The sum of the log-likelihood of all component models
  • e: The concatenated innovation vector
  • S: A vector of the innovation covariance matrices of the component models
  • Sᵪ: A vector of the Cholesky factorizations of the innovation covariance matrices of the component models
  • K: A vector of the Kalman gains of the component models

If all sensors operate on at the same rate, and all measurement models are of the same type, it's more efficient to use a single measurement model with a vector-valued measurement function.

Fields:

  • models: A tuple of measurement models
source
LowLevelParticleFilters.EKFMeasurementModelMethod
EKFMeasurementModel{IPM}(measurement, R2, ny, Cjac, cache = nothing)

A measurement model for the Extended Kalman Filter.

Arguments:

  • IPM: A boolean indicating if the measurement function is inplace
  • measurement: The measurement function y = h(x, u, p, t)
  • R2: The measurement noise covariance matrix
  • ny: The number of measurement variables
  • Cjac: The Jacobian of the measurement function Cjac(x, u, p, t). If none is provided, ForwardDiff will be used.
source
LowLevelParticleFilters.ExtendedKalmanFilterType
ExtendedKalmanFilter(kf, dynamics, measurement; Ajac, Cjac)
 ExtendedKalmanFilter(dynamics, measurement, R1,R2,d0=MvNormal(Matrix(R1)); nu::Int, p = NullParameters(), α = 1.0, check = true)

A nonlinear state estimator propagating uncertainty using linearization.

The constructor to the extended Kalman filter takes dynamics and measurement functions, and either covariance matrices, or a KalmanFilter. If the former constructor is used, the number of inputs to the system dynamics, nu, must be explicitly provided with a keyword argument.

By default, the filter will internally linearize the dynamics using ForwardDiff. User provided Jacobian functions can be provided as keyword arguments Ajac and Cjac. These functions should have the signature (x,u,p,t)::AbstractMatrix where x is the state, u is the input, p is the parameters, and t is the time.

The dynamics and measurement function are on the following form

x(t+1) = dynamics(x, u, p, t) + w
-y      = measurement(x, u, p, t) + e

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0

See also UnscentedKalmanFilter which is typically more accurate than ExtendedKalmanFilter. See KalmanFilter for detailed instructions on how to set up a Kalman filter kf.

source
LowLevelParticleFilters.IMMMethod
IMM(models, P, μ; check = true, p = NullParameters(), interact = true)

Interacting Multiple Model (IMM) filter. This filter is a combination of multiple Kalman-type filters, each with its own state and covariance. The IMM filter is a probabilistically weighted average of the states and covariances of the individual filters. The weights are determined by the probability matrix P and the mixing probabilities μ.

Experimental

This filter is currently considered experimental and the user interface may change in the future without respecting semantic versioning.

In addition to the predict! and correct! steps, the IMM filter has an interact! method that updates the states and covariances of the individual filters based on the mixing probabilities. The combine! method combines the states and covariances of the individual filters into a single state and covariance. These four functions are typically called in either of the orders

  • correct!, combine!, interact!, predict! (as is done in update!)
  • interact!, predict!, correct!, combine! (as is done in the reference cited below)

These two orders are cyclic permutations of each other, and the order used in update! is chosen to align with the order used in the other filters, where the initial condition is corrected using the first measurement, i.e., we assume the first measurement updates $x(0|-1)$ to $x(0|0)$.

The initial (combined) state and covariance of the IMM filter is made up of the weighted average of the states and covariances of the individual filters. The weights are the initial mixing probabilities μ.

Ref: "Interacting multiple model methods in target tracking: a survey", E. Mazor; A. Averbuch; Y. Bar-Shalom; J. Dayan

Arguments:

  • models: An array of Kalman-type filters, such as KalmanFilter, ExtendedKalmanFilter, UnscentedKalmanFilter, etc. The state of each model must have the same meaning, such that forming a weighted average makes sense.
  • P: The mode-transition probability matrix. P[i,j] is the probability of transitioning from mode i to mode j (each row must sum to one).
  • μ: The initial mixing probabilities. μ[i] is the probability of being in mode i at the initial contidion (must sum to one).
  • check: If true, check that the inputs are valid. If false, skip the checks.
  • p: Parameters for the filter. NOTE: this p is shared among all internal filters. The internal p of each filter will be overridden by this one.
  • interact: If true, the filter will run the interaction as part of update! and forward_trajectory. If false, the filter will not run the interaction step. This choice can be overridden by passing the keyword argument interact to the respective functions.
source
LowLevelParticleFilters.KalmanFilterType
KalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1, check=true)

The matrices A,B,C,D define the dynamics

x' = Ax + Bu + w
-y  = Cx + Du + e

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0

The matrices can be time varying such that, e.g., A[:, :, t] contains the $A$ matrix at time index t. They can also be given as functions on the form

Afun(x, u, p, t) -> A

For maximum performance, provide statically sized matrices from StaticArrays.jl

α is an optional "forgetting factor", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to $R_1$, exhibit "exponential forgetting" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting $R_1=0, R_2 = 1/α$ and $α > 1$ ($α$ is the inverse of the traditional RLS parameter $α = 1/λ$). The exact form of the covariance update is

\[R(t+1|t) = α AR(t)A^T + R_1\]

If check = true (default) the function will check that the eigenvalues of A are less than 2 in absolute value. Large eigenvalues may be an indication that the system matrices are representing a continuous-time system and the user has forgotten to discretize it. Turn off this check by setting check = false.

Tutorials on Kalman filtering

The tutorial "How to tune a Kalman filter" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model. See also the tutorial in the documentation

source
LowLevelParticleFilters.KalmanFilteringSolutionType
KalmanFilteringSolution{Tx,Txt,TR,TRt,Tll} <: AbstractFilteringSolution

Fields

  • x: predictions $x(t+1|t)$ (plotted if plotx=true)
  • xt: filtered estimates $x(t|t)$ (plotted if plotxt=true)
  • R: predicted covariance matrices $R(t+1|t)$ (plotted if plotR=true)
  • Rt: filter covariances $R(t|t)$ (plotted if plotRt=true)
  • ll: loglikelihood
  • e: prediction errors $e(t|t-1) = y - ŷ(t|t-1)$ (plotted if plote=true)

Plot

The solution object can be plotted

plot(sol, plotx=true, plotxt=true, plotR=true, plotRt=true, plote=true, plotu=true, ploty=true, plotyh=true, plotyht=true, name="")

where

  • plotx: Plot the predictions x(t|t-1)
  • plotxt: Plot the filtered estimates x(t|t)
  • plotR: Plot the predicted covariances R(t|t-1) as ribbons at ±2σ (1.96 σ to be precise)
  • plotRt: Plot the filter covariances R(t|t) as ribbons at ±2σ (1.96 σ to be precise)
  • plote: Plot the prediction errors e(t|t-1) = y - ŷ(t|t-1)
  • plotu: Plot the input
  • ploty: Plot the measurements
  • plotyh: Plot the predicted measurements ŷ(t|t-1)
  • plotyht: Plot the filtered measurements ŷ(t|t)
  • name: a string that is prepended to the labels of the plots, which is useful when plotting multiple solutions in the same plot.
source
LowLevelParticleFilters.ParticleFilterMethod
ParticleFilter(N::Integer, dynamics, measurement, dynamics_density, measurement_density, initial_density; threads = false, p = NullParameters(), kwargs...)

See the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#Particle-filter-1

Arguments:

  • N: Number of particles
  • dynamics: A discrete-time dynamics function (x, u, p, t) -> x⁺
  • measurement: A measurement function (x, u, p, t) -> y
  • dynamics_density: A probability-density function for additive noise in the dynamics. Use AdvancedParticleFilter for non-additive noise.
  • measurement_density: A probability-density function for additive measurement noise. Use AdvancedParticleFilter for non-additive noise.
  • initial_density: Distribution of the initial state.
source
LowLevelParticleFilters.ParticleFilteringSolutionType
ParticleFilteringSolution{F, Tu, Ty, Tx, Tw, Twe, Tll} <: AbstractFilteringSolution

Fields:

  • f: The filter used to produce the solution.
  • u: Input
  • y: Output / measurements
  • x: Particles, the size of this array is (N,T), where N is the number of particles and T is the number of time steps. Each element represents a weighted state hypothesis with weight given by we.
  • w: Weights (log space). These are used for internal computations.
  • we: Weights (exponentiated / original space). These are the ones to use to compute weighted means etc., they sum to one for each time step.
  • ll: Log likelihood

Plot

The solution object can be plotted

plot(sol; nbinsy=30, xreal=nothing, dim=nothing, ploty=true)
source
LowLevelParticleFilters.SqKalmanFilterType
SqKalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1)

A standard Kalman filter on square-root form. This filter may have better numerical performance when the covariance matrices are ill-conditioned.

The matrices A,B,C,D define the dynamics

x' = Ax + Bu + w
-y  = Cx + Du + e

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0

The matrices can be time varying such that, e.g., A[:, :, t] contains the $A$ matrix at time index t. They can also be given as functions on the form

Afun(x, u, p, t) -> A

The internal fields storing covariance matrices are for this filter storing the upper-triangular Cholesky factor.

α is an optional "forgetting factor", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to $R_1$, exhibit "exponential forgetting" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting $R_1=0, R_2 = 1/α$ and $α > 1$ ($α$ is the inverse of the traditional RLS parameter $α = 1/λ$). The form of the covariance update is

\[R(t+1|t) = α AR(t)A^T + R_1\]

Ref: "A Square-Root Kalman Filter Using Only QR Decompositions", Kevin Tracy https://arxiv.org/abs/2208.06452

source
LowLevelParticleFilters.UKFMeasurementModelMethod
UKFMeasurementModel{inplace_measurement,augmented_measurement}(measurement, R2, ny, ne, innovation, mean, cov, cross_cov, cache = nothing)

A measurement model for the Unscented Kalman Filter.

Arguments:

  • measurement: The measurement function y = h(x, u, p, t)
  • R2: The measurement noise covariance matrix
  • ny: The number of measurement variables
  • ne: If augmented_measurement is true, the number of measurement noise variables
  • innovation(y::AbstractVector, yh::AbstractVector) where the arguments represent (measured output, predicted output)
  • mean(ys::AbstractVector{<:AbstractVector}): computes the mean of the vector of vectors of output sigma points.
  • cov(ys::AbstractVector{<:AbstractVector}, y::AbstractVector): computes the covariance matrix of the output sigma points.
  • cross_cov(xs::AbstractVector{<:AbstractVector}, x::AbstractVector, ys::AbstractVector{<:AbstractVector}, y::AbstractVector) where the arguments represents (state sigma points, mean state, output sigma points, mean output). The function should return the cross-covariance matrix between the state and output sigma points.
source
LowLevelParticleFilters.UKFMeasurementModelMethod
UKFMeasurementModel{T,IPM,AUGM}(measurement, R2; nx, ny, ne = nothing, innovation = -, mean = safe_mean, cov = safe_cov, cross_cov = cross_cov, static = nothing)
  • T is the element type used for arrays
  • IPM is a boolean indicating if the measurement function is inplace
  • AUGM is a boolean indicating if the measurement model is augmented
source
LowLevelParticleFilters.IMMMethod
IMM(models, P, μ; check = true, p = NullParameters(), interact = true)

Interacting Multiple Model (IMM) filter. This filter is a combination of multiple Kalman-type filters, each with its own state and covariance. The IMM filter is a probabilistically weighted average of the states and covariances of the individual filters. The weights are determined by the probability matrix P and the mixing probabilities μ.

Experimental

This filter is currently considered experimental and the user interface may change in the future without respecting semantic versioning.

In addition to the predict! and correct! steps, the IMM filter has an interact! method that updates the states and covariances of the individual filters based on the mixing probabilities. The combine! method combines the states and covariances of the individual filters into a single state and covariance. These four functions are typically called in either of the orders

  • correct!, combine!, interact!, predict! (as is done in update!)
  • interact!, predict!, correct!, combine! (as is done in the reference cited below)

These two orders are cyclic permutations of each other, and the order used in update! is chosen to align with the order used in the other filters, where the initial condition is corrected using the first measurement, i.e., we assume the first measurement updates $x(0|-1)$ to $x(0|0)$.

The initial (combined) state and covariance of the IMM filter is made up of the weighted average of the states and covariances of the individual filters. The weights are the initial mixing probabilities μ.

Ref: "Interacting multiple model methods in target tracking: a survey", E. Mazor; A. Averbuch; Y. Bar-Shalom; J. Dayan

Arguments:

  • models: An array of Kalman-type filters, such as KalmanFilter, ExtendedKalmanFilter, UnscentedKalmanFilter, etc. The state of each model must have the same meaning, such that forming a weighted average makes sense.
  • P: The mode-transition probability matrix. P[i,j] is the probability of transitioning from mode i to mode j (each row must sum to one).
  • μ: The initial mixing probabilities. μ[i] is the probability of being in mode i at the initial contidion (must sum to one).
  • check: If true, check that the inputs are valid. If false, skip the checks.
  • p: Parameters for the filter. NOTE: this p is shared among all internal filters. The internal p of each filter will be overridden by this one.
  • interact: If true, the filter will run the interaction as part of update! and forward_trajectory. If false, the filter will not run the interaction step. This choice can be overridden by passing the keyword argument interact to the respective functions.
source
LowLevelParticleFilters.KalmanFilterType
KalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1, check=true)

The matrices A,B,C,D define the dynamics

x' = Ax + Bu + w
+y  = Cx + Du + e

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0

The matrices can be time varying such that, e.g., A[:, :, t] contains the $A$ matrix at time index t. They can also be given as functions on the form

Afun(x, u, p, t) -> A

For maximum performance, provide statically sized matrices from StaticArrays.jl

α is an optional "forgetting factor", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to $R_1$, exhibit "exponential forgetting" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting $R_1=0, R_2 = 1/α$ and $α > 1$ ($α$ is the inverse of the traditional RLS parameter $α = 1/λ$). The exact form of the covariance update is

\[R(t+1|t) = α AR(t)A^T + R_1\]

If check = true (default) the function will check that the eigenvalues of A are less than 2 in absolute value. Large eigenvalues may be an indication that the system matrices are representing a continuous-time system and the user has forgotten to discretize it. Turn off this check by setting check = false.

Tutorials on Kalman filtering

The tutorial "How to tune a Kalman filter" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model. See also the tutorial in the documentation

source
LowLevelParticleFilters.KalmanFilteringSolutionType
KalmanFilteringSolution{Tx,Txt,TR,TRt,Tll} <: AbstractFilteringSolution

Fields

  • x: predictions $x(t+1|t)$ (plotted if plotx=true)
  • xt: filtered estimates $x(t|t)$ (plotted if plotxt=true)
  • R: predicted covariance matrices $R(t+1|t)$ (plotted if plotR=true)
  • Rt: filter covariances $R(t|t)$ (plotted if plotRt=true)
  • ll: loglikelihood
  • e: prediction errors $e(t|t-1) = y - ŷ(t|t-1)$ (plotted if plote=true)

Plot

The solution object can be plotted

plot(sol, plotx=true, plotxt=true, plotR=true, plotRt=true, plote=true, plotu=true, ploty=true, plotyh=true, plotyht=true, name="")

where

  • plotx: Plot the predictions x(t|t-1)
  • plotxt: Plot the filtered estimates x(t|t)
  • plotR: Plot the predicted covariances R(t|t-1) as ribbons at ±2σ (1.96 σ to be precise)
  • plotRt: Plot the filter covariances R(t|t) as ribbons at ±2σ (1.96 σ to be precise)
  • plote: Plot the prediction errors e(t|t-1) = y - ŷ(t|t-1)
  • plotu: Plot the input
  • ploty: Plot the measurements
  • plotyh: Plot the predicted measurements ŷ(t|t-1)
  • plotyht: Plot the filtered measurements ŷ(t|t)
  • name: a string that is prepended to the labels of the plots, which is useful when plotting multiple solutions in the same plot.
source
LowLevelParticleFilters.ParticleFilterMethod
ParticleFilter(N::Integer, dynamics, measurement, dynamics_density, measurement_density, initial_density; threads = false, p = NullParameters(), kwargs...)

See the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#Particle-filter-1

Arguments:

  • N: Number of particles
  • dynamics: A discrete-time dynamics function (x, u, p, t) -> x⁺
  • measurement: A measurement function (x, u, p, t) -> y
  • dynamics_density: A probability-density function for additive noise in the dynamics. Use AdvancedParticleFilter for non-additive noise.
  • measurement_density: A probability-density function for additive measurement noise. Use AdvancedParticleFilter for non-additive noise.
  • initial_density: Distribution of the initial state.
source
LowLevelParticleFilters.ParticleFilteringSolutionType
ParticleFilteringSolution{F, Tu, Ty, Tx, Tw, Twe, Tll} <: AbstractFilteringSolution

Fields:

  • f: The filter used to produce the solution.
  • u: Input
  • y: Output / measurements
  • x: Particles, the size of this array is (N,T), where N is the number of particles and T is the number of time steps. Each element represents a weighted state hypothesis with weight given by we.
  • w: Weights (log space). These are used for internal computations.
  • we: Weights (exponentiated / original space). These are the ones to use to compute weighted means etc., they sum to one for each time step.
  • ll: Log likelihood

Plot

The solution object can be plotted

plot(sol; nbinsy=30, xreal=nothing, dim=nothing, ploty=true)
source
LowLevelParticleFilters.SqKalmanFilterType
SqKalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1)

A standard Kalman filter on square-root form. This filter may have better numerical performance when the covariance matrices are ill-conditioned.

The matrices A,B,C,D define the dynamics

x' = Ax + Bu + w
+y  = Cx + Du + e

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0

The matrices can be time varying such that, e.g., A[:, :, t] contains the $A$ matrix at time index t. They can also be given as functions on the form

Afun(x, u, p, t) -> A

The internal fields storing covariance matrices are for this filter storing the upper-triangular Cholesky factor.

α is an optional "forgetting factor", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to $R_1$, exhibit "exponential forgetting" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting $R_1=0, R_2 = 1/α$ and $α > 1$ ($α$ is the inverse of the traditional RLS parameter $α = 1/λ$). The form of the covariance update is

\[R(t+1|t) = α AR(t)A^T + R_1\]

Ref: "A Square-Root Kalman Filter Using Only QR Decompositions", Kevin Tracy https://arxiv.org/abs/2208.06452

source
LowLevelParticleFilters.UKFMeasurementModelMethod
UKFMeasurementModel{inplace_measurement,augmented_measurement}(measurement, R2, ny, ne, innovation, mean, cov, cross_cov, cache = nothing)

A measurement model for the Unscented Kalman Filter.

Arguments:

  • measurement: The measurement function y = h(x, u, p, t)
  • R2: The measurement noise covariance matrix
  • ny: The number of measurement variables
  • ne: If augmented_measurement is true, the number of measurement noise variables
  • innovation(y::AbstractVector, yh::AbstractVector) where the arguments represent (measured output, predicted output)
  • mean(ys::AbstractVector{<:AbstractVector}): computes the mean of the vector of vectors of output sigma points.
  • cov(ys::AbstractVector{<:AbstractVector}, y::AbstractVector): computes the covariance matrix of the output sigma points.
  • cross_cov(xs::AbstractVector{<:AbstractVector}, x::AbstractVector, ys::AbstractVector{<:AbstractVector}, y::AbstractVector) where the arguments represents (state sigma points, mean state, output sigma points, mean output). The function should return the cross-covariance matrix between the state and output sigma points.
source
LowLevelParticleFilters.UKFMeasurementModelMethod
UKFMeasurementModel{T,IPM,AUGM}(measurement, R2; nx, ny, ne = nothing, innovation = -, mean = safe_mean, cov = safe_cov, cross_cov = cross_cov, static = nothing)
  • T is the element type used for arrays
  • IPM is a boolean indicating if the measurement function is inplace
  • AUGM is a boolean indicating if the measurement model is augmented
source
LowLevelParticleFilters.UnscentedKalmanFilterMethod
UnscentedKalmanFilter(dynamics, measurement, R1, R2, d0=MvNormal(Matrix(R1)); p = NullParameters(), ny, nu)
 UnscentedKalmanFilter{IPD,IPM,AUGD,AUGM}(dynamics, measurement_model::AbstractMeasurementModel, R1, d0=SimpleMvNormal(R1); p=NullParameters(), nu)

A nonlinear state estimator propagating uncertainty using the unscented transform.

The dynamics and measurement function are on either of the following forms

x' = dynamics(x, u, p, t) + w
 y  = measurement(x, u, p, t) + e
x' = dynamics(x, u, p, t, w)
-y  = measurement(x, u, p, t, e)

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0. The former (default) assums that the noise is additive and added after the dynamics and measurement updates, while the latter assumes that the dynamics functions take an additional argument corresponding to the noise term. The latter form (sometimes refered to as the "augmented" form) is useful when the noise is multiplicative or when the noise is added before the dynamics and measurement updates. See "Augmented UKF" below for more details on how to use this form.

The matrices R1, R2 can be time varying such that, e.g., R1[:, :, t] contains the $R_1$ matrix at time index t. They can also be given as functions on the form

Rfun(x, u, p, t) -> R

For maximum performance, provide statically sized matrices from StaticArrays.jl

ny, nu indicate the number of outputs and inputs.

Custom type of u

The input u may be of any type, e.g., a named tuple or a custom struct. The u provided in the input data is passed directly to the dynamics and measurement functions, so as long as the type is compatible with the dynamics it will work out. The one exception where this will not work is when calling simulate, which assumes that u is an array.

Augmented UKF

If the noise is not additive, one may use the augmented form of the UKF. In this form, the dynamics functions take additional input arguments that correspond to the noise terms. To enable this form, the typed constructor

UnscentedKalmanFilter{inplace_dynamics,inplace_measurement,augmented_dynamics,augmented_measurement}(...)

is used, where the Boolean type parameters have the following meaning

  • inplace_dynamics: If true, the dynamics function operates in-place, i.e., it modifies the first argument in dynamics(dx, x, u, p, t). Default is false.
  • inplace_measurement: If true, the measurement function operates in-place, i.e., it modifies the first argument in measurement(y, x, u, p, t). Default is false.
  • augmented_dynamics: If true the dynamics function is augmented with an additional noise input w, i.e., dynamics(x, u, p, t, w). Default is false.
  • augmented_measurement: If true the measurement function is agumented with an additional noise input e, i.e., measurement(x, u, p, t, e). Default is false. (If the measurement noise has fewer degrees of freedom than the number of measurements, you may failure in Cholesky factorizations, see "Custom Cholesky factorization" below).

Use of augmented dynamics incurs extra computational cost. The number of sigma points used is 2L+1 where L is the length of the augmented state vector. Without augmentation, L = nx, with augmentation L = nx + nw and L = nx + ne for dynamics and measurement, respectively.

Sigma-point rejection

For problems with challenging dynamics, a mechanism for rejection of sigma points after the dynamics update is provided. A function reject(x) -> Bool can be provided through the keyword argument reject that returns true if a sigma point for $x(t+1)$ should be rejected, e.g., if an instability or non-finite number is detected. A rejected point is replaced by the propagated mean point (the mean point cannot be rejected). This function may be provided either to the constructor of the UKF or passed to the predict! function.

Custom measurement models

By default, standard arithmetic mean and e(y, yh) = y - yh are used as mean and innovation functions.

By passing and explicitly created UKFMeasurementModel, one may provide custom functions that compute the mean, the covariance and the innovation. This is useful in situations where the state or a measurement lives on a manifold. One may further override the mean and covariance functions for the state sigma points by passing the keyword arguments state_mean and state_cov to the constructor.

  • state_mean(xs::AbstractVector{<:AbstractVector}) computes the mean of the vector of vectors of state sigma points.
  • state_cov(xs::AbstractVector{<:AbstractVector}, m = mean(xs)) where the first argument represent state sigma points and the second argument, which must be optional, represents the mean of those points. The function should return the covariance matrix of the state sigma points.

See UKFMeasurementModel for more details on how to set up a custom measurement model. Pass the custom measurement model as the second argument to the UKF constructor.

Custom Cholesky factorization

The UnscentedKalmanFilter supports providing a custom function to compute the Cholesky factorization of the covariance matrices for use in sigma-point generation.

If either of the following conditions are met, you may experience failure in internal Cholesky factorizations:

  • The dynamics noise or measurement noise covariance matrices ($R_1, R_2$) are singular
  • The measurement is augmented and the measurement noise has fewer degrees of freedom than the number of measurements
  • (Under specific technical conditions) The dynamics is augmented and the dynamics noise has fewer degrees of freedom than the number of state variables. The technical conditions are easiest to understand in the linear-systems case, where it corresponds to the Riccati equation associated with the Kalman gain not having a solution. This may happen when the pair $(A, R1)$ has uncontrollable modes on the unit circle, for example, when there are integrating modes that are not affected through the noise.

The error message may look like

ERROR: PosDefException: matrix is not positive definite; Factorization failed.

In such situations, it is advicable to reconsider the noise model and covariance matrices, alternatively, you may provide a custom Cholesky factorization function to the UKF constructor through the keyword argument cholesky!. The function should have the signature cholesky!(A::AbstractMatrix)::Cholesky. A useful alternative factorizaiton when covariance matrices are expected to be singular is cholesky! = R->cholesky!(Positive, Matrix(R)) where the "positive" Cholesky factorization is provided by the package PositiveFactorizations.jl, which must be manually installed and loaded by the user.

source
LowLevelParticleFilters.combine!Method
combine!(imm::IMM)

Combine the models of the IMM filter into a single state imm.x and covariance imm.R. This is done by taking a weighted average of the states and covariances of the individual models, where the weights are the mixing probabilities μ.

source
LowLevelParticleFilters.commandplotFunction
commandplot(pf, u, y, p=parameters(pf); kwargs...)

Produce a helpful plot. For customization options (kwargs...), see ?pplot. After each time step, a command from the user is requested.

  • q: quit
  • s n: step n steps
Note

This function requires using Plots to be called before it is used.

source
LowLevelParticleFilters.correct!Function
(; ll, e, S, Sᵪ, K) = correct!(kf::AbstractKalmanFilter, u, y, p = parameters(kf), t::Integer = index(kf), R2)

The correct step for a Kalman filter returns not only the log likelihood ll and the prediction error e, but also the covariance of the output S, its Cholesky factor Sᵪ and the Kalman gain K.

If R2 stored in kf is a function R2(x, u, p, t), this function is evaluated at the state before the correction is performed. The measurement noise covariance matrix R2 stored in the filter object can optionally be overridden by passing the argument R2, in this case R2 must be a matrix.

Extended help

To perform separate measurement updates for different sensors, see the "Measurement models" in the documentation.

source
LowLevelParticleFilters.correct!Function
ll, e = correct!(pf, u, y, p = parameters(f), t = index(f))

Update state/weights based on measurement y, returns log-likelihood and prediction error (the error is always 0 for particle filters).

Extended help

To perform separate measurement updates for different sensors, see the "Measurement models" in the documentation. For AdvancedParticleFilter, this can be realized by passing a custom measurement_likelihood function as the keyword argument g to correct!, or by calling the lower-level function measurement_equation! with a custom measurement_likelihood.

source
LowLevelParticleFilters.correct!Function
correct!(kf::SqKalmanFilter, u, y, p = parameters(kf), t::Real = index(kf); R2 = get_mat(kf.R2, kf.x, u, p, t))

For the square-root Kalman filter, a custom provided R2 must be the upper triangular Cholesky factor of the covariance matrix of the measurement noise.

source
LowLevelParticleFilters.correct!Method
ll, lls, rest = correct!(imm::IMM, u, y, args; kwargs)

The correct step of the IMM filter corrects each model with the measurements y and control input u. The mixing probabilities imm.μ are updated based on the likelihood of each model given the measurements and the transition probability matrix P.

The returned tuple consists of the sum of the log-likelihood of all models, the vector of individual log-likelihoods and an array of the rest of the return values from the correct step of each model.

source
LowLevelParticleFilters.correct!Method
correct!(ukf::UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, u, y, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R2 = get_mat(ukf.R2, ukf.x, u, p, t), mean, cross_cov, innovation)

The correction step for an UnscentedKalmanFilter allows the user to override, R2, mean, cross_cov, innovation.

Arguments:

  • u: The input
  • y: The measurement
  • p: The parameters
  • t: The current time
  • R2: The measurement noise covariance matrix, or a function that returns the covariance matrix (x,u,p,t)->R2.
  • mean: The function that computes the mean of the output sigma points.
  • cross_cov: The function that computes the cross-covariance of the state and output sigma points.
  • innovation: The function that computes the innovation between the measured output and the predicted output.

Extended help

To perform separate measurement updates for different sensors, see the "Measurement models" in the documentation

source
LowLevelParticleFilters.debugplotFunction
debugplot(pf, u, y, p=parameters(pf); runall=false, kwargs...)

Produce a helpful plot. For customization options (kwargs...), see ?pplot.

  • runall=false: if true, runs all time steps befor displaying (faster), if false, displays the plot after each time step.

The generated plot becomes quite heavy. Initially, try limiting your input to 100 time steps to verify that it doesn't crash.

Note

This function requires using Plots to be called before it is used.

source
LowLevelParticleFilters.forward_trajectoryFunction
sol = forward_trajectory(pf, u::AbstractVector, y::AbstractVector, p=parameters(pf))

Run the particle filter for a sequence of inputs and measurements (offline / batch filtering). Return a solution with x,w,we,ll = particles, weights, expweights and loglikelihood

If MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.

sol can be plotted

plot(sol::ParticleFilteringSolution; nbinsy=30, xreal=nothing, dim=nothing)
source
LowLevelParticleFilters.forward_trajectoryFunction
forward_trajectory(imm::IMM, u, y, p = parameters(imm); interact = true)

When performing batch filtering using an IMM filter, one may

  • Override the interact parameter of the filter
  • Access the mode probabilities along the trajectory as the sol.extra field. This is a matrix of size (n_modes, T) where T is the length of the trajectory (length of u and y).

The returned solution object is of type KalmanFilteringSolution and has the following fields:

source
LowLevelParticleFilters.forward_trajectoryFunction
sol = forward_trajectory(kf::AbstractKalmanFilter, u::Vector, y::Vector, p=parameters(kf))

Run a Kalman filter forward to perform (offline / batch) filtering along an entire trajectory u, y.

Returns a KalmanFilteringSolution: with the following

  • x: predictions $x(t|t-1)$
  • xt: filtered estimates $x(t|t)$
  • R: predicted covariance matrices $R(t|t-1)$
  • Rt: filter covariances $R(t|t)$
  • ll: loglik

sol can be plotted

plot(sol::KalmanFilteringSolution; plotx = true, plotxt=true, plotu=true, ploty=true)

See KalmanFilteringSolution for more details.

Extended help

Very large systems

If your system is very large, i.e., the dimension of the state is very large, and the arrays u,y are long, this function may use a lot of memory to store all covariance matrices R, Rt. If you do not need all the information retained by this function, you may opt to call one of the functions

That store significantly less information. The amount of computation performed by all of these functions is identical, the only difference lies in what is stored and returned.

source
LowLevelParticleFilters.interact!Method
interact!(imm::IMM)

The interaction step of the IMM filter updates the state and covariance of each internal model based on the mixing probabilities imm.μ and the transition probability matrix imm.P.

Models with small mixing probabilities will have their states and covariances updated more towards the states and covariances of models with higher mixing probabilities, and vice versa.

source
LowLevelParticleFilters.logsumexp!Function
ll = logsumexp!(w, we [, maxw])

Normalizes the weight vector w and returns the weighted log-likelihood

https://arxiv.org/pdf/1412.8695.pdf eq 3.8 for p(y) https://discourse.julialang.org/t/fast-logsumexp/22827/7?u=baggepinnen for stable logsumexp

source
LowLevelParticleFilters.mean_trajectoryMethod
mean_trajectory(sol::ParticleFilteringSolution)
-mean_trajectory(x::AbstractMatrix, we::AbstractMatrix)

Compute the weighted mean along the trajectory of a particle-filter solution. Returns a matrix of size T × nx. If x and we are supplied, the weights are expected to be in the original space (not log space).

source
LowLevelParticleFilters.metropolisFunction
metropolis(ll::Function(θ), R::Int, θ₀::Vector, draw::Function(θ) = naive_sampler(θ₀))

Performs MCMC sampling using the marginal Metropolis (-Hastings) algorithm draw = θ -> θ' samples a new parameter vector given an old parameter vector. The distribution must be symmetric, e.g., a Gaussian. R is the number of iterations. See log_likelihood_fun

Example:

filter_from_parameters(θ) = ParticleFilter(N, dynamics, measurement, MvNormal(n,exp(θ[1])), MvNormal(p,exp(θ[2])), d0)
+y  = measurement(x, u, p, t, e)

where w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0. The former (default) assums that the noise is additive and added after the dynamics and measurement updates, while the latter assumes that the dynamics functions take an additional argument corresponding to the noise term. The latter form (sometimes refered to as the "augmented" form) is useful when the noise is multiplicative or when the noise is added before the dynamics and measurement updates. See "Augmented UKF" below for more details on how to use this form.

The matrices R1, R2 can be time varying such that, e.g., R1[:, :, t] contains the $R_1$ matrix at time index t. They can also be given as functions on the form

Rfun(x, u, p, t) -> R

For maximum performance, provide statically sized matrices from StaticArrays.jl

ny, nu indicate the number of outputs and inputs.

Custom type of u

The input u may be of any type, e.g., a named tuple or a custom struct. The u provided in the input data is passed directly to the dynamics and measurement functions, so as long as the type is compatible with the dynamics it will work out. The one exception where this will not work is when calling simulate, which assumes that u is an array.

Augmented UKF

If the noise is not additive, one may use the augmented form of the UKF. In this form, the dynamics functions take additional input arguments that correspond to the noise terms. To enable this form, the typed constructor

UnscentedKalmanFilter{inplace_dynamics,inplace_measurement,augmented_dynamics,augmented_measurement}(...)

is used, where the Boolean type parameters have the following meaning

  • inplace_dynamics: If true, the dynamics function operates in-place, i.e., it modifies the first argument in dynamics(dx, x, u, p, t). Default is false.
  • inplace_measurement: If true, the measurement function operates in-place, i.e., it modifies the first argument in measurement(y, x, u, p, t). Default is false.
  • augmented_dynamics: If true the dynamics function is augmented with an additional noise input w, i.e., dynamics(x, u, p, t, w). Default is false.
  • augmented_measurement: If true the measurement function is agumented with an additional noise input e, i.e., measurement(x, u, p, t, e). Default is false. (If the measurement noise has fewer degrees of freedom than the number of measurements, you may failure in Cholesky factorizations, see "Custom Cholesky factorization" below).

Use of augmented dynamics incurs extra computational cost. The number of sigma points used is 2L+1 where L is the length of the augmented state vector. Without augmentation, L = nx, with augmentation L = nx + nw and L = nx + ne for dynamics and measurement, respectively.

Sigma-point rejection

For problems with challenging dynamics, a mechanism for rejection of sigma points after the dynamics update is provided. A function reject(x) -> Bool can be provided through the keyword argument reject that returns true if a sigma point for $x(t+1)$ should be rejected, e.g., if an instability or non-finite number is detected. A rejected point is replaced by the propagated mean point (the mean point cannot be rejected). This function may be provided either to the constructor of the UKF or passed to the predict! function.

Custom measurement models

By default, standard arithmetic mean and e(y, yh) = y - yh are used as mean and innovation functions.

By passing and explicitly created UKFMeasurementModel, one may provide custom functions that compute the mean, the covariance and the innovation. This is useful in situations where the state or a measurement lives on a manifold. One may further override the mean and covariance functions for the state sigma points by passing the keyword arguments state_mean and state_cov to the constructor.

  • state_mean(xs::AbstractVector{<:AbstractVector}) computes the mean of the vector of vectors of state sigma points.
  • state_cov(xs::AbstractVector{<:AbstractVector}, m = mean(xs)) where the first argument represent state sigma points and the second argument, which must be optional, represents the mean of those points. The function should return the covariance matrix of the state sigma points.

See UKFMeasurementModel for more details on how to set up a custom measurement model. Pass the custom measurement model as the second argument to the UKF constructor.

Custom Cholesky factorization

The UnscentedKalmanFilter supports providing a custom function to compute the Cholesky factorization of the covariance matrices for use in sigma-point generation.

If either of the following conditions are met, you may experience failure in internal Cholesky factorizations:

  • The dynamics noise or measurement noise covariance matrices ($R_1, R_2$) are singular
  • The measurement is augmented and the measurement noise has fewer degrees of freedom than the number of measurements
  • (Under specific technical conditions) The dynamics is augmented and the dynamics noise has fewer degrees of freedom than the number of state variables. The technical conditions are easiest to understand in the linear-systems case, where it corresponds to the Riccati equation associated with the Kalman gain not having a solution. This may happen when the pair $(A, R1)$ has uncontrollable modes on the unit circle, for example, when there are integrating modes that are not affected through the noise.

The error message may look like

ERROR: PosDefException: matrix is not positive definite; Factorization failed.

In such situations, it is advicable to reconsider the noise model and covariance matrices, alternatively, you may provide a custom Cholesky factorization function to the UKF constructor through the keyword argument cholesky!. The function should have the signature cholesky!(A::AbstractMatrix)::Cholesky. A useful alternative factorizaiton when covariance matrices are expected to be singular is cholesky! = R->cholesky!(Positive, Matrix(R)) where the "positive" Cholesky factorization is provided by the package PositiveFactorizations.jl, which must be manually installed and loaded by the user.

source
LowLevelParticleFilters.combine!Method
combine!(imm::IMM)

Combine the models of the IMM filter into a single state imm.x and covariance imm.R. This is done by taking a weighted average of the states and covariances of the individual models, where the weights are the mixing probabilities μ.

source
LowLevelParticleFilters.commandplotFunction
commandplot(pf, u, y, p=parameters(pf); kwargs...)

Produce a helpful plot. For customization options (kwargs...), see ?pplot. After each time step, a command from the user is requested.

  • q: quit
  • s n: step n steps
Note

This function requires using Plots to be called before it is used.

source
LowLevelParticleFilters.correct!Function
(; ll, e, S, Sᵪ, K) = correct!(kf::AbstractKalmanFilter, u, y, p = parameters(kf), t::Integer = index(kf), R2)

The correct step for a Kalman filter returns not only the log likelihood ll and the prediction error e, but also the covariance of the output S, its Cholesky factor Sᵪ and the Kalman gain K.

If R2 stored in kf is a function R2(x, u, p, t), this function is evaluated at the state before the correction is performed. The measurement noise covariance matrix R2 stored in the filter object can optionally be overridden by passing the argument R2, in this case R2 must be a matrix.

Extended help

To perform separate measurement updates for different sensors, see the "Measurement models" in the documentation.

source
LowLevelParticleFilters.correct!Function
ll, e = correct!(pf, u, y, p = parameters(f), t = index(f))

Update state/weights based on measurement y, returns log-likelihood and prediction error (the error is always 0 for particle filters).

Extended help

To perform separate measurement updates for different sensors, see the "Measurement models" in the documentation. For AdvancedParticleFilter, this can be realized by passing a custom measurement_likelihood function as the keyword argument g to correct!, or by calling the lower-level function measurement_equation! with a custom measurement_likelihood.

source
LowLevelParticleFilters.correct!Function
correct!(kf::SqKalmanFilter, u, y, p = parameters(kf), t::Real = index(kf); R2 = get_mat(kf.R2, kf.x, u, p, t))

For the square-root Kalman filter, a custom provided R2 must be the upper triangular Cholesky factor of the covariance matrix of the measurement noise.

source
LowLevelParticleFilters.correct!Method
ll, lls, rest = correct!(imm::IMM, u, y, args; kwargs)

The correct step of the IMM filter corrects each model with the measurements y and control input u. The mixing probabilities imm.μ are updated based on the likelihood of each model given the measurements and the transition probability matrix P.

The returned tuple consists of the sum of the log-likelihood of all models, the vector of individual log-likelihoods and an array of the rest of the return values from the correct step of each model.

source
LowLevelParticleFilters.correct!Method
correct!(ukf::UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, u, y, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R2 = get_mat(ukf.R2, ukf.x, u, p, t), mean, cross_cov, innovation)

The correction step for an UnscentedKalmanFilter allows the user to override, R2, mean, cross_cov, innovation.

Arguments:

  • u: The input
  • y: The measurement
  • p: The parameters
  • t: The current time
  • R2: The measurement noise covariance matrix, or a function that returns the covariance matrix (x,u,p,t)->R2.
  • mean: The function that computes the mean of the output sigma points.
  • cross_cov: The function that computes the cross-covariance of the state and output sigma points.
  • innovation: The function that computes the innovation between the measured output and the predicted output.

Extended help

To perform separate measurement updates for different sensors, see the "Measurement models" in the documentation

source
LowLevelParticleFilters.debugplotFunction
debugplot(pf, u, y, p=parameters(pf); runall=false, kwargs...)

Produce a helpful plot. For customization options (kwargs...), see ?pplot.

  • runall=false: if true, runs all time steps befor displaying (faster), if false, displays the plot after each time step.

The generated plot becomes quite heavy. Initially, try limiting your input to 100 time steps to verify that it doesn't crash.

Note

This function requires using Plots to be called before it is used.

source
LowLevelParticleFilters.forward_trajectoryFunction
sol = forward_trajectory(kf::AbstractKalmanFilter, u::Vector, y::Vector, p=parameters(kf))

Run a Kalman filter forward to perform (offline / batch) filtering along an entire trajectory u, y.

Returns a KalmanFilteringSolution: with the following

  • x: predictions $x(t|t-1)$
  • xt: filtered estimates $x(t|t)$
  • R: predicted covariance matrices $R(t|t-1)$
  • Rt: filter covariances $R(t|t)$
  • ll: loglik

sol can be plotted

plot(sol::KalmanFilteringSolution; plotx = true, plotxt=true, plotu=true, ploty=true)

See KalmanFilteringSolution for more details.

Extended help

Very large systems

If your system is very large, i.e., the dimension of the state is very large, and the arrays u,y are long, this function may use a lot of memory to store all covariance matrices R, Rt. If you do not need all the information retained by this function, you may opt to call one of the functions

That store significantly less information. The amount of computation performed by all of these functions is identical, the only difference lies in what is stored and returned.

source
LowLevelParticleFilters.forward_trajectoryFunction
sol = forward_trajectory(pf, u::AbstractVector, y::AbstractVector, p=parameters(pf))

Run the particle filter for a sequence of inputs and measurements (offline / batch filtering). Return a solution with x,w,we,ll = particles, weights, expweights and loglikelihood

If MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.

sol can be plotted

plot(sol::ParticleFilteringSolution; nbinsy=30, xreal=nothing, dim=nothing)
source
LowLevelParticleFilters.forward_trajectoryFunction
forward_trajectory(imm::IMM, u, y, p = parameters(imm); interact = true)

When performing batch filtering using an IMM filter, one may

  • Override the interact parameter of the filter
  • Access the mode probabilities along the trajectory as the sol.extra field. This is a matrix of size (n_modes, T) where T is the length of the trajectory (length of u and y).

The returned solution object is of type KalmanFilteringSolution and has the following fields:

source
LowLevelParticleFilters.interact!Method
interact!(imm::IMM)

The interaction step of the IMM filter updates the state and covariance of each internal model based on the mixing probabilities imm.μ and the transition probability matrix imm.P.

Models with small mixing probabilities will have their states and covariances updated more towards the states and covariances of models with higher mixing probabilities, and vice versa.

source
LowLevelParticleFilters.logsumexp!Function
ll = logsumexp!(w, we [, maxw])

Normalizes the weight vector w and returns the weighted log-likelihood

https://arxiv.org/pdf/1412.8695.pdf eq 3.8 for p(y) https://discourse.julialang.org/t/fast-logsumexp/22827/7?u=baggepinnen for stable logsumexp

source
LowLevelParticleFilters.mean_trajectoryMethod
mean_trajectory(sol::ParticleFilteringSolution)
+mean_trajectory(x::AbstractMatrix, we::AbstractMatrix)

Compute the weighted mean along the trajectory of a particle-filter solution. Returns a matrix of size T × nx. If x and we are supplied, the weights are expected to be in the original space (not log space).

source
LowLevelParticleFilters.metropolisFunction
metropolis(ll::Function(θ), R::Int, θ₀::Vector, draw::Function(θ) = naive_sampler(θ₀))

Performs MCMC sampling using the marginal Metropolis (-Hastings) algorithm draw = θ -> θ' samples a new parameter vector given an old parameter vector. The distribution must be symmetric, e.g., a Gaussian. R is the number of iterations. See log_likelihood_fun

Example:

filter_from_parameters(θ) = ParticleFilter(N, dynamics, measurement, MvNormal(n,exp(θ[1])), MvNormal(p,exp(θ[2])), d0)
 priors = [Normal(0,0.1),Normal(0,0.1)]
 ll     = log_likelihood_fun(filter_from_parameters,priors,u,y,1)
 θ₀ = log.([1.,1.]) # Initial point
@@ -17,9 +17,9 @@
 # thetam = reduce(hcat, theta)'
 @time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 5000, θ₀, draw) # run on all threads, will provide (2000-burnin)*nthreads() samples
 histogram(exp.(thetalls[:,1:2]), layout=3)
-plot!(thetalls[:,3], subplot=3) # if threaded call, log likelihoods are in the last column
source
LowLevelParticleFilters.simulateFunction
x,u,y = simulate(f::AbstractFilter, T::Int, du::Distribution, p=parameters(f), [N]; dynamics_noise=true, measurement_noise=true)
-x,u,y = simulate(f::AbstractFilter, u, p=parameters(f); dynamics_noise=true, measurement_noise=true)

Simulate dynamical system forward in time T steps, or for the duration of u. Returns state sequence, inputs and measurements.

  • u is an input-signal trajectory, alternatively, du is a distribution of random inputs.

A simulation can be considered a draw from the prior distribution over the evolution of the system implied by the selected noise models. Such a simulation is useful in order to evaluate whether or not the noise models are reasonable.

If MonteCarloMeasurements.jl is loaded, the argument N::Int can be supplied, in which case N simulations are done and the result is returned in the form of Vector{MonteCarloMeasurements.Particles}.

source
LowLevelParticleFilters.simulateFunction
x,u,y = simulate(f::AbstractFilter, T::Int, du::Distribution, p=parameters(f), [N]; dynamics_noise=true, measurement_noise=true)
+x,u,y = simulate(f::AbstractFilter, u, p=parameters(f); dynamics_noise=true, measurement_noise=true)

Simulate dynamical system forward in time T steps, or for the duration of u. Returns state sequence, inputs and measurements.

  • u is an input-signal trajectory, alternatively, du is a distribution of random inputs.

A simulation can be considered a draw from the prior distribution over the evolution of the system implied by the selected noise models. Such a simulation is useful in order to evaluate whether or not the noise models are reasonable.

If MonteCarloMeasurements.jl is loaded, the argument N::Int can be supplied, in which case N simulations are done and the result is returned in the form of Vector{MonteCarloMeasurements.Particles}.

source
LowLevelParticleFilters.smoothFunction
xT,RT,ll = smooth(sol, kf)
 xT,RT,ll = smooth(kf::KalmanFilter, u::Vector, y::Vector, p=parameters(kf))
-xT,RT,ll = smooth(kf::ExtendedKalmanFilter, u::Vector, y::Vector, p=parameters(kf))

Returns smoothed estimates of state x and covariance R given all input output data u,y or an existing solution sol obtained from forward_trajectory.

source
LowLevelParticleFilters.update!Function
ll, e = update!(f::AbstractFilter, u, y, p = parameters(f), t = index(f))

Perform one step of predict! and correct!, returns log-likelihood and prediction error

source
LowLevelParticleFilters.update!Method
update!(imm::IMM, u, y, p, t; correct_kwargs = (;), predict_kwargs = (;), interact = true)

The combined udpate for an IMM filter performs the following steps:

  1. Correct each model with the measurements y and control input u.
  2. Combine the models into a single state and covariance.
  3. Interact the models to update their respective state and covariance.
  4. Predict each model to the next time step.

This differs slightly from the udpate step of other filters, where at the end of an update the state of the filter is the one-step ahead predicted value, whereas here each individual filter has a predicted state, but the combine! step of the IMM filter hasn't been performed on the predictions yet. The state of the IMM filter is thus $x(t|t)$ and not $x(t+1|t)$ like it is for other filters, and each filter internal to the IMM.

Arguments:

  • correct_kwargs: An optional named tuple of keyword arguments that are sent to correct!.
  • predict_kwargs: An optional named tuple of keyword arguments that are sent to predict!.
  • interact: Whether or not to run the interaction step.
source
StatsAPI.predict!Function
predict!(f, u, p = parameters(f), t = index(f))

Move filter state forward in time using dynamics equation and input vector u.

source
StatsAPI.predict!Function
predict!(kf::SqKalmanFilter, u, p = parameters(kf), t::Real = index(kf); R1 = get_mat(kf.R1, kf.x, u, p, t), α = kf.α)

For the square-root Kalman filter, a custom provided R1 must be the upper triangular Cholesky factor of the covariance matrix of the process noise.

source
StatsAPI.predict!Function
predict!(kf::AbstractKalmanFilter, u, p = parameters(kf), t::Integer = index(kf); R1, α = kf.α)

Perform the prediction step (updating the state estimate to $x(t+1|t)$). If R1 stored in kf is a function R1(x, u, p, t), this function is evaluated at the state before the prediction is performed. The dynamics noise covariance matrix R1 stored in kf can optionally be overridden by passing the argument R1, in this case R1 must be a matrix.

source
StatsAPI.predict!Method
predict!(ukf::UnscentedKalmanFilter, u, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R1 = get_mat(ukf.R1, ukf.x, u, p, t), reject, mean, cov, dynamics)

The prediction step for an UnscentedKalmanFilter allows the user to override, R1 and any of the functions, reject, mean, cov, dynamics`.

Arguments:

  • u: The input
  • p: The parameters
  • t: The current time
  • R1: The dynamics noise covariance matrix, or a function that returns the covariance matrix.
  • reject: A function that takes a sigma point and returns true if it should be rejected.
  • mean: The function that computes the mean of the state sigma points.
  • cov: The function that computes the covariance of the state sigma points.
source
LowLevelParticleFilters.prediction_errors!Function
prediction_errors!(res, f::AbstractFilter, u, y, p = parameters(f), λ = 1)

Calculate the prediction errors and store the result in res. Similar to sse, this function is useful for sum-of-squares optimization. In contrast to sse, this function returns the residuals themselves rather than their sum of squares. This is useful for Gauss-Newton style optimizers, such as LeastSquaresOptim.LevenbergMarquardt.

Arguments:

  • res: A vector of length ny*length(y). Note, for each datapoint in u and u, there are ny outputs, and thus ny residuals.
  • f: Any filter
  • λ: A weighting factor to minimize dot(e, λ, e). A commonly used metric is λ = Diagonal(1 ./ (mag.^2)), where mag is a vector of the "typical magnitude" of each output. Internally, the square root of W = sqrt(λ) is calculated so that the residuals stored in res are W*e.

See example in Solving using Gauss-Newton optimization.

source
+xT,RT,ll = smooth(kf::ExtendedKalmanFilter, u::Vector, y::Vector, p=parameters(kf))

Returns smoothed estimates of state x and covariance R given all input output data u,y or an existing solution sol obtained from forward_trajectory.

source
LowLevelParticleFilters.update!Function
ll, e = update!(f::AbstractFilter, u, y, p = parameters(f), t = index(f))

Perform one step of predict! and correct!, returns log-likelihood and prediction error

source
LowLevelParticleFilters.update!Method
update!(imm::IMM, u, y, p, t; correct_kwargs = (;), predict_kwargs = (;), interact = true)

The combined udpate for an IMM filter performs the following steps:

  1. Correct each model with the measurements y and control input u.
  2. Combine the models into a single state and covariance.
  3. Interact the models to update their respective state and covariance.
  4. Predict each model to the next time step.

This differs slightly from the udpate step of other filters, where at the end of an update the state of the filter is the one-step ahead predicted value, whereas here each individual filter has a predicted state, but the combine! step of the IMM filter hasn't been performed on the predictions yet. The state of the IMM filter is thus $x(t|t)$ and not $x(t+1|t)$ like it is for other filters, and each filter internal to the IMM.

Arguments:

  • correct_kwargs: An optional named tuple of keyword arguments that are sent to correct!.
  • predict_kwargs: An optional named tuple of keyword arguments that are sent to predict!.
  • interact: Whether or not to run the interaction step.
source
StatsAPI.predict!Function
predict!(f, u, p = parameters(f), t = index(f))

Move filter state forward in time using dynamics equation and input vector u.

source
StatsAPI.predict!Function
predict!(kf::SqKalmanFilter, u, p = parameters(kf), t::Real = index(kf); R1 = get_mat(kf.R1, kf.x, u, p, t), α = kf.α)

For the square-root Kalman filter, a custom provided R1 must be the upper triangular Cholesky factor of the covariance matrix of the process noise.

source
StatsAPI.predict!Function
predict!(kf::AbstractKalmanFilter, u, p = parameters(kf), t::Integer = index(kf); R1, α = kf.α)

Perform the prediction step (updating the state estimate to $x(t+1|t)$). If R1 stored in kf is a function R1(x, u, p, t), this function is evaluated at the state before the prediction is performed. The dynamics noise covariance matrix R1 stored in kf can optionally be overridden by passing the argument R1, in this case R1 must be a matrix.

source
StatsAPI.predict!Method
predict!(ukf::UnscentedKalmanFilter, u, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R1 = get_mat(ukf.R1, ukf.x, u, p, t), reject, mean, cov, dynamics)

The prediction step for an UnscentedKalmanFilter allows the user to override, R1 and any of the functions, reject, mean, cov, dynamics`.

Arguments:

  • u: The input
  • p: The parameters
  • t: The current time
  • R1: The dynamics noise covariance matrix, or a function that returns the covariance matrix.
  • reject: A function that takes a sigma point and returns true if it should be rejected.
  • mean: The function that computes the mean of the state sigma points.
  • cov: The function that computes the covariance of the state sigma points.
source
LowLevelParticleFilters.prediction_errors!Function
prediction_errors!(res, f::AbstractFilter, u, y, p = parameters(f), λ = 1)

Calculate the prediction errors and store the result in res. Similar to sse, this function is useful for sum-of-squares optimization. In contrast to sse, this function returns the residuals themselves rather than their sum of squares. This is useful for Gauss-Newton style optimizers, such as LeastSquaresOptim.LevenbergMarquardt.

Arguments:

  • res: A vector of length ny*length(y). Note, for each datapoint in u and u, there are ny outputs, and thus ny residuals.
  • f: Any filter
  • λ: A weighting factor to minimize dot(e, λ, e). A commonly used metric is λ = Diagonal(1 ./ (mag.^2)), where mag is a vector of the "typical magnitude" of each output. Internally, the square root of W = sqrt(λ) is calculated so that the residuals stored in res are W*e.

See example in Solving using Gauss-Newton optimization.

source
diff --git a/dev/beetle_example/04bb4f6c.png b/dev/beetle_example/04bb4f6c.png deleted file mode 100644 index 9ad77ed847555bd8532bec8e38e0d659e598b621..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77111 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

pC-UVd39f5Ci9alG4T_`(|ar0s`~f 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�T4Qqwg7wnDyUz{Yr_J&)|;j>=WLqF3e{ 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 b!xU|Q#ReySM{UezA6yr8jI_%!_7VRFH!nTS diff --git a/dev/beetle_example/0c78f876.png b/dev/beetle_example/0c78f876.png new file mode 100644 index 0000000000000000000000000000000000000000..1402c948f3f35b81cc9e5652e0048fa858ba4142 GIT binary patch literal 81319 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

it2%%P_0d~`f`W;G+V{j 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 literal 0 HcmV?d00001 diff --git a/dev/beetle_example/18eca807.png b/dev/beetle_example/18eca807.png new file mode 100644 index 0000000000000000000000000000000000000000..37f4dbea5b1f7b831fae034c721ecbd9df73cb6a GIT binary patch literal 55912 zcma%jbySsG^exRHJv7n>5D_V9X%3CFG)RL8NJ)2hH_{+d(jX!&4bqLINOw29&3)rH z#{1*FG2Xf34wQr6`M$l^nrqIv)+S6@Q5px63=;tX0Y_FwLKOi4@f7^e3_$|l`8hk4 z4Zffmzmb+eczFCTr@1fz0f7cVRzgh8HDlMyB}31w`QD@dcbdM-_Z0fZ577A7SY~hy z)G=<9F1+aryQaKrUcy%QCEE^dUEHf}s$tE*!mgIC82s&@&SuOE2jUK_S& zg0Cy=C|LX0;1vSXvU_i6Xvl}%?l188vqli&`KP3$q`2ah%R_B#ZFZ#os4i$|Xu%y& z<{zBw?Ccc5|8t4X3G@q({f3@{ix_YDT;56MSM!w0{#4qJo!5PJs1i5&1?8GZA#ew$+Ukc%p{KK0Y3~Lt{X>c06fb7 z@hty8AKfCtm@+`^bNkABvDw3gHjYn}jW9~8@#oJHZyj}Yk^4&%b@ftjbFfwcD9k@% zFy5rFW@`F5@;6(I<{4MXK(3BcT5qRxZSmmuw;LiN7xSMcy%t37k7A|`e7u~7Wg&fQ z4iUsGs)PmG@6ExM$k>H)zfvIj{_)TGT9snogp7RvR|+ zBEJ4bdfc&lROV0AFX!gw)_28(vkmHP-ZkibZC&{3v@@(|HG~Jx>OCv)#9gUuu?n-t5)e zgH6_|w^;~#p7q21Y+ICu{Z?+?=HfHARWggN^LpC*`^z4YZZiqmxR(`8$7j<9B0Jw| zhWJ*oufw~Hk8VIL$Ue_>yjn{UdAL2(^&H9V>_2(|Q5YOvBC{ zIJ~E4XLtXei}aatlxkM+kYZb(w1eErv1}KLlMy`m&ADRtBR_xDAB$DgH^I!UBN(Sj zYj?M1n2PEP1E%`fg0tj{r)9?}Z_ZjxeY?6l z@G)>Jk!LsopYGADUpOuc(FUvkR!OJ}U{HsV?>5Rsd3pI7xV(1tzs>v@@9pA3VphGG z#l@`QjmPVL{rWWsi{vqEVnEuVlISTXrQD$Nm9Iqi<>T#x&?tD5@^?dxiTk=;NJywa z^}}qn*=byYB0q)*&Gl-k1Z|aRAHMtVAQJslxq`n(uF}%zRB7B+Q-{mysy@t zXV}5T#l>xHZTU01SJ46xUwwueS81shCzh1xSGdg8esHzBKHU;moLpKmU`-hoy3o7s zeSGq3T@#SH^vapb-g|Y^`c9MTBA4w?n5aF$ZD9ueIvEyWgTO)jQo78mtSx)T`fa!| zv07VLKv7mQT^2_z>%?&hQ2eM??f8T*myx4aH*M9`xk<5wv!5I-tR7+eb2)!f{ypr8;Ko0XLXLkHoWGOz}~g)$xg5x~*Z8H*V3 z!+4iGPfAM5-5=M<>sRt~ z8Y|$Pw-aYbfCcW(RGEx_RS=H`OTWrOJaEza;3cV|rha!it_0Ab-+sOzMc=)L(&gXD zRZC0D+0OJ6A6TYh{ih8@b#)JScklC>>?m(_kg|gcybHBnH|HQO*i`MDs zX^-Z`*PqsxNmB-%h38H0P-ek`J66!CJrC2~XSMt2>gY^;)8_m~Dyb4&*p?7>b+SPo zC3S5e1|??J@{N2foEoJ`P=~%}Dc18pj!v>4ZZlqgnyN5(NME{LZ(O?DZ*n`Sp0(E1 z{qxRcK@#%8#)c<-kS|Os-wgm->q+Lp?~KOiJeC@d`(LJi{tTeHy!HP2%a|m0 z`lb?8f~hGDW=@k%P+^__e5}uO=zoE}zD;_Mc#ZQum4afMR}YH9H2H_TB({Nt1uh>!W9I0 z%kA;N=BUp~5Q(DTk;DiIc0!ohK(f%yZjHh9SjyuT-`^ZePfW<45xrt(mq#nfPj1*L zZ!B-Q-UjI63dj+Nc9FX+B@7rSgiRY+9va`YUisX67L}DA>qsNHdw3`?0DePuK(JuL zJA5MUECc>QzNHMvIXaZdDrzkNw+0W_(*U)SUTT8%Eof=Ug654{EPCJUvH4sLeEj&4 zoY&?X;ag7Z_VRa)m9$7!)8%)2wmyy28*a;f=;y`RMgUasmFsXPwQI}=K^f`|;LqI0 zGPwK|+QX>^O3wx;bGO&it-_NezW`}V^?e!=h4JV6$D7^vA_6Y^^8`wQM<5KI1vXu+ zr#~XVg3FTE?^it;KKEB%US5D8oQ@T|Q35p+e4k`kjv-+h#Ce`%#L(-F3{3+sq9-LK z?n_=5nT}(!1Ia9nV9nIk6$;0}jV@G~^vu4`_F8n?SgF)vc0QZb98Tvwcw=ylFR>XI z3m`zfRD(sUayc)8H7~O?SJ`5+M7@XN)9;77)(4Vm_eXLmF7RU`T#hMQ82S+0Gy=+I zjd52vxDyvpjB4HwGX!4V-J?^vwpsJEg4_Y?m3{U5{r!1;>)pOfYvXS9KzY-#oS+rB z@TkS<6Q9ct@Xp>Fwr0W;q5al}dw@YA*PxI9jCm|;tJDuOhU|JS3r^#ON)K1VKKCQy zPgWWp-%irhzv>aWx3{x9%<|ZW1=1(8M z-Y4mSu|7BTJ|4SOJ;Jw#;+cvrkM+Xm?rhYeR*SjibnMNF-Hc5=FE{r)x3#2Jz*ML_ z58EFp3Mc@uQuqjL`YxDvW2}e;MCmZM{8yp6z)oI*;?X54a(Ab{mk3(xfL!LsoZxNm_pZ z=Hq?YLCvaDyBQ*K3)5>OBO^Q14QMy4|1+uspq5^?nwjofzCt2&Y;+W{$2q1)T;Unu zBMUYcp%pSpHe6&YnUO82S=`C{0si5Sexwt#+iwI9}!{+g!IPmv{i=&Z?HZ7zZ}R~E z?n0cn>GB!Qb01t5-JYAvyrSTv*cR3Zp#Y+7$l~e$T@3y|1yrcG(gsyb&okN2+ogP} zzG6C$s*?h@YI$*S5qE$k7#UMt{dF{5phca|6j4{39phgp*8W6i#)|J>8H*#3QcdlA z{}%yj#H7NSLL{j|XqKHdj7?aeTCB_{-@rB{7A+q6>AfM}Z)K*W%_oAx@nv55TFmA( zvknc+5dTpNiM4DazDLcQDmOCI=|2G_#6*>_Q@KrHS7%MBnPu)y;O6FjWpujO_Q*xm z;DnOVs}d>{_`jm<5(m~C8orfS7OUZ-j4L=q_|FkY!1*!*Ia+gg8tEpSJ-l(!JCEg|%uGxq`6^A` zHCDLGkXs_@wz|4{;W&nW z4x?PIa;%v)G*FNAJr^0?-=mkZ@j0|>e9;Aag#UR8@=VGvBrm5d>+GnAP!P9MREs<9 z^#rNd!1BV|jjJI3v4iFWVS&>-YkWf%T)5cSfgMKb>bknREW}u_PE(HAJ!hGiZVw@v z9k;CP;~>O8(UyJQk9*7~?~DJe#~%F?Cn5d`JXaKghl2Pmf(9Zud?HveYT=rdV)i;o z&Wz(JJXF7;$9UPfalyu=N^4^0ELWK^O&-&K`Qk=wAW^PBjj3RK3mdKDhkt%aiPk&l z(v#RMe2=(MUg82(3{BOtYQ)FI3!#d=!iO`REikI!KQcP8m)GljAo&~`A}9XZG};e1jfq zlHBSxX%VY*%oEhyrvp+|T7)Qw5v+^%i^=*-XT{0i5`aS!EdB)QyNce)A?Oc*`=nBg z{3F4*6pkU0#A}a6o9h1tE)&wR;^&7L(__L#row;|1b_GL-In8=DF-(f*XG%^L&L5e zA2V^pto8R#f2D;s~##;j4wo65@4LC42Tz!yz!ChyM}E?)aU@E^p4 zP|=XV0!0y`6{$^+-Wr?44y=WDsW_en;7wt`Hg%8+aI5I363w1|u%(R)m7ooR z1NKBi7IiFm;K+}Ih79Z6a{Mg+_4{`o5T4s;O4)E>OaX-IkmOuyl>3O4|XHH z(W)n%nih|-jZ2&J4BdvaW0i1C7ut^jo3$oR*2moG<3jhW64Gdy> zaZB7WiP!{(HGihAcp06sB*}q|P-fgbb0?dRTL$^>DLiaHuf-#@iuAbp=y)SVVe`&1 zxY20TwT>D#w*VaY6jc(fdD7(>6d2wD`DXTJ!%wPMEuKE?x-HV1{rD}4fQ04Y=zsAP z)Ug62;{N_V@B&Ra(&P&I*BlrUa!pZ9IeF5fHm(fWNg*h}UVHJhpk$k#%{m{M`dRWH zP=_HZgwIk20Cur|C{TTosVGg0r$V^r+&I3~DXm9j9Q7E90T7SU1~FCmIf`^|M=`2k zk9`mvMjYYyls$cr0AoKXKBfvG9Xo4dr965tq@;vS?mBjnAwiaY4&>70s2URyHkuHX z();%t`wNXQ=P%dUuoRNV%FVg?8N2`=u;#I<|5NxyhzRS6Fr-r6HKtN&#DXi25sn^q zuERVw;v3vy^uIB4?HH6tRI$oGdy{jXkA^0DQjU{kv%XRp^qDN#F$pe7IPxo$egzx~Kg^Mz5;JJthF4gwX7<~pB@UXnI_C37bd-N4SAbvrx)LgL zEfqPSoT{A3=cQLVDV48sS)Rj9{dTkMD*D2m=^6F1()sL9jCH?z7e`s@qH}mIG)zLY zg)RzpDPD#i;5;KC*|Tb7NHlOnE-N}#V$Eg^*?X(4Ino%)zJ;rzmrFxYoSrBv_O3ZN zjwRDTG)jqh<)A2)C(xVKJ(G`gffJLH+GSH=2IPu69HFITDK z{b;|fzAt(K<;!87u;5}yzz`A^&wH5h`$Fz-FB=baKc77d&yiX%w0Pm#`3x}~8*EXS z#Ml-W3eSpNDilAWE56TEkP2N$h~HE@T7nkZbt2g6abXiBwd%+p(M4-RHzWv551&lL zqF25G{x>*OJq|^TK&c?|7EJGaYRFJ5>_8993>n_YKQmQJrHc!tfw+PB;3{kRsAE-uf)mJ+RG6cC~sZfg@| zC;jr`a8sGk3_xO>3~&i0XaSKTCnpCm+@MD+i6@Zmh34{;!^obDE-tChw5@~yPNNQw z6Hi_PAsQvstk2euR;Bd~xB@TH|7C%k_?dHme-Ch{&$Ke;1#v`}#4qD25G#|@(@IU> zbOx92&;Qs0r+Mp9P~KfE#Yo#UtR;s~xr0Cp%ex$V!v>7|vT(K@V22{a^Qrx_<{^)_ zkCH+zH?dX04++aleWYD_v~j*UBgR$#PTY18f~8HFF+9@wF!wNVMW2c$o9$xI%aWPZ z0Yjn)=j-@Za4=dEtN;38mUq?$3>_OSz@LVX0yk2XjDjK%$)SmtJx->#I%CirIBV&H z&W+7wWkAWM4X%6PUziRn`bVFZ&L64udsj}x2?>(I=zFN{XRvc-8%EMp_2F>$Ff7CBW&rrtn z;8DC#h@lR)qn!D8=_%a0q*RXz%;%H=N!qw76Y(??MR7)C1>G)K;eikjB#u+azS!NEoj2P{mT5ofB_`Ixzj024(DQw&C>{f z5psYH?KRcLMGF89QTFir8trENm_#32R8@Y;unjl*0kv{YQ`t6DAh?tn6Z=emn{z@i zFL5G^EUD>6=E$O?s{CTj+_EXvA@ejlD(jP5jv$Il8T6^H}EV>Si7_U1tfS^__ zo|u{0wBzGQi(ER0k;+e#N4wwwtEKuPpdBz86+RF)B_*`FnuO1&Vod(TDHZ|{P%PZp z+eNjxikc*A9PMywTu zC%p_fxJ;Tr1|1^1aeY2E(`F^al*x|s(4fMAQ^@i%ImukdKETZb-Wqjxg?3_P;nE`2 zVwk0^(E7@A5@KF?ws;B~=<0%ipuk0!H>nh)iRy~*Z*Gs6v*t0iRdeF}$C6_~5hVrC zjKu^nkk+N_KGSZQx)?|ah4hXxZJa1QH(8X&pB|bowBJlRzthVmhQNsOIXCm(eDnZp z4QLk$+J%LMK2!WixduIe(m+4N$+W2;@M|8v)+y5{95<`chKP2o*a6@CSk|MWQa4;G z-vpL;9>#>?BB=sQ*c$Jpaf*n3a&B!wOX zjFGx1wZd9RsP$)#UM^4NlM8tU0tgCN6|jjCw7^DBQkCzpu(1i=qh$@)Ee@qUQ!G#o z&m)YGbR-&OkJ^-tVI#x@%4hXR6iuHsC86)j(t%6kf_JOWrHx4wFK3cm!@@p5tjURq zT3`*-)+$S0K@F$SVJPD_v~iH_JjFr+2a>D}f-niDq_LedKx`_eR~0}*N``)He0=rf z3ds*4GBiqxP9s#A5oG}7+tX@hD=t86$f8$8M{^`!rVoOqm$i1VExqd0i12I_wNfC!-s`$cDqOn^mKLK$a0rb zovWr9aIYWI0ZQB<#D@EvpFa~fKv%48z!-8}`4v>r zd`=eacCp|BY8^04p5Hq>;!P1Jwq>r&zgJjBKv6DJR6Lv;fsmb`dR&Cdq3-4U7d+SMd(!jxR%nx9i_-2ny2&?2=+|SEZAx zulT%Jr-)?Z{~qz->slAOvY8_8dLFeSmQ0Q$aFCqhwV zO%abEhM^df!b4}RyB#8$heElyVf2}bnr5cbN$IJIuh$5FW;N=S18e(CTI6~Z*rQ&v zW+@B6AD#4K0cx787f~!&?OGtuI82b_HyQ**I~h-Rr5LbOppo?}&_fW^xi$QO7%{E_ z&Q&ggST-Tb90)-*>sfM&->U60_EU&ju<0QhyNv#q zx#9LL#Zbmmm^xWBq{B}D8q-50=~v+^l@G9wI0BW{1+Z#tG`cuQ_{>Q6$O489B_s1U zef~^PM^^SqOTvk45-$YsR-lqe0XIaNdMZ~-&)y_IHlQcHFhGwG+0hVnlf-ms^GJ+K zLM8|wh95@L0sJcciu%Sz;B5j8pE98S_APQhsYJ-Y8t8~Yq#TV#wj5<<#6DWp>7);8 z6#I&*69-}tr#m!QbCHd*7msh{^oi+&XQ|Sc-WL)<0DEs2cW6K#xU9d@0!%&C;(w0(Tk!!%Xlh@8r4aGV`@2pVL&6JSwRISA zN!8WW8Kp(`tO6#xbN0)|8)6bYZplTKsTh((8e>8iBndAZH&XBT#q*b3%-*>5phIMs z^XM&@{D>rx`O~q&?nuVP@t4gYf3)p8Ngv-|I^*&`d)=XV%8bAnhkkL*dV+#frG>qL zcobC$$dv*E!8v-I41M|_D5n-}A-ybZxG;00J~6syNRAw75?np6Pp+EU4P)uUSTSfq zEv>9Z(URl}Bvfi=tu2&6kmH5~K>cqiTQ&gUnCGGurvG=d=N@eJh9RL=n~)4x=Ly3b zKq~gwo7X%giE#<%#p*z4T^hCrJTRb*kl-Fr*)C(m>A*EkQfy#Kx7&F4mad}DIp|%z zygbi&i$VTX#o?riUCrb_JL)Y$Xn*kwOe!u?Y-om|p<|VngkVr7a2;ZL#{c{w2N!EM z1V%*~p))IBemiGi;bh~%O&c+Vjp;S$1tU<@3A+x%_Y^Cn2_-?WF}No2H z=7cru!X@4w5e%i3jR%ecFkcg1B+0?9#pQ}dEtVZaqx(f^d?Nyj@K|+bKK51v%MA3X z13#_Uk%oIDx&f22XBANw#|u`3-K6mEz~o@5y#!&B?%G7>Kou142EB4+##)byeR&4tV9E^aA|Gp#Selr)M1-iOW`lG_WXfe~aW1}DeEQ@J-j?n2+tag0mnVFdhY>QC~LT&bVJ^C)tGk%*vBLbR0 z^c0~s&W-O>5`mXx$UZYNq6}f%##coE%XK0%<2zC*vNjO1_so> zt=p4U#V(!OX`ZFY`zPU|ARW0jY zH%4<>KE>Peu`i;JULpfIqj_Eu8f8pqk_3;c=#mvLU z2RyraIxX=I-ngC382niNADaQ#PqD{SCAl|D6dNX=((h?exJ-` z12Nw0tjsRR6d9rux|kY0RR{9`PFbo zedQYEVOC;#oMcgzuf&QT6?w5Jpg-H;-2)B{g6!t1g|~q2cR>zapLzzO!lcFc0B!_^f9jF)@D!6 za#QQYa`yjzC|_Zv%W^|5CE@Igo4b+UTaG{5+rdB@cp4NWkaUpG7HPQ|Y##|GEx6DE z{Fu&x0@!^Iitq4A>c>F+D|v<*Fy6AhZa%_ML;xBlhnIe$2*IoDB?S&=fbgrU3kV2+ zvMN?B9;PJ3fB~!Rs8MDF(-mqjiW>>JIdfcm8MbEX)CxYL7bcl$$J76t2AgWgzDx`2 z@0`O>qH5AEnv0Ukm&*5hcqZ>b!wN5Co#Ih_Me5x8ap*iPX&nCo1&noe;34)i&>3WH z4_t+;S%byqp@g8&99mdg2VRm9%o)Z;^gRjPO3JDYEddRqx7QY)62vk5OlqvDYr$WV zs=EP_J{4L=6jP*=#s6Ivo18pgHnJZk@welNNZ?!`)W2oikR4+5MDN`SDq6OTn&ZnQ zj*mUmNL-ilBlr%Gk>^1+H0+9YzJ7D)uU(mm$9K*uFOZgu>;G6;T5b+XXtF!r)$WJm zXb@@UuN2izW-FDW2jUu+ftLO4K-OIA$#$q_X@BY$SO z8q?Y7DGHLGoB-jxR4h~MpAP(&aWaMx?9NkpKjSi?NZD+VMOau^&nmEcfUds?V2^?$ zVIt3b%JB>jq}(^RpzlTmn@QLOoct9zbX@rj;49luU<;p-21RaSH1Mut>y~LKAIgNk zYC%qS)QU4SMpJJW*EeP-1uS+7Os$}b`Em;UfCRqNBF&2jH3oE@fTc)}zqP%+y|))s z#aG=0A<-$u$iIH zl~SPKfH(GIlr5wA#)(k3OY9huw3az$o&M?uJa{$$2s;|DULLah;_KcF7kKsM;a;?f zLhF8om30{f8x2h3i34dE1V40?V12?O4eEk>b8Kefx$kF$fokmUfwxxWQ9MPC{O=45 zYg9>UkQ9rjGF)7d<+Ximfs$EYG4I7)+H?2u`3y z?UtofpnAHOKN9|xsqz(FR?Rku28W%aj~|H_9^BkKG;gV2TBvJC0~n8n`0~;O8p^yN z{OjnsxhbkvkhN-}O;j1ays^@}&i;!#O@4$qPrqc+60|7wlyj_)Tm_TLwq4&%P~}Pl z>U^z!ftGp1{=rY~T|7Pejd(c>3W;26MmC9@PLf<;GG4$KukJeb`A9~3K#=S5WuZp7 zRjW*+h!f^oA(-V3lPCMC?Wp;?cpUSVO#oR$(5*Z3;M^9s5Mvb-m~LFM&te*pI}Mwb zVpaCprAW2ZjvQ#;AsuW|h2x;r2b{}5IE;{U(7Xm1t9%rjrx++m;$yrMEH8r`>B6^Z z9R19~LA4}{di%yl3992K(m1IIxq55R`Fx{e_UPFV4N&T!g8^Ep3&_w1c?Sw=Jd)pb zJn0486$ihG2Ue_CdJ0__pE<3a=xPxVAa`hqnebCm^9!y=LtOX9FeDrow-#}OtNo!! z9g8a;gnJ!#(F{peFK#4NtgWrV=!^18+WGOqHd3s?A`_nh(wB%-Zo9+$Gj_Ag)5(>) zvKv$)E;bwn{1-0S{{~h!jg!n~SC5p@Ye6?I9BsArNhc~f_phx%FcHsa^|Y81-h+XAbF$ zMoQIt31@?Xc^D}66FA?1ErS-yU(bl|44I0&`eVrFo9gztpP4+3ocE%9wuXoXs8Li? zet#1x>pItYxD1c-ZWT!%{5)tLDK6IcGkoIeg~Io8*Y4*JtNB;mzrH4MS{|F7adKw3 zv@RVezK|-59g3-B+CgdQ_<9iiz!~i^{xBnNi29l45e}=_%Vk1x2@bixm6mpJ4XH#I zwyaD9r);>9rsr(o^;@L|gRb%KFKDw!;?9f}VuKlW#5`rKj2Du1p!5Fm8xb9MxRqVm7Q zLfyE#|0t$TS&q7mVLs#4rw%P^7&o$foy zq~A_tQ@?HXywvWd^_P;A!y8nus>)j4H~w1EnXsOK45WV)&+^czQFxK0Dcou%vAu4X zk=x&92Sr*_E(r*<%ZtZZ(oG^Nds&$r)w2rvT>(iK8u10coKu?(Z=QUm+Sh^n4TS#N zrSWGWenXEh#*1@{*4ujThUJg&=BQ*TEr2*>xTLwVxjVb>;`u|`OtSjf%Zk0rMT~LQ zw5{vD=Qrc)Z{G?1E@^P`*^cohm1!0ty_u?Fq2#$MV6%x>zrT7VbXvUOx zPMi94W;;LRPQjuht~EgjM%AU-s{*}?o722*0p9a}K0;0XH>NcCJiKlTE`PVeZ@3hg zcitk`@yo&x0fVfKxMh<~r3O77FnZ!HNLBcOq1@=$W;XHfudN}MrmzsM+otsR{$Fd-vxYHo=dz+z!d+{m%z#2zZ#58=1=!MUJR#++;IuTA&Y4t2~(`fsuxNuAt+76U? z8rCBCrEYt*>zMea!UY8a>!1^Wefd&y;F?g#^M~guAQ`|(E2N4kezF?C)b$Hqb7ZErQ#G9V*l zQD|_dFMEek_>bd0CL^3Mlym08WF%NLHv(PYsry~zQ_f{*L{&!UO>Hj5@UI_=uDrk4 zziTlY+dWx;wnd^kZ)o9f7QmnO*;AMvn+|I|k-rqg&mp)pv5ZVdDprYhYZ36g2^$Al zce|9?{xJKOa;+EHughuOx%6JZXYc8BjrVzRA#a?Q`$mg8|D%&!hIG&gD5#d-GT+fj zTRpLn&1J>rlS$0|&~?aP_KAW7mmFSc&cgp%3xH@qA&lWbdJn9@&!b?Zfw90M*Fk$p z0dLT+2sxvf!p7zURC`nKSEyzFD1;b-bL5Edg8N0MKVF!`=A2ZR2k8j)>%be&6njl( zIufb3&ziw`f!bLQz09jlw1FkBu(Flhbxd?ZgVc971C)O751yYVeyGl~2lpyM?D;bz zla2UJ5$61$aG|=FJ_9F$dAdaDOjWToqrq-4$DMe3u}=Rhu_C*?zGn%2MI~gIL4dF^ z&LWYJ{5UWcq*7n@b@h9LP1~qZS~qK5pxS3sZ$ga1+y%-=&uVV-*Z)j&qq{cu0CfA0 zTCkC0etox_+=wox+}2)OQs|_di>PLIC+MZ;Ly!5NAfy_R3vXU9{kq1#I=yOXNZM|7!b@>-@n* z#}J7FrTl0koXH%D6P672{has>ViX0v&$8Lbu6k59rdV@Y~~1#U&M`u@wFx86GhWaBx^jswi)C zeie(S5A^;wvH6@f(D!U=%aJ|f7a={AuE-xKciH$hWzbUE1^y`De!%(99tM2g!U0Sv z{%xGJ>|$3vJm{SQOoofBK&pkbKXO2W5OobvRV9S4h~_xs9lrQ#?GYK}9?xA=gsz~& zz0gvszX0r?2rmv4?tOXR7C|yN9pU-iwe5lzK;qI|V_+3i4(`|ghKbmoOcUcd1K1!jy+}}{D)Ml)Cz6l*7i%xP;#enYc47TVJQd}fs_~lbc9q1{rvZ*+#na6M5&i;@H zx}!SQP2%y74`;hTIU%Y1 z2Q0TtMLKQJGzK#%0M?MeNwug^$7*IQf8V2#-dU5XRA7*jVncQUp-otU4p4zq?(n0+ zJjSutMZgXsluVRYAqfg?0iG~C*OVjd>9~a%QiF)`W!ABglnYC`eeHNEThhZF+q?Y< zkuB@E4I81BkL+osoEF4C6YJT!j&U^OvRf2x; z#{B1y%_o$9w*rfusGJ!9CiQn>)LmLRC>RpL_y-lh2|Lb6qTXlH6Th*IRB}RKfg>NX z#c`?h6(lbMz6PN+VvKRPzO!2c&JmcV1T%uxJQ7+XY@o__P0G+C;r19;rOGp)Tzd*X z88DzgCP$7O0EWW|2RqZoqt!wYcWTTbSSw-f_gIbs41Ab6cU(^(im&;FIIox}J$t zR#zJftS8bkQTivHZlAJe_Oo}`=kG6CnwyEGdtZOV^+U- z4HpRG4{-j_T+mUH{$bqbVL{)A!RMm-Y5hZUy?X^aM+rAwB&tjBD?d!ZL-A)7{$J8} zkJNH|ut_?WHM!nRg1H26Hj)gYnDegPly6RsKhCNfmE^Jc6cslJ^dT5fNL|K8#exN{ z@|lhUuY0Ox`4hYT>oj?=GEMp2-BPmgc0*ds>u2tx+++Y`ci+~`f^I+P66Z03UbT0t z0Z3jFb93W(JTFtN{RQUbD{JmX*57)<=&CNIK99_qrDIYpp3hz2tdg?Pr47D4pHa=07 zTa;hw7)-E+IpQz+AoVg07#)ja(GJozD22OHTRM^_tDJPo&`LN|unc_z!wGa@{vuSVUp}?nm zc`(lJ+|5yODk+fv6y9qfbX37&;kem}o9?Y2byT9s-!Y3+y(-G^P{-?RPvIgJ@v)0b z+RW~ta*JGH3@~+BqVQtRt>}cW*>k4i<68+EgOeDy8~2rUv&@5)+m1*NS7~4c4jaMO!k2$Y)~!F>+Z`5U^}Z3pgUhshyRZI4QG;1n9@ARc=pgp*DZ6giF+}T^KTR38_5;eDqi7rEZ@w31*Nf z$BO|DxzBc|!EwGNC7a+dD=Oz3mFEbn!}fYS=}Gh$=Sw-GU}DUa1DJUwCBRk49-dxW z${sX7;^UzPz4N|Cu%1|?SrKngZN({lVdWM3JzSU>{DWy9&oyuII%dHfhMMh&_tDzk z!%bTLXZi2yKJ(E%UJmzNS-o{9>Hf2~jV)iE-?8Z&E5Sd&WkiQWE@s^{Db;<(4H`H2 zqn>kXS)Km9{^-pl_;9yBvhaNP@~uJb=ofCQAj7YR8*fPZgW|;tW!K*{uBII{kGpsV ztWh2W{reP|M<6okipVw=mK_3eu*$!C9_FM7-AT$2 zU`m_F#uB4oN%5yyb`8bCJ5xUSz2*Q=g-SOc-DUd_b%11K%AW?b;Q4Qm1`A@JuRFZv zKf-lJ0-YG+s?fa96s#b)qk3C3DU*|hlQIUtCg9svs4^wpdW-O&j12n*N&f{0KEWUd z+Inss(WwyW^V6@tvb{J;zp|Kbbw#WLG1u@hI@|N_{f|7A&CmJdErJy*Tbb>iAY>x` z^fMJ_FduDdEWIHaT%sHno_y`_<)pvAi_Q9D{Z^~XuUb{@yOoZ*n*Pp1 zs`M_nzVW%YtO?@R#*qimxhNq$sRHa(W2DK|^s1W zT-WLm7>kuuIdyMl9solzdaTn^Q^v(PdOl`J7+WHI&@UZYEN%akV^Top2{@5QeAo?k z@rLZ794~&cevO20g|eVJ=HjLhZI400T{kxxd&v}k;5B+Gx&-6 z+LVtLo7U;9?0Dpe6yw<&=bt6D^zQi_G=7lX@yVV#y5xBX&TJn~|Jd9&zn#C$>TQH2 zLDSL2WM6Qp!d_R~&LL+T_q@z?tlvbpsoi>|ERO!AOVgi=8YLldPl^X&bD<|P!}C*N-5L1 z0!YJMqK++VcI=U#yJh%AC6@e|=QnqKreiks9iedyL%o@w8Yrq=BU2)JRxLK{`6xO?-XB-=iC805>kulwg$y#CqFfYA{D)4SBx(QPUF+Jx$L>#&|H;Xz`2iK4&w z!S|xuu30D6fc5*Bh3stgMxXY(33J^ly?a+|Vu(k_kFPMf_=%Ab!#W+eERgPCAHj?1 z9QhHDuuJ@kt&2tbBeSKA6oH)@IS|*B&q83zU-#ZG8EqjKWC`UtupV_f@XUBl-*5Kk zDhEE0P@!yyL)x1@K=+G6e_4)#k>^2k<=ZPyeHB8k>wtSSmIN^ASZjC$3A)ck0(KB^ z3VWg{*`Lg$XBjyJuguaP^$~rtI-QI0zWBhUX}86_q2$ssN4@aJlscf7TGL9u{)n1G z*jDGU>|oXGxZ}@~{Oo8nxfwBUnj!G6D&)`KD#7xUa{TD+MdN%j_T59o@gY~>^ekwQ z%x|f%dHO-1{H&@>nBUaov!u%(jPZTfdRy8Q6la^>U#+}gfB;N1j=1ZTO#y|JIaD%Z z3r3mQIV^Hx)@jt1wbE+F>B*j`Zedxb9yb3vR3#KN%7pxp)Crd4LMaAEVZq4z8pW%{ z&s@_Ts_sA6FuShgpj`3E(Y0W2YA7m9>k<3$0F?>(jKuvPf(s za&NX-bm<&89){I7%Gxg*7frR*Pi`i;9Aib}={@&n-W8k_*tRt6tj6jwCfy`7M9f)v zH(FJsW5jKg3;(=7)-I0;c<~ca2ZYuq8lH3Wq7~Vnz^>F{?j;9<|HqEtAcI2#Fu|>9 z+_GHwD2fcDj*$LqkkSQsTYbRyV-L}J28XdE{?vp0-%?;MZ-Bo;$ zfvcMbm!<^Mbr)cNQ=e^J8?B-{D!DllcZL;ylsWeMaX6WMKf0%?x-BF3$l`O^uX&f- zT-Wqn_iRaTMjn!8&~D>2bDC*F)o#R2%C7t@PG-3=a5fw_1bHee=Mv0rhPH##8;{eo z`T6+;1qI)~Pg(QqoViCyaRLAVFtYAZsrg@|h}tXTU~@Po;=DX@w6v03_${6r+p~&+ z7GOc>(6|6jl=>gW@e9*h(!~J+1A4)ShOfw?#BWWPdqa(j6${0uvgHaY%fbBekAfXX z{uzESV+&Za41JD*#M{l~WiUkmh-RD&=mq)76(#0<#*BEkx%1NYSNrRPYe0QT>Za!p zou|?7Cn!QzG&B7cO{1X>Crj=v4)Pt>pEhKWeEJ`}za{n$=((Dr^3=PPI|iiWh-U1hV1N#Ee1}g! zuQ5yl3D@56_p8KFFvQm$^v>`Ziddyi8R&F_-_(#P60F6R1yz^dLvORGv9sn)g?xUVh$yDTsmW3DcmZ#_xr?W@`}A<#Qjz&r&a^4V z>$Q5DM9iMAqVD#YZno{s9VHJYw*QKU+Pnq?=00BUyC!e^a4z*`7Ajg+0>?AK;Yt;e z5UuZDzjoWyH|l{NsNw67zaydT3y(9x>uH?tzt`2-Q;^_>yb`NtGD($D_itn#cmjUm z05}c_+EL(e=%%i1vlI9Q2bYuGQRLuPjev7k?%;rLnQnbK(e^^cmmnc6^&k?`-QCg%NH<7#cXvujmvnb` zD$?C0(%pU5`<-)e41f3seAs)fJLbG5Se;RqiNKrHsDqajCn;ZpEmM9wgW7FM3^hv| z-#p0w{hnZeAha%aqh4{j2On^vWP!CR1u$J9;RWij@=cfI6R^u>r=_=bFG8(4iXAR$ zT99~3lBT7ztmS(uan%y@X{7bKr<-3rMXygQP_N{|^=}6XTrMJKXJ;URC@qyB$Nal= zeSOVp`p3-DQnU+kJ;8P;%H%&IfDT`yk z)dxW@v_-(7payWoz(#YZ{`N*8Bna*AA1n4+4xi@8@V(-EZKrLQJp6^}0H(Ur zY1UnfI3k-@oVd@y?N%LK)dKJQ8DJ#FFHc3jWFa%!dKMhK0`^Y!-p(j@h-#68h0Ej4@=lE$rB z(`N!*u`E|F(Sb3`{<)jW>Duw_BQhjh%n+F7jS};TMYvifTkZ9%A52u~%YLdeV2beM zUwq42X0ex9^X2w!k<~c`me!z+m_dE@v1m8`JCQswvH1)CpUR)gh$I;-s@$E*6gHaE zlk3}=F|ti3GcSN<<+4_)@=V+HF22rm=(51I9oehr3~k1u!J}i%rU@9gKv#a$*4XF* z@FL)}0+KCI6&C>o2wl==`J%dticyOO&@lm77^-_bqr`E!ffko7*Fwk0Yd;a z%J&Z{0zG9DIxues%Xy!If$Rjhko}86YZopi@}0tt#Z0ajAurW$hOC4 zXE6GPo35??qYzLAyqR)C4g3Gn`l?#<*E()KZdz(+Xw#P*?7mhzr-|QIh|?>aqKwtN zXUx`V>Na^1RWKfgIwAEvS|f4RUQl}U__?yM5JtlQw$}Oiu<~WIpCYCf7PxHJ+JRF? zb|v__3yg5cyA5lES`HmrCOjb#hTh)%JlC?6Uo0(YpCoJe3kdZp)PS1|NEs=l5oP|# z0}+1}AU`bIw4uTK1G8%&FTw;63vBjuG&S9BMKXpYe1aGQkj*&IOvV`*YY4byD4~B+ z)Zw_^Ek&777DIcRs};(IQLn$FqM(u7p$oS9;GP|}G1ia>#YEKwYOy`+rv@_kKn#)+ zevg=qIFe`y%=4N!qyQ*lo)u~(x!_jJ5a>y>neB5jt=oGqnmjZ?_0bErtJ?#9%W>_G~eSi<9d$fyeD%{_%>e_47*Vz30XLu2KsKq zTK#_$sUK`2Y+uVcEnX-1RnWiCmHEcvBJydA9e6n$S*b^cwEC2$8>-V?VDU#IRb~!(SkoE zIvs-9dHRIh`w&1u(q?cyAHZvBYy^aeKBwnY4(lc0i9Ejqe>G?xhh=~fGB_u|8C?83 ziO4+1XHT^zKHsk&%O zMWQWBs#{jiMI_o&tVVC#TRMuZaGAS=)E2F+a}xfHQ?QFY0HhKNf|NQ<4hl==0pzg z+XFW32{{X3mW5yp2Z{@)ydwvN6cB?(;)?O+*n`m_s0uZ8!KA^}wQ2nnsEL81?ZB$L z2O%ad>6l&5-FfJ57n}7%ft)Td02CHd61_EA1*27bOZk+W=Ma^mD&8*kRRY@w5lIin z3{NVm#mG+zTc2qX;)3xUV-Aau5o!|ehstv9!jHG(z8JKjL%PGNfKTr~QX4?AfXNBq zXaP=1VIji0b=L0T!9j*R)lt5C7I+$a5a1(;@bST55*d2W5y1dyma+0v$_T^~S};(; z<|!3uWJ?Lxkxk8#W4YC7phHpHu(V0!rR-O+&}FZ3=)JTgU0!a@EiToB#2qiXCm8R?AVFD=Gw z{vvOO>?K?Wnfksj5q=EvTf~6#FCIS%_%Bkou3McLS+_<}X74nO|tnI3N`G?AD+o93ml?=vINpVx|x36vo!z?(gQa z5Kh1&0O;gR?uB)=UIUa`^Ja(`d5;*&JH*b9qJ`L-W#PkG1DV8~wZ`bny3&W!N2rTV zWEgvZadL8U#>HV=FC=r=H`UV~$yuL?TlAc4Li; zG~Wm-BY*xj;uagixYl-}7Nb(BkV*zd(5UDkn4h8c}97URh;Q^ z4=s#=G4wnpKX7$ZE%&Jl zZa*lTQfXc>a4*ch5Ri! zRn1-x3ApEjZ`v?Lm{fo}j3m98{A~3UKW3eMR+drp&VY-<&IrA)E;(e<0*4PirC|sh zNO6OcX!+HQ9s3`6iFZ9`BYI1;Efog#ShNU}<@qh}=PCdv$)m%sow-eW-nm|zOdZG~ zi_gB6sTxDE@j#BV(D!tq;0yQyfU2rJxD&Ob?JjI=7u$fB8Y+NHU%r)Y1bni;KfYYo zymnqX>(!i@Zj^n)q`Tzhy$sn2t{|ZhQLLTYT!F6kV-@lZe>IeQCo;hU7h+hU)+dFw zL4~m!Fa@>trjjBL2N3G)xHf{7T*YIl1>(uStMA!C@0pAE`0Yv`-lEnZ-npVv6upAuWYuBTq&JRVYW+r$jf;((B-D!HF9A zB4g%`?~1x=0ejcc+ob8}U*pHq#&XqfR!`UeXuq2X*X_!;Dej^;dfNvJST4kG5ep62 z(&fr#KPORjWBTby*bkf588jixM}Cr-KXk5J)c%x2mIFK&J>L|Hror9NPFU~fRQp~r zbIO^xo|yPldm+2-ZL2Z)G!fs&cPDdWHl!@a#}IOY z?f@1-vjPE^ue8~zs<%*?4j0el!R|SdKeqE%Ck?&ak}Q7%iJ>Ti)^$F!LsuqN zi=A^+uLRZl(v-3+WJ_0SF9Wmry2U`%P7w)!)&ovp_|nsG+RMkMvjZ^!;! zE&Ou?lY5S>@+h1?kg_=Qn|4dbi=w)gRb&yQKIY9PRE8D)SuSOidr<~yn3$nUK8X#6 z)=7s}VWg78q`h7A^eDXXE-JIi2J2n_*pYuSbdK|9aU-sncSmz7A7Am^D;JeJefqkd zyI|L!s=U`*ck*0qH~6129RY z;~eM%&m7py5Qo<9{hjw^A16MnB_w?cJT|(2SoRh0&=l}92&-fzGJ0=6SNPjP2f52+ zg6A*U$59T;nI`=9Iu6-~IR;jHlQ~tKLy-<`hOQ;|hVLophejVu$kk)_+W=E1V?2Q* z@2{4osuBr(n_T5o1MX>ojt!O3RoZTsAc328>>-x#%VOdoi(p1ufn=g%^j20qm;?ul z{E!I3q}AW{L+{+{XP2Wbh(PW8TX)~n#oP7K0%6f_eYydffzgY{i<2UJB0luQEU?Ef zwWIix{{%n-Qnw^n&_cV6o7UlDZP{@FJH(V^Vkdq`YS|y(msDRt!Rlv5mnWLh5G8wY zjU)_U?>UJSsE;M+=y!gptUL}-ayy0R?7Dur)y8SDD)L>HSY24>zIB``uE$+rPG(VE zQ1_$>>1_V8+B98lCmh!Q%^zLzdO|4*rUE_|5q|=-0`fh7ukXEpN<9{l4DU&cA*FJzEa_*XgA`T5>iJ2C0sN z6W%*HaruwWG<$mc!K9y!K?G?Ia)8oW8F&-8*+Gr8nRsT%wnGpNrW^~)%UbL+lWmBn zdX}?-=XX@=Oc$-8g}x@6f2zW?Z+;coJl>56EF2?YiumF82UF`I=DdI)tJu`hLK`2m!9 z!#uo#NHCs$hQ*Dj5I7x|xO;d_7#sr^s~GZ&E=f3Ri98Np}C zoZr=Sk=$@V`!JCbqDfFKrm6}CBEMzaWIA-mIZ;U6|7E`#|3zP`c^>tgM(ljpa%Fs* z)iv6*bKO_v?tVM6cHaGXn(4-5{APvqd|Hdai?iF6&GG4M8-nMPdL@`1MooGsr@YHc<0{lR%l=hAq;ri# zgq%jS045d0z}~otCJDa)nFXAwE!qe?v6!y-?kM7K z-J$^~S5PopzQ|X`@7g5#Tk4zVt%|NJfq`u%qV3n`tYFVV5nDpV!-Kz6x1VNl`&fH8 z-}VFL#Yox@*o^U`3c;`Q=*i`1Mn5^pBl3XrAFHTaYby}mQ`hc?HBNyDl5kZj-N+vM z<($=<^b2!Q?l@;Xl{K~LGG-C#TW!m}a}^d%>(cVE;-LBqIs3>FN4a8VwKcZtUz>LN z27OKB`hd0aHuOXKXck8B$dkp|-=?dlo#ef*v1Vv;w&-&GgWa_NW#QDe8peke4mXQC zYRs}{Js1Q)1)DBynCpJFu+MA2sZn6YgpaKj{rkM;ejmE#)<3_?tFJpccJx@_d*%;@ zv6uNWn-4*5@Zf~Cwd*nBXP8%b4&@uR5wwOR4N_eQBIc0(41|Nqk zN=vLOv`s03M0N*$raN%B1L1Z%lzzd0Va@U}&}@G}E|o4V6){69LYp$KP=lpWS5>tu z2JTpWH8BaG6l;&X)?IR3!xs_oP%>^+8E2QriL=i*wZ{3o^3J}1nzzZ#^VMr)#+L-O z%ek1O0)IOS`}-eLM^{(Z0%d3t7&zGF8yBCyn1|EPbv}0b)oQ>b*P%PagksWY0D#|8 zXS>9;bs80FJ;4R^nAE$9{N%rp%y!bV$^ymat|m>XXLeoMgcHE~0JK9u*rGZM^i$Dh z{m_X$4dwJt8)ox|kD|7VY`3!?s5i-+{S?i>llCP61Ev>MBv~XEw9EJ*G}tJ91ef=G zb5B|K-d35+=7Wi84V-YWwiC{o2C0(4-wv-O>KJ?t59#%|A2P@JZVM)R@9-)+lD^%O zNOH=DjWtxJcUNHhwFB(Sg1Tl$Id- z0VLj^C|a59h>-pP6l91288VbJ6QG4vNW$6sc~keHLa-=&0sbkg8(@~ACB{Q&Y>I3| z8G0=AZwqk)WkeZr$;;l%;;6o}Av%j`4%Q;cD-33%*c3qW=b|#~!suVd*C}2oNKsDe}83 z3@CveU30o0N=*YST$5&n8D<`jQ$@Sg`ey2Dm3@ts@YR$bv8E2qG6AK#>mLFYG-<-SCixD~o@?-h*54`Q>P=-;r#;)&8il^|&z-d) zz8+~!3m!R(josSnaoGB-PM`^LU2N;5y!x)EHPfn&t7y)0qCG>~d7XuT3cCBxy7I34 z_E5C-fOcEYjzNV}BX(v)B;pX!%NrbVhjsy8w1pIo!rtB9k$l^C6GP+@+sM%|svRc`@pFZ?aBa~Bx-@KYeRiZ1jE#H*S|pg}ZhdQVb11^VNGL`l zmeh&UR@~!hG)~qbpVL{bwcEXZFB7AFiDJj!PSg_qD8G06SQ3@hubSfpxN1RcLQ4V(p?l4z@=)8%C50dC6j_0>^q zWwoBMVN{@(9w6=@pCaW_SU8nA`4E;>UxLF7ji%cOoRho$L#e-7JAaP8*pLcIn#+xPnL5MFErzr#`) zs~Rw&HGl2Uf;wJVY5|0`^ZnEWs4IXJ!8b07hA+1u^oL!pZuvNmntY{9<S~Ajbt6T*8gz2 zvgB+sY|iRH>Sc9N#TeDyqKE15^vEtMNF;NdXcaq%lHKL7!QVw#WV`RGzSczRw4C+B z-=xvAf>bw;Q~v<#VZEt=;|s?FJDb8i0|FXvJf zfw&JrKiYyM+CMvyBf!U~P6*G(79~i%b!|+X2-(S?-_xAOWiI8Lj~w0uFTfv@<_83J~#v?a^-x zvzR>>-Tm6bQjXWv@E3HO>~x}vf2DxuxdUw_gW+t>M))YV{fB*SqbxL%@#n6uUHzkV zUuV}IquZ?LMIw`}*`3KUiHnV)ng9j38pev$#y%8C+*3{J{Rp#9aikqTr!E7l0lAY- z)mB-qkjFa{()Pz;1p&|Nb!JpnttdiulJ_LmrwhfEGxEIOGI*0}ALO!!Yl;cZV4_#> zR`IDVm@V-`rD~*>`ekFGChRom^%9Bvu>u@nCY792GmhpVL1Y7976EqnEW~%p7*0Xz zzzhI{?RW38guH|k$1d*qOtnNcp<>D9k(a7#>5RJ3e2}Se#iWaMrlE`6N`1fFKA7m- zAQsl9gc6}bcp$LyBlCLP7Zb8K`3mxxGxk;zC;u*6V{i{&pAJ)>Q!T1ipN`TQ?|!Mc zbQ`>kZT7zp^?qbc^7Zogw_CM7d0H)ta~Kp?ZPt2SE1)rZ;<>7(L)8`W4-XBMJm^k$ zHgh>s>eWKmvY4{V1RMvT#ZB_%3GY&i!A63#yh^+2PU3iMcWbxIhRwIn2NAwucWCFq z2uT7PJMe5%#S{k{{P5^FvEw>&@dRX^p=}|3K>K51g1b{U5Bs#o)3aK{pDm<#-KfiU zM$paZW~XQg^j%=QwXV<9yn0eu$w0@NwF_`}bR&MGIt=q*AB$Ya!#y4LYR2<) zlUuTU1HK!W=0;0=lm-k6qz_XAvbklrUDmz#50zJpMjkR+&4~=9Z5K4u1i3r#Wp!=43_cNaCQVz+V6x4x0u{8~T zJOmnaKAgK4ClL|`Vtqv}r$pU-0&q&QMzudLCU>u?+zS={X8u#=!GG%OWSBC}v4=Hy z+3@E1W+*RsBvAgt$S@V_N259!{PFp2ws^FLH zX8*#=Y1O$saDN&_x!ys~l~(3+)54t+-o>-^kbOT;r>yb8^1XeG?`!d#qDHbw#KTM% zQ888NPvYkd6Nf^~u5X%S?3s+0`?Z6-(Th~E$TdB3qB4<&FvSc3!8N z{NOc*sEsknQe)Su)0LK*)@iI*Cj5ev!eBoG^_42B=9`A)V>Vs?lq$6{vJY4y7#l#O z--8G8dVZ`TTvrnFx&S`9Y2CgZR}NI#=K?6A3Ww)N&VtW5>o`ZLn)22E=lo0zed zf9@|WGrIJ&ySsJw%dygZv>&-&^36qtC#RH_(m(V3jafzaB>x)xK<-Wct!%{kOzW(` zEUqaz7}^idNx`fKwoH4wRkJOVb&S|DzBPo^R;JImj5W=9d6$*iL$nEzI_yUK01OISnhM=mS(a#SHCUzYP{n6v^5+j zbGMi9MFq0KS9Pp-Qm}W?fgbxS?Zv6x$vlOBUU4hw-x&&&?$1us!9gy3cSlDZsi1v}Uo^pR8F!0q* zvGcgLw#N@ajdK&nA98Q6Oo~3G3%n6on&5D;qH}6p*MIb9JUrso{KX@T-&k=UZU+?# zBkD&2hpyb9DIS6Hoh}Qlek%8G+i$9^nxX*%B8&m`vp*BI^hf~M3y96J-ZkpL&$~A( zPni(L6~~hUhXPH|&*el8Z9Z~gek@#q+UK_xlL>W+CVwANZfZ+#zRsCcGJHVmxtiVK zu(5tS@bW0+HE9{5-K*ZYX2}WUhJwitV`kqm9Om5~WWL%yEYV8#=Iuv%8sXgy2&Ytk zcWgR4Iz^Wfd1@P5a#20gpW~sYH3g1JCW)PV4(tFDMlCw zTrAE7lh~q)(g+a3T-&wP2Ln<+F!qok=TXB{3QvWIgURz5)l`hFq6sEkj~Scc3JRPv zX4aRem;=hZB{5QF>F;M;TtqROo50Zoczn6r&A(UYRrzm?d%aCk?)m4o+#0lhWUTNn zF0Wc1V>t#ET=fjl8sL2S4|EQ-w%A~a7XUeXgK<^Pe^rPKy~V*p>UK<3C-L8vD{DEf z#m#CopTZBF^9xCOLP6m*hzt91LbK73&=|s)@0hI=8l*MD`!g?I>??p~{MnIQZ~ZTyd`;Emn$8BEWZmp3 zvGnu2b6>W*iyBps(T~Wdt)i?{9S=3PZ8J&5s&};Lk1FkrfklVpl$mS(z$H|W}L({kMF8v2u|(3Biw)fdxk`{iRIRm)}#YZg{kh~R>N zfJ3ZQRaHEypsK=`M2m1ad5zbb`H=hH%53BBCFGhTv?evrnKw_oP!VIE(w@9ZrrI(w zAqQ$yZ5j2*+-5KUlhvb-k5EEuttTQUJ%7EpxTsE7SXxRUozo_?8+j6t`7I#$<4EnS zMQ{S3y#u1O%BNhhkRyBoPLC??7}!)G#{zV7b-EC8d_!70>PgRlSfT3JP>f#!e3*pV z(poH=sKW!=>)SpYN-qhRdZM!)$NxYS#lrZj;=@IQ=tqr`hI-$pYgAnq`;_PSmZ#n9 z*v6S{d140WU-ejNJjk zYIas!dP}_kT$b44z(g`Tt6DV=!q|iY0Vqd`S*rptjKMF(rfK=uB_HyZPZOvH@T$xS zLk_nPrI>2zBFAU|X_1Fc1>&A1X;yW}gL08a4WL>$k>XzYRveM>&a^uG1=O_S?k}DR zjiY00U3^sns+F?1-%dzAP!VYQO?FjR1H>}ZFXF%6pTFpOHveh}Rn1h3yU(ycvCCA4 zt2eli_2FS*+!%pc+6czWgtS9QVrLb;-*{}8A&t}ABG87AWJfd!Nn<_>=cEBPxM>~o z4TIAx@8k7X7>l^GgH}L>qNJoOoh@BI#e)M0Ir`Ml)oxZy8?E32aEb=k<&37i8W3(U zk&msLv2C%%S#IYEzkQ#2O_1Fp6b?}7KHyIHN{|704Akg{>b*pnfZP6QgZ~h3yTijsQtYg(tR*TIHZ~_g&o;B+ zhSshB&7QD}cr^O5B7VMuCK|gm7B&hoVEXV<|4`#N*z!e$vy}f^XE}*IJkh30Sev*~|D}-S?MNlb zUugZ897i~DCSeSgRMZ?*#K|TFMB#6Ey1) z?5VTe*9)WhElZL6zrVhvv!fG5N~N0tvWb-!*_~9k{bf$8ELu(hANz4@MlqQSWUeC~ zh@e1P3&)lZxmr8<-)8&nL+1A{;~%zhvxps#eechh^B#JvtkaDj_nln2%~R>hW zdIt=fi~n=#5Dfv3CBS94v@y54nwpwkALh_L%;2Gy??hA>7pHAO#2ftTO)BR%OB7s# zJjS?Or%v!;+S~S8C)TpXsrw}epxFH^f1pZUKQ6kw#!rzzP|2Mta{u6tkY*Ffc1a|K*3tUY}gt{BuDMQVx!X|Q)> z+TPw)+#5*H0J^1rZ-b?bPjZ$&VD{jEOYUdjnD5}x@3`$2G34`R`LHQd=1*xa-73i# z7p`qZr_C;V`)>PL;U@iCDN6}8y`GJsm8iTg$E7`zdH0deE=A$KCRLukg-d3V&*1%9 zZ}z!Nxf$f(9*uQU`SO(|VchULoy0G?qW7pH%~hyBT7#ZmDGq8<@_ZiOD%>l|>oL@* z=Np(znGp*`0QC|RnTS+{8n8Hkzyz@Np}GXic}bxtFca1{=FJ?_XQGw{W&~)wwcSg4 zIy%28st9sJ7;OI|7hsnwdPg6(451Gj+6G0W28=E&)|)XDfFPwpGG_>Im8u6JfnDqW z9aaDeou5IO&&Cw@wpynLeIn!W%KL%mXvOZt?wuW}F?Xo=W@M5g5){nOK+EQcTp0Ol zC@C$|F!T4+-e#VC+t73*3|909ZHZ)I@21(%=-7Cw-Y^>RUd>7KatjeIo4vPCD^L#K z1`chI0uql`busx_s}{i%7Pa9^VjWr1SAYO5!G3s18>PIGhn(O?4uD=>R}=~Q-&;6R zNl`(70vY@kynH2xLelr)8gXY<-qMRs`tgB$wBH&mQ3>c&E;fCuO@4_ zo2tCZ4*C(wsdVxwp^U2Ll7h|BoXYj<^rRk-mc^45rRVEm<9-m)@2>+DCl@_9_bx#g z3F}j`^VXtc+B^o!TL%w)FKV6p3nw(OxGd;Hgy)2ie&=w;>+Tgo1qY2j;?OKOA|6U5 zePz}Q`l9K@)m4D#uWrw!hed;m8&y@s5wGd$dIj3}J|}aLFrXRub`k$U5^5ESVdx^T zlHx}IS<Un`Td|$w$QS|lN=LcGii>>%* z>Uu>(acK+>10Vzkl;`&#^+tjO8zK=KrI)e9R;h{J(U{%5u;o(u^Lm_qgO0d);7P#866@$4BmYcPiS3XeuOa`;=-opls{QKYk@5S&G;h= z!HZ`Paf1VD599}d6x4e!l06K3O(;76-TI1H7zdmCijhtvmIGcSguXtSKvj_B!6rwW zGV(vmyKsIDpr(WASwVmZ0erudXJTj`bPG&FNot_lVyXq)N3No{5OMDWJ?1wq| zj}7sA^Fx0imbbhiR07ulm3u)Ly-Z_~6#t1nPDWr^U5PA`w5A#$`$-153Q;~rvbN?w zmwpShDtbWrA`$iInhDr_RO=} z{E&Ws^nqXb_N`4#cmXk>Sb%-zO)Kp_77mLh#2>N;=80t-hTf%EJ&t%b3Y!Y8vQBh2-D`#WvQ$&D1k?qgSY1F<64!-WuOmW{Q5@^h< z;v@m_dFLo*05NrAsty$$fS;fcaflp%X~$yO1BHw)OdSS{!UF6Bai<4q0^Nv|4nGOH z#dGl?j1ROyybH|sm#fAF7UQb(zjS3s{<@AU#P#*%PJ~pJYOuFi#1PhTfpqGwZ=P|G zKZl&suI*g0T{lakRqx~8ntrmyPqcBj`i@Zx$;zZ7m@eIasD*)RpY6t9RD1c@J>NN< z;O>;$%=u*{o%x<_txRM;)CeJk=1%fCW3*d?OP5XF+uoN|gDU9Hihc1TaUXaUujgdG zma8Uei4)Mv6gj-GZ9zK$J0<`^%+V)PXH>1)oE{vA)C4&pDLN7%w(`_6Fy+@b`ezlJ zr!5}?oF?CY$+Y^si6OCtXj3OfhWLZPc*}*p(4koYN^IwVBdYSRlkDL~(3e$@4-XhQ zWUGAFJBa`J%0Q0^lr&CIelI!Zd99wceyC`on2*^4C+plBE65O`<&uPtBRwaHOr3kT z*fSy1+BfWxy67A452la?H;*vxU|pbO{ij+=OY1Y!#w;|RLm+Yz!`gJXz#H)KZA2at zgr03LkRyigEj(=Ly9q0f&3x#2{UfLVONucWLAL*_$M$@E0c1JiCO-dtWpSkc7&TRi z*t3F@np1?IFOc9x&TRs{AxHAyi@#28wb{#tQNnqt6}#PX``qmbQqTW32+t!Pua2)z z{<7CQ2D|Yq7W9!+mLphb73oJeI%`i~q#YH{bctC$o9av^XpxWJuUeaG99$xXt9a z^aJAY{5g-%L>i!GyM3g&H>Ssj=a;5qO&_I{R`&Jv%~b?>J*lz)LjPxM>{D69c)20j zE7S@pAz`m5v|9SmHaGBvo!Lzy4^kawV*biJ33u4_bCleDyFiR&zSyYDz`iuyQ~!uS z^DD?{#t1W(v6Uc^Ie<&YI+jXxY5Lz;%ifF7Xtm0xO*3pFFwWYr4MRD8!bWMv`XVC|HAE`Z^THm=jH%I}7n@4^z-nPy{hIg7JBn)y=Z?)+p_jUssOkj>j=Y0&Iz-1c?$@hYrxL%?e1$0EKgy=P!Pjb8MlR zL#4FC;jS|jHQ3Y+e~535ZzLVcX8M9$FLLz&l52qjj$W(L$<_4(f@C%vSMv|L&)ILd zyzj_FkVG72^pPP_r$26x-pY1^IIBGvVZHYr8kn;O)_tO%Spmh_&y}0#ZP1|Q{ex2~ zrpSZ@P{4yC%k1>776=BQCwLebH5KgDjc1_}&*%av4$j?#o3ujEy7@`E_tt?|lb z1Vb;AqaN?n;(GC1;(^;_>o29H>^d}F_fY2BetUAnOIP_;#_Mm{QDw7e-H|{H;30_& z0jaryF}RSXWowpHP^~t)@KF*Cxp%AqClxrj-1$gQ8G(VK7%^ZDrj^Is6?Iduk^U%3 zKOja`xKg6Pl=^ev8WNO~%!qtg83qFxPsrQ{jNAr2==v7J4#=O{-i zCI|Tt!-@6hxJ=(LD(KSPH>&|JK2?@Hc2HLLh-ibomQITroBA1n9SAxE1qJn}v1b~a zjX+`*k0nPss5}<>nj6a*p1Gc68tAHT$=1bkQP+qlJTkxs!sj1AhK(}PCLdyOR>9o1 zfn8Q8bG!o?GLmV(S>4``)y1wMSRhp}otZ9C+U{J*_O{BcQM~S|Oesz~RgKTjUT>;* z>|jybbHBySAF|rV!|U`_`5NmPtZ81rEAb&S4-znl4PuuzR+#?|TQu+xy*=8|)(Uyo z&iEhWT8J9ESHAp^=hLehzc>+8R#dKNAR(z_OV^$QXx&vV36elwPS6IFB?8-fJ`=kb zH(V&K?c8n>zjrzDb4zGNh?US6&S5_ShPE79phU71xv|=zo>0*cK=h##4}?j`WG>no z78-hw8q4F__{wMeXC~|zh+iP$bF%}9=62tJi|%Yhg*pB}S1AJy15x5xIhy3^&d)Bu zfcYnE2XrtIHAy21QZ7(qseDQr-&G0)mcIYOOv2h?Vo-l4^f-i`Fw7)Y&n<2zd7c*( z78Nm5Vk^@R%N)7z=DB_TDeND{g2t3d3<=Mp{$>1~K`w)Xa(hG8&qPU2uS5lKzuwW(zr#ZnU=oR)UP!qZ3A$a1nPZZg`VJ09u!+RI0LmfuA3Z}Y!1kAb{Vy$|vl zN?;%BjnvXfs>xISjtmjW_I^Q3xL%ByoAG!ZcP~NQ{kwya^q_6>ZzME|#PKPs#6+*! ze~>8(T>B>{2o?ZwwXxJ4>OX^CjF^)R2EwSnF5LL+o{M#XJMoHbV^Ro8ESU^Jg$tey zS}M@FcCtq&cUwa-s({*TSGf96vGo0*+hpgWGyV;IU=K*LwC2zPm0hWvU7LPl1&h(@ zjsuXoQ=-a3D44lGaUAqb@-FPdC130cc9;J&SH;AA>oJkt$+d^K%YR?E9XMf}(w;XM zXSg%mG}N(M0`tjVgSsS6KW5N)ebh$*%4|zsE;^(bzkPpJA$$03r+6#FO+!rByTEt- zEe1_OZzDfk4#gVx{_|&`ICEUMp;!kMGsKaLG-CCg2p#U5)(*@HqcM%$hTgiO(of`O zpSy?jCU2odReEdbBp4yyxgHWuTAGo}Mc-zitQJguu_vlnpZ_Xu_1RtUz?glf`FC6r z3F4prV7N|L6@?e|T|=H736fOPJ2`%QctosY9If6^bD_sM0eo0uKZakS^eeiAqc97!b)q~vLY!9J}Ll*PmAQpLZPvowG9pprRe;bYn;4~&$NP(n+Bfn zJZkDGLqcTyaj=m=4GHxqFkM=222Z-q{57~lgA+go)~Km_7Glbq9f64snjK7MFDZ5E z2$&#DN8@5Y_K1XGA!uIxF-DI_%-rrBOc6!bfN}UM)XhZT|3(Rp`$~Qu6bqXpES{NM zux7M8goQX96KrCpu-QEY&5A{fN<%+902sll6XLo_rSwyjT7~rHK|>_wEI7$PEG8LC zBJLNc9W>U;Tk<|grla$*tyKrVTCmGFW^bSMkTSH#Jnio9n_j<;$KyW9*Bx=WIVPe& zjM|8AdcRPQxizjh!%*kEL+D06e`jN2B9q2aX0W?hv1wYh0Z6B`!qL%DU^VK`LOOup z2uVZ7N%XMflOgZ_7;o4UrTK-^^Nx>wRBiEQ_>0)>1ZJL|+UbP0;qvcU>^a1sj*~Ls zrQf*SIg0Ovz9mpdfB5jBIC=EXAHSZcCMHzafc#Y($qIZfisPo_&RSep?67~_IOv%;4?w-0uPKMhV)V3WF2q`4P zuxndY|4lcd{9Nno<}wAT^^Le$5{T8`I3e_X^69AkaE9C|f86k`dfKnn4C{l4 zkg=S*)e&^DYhB_$d@NO#9?p5iiN?DF%B=1VI^~g3V?*8aAx1j4J6PhF0ra(WfJnF^ z+`Xvc_U2+wwylf+H5qsf!^JixkRd?Jz2z+H8OD%I5SLIuDyM@#jXO5Yi!h>?1(VG4 ze5y?R)=#jWIbBC%%_ce|kc>E&hTQ@yox{4<2u8bR(#)?mYU~5ppuR=TG6{0}Nq^B( zTRyS_)Ahynjd#Aw0Z5$C+TN;K)3|tF@7UckK0f}fZb*U}J8}RZ?0Ou!!zS4yvca>w zIw8akvY-A7J_CGzkd3FHfS%0DfuQLfoDEMLe50o?W(o7&l7h#ARE3zZ!_NpwT|`vIxv=WcX_KtIW92@v2%4?Xb{wMTaDE{-jv;J+^q|h=<36vFSR2}rBk2j}TzTu5b;LV}ON_s}J0zdBv zOH{bgi z-mLAjWLCA3UECo}$>{%nTK4@A@c0z6N?aMIl`eH!8}d&%d%Vef8u-w4z+}lEfcXb+ zP}%V*yc7jM#IR5UaF~Fc4*~)r6id`1rz0NcD1H81gSI?jS{UC3BNpiAcP~53flwv1 zMf&_5EQf8BSAT_niyecI9)Di+FzsX$AW_;N9$P(jaXhX$Egql56+ipztOIIdyN3;d zoSXrBqO12%LP|Rgb<<#uk|j&I`!5EWs-zU`Iv}1f&2bnowlQ8nH2}3}*RSpftY7hM z;OyG!YuSz=&nvn^r7X|?SyF1jlB%t){v$hE@*}QQhH?oAZUzSdJ80-HQG__o-1vep zitnbaQbL&6Fn(laj_x?@wTq`qGo*m=TO9$&T*Hk7<8W->Z_BX!)Z(E66f@C3@FZRQP&2z^^BW{rV{L*yvtfTll&tnm_V; zIAZ~S@b$oE&4z*}_34kmn!!<*NqX}-{Z)AI?w2h!*PBUrk+5yAaJ=Y$)uW9AABzrV zYw{>bADf?8Y4(#gr(TX|d>D_a)X|YN=Us_r9wq{UC~!*Br}xE35W1r=z-%6h3ygHU z1jd_&$d!M_IJv3guals*3@%aTNLl|HcEeA8m#0~2eN~nCzAvLV-|jdh^eeVFldqz} z;0BdOa!<1)QD9l98dTJicy;U^;vK~WIuA0se3v$ZC=c>J|DEOwGbEYvRMU~f+H}s zpTZt;3lGoT&hRI4ptOnOf|abmW)*1P(6K%<--#8jz6Y<_^u7}vE-Z^ElCT`Y9kMQL z%aArhs0%NTL#%Qw5=2&Ou!Hp<3LgREEkvg`H2Vh~TauZ3=ELchX;Jg4D7N=zB~3-i?-HQcbh=#*okAZf-5xk; zLf?I%>bWRCRb74KN?IY8WSyRwD@gL=VM^Eoj(hq?=d-@IixFY%o?F7T_(>R)kWr{9 zASSB4C@~82leQ4Q$k=lipS@q|`;koIODrF;|AS=3JQ1}H3tuiZe!-UG=WAA@aUZ$6C4ab^%m{CIxxf!5e@xA;^8@+s2Q{?^!I=;VukZR3fbTi z=8uNOyO4x3rWr(nvQ*!*U}HRT!kJ3agNrR=)h~_0MIbNoS)T1467h6# zyyVG@%tBK94U#XX|FW}5!fB1GzZY8p?3NYs3-q?I7%HQqvfW2F8r7U{&|>Bv&lM3w zwjc#nh2l|mwNWx~rJ4ULkPKWRG9ViC<~MFUqKX8yy~9L?plW)V0fCSLgS*J`HwnF!|}H?%ogA56}Jmf#v1XH<0Urd{UUHVE;6}$FhxV zBuFR>p=M&Dp*FwgDAJMk3Kla!x6aCv=!}(;#(*Ka9SQtWD*+E<>@AxDBcd|bs9upY zX>MU|p1X|f$`Xwn$A%OL!ORbm)O>t$S>Q*234F@95f$3rzBA#p_pHe9V0F+e1|{RC zgI-%sVCuVVvb4*+U71|GYu|9tU!-hL)?Htv|F{rO;Lfr@$@kVBU{M&{8!H#K?;3{6fwJ$j%dQ`yIF`PoEonJb* z9-0Y_7Q%_SvK6ih#2|T3(H}v*;j%f#sU79zK%heBC@;Q%uxwy$EGm!x3-E|HNMvFw zOTH(l|1HSO$}u3n0mc@vVy$uz-+KWHSP~lQkdnl|7u%IyRM1m4 z{|03a=Di@$!kU(uo}O>Z>3o#PSs!6Y)b0SRzb|VbQ1J;6g_Kb-erWb}LApc9qFjlv zxB}UXQU-9k%$6@NFO#Uk=8tbR8Q=<=uI~_NFlqtzH)B$A4#C#0(F#}l!}PfTD%UCH z2?d_Shx|iSApv|wE<|$hem^}kD`i->5w%uxFu;_4-EGArLKy~*&mwHI#PI~557}=n zvuj_QzB%sZ$TC@Doi>`+3%)8cTShL>4!SQ8A{>H#>_g|-FO9M~hS2`NbUU^!!D`*G zjL`{AE7=KE=w9&avmO0UrIiUp1I4MHd24c#l{hw$@blg?jQS$o*~v%xd+D4!84vfL~IR zVw7s#6lqD!KzN`}&H#H`l(-IJ_Lw97{Qfsc=n#*~WES{nVKz-GTLWQ2_UJ+i6|E5QmR2MQrqe9FDWYPwc}l4n|NU`l)BW9`^Pw5D!>n}Z zb;{eQ`$~CD_C016ovmxAs5{lq z-u{ss^}cC-fhJwa_M@Y+4ubPC8F&*>(og zteOQr+()ttS5WRAj0Ea9YM;PyOrGk0y^OBhM23)6&Q-ts|M=cc3t%123v{?lZ?*px zx(&fga;)$!1p7Twr!y3S*D&Oa(Z~BLujI(C=W~{roo8P^%69-uVu(sc6OfOLjfAP8 z%*bfSY@d}SKdf?iWiW(6Wkb!TfRN=WuQTTjJ%>=+Gja)mt>ytmkJ6y%fC?7+)zji= zL;nVBiGWU&T#wQz=yH$@g3$Bw^aQD0Yg-G8C52yz``zSXcF^i3?F-rxMo5FK&nSJ) z&l9y#*Y9%PX8os3ws@$<4)7E>)^TjQ&f^_Q$Nye?*xsf(S~M(!8vREqV2I9r)2;%p zB^*6XCbu=`&&d{#x}x<LGB27mRhhf&JYb^k?4 zb|%;n)ZT1^uIH%spWA?MO&T32!hrjpm{@`y*U|$aSK;NVdWz}lI~tbTYW4wL%~qxN zeN_@hqqpA@mW8vU{jl|40kmnZ3g1)+=nL$NI zr{D)V@n-)EC+{67>e|n8`+NNWaNXZPmEbWS@Z8t;`aSZNG~`F=dIuPr!bsq;C$Kiq z4IH3caye^=QRB3wTd6+TGGgg;4f>dUrbcZ_vm?wIE3&y-^kVG8-1k^Ljfr%eE^Vo{ zw_D`m;QsmXSkGlL&Zf!nmLR}|ll{*2^fIE-vu#RXd-vZe{`D4u{&!> zYphG)*QoNQ5d32~FI4+=?zqE%J`7j;sD$--Qb>qZg%{0OR)E{$Y5Jd3HiP%+<0Pri zl_fO{x)=@~Ue4Fpbnz)h!s6+T;5f>7=}aozMdC%Y&$vfn4f9g@A!Z$M6GTsuwL8rM zP8FoXoF|#DEzmbTx0+3@%pHezt_r^2a$H8f5DOuOz8-x}rJm3CfJ3=M`;8Z_h!E({ zixpl)b75$wzw%2mIubH7%ehO1oz4gH3!6NxrZb1XTK-B@6l7I+t26MuQ3zT$r7zop z+t83SpvvF(BRHJmP$4Mi@yk77O({$%C{#G5m_0<&S0jXo^0}RL{#&u>d6=~Ok8-Ow z><}es!nnbGzg04jp~vOgfj))1&rxJ$937Gzv>#JQ7e+`YHu3?z-rain+w7qPem3SQ zmEHn&N#7P$V30z^D*KWl?n&rN4YDkyvv0A>!w-Ho;0u~gOB=BkNk)tA?B zjGiw~@0{#S*W__q`Lb`zSTc(7(wWp`_m{i)!qRAChz zaO}Jh3d|es%xpT8J;C9|T5nlxi)0H(zAs4j)H(SPjM3O2tO&<}I6cqtSqzWqDA|zQ_dV~r131^GvyRxER#0d7U+1LHuNTd;;^Vr3Ha@g{ zg_|pmwCaP8tx=J>v1(Y%g^1*e+dB-M>Kd&1hZ#-k$M>iM|Et7{I*;`6dR|7iL!a7z z+uMUCb$1SYL@DL`H8lmgVpLTyxxQ#sKRi5GHy!mfm)LZ6QWSSR9i~Z8C;L#jY_OF* z@%j=Vz);GFW>I4x5c!_fj#_w}S<^l>+?UiGa5*px#I^9dbL-iOT!gzerpr^YF!a?x zG$2?PL43uXk>?t0b`NGY;Cs%2$L;pv?!&lh(unci%^$JI&eFT72maS{0)sj_G`6tH zXw4*CIa)@_Tf^UXE7DtOKa}||e~GK%V_sKNHbNM|t%US^fnzWuR)$fZ2-zTWB&krN9^M_Oca5+PxL}-hNd7I(>1?`+71&6moz`VN4;C z8Fo5aFlYK&e4<107b(7@)85V|ng|9+xWc6dkn4;uD5FpOaq_t%ouswXz3}M~Ys09< zLftrE6J$;w~^gXeo{zofXBERZmE z7`PAaQ{EdB4Rn4uS?f}I-ra-F@iza5*T5qht}p^mlJR_2(W1MFcjruVCn-KhRk9ba zhSNucC!L)FKL#I@cj}JaCu?1NJW~_P=!1NQX0m9`XhaS1VOAX?I- z$TwsjRfi*-2)M;Y!F8Q6wyx6zdQAE^OPS}&uSxt>k}uqUL{c1Kl)mS?P?a;IAF;?U zy0ol*R!jB&nVW?8qLe^sb^0aHpKI#ij^BeX`j?N9k&&q>jF4Qy;59fs_ABpakD7k# zdHL6I-u)h&BhGy9IyU}1Kt*Bcm;(P&K8>hsAV#2wL7WEM2SjB$e>Q|qVyE~sUb=Y3+e!R@`2do+P)|eq*I@9x>q>nzGuCy!az*ly5>awRRf_>P&pl}K zzv%CT^m9_f1vKfp!;{Gr`l(=L6f zV!xxmP56R-d%ga1%0K4an-Hha=tsv|(5ctCPmZ0>@Ze55@MNoSu>0_1;;YYH4gS_d z;WQ{RY^GSE6i+hCZAg@jg?E$VJ1SF1@gCy7H_j~$@|H;YjJHfT3iD2I$qj2tVJ3U(Sr{0lJBqQM0b4TCN` z<+9%(8FK0FQ_Xspb;-BR>W)m2)uZH1u0<6*QqK>ZO|S^?1-^Vnz(i! zGX9Y|>1@tQCj|d&19~&)K(}NExj-_EiwAEq))Hk}V0s5)Kpp-7i)>qxhpo}YPRHNZ zCux`b`wQDMumM=R+~&Wy%qaTh#5QHq2Ph$d|~iEvZn9hDg;Kt>r--&%U8WkAmIsf;d)d1s?% zh5k`WJ6ifHV;}cwwn1H8rC-bHpSii982E7PnW_A52on66oSssc!qY*yl7Y$6U$E=? zAu0TW5GGFDe)-@eQ!{#P8-=CPb4yR(9`7D9fB%LlYLDE@CH8h?^}<`Rs{QTG%J~eO z%G;Zrd8^7niIwgnYs&a-b4%B0f*h09A@}d|fzZ&LG#pPM*=vEdS@uuJ4`8qZjrriJFV*F?gCVqBk@B82`M;n7 zw@#OfuamE7q{R6+qH1b~i+C-qmFgz<>2cc}60B8spDRc`td(b+|8o*2Py+dXLJNSB zz#w^^Ep|AF_C)$8q--q%9~&E1>@c98Kkm<{=Ml8lSsZ@%EwNr+VT17XT(jyh z+T#x<$R!b*yc5%(EYg6-^uSw0?C|-Sf4p9kpG;Q_tdk~r{#+h_)@I{wU6nzS=2YJtl?Mf`JzkQUv3xQPB&gpEd;L#viHw> z-d^RHyRhdY5;-i}z5u@P@Dk)mJ%A2dk^-;QM;-AqFr&Xwy9sR8X557b6y88#_#M%G zVo^gtNT%Q>6EJ5@1Ax{>17|%c#q=3VP;{F>398x}ML{d>Ro~jP*i6pp#eZkp$sX=m z+X7Tzre?Z@XZpwUk-U)gbtd6i)s;#8b>Kl+M)0pQxH(v0Q46)FwIQCtJiw9=XvRV! zB_tV;kjIy8jV58#SHHHl*H8Rns9*mkjA-Pi>8I4%v3GE3iP9!m5QrlDO9;2LE`7|8 zFI<$=#m(;W*?6XAig~_-4ohLxQRku<&pgL^dp#r&m3D}*2z$BfYmG1=eJIHK)lAiSyl^o%IQg;zFyMxwF4{5P72u_;HMj3O0@^-uviH5 zpk$lx_{aQP*m0xA^#Cmie({;mWHQIg%fk*%NGS;=#7n736K`0PZ|T?U#Qb8 zO*Tg0n2TY!#avrk-@fW$B-=hHW+WoX#FMJt9?3 zmMdY_Q#9B5ecP1JS?K$3OJKp~>b{IV_c`}E=0hVQK-v0QrGD+sfAKrD@4&GQ<5#W> zdIRPrQT(WA`oyeLNN|YTVYHM~8wWl02whLMS4pb>KT}i#M3#d^R#3E;S$VRk{ZNFnJmu z+k&4YcG)&G-JwcdY|Wx&)yvBZR6|y&%azPU=5MaCY^x>j9W4IrTnrIlMwfpGQOwZN znDo_DPkrCf>_DmeF)Dvd@|#q9Q_Y&R9WFtrZk)Ose^$q7+ktI{Mcbs!Q-AgW2nEmk zWXnNq&&f5qYP5`t#?*O(-9KdRjB3;HUu3SE_MB8^Tr=3!jJtFU>WlacDF%V<-*|W9 zhd+A_&Mk|NWcP{+@?@y-QDhT-D3o;RGyg93cg!WnT0#FVh$*t5-3_HaLRXFxj8QEh zkZHDT&ppu;76Pb+@|^>jW}TY<>+2RK+q`?ibmAsLlSzOPS!#E&0Rymn31T2VZgoJo ziKa%p;{})tep_f^_guvmG|zs!Hjz8TSf>&}$SkJ%N8gBE(%zLc?msFGa|dgva05HB zLa#fdZ`?_;r|VrAxEhKJ;2FqNu*g#)3l_%2`^160sYJcyLGrFOcUahqxQ{t*%$>jb znD++rli>=;evO-P`_wGjuoLE8$4IBeAO#7sl<%hQz{Z#e=GeKUDu0XKXbrFV);tk#_->SaDr*Af>|bI(=Z1ht=lipTNh zZrsE1S-f+VnicJxyeWvB4J^}e-kqWF$Ulp*4I5FJ$0Wf(tG<_@&`6G5EviQ1 zBTXBx*;Ds@lfE*jA*2kJ-v!(ZG}bmh=n&2VdpU;shg^blN87W`e0ZdJOna$uih zp$5i?!$T|SNVx=dc6OkZAdu5s^%qsOur7sfZC3C>#Ue-ws7#5)-s=%x&QVx2E zQ)@t=?Dg&6F9GRaSG?DD8|QakcTwi-gfa)lQ6V(AUXUie{t!mgoJk*#ZAIzIj87x` z@S9Q8>hz9N={fC7Mu`;l1I0<72KPGEk^tH(~5L;(j} z6OHetjH@4&tLcJsThn+_|4?0UtGJn>PT%!oblp@n;@iwzhfo9WO-RE#gXj4GKY@e?rRh2swF}|mn@f^& zpAM;Fk{}GxlEpM{T&wN-f0|pv9f=0(Yfn{+VZj(@=nu$G4bk3TZ&G@=91_u!L4r44 zdUwrfDoGX}oKn_WwW}n53MA5*7i;mrIDg=_5zAA`4gSWO1{5{ABx`0Vwq&dwOb}UI zUA3vxj3MSTuhaYxKhoO^ks*{g%FfSUId=#Q{?Gx!;En9rr5YqDDJf5dmBCh4Vd6Ks zrbn|WP07m1`LpO(3JD4v7`B4itAPe??Xq*h7qN*$^ySV4tv~MC94u3?dP=wmVFMP~ z9#pKSN%R_EPb}I$xZ_~%Y-of;OWSoBj3F;u$lq^B^?m5w_aTJ%k+6rZJd==gV1Gv$ z#S+!5S^&S?_o1avphr3iUyBjc2lIWKWgxH&%{2|exvxaDVeO-+;`~JF7)Dw}f7SO;wzEb* z<1uGFc(Y`=cdL1|uNc?m&3yBublNFi*H76y3fMG( zm!w7=U|Wj%=bN&BVklsMtdC9F?$^U(JKmGXgt|w%?sZbO5#6Wc!5KE&^8lUgsSWT1 z0RfN->BBoBx6C-ePlLEO&^QIO9}oec4*mB?_nWh&%znCfq!jlkdBSEFkmo~YjtXHb z)T;n$eAKjFl@7FY0p^0kpxbaSgDBiDNRUqevFQ8DozR6w{)|c7??d+MQYXNF`yoCY z49CS1vhx3Y13N|{K$-xxiJi?K6Hml2t$5-=fk4UiDjMQ)rk zV?-18=W3F148*h}?dBZYViZlrVAfQJ#pLen9Y@f#h&7hHI=#`nhd zuQmUOE{?Pjgop-=(&q2kGls>1=rH@aJKX3uyBli+CM{@FJnp*UX($c2Pe7TUS@!!$ zU~zMME90j(7z64;iIGm7Kv; zL_uf$0hOaB`aY{vRb|8;_I~>!((LEpBZGrasr?BNYud!)?J>t^KF=G_>sHL?UCzP& z8MHHnzX9S*K~W-IQ6{^bnd49-PHAczKe+P*ENwGJ)`Xt7(C6?XAJP|(lNM}&E-O&6 zdJ4W>Th>-p(*j8{j9yvZcM-L)%N=gal5g@p0|=J3wow6erYr!ze(2!cgCKx;O4~Fs zDz@l2nb|?=(~^rE$mdOy!V!UDL<|>7Lc=*@IRb8LQ9Qa*&n^-L+)(10kFE#L3~2&C zeL<2{d8iyn?Xs}+Qb@Y^{qe4#Aqxc!4OEQO-vigzIm|$+QrX?@Er@<3!*ecDraqU0 z-N7@h8e}y~+XF@w6CW#VzkurnZ&u79>D3b0tJ*4EJ$SS9V+Tjb?nW)!CP(TvELY;P zJJkq~#43V?&&-9L{Pkwp?bTT9W^(44udM(5@O3!FVTq4lK9Ngm4IjmoP|m8*oQCUGT{HBm%ke8?Wt^j*I6O?|=>gQ+4O1SOH&b)EW0IPyKb1C>I+v8wNsel+*{z z6>NLcIriv=PqZFx|K*d7Z;$3}tAI54^;@RLqt?AZhi-L~&EmrG?f7xF!Bww9j9I7|#3&E4H#=dKDjg`p{?`c5)9gp zKqOZj&=L;so(`KOtgsMZ)NAxVyAiD*sybsZgICO{s|vRn-W2RGJV?cY??RkJ2PJ0; z4*}*P+q^A*chjER-m_Gd&Q^SByVi3neDl^*E~MP7V2X`Iu-k99Hvn2?%A;PXYiIs& z(tSMoZ&pn=shjq{qVIEpy{Veao`m zZ2(C{7cFAEvPrVw6G^O7wX|(o9O4s5qGLsfvlD)%e8>J#yxFM{@{<`am17Kry$ERD$0- z?aE)CN&%`X!ML;DbHuaS^r5@q*&RFiQ~Tz2?XvBAu5ZDHLn{%vqcz`6QPl~v^{$Mc zm;*|EW)_G(ZrsFA;$|lc-rNuprx^5F14JF%(M7`|qvt z;|b4w-q`9vQ&G7T@9LL#EKQS178(lS4jq3gK@1tFdcWTGGB0`#fv4P21s>?c-XH0XZ)uOO$N#LwHW!zWpU0Ff8Y!3F*m7N_ z#Mti(uJS9L5ev?GX(a$}b_fr(PyfFA&>Dyp(%axcFH$BTAxV})4$@|ckjx)I;b#Cn zma^PL=47Ok>NIB&$V7Cn;@-+v>UuU8Pz+eQ7-D3=6KV<-NqE$9Bldx0NDb2yd^p(p z?(5uQa0Y`WiE5)$B)Wl!YViB2J@ilIs}S~ z#j_wT<^`*FFx8^2ET1Ca9P^IkSBXMN0b2~$hk_PO25|TS{PrRsUzE?&p@Xs|_Xwp) z5a=&_n9Y_)fP6oo(JM-?{TH(GK-?AA{Dy}+)WjH)Ldq;$Eo>53&$d33B3h|cG?_9j zw^r#OaFa<}&Gzs}IJCm1?KzGt5&koMntyY$uGEuBIBY_%l^>tB(H>Rr?{v~BW8rmi z5HB+bnBR3K!6n8>%Y_S}_= z$G{_0U_)!em!*KRqDi+ocYrpe>K}r|!~Z0dj;@)vDwobMabR}nwx=UpEn7p&Y2*#l zEu~J;wqv@Kq1!t>yV)wtNURr)eN{f8mj~TW(TYr77>8-BT6{WalcfM}!^4Oi(ft_# zGFtGETEr*GfR+!U)vC;f@(GJ^K+(4=KsZ;qOzAgReL(Eg*}1W%1|3onL>&&Zhj##I z=NZi*;sfN((+gltCZ7JiDZbJ--LvOokb~iPfZRgmrt~h8e$nLLzI5j%0toB-U9!Wx zhO>j2f*XDE9;Am;lH5D*db!b-caKJnODXoj z37232wQP)dA|hvGr18FB6j21rCs;W4hOL{B?1X(~4W0lNLw~ES3OrFi&ktAGq z*=@J)1f_nY#oO_Q_fV1>_-KTeep*beC=zH0?U~@96TZUDZegU**_Ku zIn&$QJ3WmN#rcW2z^`H+h)$`pBi50O#Js9Zh}AGM(@pzW4E(9uCh(tmG^}-2h00D6 z27J=b<*b*=Xbe^N9otrz-K!xJJk<}{8rA6-6rDfY!yk+)up1e{N0Xpw+@OgE|JF+A zh%Xy$PxI~rF{w#&xuSPa+;qM)YBYOBI?|k%_N%3dX9nfD z_?i)#W;Dt5;2Doc*k|Nzs&+CO^Ynl{N%%earxr^J9c z@1r0OS}2;XzZX^M#h94kRPu^ar(_{aw*Nj(elS}prFE{F>DskCHRkgjT@&MsRPqEn zW=*oBtWMu9{r##k$o%4(d25gfPLc(^vxzgmr@5Z}y7RY7OZ4RQX z9xy_tJ-ZZk%?ylNR>7PC6zi;5pr=fx(y@zP{LQp3#aTirOZ${2k1fhw)ad+$Q)(d6 zi={L9#1|w{VU7)1xaSZ^a1GN7$M#rv6sZZ+#wta%{lUx!ykA;Yvqnv6aB3rCV`JIS zv!EC>U{NxPt>S_omnVjCl6l$>w}t|!3TOGum zb(PI!J*JLnyspaU=$u(fzlivQBdAjU8;%TeCBj@RL#%9g#|R0B{C%^hscG;J(m6xx zU$zdr@OkUfre*Wiym@TMP9}v%>)4qF_FPL*fBlEv>JBaxH?oH3Br1(JgO{ zKiNB|l7Xh-WeLBQtav34K3RoGYuaARnr53x_abLi8sHwFQLTXIpRH?2r5BJ{PdwWuq zQD8Z{h^=3v3IX8OwtB_4+^9J>3SJUFFa%f|DkIf@`4L}B4R zqUH@e?;>vQ?&bvK=2d5Hu<Vx5EHMAiP;56#SqSbE7W3?Y{wrQA_2S=tiQl#6i z7r$KHji+KRkXY1T0+796Y#2)XBrIlwM5g#7rgiP-qP{E}=-+*fcD@Q3sOY)E^y;a& zUq6R8efss?oeP$FT|R{ASm1G_1FnSjKB9HqnEUlQ&%6!uSv;`M-ASk=3owfuxJ=e~ zp5d?@O6oD%lNnK-np`JH)K(rYCW0dm87h;g2-lZ89AGkNwPpm&l1Gg#b_znvr7q_3v2Jcjd!E?qe~JKE<} zMD#AGsrjT{vS2R`zZLCH!8sT0V!taiKqSA-t>Ga+E{N zkdvS$umDK>_R|dR9Qv&Mvf~F*`OUahw9$u=dp@a!@O@TI1xXt2wC-*}8p5`taNHdc zZY)t?;?!k=9|Z(GunenY7$sBbf7Z(X7w~?H-}`O-N{Rd;;y%yo)nHFk1|fbU=Q0b= z1;sOz^hNK`-gi^Z;%ANCeBbhnEhn3vG#%^y67|R9(h>9Bv>!#%h}dVRhtGxYucl-+ zLY{HKSMo%C*g+fYue^h7>_qnU(xPf%q$oXQcIsaie6+NnX5ZT z{k;t7XOTQ;Rr?$vgxp;f%eWAX(uRn?r#+|t?nNCJyZv&;S4S7rA6NFMAo2|wQKHMT znx9U?)wz3TAx5mIj~8n;K<}jBp^1=CIookphG<&xbh`G#h#%TE{;EUac_^x9VmG_$ zG~vn?>6weqNRIDU&o}0vK8)`}7)gLU-#J_8?x%gBMT8bMwGVcp()c`G_%5G62i#V9 zl-C=RPyH(tLS=MPT7cgDVD*=;*ZLzbEtsmqNt03+Zjm z#f7u+{g)Q&HN|w=U9`caMf5v8*jn8{k+x zgh;?w5&w+f^!t^LM!IxUkd!PCyJ~}t$1zXorCUQ00)k*(MqETS?g%^W&IJKJ_&II{_=r0(Gl4Kdbo-)-E8Q@GzOUug7FvV&b_Q#2mu~EYTwie^S)!jzxld7 z^+in?B{X3`Ik5xN67GaYD(7voKLtQ3GNsVROIK<)A*rySIGNTgsLGn2T`F{U=q5h541Z z5z3zL^AfGf1J?_vXELrcL>M3mxe|t7$!Z7bQ~*;0v!L_4{cDd|Yj3xbuf)d7{_*GD zs9c6qzqykqIzIT_<&Ibr_IBMEgFPbpI{MYzll$|gOW%=8e~f(^HK0` zdvcN*T@oGTK84SlY9efO6yo z3nrKEWex;XdX4Ej;ZKRK+87ii?6JkxqQh9m_OpWLI$%Nc5Z_IdldT6iJyJt*0=hmTXaPG?(1s4gLJ% zDNkgZU|G$?#;tXaT%D`Fs7HAx&M5%3)Yh&_ox;QPN7$sf$@BD@NJA+`za{(Q%d0#U zbQc*TiiKzLpKkzci$ZRUPp*wQ@m>@EhS6g9-yG}lf>dCZ?9)IYYtpz?ag)e`f`Xm^ z7A7_mX2P;Yyx!LC496lyUsmgK+kj==MF8iAgdyx9^_j z4jTuyM)t3r%I>Z_v{+aeki!Q03^DfoJ-Y;foc!sN2su~Ilp<=bHwO07uKI_|16;v;55h8d)m$59-uet}+?4>pg~&VY_YNm1z#78aJqy7YkW z%&6h1VuPUu`q4mDh5HF=YDDBeQrMPatJBer;hp$K6vEGinXPGZ&AXH>;`JRaE3Nz$ z&U)q4F39Y*uCsOjU0rNbSP7XG99$SZthEq~*?Z?YbWu@HUw>Ibcr>{Cqoq$O~qf%4E2=@c*r`Sd^LEmR?K12o*4+Hi; z`Zaj52LBVJK&)m$|zV{HD&FC5(!m$H8U~{>8-T3K2%m0cYsO!&GPOiNEQyJ zfP@t99tis8Oi96%Am(Z^uofYdz=&V|=L)?3_%6bdT~@civG=Nh?6EY_BLucGdg|s8 zyX(PP;m>)ErUs`Z8O-5xIxz^<$7zeFDIw#^S#6K!J&d<#~)FIf|>BI z$rGBR@kMvbjtCyJ(aIu5dDCV>84^>=9SAC3-i75g0^4#0_T?#H`5%c*nNYvb zg)$6NEmLLrdqUQ(p~OvIy4lVC>1%9k<_h_H%Po1JaG0Dr^Xh$wr@{RWk|)|=yL_3o zwW3T3owno5J3RcKMOeWoy%;ciQpP3ZKv7GS_y@QkBX94u{p%#zqV;usP8c8sMT^?m zogW;~U`ef3wALSex4W1{y9AN~n`E>P&$JQ}Da3EHM$=DC!|>fYjZ}IgQQ1=YzMxhZ zsH|Y1?#SpWx~cuL&tcsfL`!$j8noTJK))ld}C&sghmf(%j0680Q*glFLro zbgTa(Cv(mWfXdVZmy~f1PEJW8JVv@s^$M9Bh{{pWifjA#2aaCN;&=ktK>MgE5I-%g z5Uf>(6J>GUtc*W8AN4+fN%VM0ROJPvFzlU&sCLm#MfXw|8@0SknfMagDkvAS<&Hv*U0G(Q_-Aw7HEZ&P3<-0r|aO+v6 zCr|Bydoi7vcYrS^RtyB~+P0ja za|%bb;|~c^2vBbinI-gs+K?XjraoTo#{)!oL?MQ#&1B>|Q5J0&Y8^eBLEuYG^#o^ArmRZ5 zz!RWe0VW>af`C5`CnMg+!vfnK~>*{P|9NQzG{G&Jg!nsqn6`F~O^WT15}!-i|- z4#BbouD>ZO2CI3)!)9O5tZ2d!O|~)Ut+V9>tFCO$jHM|N{GEKgQC{U3c0A}61HD6& z<{Y2pDBmqbgPzHjRe?jK!=G~%x%Q8SkWgnMBO}WeIe!)x|09h{70iT@cuK!6p0;cV za&x;s?4{VPwO)c7k@`&^i5i-xRz?95TXZDC2efXd!;j#qjAa9<27F10qo6`V2BvQD z7(~Pl9$4bitZQLQVksOH6%~QNs~8$&WTfQW5ZK>u4EdiPbN{&513d8SK6ig|o_DGJ z9#Z^3cV#d}P0#D&UC-M~%Z9HPD7#A0_dL|-zDi2;V-87#ymB2&N+1B_h&{(Nl8=w6 z2WX7A-@$wfzyomy$V7&+q1E^g5mxEZ>sS{{M0L<)4!j^C0(7tt9)Vb{`H5e+Z=>S^}h@fK<793ZAD@8a2C zRv5KFu@Vi#D(PE4)JoQ>;{-`Us%RdWfDxb?ZJeJU9)edTkb_St*tEYe0Sjd45s>h} zs&$Ja$v#&uxI`-ahdWE*r%x@pC1(Z}7S^8QvU$U(iHg>=*3MDby+$xFyl2W-?;N5b9l=d zsWXJdu`d1(kdF4&VYkr@di=ci`8L}ArrYdhS!B5^0E1WS%NTvlAc)d)^PfYjY0~6s zWsU_mD(+)2=6Sa1hSF0T-95cTi1&m0TAm6>;6S@lr?1QYm=40Y0GIQre0qIL=pP~EBj1;NQ%}jheCi!5_%W}@kQxCw7-mP7O zAH3#yT$S_oyq{vB?@DOA@})w#5(=5Y4nT`DCKom~NF&76tF-4A7sIxTbeZOU$=3Zg zZ}_}|B=7SA;^B+<9BTM}+uHm4Odir@v&N+1{j+^g*sAnNNQh6rviRC820~Fmb`=}x zP3;p*{iLUUrjo3D>CS5=j~;?QYUdmN#1 zUT$rzk`Q&sMi5FC5?ukOr3 zk`sk>3mNry3^27Q1yWy`dc}mCD9?a18aIKqyv65Uvj&?YCQ|8U zH4CcrDnRn$ez!Ea@f3)Oy-A<731ZJKjcyW#7r}088{PqD%k*N<3Nh9^u1j5zYaf{# z*wKH}TNeLVj?w?E1u!}A@oCe45D8>eYs$I$PRbSm1~2}8A)zZa_!@p(=o(21caN`z z;+lHuSIpZpZ%(x>@fv@DNK*9r0SU!Zc;=DDEiL|+c z{r>2Ij`df~ToY9#rBpaNCyfIbo>fBF!V{^iJLG!RO?$r62`X6F5ZHkKd;xvdO=Alx zsdsHlBNH&RS>jk_*k?#cC1~K^rNScfi3b`j=kH18=7Os{O`P_m(epSD_PEUdzA#X% zxvqXabk;@?8GmOi#Z55UIR)*AMb;IF(+ggn0KSd)M3ap9t^JTHRF=ueS;`*ldf^M6 zum$m-xAA)LiHY}`hm8M+@d6znqIv!cX6rS!?1U+&WG86uf72{9|F5uXk7hGX&dw$RRKELM)w+nU%(u_uN zVp7@6+0hVV@4;(`tA8s^aOi21T&OB9_l9jQ+++8Ij)ukbUo%85b>(&5I7t2N=~xcB z6uG$jdVT?TenBt-2|qc#gvcY0zo`=~Om{cHgv#Hh3eUt%NH>Ew}25wD($orzN!+B%-S6CkIPXDz|Rb1 z>=4acM2xN<`#Y!8&2SQZ+!wlwX%#ect1uYEG=&w(RPYbjGn&y#X0U!sO6-gO6gD!9 z(l(-bLP&iSc1#QpO7RAOy``XNjmtPb(h^ChsUO_#PU}cqHGjaGZ^|>pOB#KO^kwV~ zf!$xEt&xy+zw&46Gha4DlU8LM;MREv>vVG&X-cOP(x$%gHoSwJdX}M|m6mv_M9w8| zf+p+|x(KtyW_EoTxtLFymKU(uY%FCtN{r7=;lwOFML1_o`?7TRZD!SdF8uA;eD>-y z@d|jSZV?vKK$slE#TgeXndpVHB-dq)z7U7k6%cbOqw7@@t%-2>FQe@M;{uq5BPglD zv<1#sSO)!_psX4E*_O_cagJOP*-S)}~%9B~@%IX(lBku$!uj@Om|q z#-*95t2w}dE8i|UCYBzi@7ufE;(}nIz3387hN~jiCVuddXUvxTfheGzdH??2-Mjij z&R4#LwoZaGRn>QuESgDxic6q@WLT>E09{nWj&U%y_kIq9M)DGgq{1mh`$@^r6sT~` z>(=Hs)I^^rKr9?&`7hnMMtXLTbIDLmqv3#{I}bry&vTJwuXPc5x&^YbOxwybhJ}$B z8S!vDGugBbVeyGV`}t;+O>HLSpG%kx;rYs+JnHT3iCvoUOmVFC)gJ4}7SW1Eb(|A4 z6HpdG{V2V7B;JXLdRJ4Ds_#MZn$zb8Ac!O@!*JVGJC0%7XPs5Hf3G1VjsNR#4ZQq` zHu){-3o$;h&%JclZ}QV6`@a_jWH1Hs&|+gG3iBkaH=b>oHJvm?R&ES>nWwZol4cB- zfrWA#j*bs;{Gb_iR?Num{sid$qR-)lezt%P?ZShGY=@Pz(GNnh4;?Fw2SSqN9U6EJ zH2nZ>2FZjx%_u4^Vs98binwS}g zg;Q%g9P$UYg}LV|+24(w7zl?_R<`%R%=wq!=Y9Q&gioVkvBEs-UXj>M*UPPab|rj#<&E-T@7uWkiG2zyQkX#3b`CQB=SoE z{$q_XG}jOy5Uj05^uOX82KiQ2R*_a*AlRpfQ{47GMM3-KaG-gcX?`rV4&I(#9;-hY z4q;4cn?;oM#!m%FJ<;`<*ROvrdQPOQT!FafxHV5Reg&iD2t7ys>UA_?WxA0td4w4R za$RD_QccG2XUgKF#>+sI10-B>#vg3js~AAi^LEzYBghIeReMpE;49#o^eY@+mJs5& z8(^#cva~#*G8<%ksI^y}&UdX{>^)yVNdjz;`kc1|SKWI^7`VnAM0eh|dya341MIih zu);8;0NXz5hjgVwf;yaY!~ntbm*0$XJ9vAe-<4wq?D(1;FBtMya8u`6o| zt_g2^20+o^!Z>GO}|uov3jHrV^V`2fNZv4C7|xDq2iN8 zG3ocXP_rjR!Rz|U15chWOgkxmfZq2%FNt*hLDW%RXYruknEyM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/beetle_example/3551aa42.png b/dev/beetle_example/3551aa42.png deleted file mode 100644 index 702445902628c814ff642bf53108601224ea21e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71877 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 NdaN#2C1V=+e*jv!1h)VH diff --git a/dev/beetle_example/3da61457.png b/dev/beetle_example/3da61457.png new file mode 100644 index 0000000000000000000000000000000000000000..d772729eac7218b6e9fffea8a5d15615b8ac42a2 GIT binary patch literal 50359 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/beetle_example/7d56539f.png b/dev/beetle_example/7d56539f.png deleted file mode 100644 index 8c71a3b692cd0b92f65fa5d786c09e7173020f9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83160 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 z zn4u(TM*Gx6$RODoK*}tSpO#M;lJql^@}dA>l*we`mLm9r;|>JgT9l<ð%g%R+RQ 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 O2tQ&zE`(KV9EH`lb|OB&04s?z*}ys4?}Vt?`x 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 diff --git a/dev/beetle_example/c17cca23.svg b/dev/beetle_example/831112a0.svg similarity index 88% rename from dev/beetle_example/c17cca23.svg rename to dev/beetle_example/831112a0.svg index 5a5b09c7..5f3761a6 100644 --- a/dev/beetle_example/c17cca23.svg +++ b/dev/beetle_example/831112a0.svg @@ -1,55 +1,55 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/beetle_example/9887f561.svg b/dev/beetle_example/9887f561.svg deleted file mode 100644 index 8805c239..00000000 --- a/dev/beetle_example/9887f561.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/beetle_example/e74a81d4.svg b/dev/beetle_example/e74a81d4.svg deleted file mode 100644 index dbd46fb9..00000000 --- a/dev/beetle_example/e74a81d4.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/beetle_example/index.html b/dev/beetle_example/index.html index 4cec25a4..b411e672 100644 --- a/dev/beetle_example/index.html +++ b/dev/beetle_example/index.html @@ -49,7 +49,7 @@ T = length(y) sol = forward_trajectory(pf,u[1:T],y[1:T]) (; x,w,we,ll) = sol -plot(sol, markerstrokecolor=:auto, m=(2,0.5))Example block output

We can clearly see when the beetle switched mode (state variable 5). This corresponds well to annotations provided by a biologist and is the fundamental question we want to answer with the filtering procedure.

We can plot the mean of the filtered trajectory as well

xh = mean_trajectory(x,we)
+plot(sol, markerstrokecolor=:auto, m=(2,0.5))
Example block output

We can clearly see when the beetle switched mode (state variable 5). This corresponds well to annotations provided by a biologist and is the fundamental question we want to answer with the filtering procedure.

We can plot the mean of the filtered trajectory as well

xh = mean_trajectory(x,we)
 
 "plotting helper function"
 function to1series(x::AbstractVector, y)
@@ -61,10 +61,10 @@
 to1series(y) = to1series(1:size(y,1),y)
 
 fig1 = plot(xh[:,1],xh[:,2], c=:blue, lab="estimate", legend=:bottomleft)
-plot!(xyt[:,1],xyt[:,2], c=:red, lab="measurement")
Example block output

as well as the angle state variable (we subsample the particles to not get sluggish plots)

fig2 = scatter(to1series(ϕ.(x)'[:,1:2:end])..., m=(:black, 0.03, 2), lab="", size=(500,300))
-plot!(identity.(xh[:,4]), lab="Filtered angle", legend=:topleft, ylims=(-30, 70))
Example block output

The particle plot above indicate that the posterior is multimodal. This phenomenon arises due to the simple model that uses an angle that is allowed to leave the interval $0-2π$ rad. In this example, we are not interested in the angle, but rather when the beetle switches mode. The filtering distribution above gives a hint at when this happens, but we will not plot the mode trajectory until we have explored smoothing as well.

The filtering results above does not use all the available information when trying to figure out the state trajectory. To do this, we may call a smoother. We use a particle smoother and compute 10 smoothing trajectories.

M = 10 # Number of smoothing trajectories, NOTE: if this is set higher, the result will be better at the expense of linear scaling of the computational cost.
+plot!(xyt[:,1],xyt[:,2], c=:red, lab="measurement")
Example block output

as well as the angle state variable (we subsample the particles to not get sluggish plots)

fig2 = scatter(to1series(ϕ.(x)'[:,1:2:end])..., m=(:black, 0.03, 2), lab="", size=(500,300))
+plot!(identity.(xh[:,4]), lab="Filtered angle", legend=:topleft, ylims=(-30, 70))
Example block output

The particle plot above indicate that the posterior is multimodal. This phenomenon arises due to the simple model that uses an angle that is allowed to leave the interval $0-2π$ rad. In this example, we are not interested in the angle, but rather when the beetle switches mode. The filtering distribution above gives a hint at when this happens, but we will not plot the mode trajectory until we have explored smoothing as well.

Smoothing

The filtering results above does not use all the available information when trying to figure out the state trajectory. To do this, we may call a smoother. We use a particle smoother and compute 10 smoothing trajectories.

M = 10 # Number of smoothing trajectories, NOTE: if this is set higher, the result will be better at the expense of linear scaling of the computational cost.
 sb,ll = smooth(pf, M, u, y) # Sample smoothing particles (b for backward-trajectory)
 sbm = smoothed_mean(sb)     # Calculate the mean of smoothing trajectories
 sbt = smoothed_trajs(sb)    # Get smoothing trajectories
-plot!(fig1, sbm[1,:],sbm[2,:], lab="xs")
Example block output
plot!(fig2, identity.(sbm'[:,4]), lab="smoothed")
Example block output

We see that the smoothed trajectory may look very different from the filter trajectory. This is an indication that it's hard to tell what state the beetle is currently in, but easier to look back and tell what state the beetle must have been in at a historical point.

We can also visualize the mode state

plot(xh[:,5], lab="Filtering")
-plot!(to1series(sbt[5,:,:]')..., lab="Smoothing", title="Mode trajectories", l=(:black,0.2))
Example block output

also this state variable indicates that it's hard to tell what state the beetle is in during filtering, but obvious with hindsight (smoothing). The mode switch occurs when the filtering distribution of the angle becomes drastically wider, indicating that increased dynamics noise is required in order to describe the motion of the beetle.

Summary

This example has demonstrated filtering and smoothing in an advanced application that includes manual control over noise, mixed continuous and discrete state.

+plot!(fig1, sbm[1,:],sbm[2,:], lab="xs")Example block output
plot!(fig2, identity.(sbm'[:,4]), lab="smoothed")
Example block output

We see that the smoothed trajectory may look very different from the filter trajectory. This is an indication that it's hard to tell what state the beetle is currently in, but easier to look back and tell what state the beetle must have been in at a historical point.

We can also visualize the mode state

plot(xh[:,5], lab="Filtering")
+plot!(to1series(sbt[5,:,:]')..., lab="Smoothing", title="Mode trajectories", l=(:black,0.2))
Example block output

also this state variable indicates that it's hard to tell what state the beetle is in during filtering, but obvious with hindsight (smoothing). The mode switch occurs when the filtering distribution of the angle becomes drastically wider, indicating that increased dynamics noise is required in order to describe the motion of the beetle.

Summary

This example has demonstrated filtering and smoothing in an advanced application that includes manual control over noise, mixed continuous and discrete state.

diff --git a/dev/beetle_example_imm/1f6e463e.svg b/dev/beetle_example_imm/1f6e463e.svg deleted file mode 100644 index c4f57061..00000000 --- a/dev/beetle_example_imm/1f6e463e.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/beetle_example_imm/4396de8a.png b/dev/beetle_example_imm/4396de8a.png deleted file mode 100644 index eb618f20fe1d6c864f2403a9ff3499789d824db6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66735 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[%)7%ULt*QEgFhTGx9} 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 diff --git a/dev/beetle_example_imm/5525986c.svg b/dev/beetle_example_imm/5525986c.svg new file mode 100644 index 00000000..4c672691 --- /dev/null +++ b/dev/beetle_example_imm/5525986c.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/beetle_example_imm/68a796f9.png b/dev/beetle_example_imm/68a796f9.png new file mode 100644 index 0000000000000000000000000000000000000000..919ac77de45426f550ea516b4484eee913f49f5b GIT binary patch literal 64059 zcmZU*1yoeu8#R3CROyhAp`@ijQjqTM4yB|)Qo@lAB?L)n7+OHOBqdcqT1pzEyWTUu z|NE}>t@Vwrr6SI~bI)`3v-f`XF;YWK{vPf_TnK{hDJsZlK@h3|1fjggMg?EF(T^Mj zzhGJ^%gaD_$RD3uixMG-4pNkn((%dI$$V|0qkDOl?ctpMNrmVa9ZW%5o`g_A21AxR z_#Q_vzovmKy1uWbn-`%cXQ=@}^$zX^8`rjabtkG4A&E%=gTiCR_wUVK@~(dM7`f`p z#OF(tX4yPDnjHG%;mCX@I_i-XN?~nbg?#-o>WmFUW&ZCK8_5bs{zf&aD9g{`cbQ>q zAQ|T)ZERH)6_qU+EiEExY}j!Rxw+1b=gs9wZxJCOVais-V9JxbzlrKx6Ms}3zL7{1 z6B8#MK`@zy4TXhKd?u4_Y|I;6t8svRZ}Qg1N@ej9!= z!4I&`4vvhBRP?YKNMdcjJ{*i9WxqX4X+OuhJIcQEY5l{hUFbCXwS1=hKDF@vtV_GD zjt(O;b74V2Pfw3-=8CKE?{edm^z_-B=i$aKt#xGNj&gFn;A?nzc(Y$$iQ4qP&(F_~ zZm-b0$HxO+C1^CF-sr(QJ3IGjL_GKYi0|h)Rx~p6@_wnRB7nYib)iYJadNhv{5D3* zZqh3~85UZ=pT0O-2zo?Jypl~!L(^(MR@l(c5D^j4VXs!?@ePg>B4LoVp6$2ADy<-H z>gCws8Jm`xnwo({v7(sBOe6Uwpf8T5x4+uD&->rpQ~O_xr4tW%KN0Xcj2G{<-$`(C zz5@68SS`b#EueAUIcTe-NaB1E?XGsEFMh#eR9vm-=w#A-w7*~2XMeH5ZKXGkX4|_N z?W}P7vi}2v$|qV2U-zwibRQkS^MXNkJ)q;hVs{P9`J*4Ebes}l+& z-M=+a%1Jgj^ob9xJ`g+y>C@Bcm)R&C;3<#`Q_#{%_#WEC_Z^L?OPZz)ItHe8@*?YY zeK?6#`^8Xdwcm+D^L$oHije>5jzbZRL;wYJdAdu*`=>qV4t&1VA34v#<^A>aJ`S#K z{mhe37kq`fe!MyMnDLSILR%oTznWtH=4e<*w@*D&#H(6=!ieYHkM8d7zb&7*Ex!?~ ziydqhWrw|ccOVwD5O}65I=t$R@(irq^WNDyM=U6ey{_=7Ua5eX*xcPmf@Mz;Lg`0A z*KQMNva+%~HLl0+tZ@H(I=;k|l)mekuPaO%6IL3Qy22kbGU|v9YkUa}4ISia=5Q60 zlzarmpyM>pI}hPZ|6V!J(a|}td%x09RmE-ivF6K{7*!Q6(zS>Gz1ur(+W`{k2n0gA zNUhv{gjC-I1!{i1cb{^h&XF8C{x?qrB_t%!)6=VEOPCrNJrsVq_oo#mX9hkn4s5pG zrCle*!ph=*clPf6$B$n@g~d_{#XS^26h5`?jX?>PjV5D_T7ES5#dgr8{f3N+%708% z2nFgr9}(TtAz5ub`-3-k`rkH5&uJKyybD;$6F{ zVjVB;y_&2~59j6M3%b2nCuP^OdHE8nf;BAzD>kFe5{ZK<`|E_i`Ewj-Vb()St`y!m z*11L;f^b}^H)_H0c!@T}%HO|#-^c$N8>@F&_~+h8L`;nJfY#&{jb{BU z5=gGEuiY#nRsY;F&m4FZO?U%v}EPf9S4a zBv43zy!HR@8}XaMh6V?Xzt}`pY_Df1VwWiAG&CKvlngGVF#{~xtzT$^*OziNJ6zUB z^PD1KW>t*RI%SLM*RhN8ZZYC=tF$r<|7#4Hq}TPKkQ++@=L#E30q7|bX%z%n!fsYQ zQKV*-XBm8?vQO71L$%lj51+o)P3aO)b$56F$YpAjax}?b&h?j z)pEh+8a86b;dNMP3hQ=+1yugy8 zr>UwO!uU7C0+V83x5WCO3VitR!L2R*@A~?KM-tbd;XL8wEcgDFD;w>-Gv&6w*a<2X zblB6~*|VnYiZTA(f6aSYl0mnBzbD?E*0;|G-Q9pa(!4Py#AAQUc7|g+NYPx%gcUe|HOR{|AOa=($VC#%|SK@5c!oL z5)Hif{sbOx{KOPw?x?{sOH#Y+>k9q!_ zZjP;kmIk?kE_e5N-g$4Xu?AW4nC1Nfey%42Sx}Q!Any7m&1~%)zI--2K*fjW-6|?v zFwlbF1nsR9l$3@hCiqZ6L4o(xv_@fne?I_EhqKT2Mw*(0xDm&nL|^|~iI=R{7U`X8 zwtV;HWcIQJl{gU(zWsyq`ooW01+wVX3>4>b1#D4U7c8h}rQ}qb&0lsRkK;|t-&GeY zr}B-jskPj>xw*n|9wM2$Gj(Xehlht#QwC5(T%4fFbF}a-%NTuG0yv-;pdWN}&bjX? z%DU3tnjbuAH>hlRuJX??n|vwHwAmZ<*fzN6v0rN_UB*%MRJSGxhBXJav~_mBYz~6W zS|uUBSAsD3Hv?Qnn+bsmmDs~H^mh?m(h~{1FJm~Hq|`^c|NiQ9GXW*^fJS7z+*kURh0#+B;353W22B;>Qc_pBWFC@Cqa+?6Y$ z{V;-S=##Esl$6Lln%Hf^gSNC1Y9(A7O+u2-gyZ-!YVU`4nXhOPz@P1XRNQ8ilw4Rj zV2RQ)Fh~V8_x`;_ol(8>d=vONY36?qDpbq71n~EOk~hDq%Jt%K6#zLYH0M40itoh` zphy?pk;LR22Cfsj`X_)c{KIM$iK1aEI5;>+f8+ewU<~k;xi?q4_dGZf_0(Fi21&@t zOA!xwSq9xBRtnk|?Y39kN$?=j=m?akT39cVBp9V-U_+t2%6@BP_T|IWg};VDc#@o##` z)oHH5ZRy)P09yq?-0bX*fBQeEO5&E()*ffR{^NW6Q~u>h#s%2*n71s3H7|zE?=JPB zAN;$ZTihNbBoGA+yf8F0R8@ASjeoiQyF8lwiQvETp#8OUm(%gZ;>t|G#a93L@6{QV zX9u26gYN6UzbLh0bN`WqlZwxBknK=_-r_#A*$N1`Qyi9{uVuilGntfqIqoK4u^r^;Sf(_~)7*JAGJ$boDD1CTz6g#=s za-?QxI4!!@qU|-h0Lms50}t#?(1;4vvz_s0oW24U%VE}Xj;eMt|9YWZ#OG}OHC2#2 z^q$cku;AVcEMC{eXDfUDmiW$ClKfY<#LUbS8s=mkGMpKVBTI17JD=xkIR^GO2T@NJ1T>iA& zo!#9oJkAcVQZcBu>QNP%Cm|%vv7Z4?L`hj$zrw`cXW}})s0a|MOCWB{8{JncOq-?e z3xR(MuthbEpVcM+D6$EOW~yk=hAsfz>D>lR08qe>S~GxQf>Jok38(e@`#~P5SK8fO zW@=f1F!MkA2UYnVz0lPKR{?LURDZQ|26p}3{!$lG<$y1Jp6g=O2%7)Se96_xE zPV()3_3Mjp$%@;yxI|k+Jztzzh7Ovo-|SD=P$9*GOgUA{f_uGyMgr1ELrS{(h*H2I zY3bp7t-ZFYF;B0Jp*O&)w_tf*&$)&7t&|iOH{6`g-Yezewy6M=PGp9hvKH(rz|x=} zUgF~7^Sj=A(=|vQ9U{uX#s=i#@W{xYnwRRI6RW(Pn>GspozOpdFGLR-?%?q7gje9s zRJD9O?Y*)V#P;O_$!k~8cPU)-E6oCd+Mue8rxjPi25&f;CGL;i;ID*KmuB9C%~G~RGuy$K#PWgZnn*DXF-RtYuWhI>ThIZ z1Q2yXR8JJ>J6}u7C8W+fNSWduFOO=7ROHKRgYOTpSME&L0G!|}QqOL)>YguIeO8cS2G~&ZH8J{hWGg9G%HYZYMM+y- zMto_R4yh9fLw+gjMdI=)6s&vX+hp@vb`d?sZ4qZu2(Ua=AD?ruEB`)HR8zx*;6K2X z&3#vs=bK;a8^3%Cn90+pjmGg=;@xxOBQz*<({a#Z_TBY5xOG}W!fH?}9T#A^TaQLW zQ@BjG9?*d9Q>U|w_~^C$oATdpa8u5p4b=_BL`2vPWzEE#=&8@mT(ChAHFQua*yO;G z0cgAOJpBGe`%{XQU%!5V8o|ILi+L#E01BJB&$Q#!G(Z>N#z3Eq>z(5zF6}t^80hJ_ zhBoI7Qbp{3(U&}d{S|fwHD1|zIs=eBV7G2Ej#m8g%ODq8Fuab;PaS1Z+Q|sp6k!e9P!H)$%5fu6xs2Iu>;MFQv<#epF_ z)h;$QcONV-(BpM8jt4$sz;FOg&BtLv1~hof&&(0$HpfXI5y0vIS&VN^4FO0)64nRRIHrCHI^-G&MFJkUBa01#$Nl8iFhx|L>!G!Pu273hx zp#|*zPoF*^DOT_-5hL8W(>?7Jnzz+8JU7yo!_m4*3ntjahJ4>B~IuQQc<&N;j>?0xFf5_5x z%ZLP&@F!W0Fb1n0Mtu;3fcBHTIo7tQTDZNr0x*%8mWHsOS?-B`0t~XGq@}Y!U33q_?&EC64ea_lI*HS-q|I5@^9F~*C@eSOnJMa>L z_W=a#Y@^4^8|v=ve7P;2c%+Fp56CO%B!ZUT;9RCn6phu1%&Id$A_M9fPyO@|d@Q82 zU)Qzj)5>}tbp!?5Ba&G&%qGwAMz(8ZWiX&PP3V1f#JHR>gNnL(5a1~y z-a8wQB4cAYxww#I0iZtS1KJkA<(l-vtzvFA)q|SuZm+^YkpQ3oYyAt`Bm?L>DXC8I zty=%RuBEch<~-utwYA#c+{kFEsH(QEel(W$7WF&c0CdZx|2+(lE4hC8?a4}YMMc8~ z*Ck|EOh`EVhWCVGg-Xa-MOoQV#H;+pXx4mza?0jdQ9K3DGFY!{5ihoa=pLG`?|40uHC}~Pm8~aX`+ChTRJEg5IzWUmz4cNnA3&Y0|of1e*R-}vh7>}@PI6a(*ytm-=1sagLG8;fy+X%rHKuo*YsqP2g0Y|UJQTq zrlBe@N(RLgBRKaP5v{OdX?3H;MpznFnV{LCFBu!W?91iGW>tPd1MO!aHR&5Bc>?s6 z3oD>`V(SGs2aL*p1JUyeIBtMfK7w4S^~W4ygY;ojyQhf3QlJwyXX>`AEW5UzV`r+Z zM-o47dc9}nFQ&Y>LIor7ITRbcS^(t$n1h3ZVmm-B0O@%PI2rHXYwT(=Dk8p$z!?>F zT~a2uy@aVBh#&s|qT1o^`whXzORvpi)ncB*>ONXPiVE{=LwllJYW#)kNPnrh> zPPoNXOV+Ok@Zjc~&iM*F3?G;ph&gI5*)4O@5JL?H;)}!Z%ioITe>1?ae)HxQtdgGO zx}B9fEk8RfUnZZeh#l(4=&A4)pRxH}e*1)pFztC%d~y{tdfz00tYZHkU3!_vEEiL> zBW|cV2bpQewY%EeHfsLdc@A0y9yIYnH%vnvMq6E74LE9XcA$`b*jM@Iv*s3OkvPQ6 z*Q-y0o&wU6z@%KLn*MvvALmmoewuc;-~2X!AQmWiPL1UCr*|w~C8%Xh^IT4N)Vy>r+xQ6 zrSfwPD`L~Akwg1UsF1Q}R}vl}iK3mH0$lXDlWxyuwg1o?oEoeear2lEyRWW8hKclor4l!PQHC8emK;2vnp-xHWX z*}msd!}bN#GPcB(QzBWJyy~VtD z_@v~;ix*r5RUOzeMpYJ43h#`G6E6#&Hp(e056HlM8D^#Q(Mu-=jTPRB{&^Euy6;Dl zOpF4#iP7yNnoRd!ExR`k6i_(&G(^3F3!b7X{;g{wJ9NGb0Ge3b@0gojAdW`#V`gS1 zaLny~(g%HO8{0IgwtDwL?+%PC?okO2IoD&6&C6lOQu6h-KhN9vN{7v^U!ej7DrhGF zYmv)GZswB%6IHD=uICaJZH_xdFF2ODj0|~;c_9z@6B#9?eUb=p%%=gufo4$w2t8nE z6vR!Qo69b5>)za4!r|yEw3pG&XwMdxKWci;uDX|-H1Y}xdIMx;kdMpYvF-(BHe%@T zne-PxiSBNhAcp%u#Iyog^A!1N1i#5YO^j3w9Ls?J(9|2j`H3n3*N`QP4&`i`#XAj- zkm`kCg#!w;=Y1_^l>-;FVy6>u#V4lLd-)U)R|8-ktVsuB->#rxp6vmHjwt!X% zj5}5AMleDn=Q6>DLTnuYVOm*Uj+q1mkY|Th$^OlowpVZh0Rel82OKZYGAecbr!E$D&+ z?dxD@9!FUY8KUe4NEfqiecaP~@JMLw#~fCRHd(&e2d9`pGsBgDreaG%3{UDLnu0W@ zmOkCqAkH*=C|CBcBA<8c4EMI1U7%*CGxWacm{!Pn891{qMluXFHQhi5#nf}a2u4Dq z=vS6KEBn&6opH111I6iV{g$aVyYgkM)t;i7}wW&$r(J zedi0d&+Y88WVl+U$USP|Do`N%ag_C|2_`PeR$y2M`tRN4WP6P9E3025c52eaAIaH2 z?B>q-LUaTe#*9S-g}NChxi+?0TVJewdpH?p?BYTbc!O;g!Vm~cb3Do?F52vK1bfOU zzXz2f#CvHiAH6x-h3KMC)zhjSbqZOY91J)M%|VbbJtp)ActfD0gSpSc`{I(o0O}Jz zn>zyg>jLk+NahHhGG^86?!7rftF7^p+esHNw1wjk#|*d%bV6~{qQ~k~cu@aCOh_G& zXoDWOI@K_J6y0-%3zkber5I9SnM=hXot7dAvn_DUC3>>(DSDn%;fkB+8 zk)~aRFRY}X6DmWBNvGB0P`44PnmoET-b}3)iJ&y})tEN<9=rv2m-s#@todP7iRP$@ z?%IjRPLZT%ZRcSDG$I(Ob=C%cN(ab8Q(s@D|5Om?{&5FJx5#S)=g9-C_$8LLN3+Y| z|H}ecTaVT^)q+R;X`y{)e<)q3a%Sh20Qa53%GZb#FRWm|--?Qgj>PtaB5nXx0EQAM zehxl9V#vzc`UwZeS2q{sniX&fu-|}))92gLar$Ki7AwMroSep`08#cAHO1Z@1NB2IA$W?BqW>0M?Iy?`SOKj-u3MfIS|vBT9tbN}5s zFd_66qlJXsmb-zc1I$>0U&5?ROg(l*_zk5UDJXULSH$2$l^rC`iM=K%u14XaH=2GQHAj<2y6AF83U0xbH=O zH`EvS@>q380PPUC`KthU3)I4{pD8)4e{}!~Fiy(F5lYYUx|Cj*Goibid*1)6+*dB3 zT$7SfgV)@$Y4mlCrduLibGL9do=9Q$Wxs0SR1AG5Xgz61m-OrEU$e{Q@g`E018P16 z*bv}_C>?W+9??-zSwXkHdE2e+SDgS{t_$`qfe{662{=;sD7fit>H&AV>XW=(sw@dS z-?z+KPgi>x`4F3zmp1VDCsGsx4-M?tEWuYZz_`YNWd|H80z?CD8t^oWfY)6abTer1 znp)hi_U>zUZ|@&qLCZZLcrI}h19VVP_M5HA%IpuXmpnxtPz!6+*)%HFwSc;Pte$03 z=a5Vo;HbACXm61=_7KL5pi|;~X-le>6{5N=v8gWh3sz-wqo{_;T>`C--bLci{ z*QYay?j5~!G|T}v>2K`xZD zv-8#IE|cO6&~b{2k&@~oqxXd7-h=j+o$cb(;57XO$)xirZL~vq1YiF%38I_;MG3sc z83i(G5P*2`q7Y1DrfZ6V8a+FLQI?jLkdx=r8Ap`G(#ke>kxam6fC9hA(S+1XV@2xg z>+4imtwA6=08$W@t-dxMf9V~McYti|jvxe#Mo#KePc%7j9PNPv2m~e{Gj`|?V00lC zM2Hjp3ZCM??B{7z@l@)^1qW7rf z18tFg8pmL~*kONx}v}x|HYb0~V zy7MjV^uQKXAmUe}<4OsZy^n%Tgb?0-C{Xs?tRi@EO=)N)H`)GOw?q7(_~M5u& zIc)3_1NTAq+B$*LdzB@MWpvmRrzzy?}+f5i4HY6;k{(pdSEUbwcp*0F1e!n#e2BB1L2qjrt5Vxw7`Tvk@p~y&O#WF zc&a6_o9Hp3LPVSfqEtD-t)!5}!ADeR<0Uz&W+!XJ?u!<+mNm?a?V4%RjEYdEV#cUY zrmc@KgaEFkYJOqi8_=1+j94{pYHAAfq6~kt=;vDj1>+Y3c(dNX$pT_sQC(dq%K54W z2M-q)_*GyN3W9us^6NroX0P0*I62RB%@SHN7@OIAIG|v=8p{cCk}l8TgrMBe2hr~V zwqoV$!bxAgZ|jPk{661YgvDR7UP6z)ZpEJQuAeuxmSrg7x-gVc5xC)Z-`?T1161e= z54@cK^MKmgTA;o3%9kv_Kp6=)y5H#uJLyFSWYth1vo98^DA4fs&B;l-9GmUqS@YSW zp(kua@8A3uaG030RBXfccTCmI#kK5!K~P9>3uiz5_*1E~ukSlFi4&Ro!MM}^c!LKB z`k?+_Aj2~_FfiwQ#y2X41_AU0nH%SE4}N=7KtV`8u_@9Mats+F+{qvUPO`XSNW(~L zX4p+d{`ynDu<}POwpuBa+r|{7G2&=UyXmi$r443M*kVADY+n}zqz7@6XlQ60b~$BrG}upTM%zU8h#*D^%n`4O*^V?&FsR)k7=I~%=XK!@?=6C zR@D(e+kPq&@Lf6K*vQZR{V{<|pvLQT=TBkC_9zKEtsL&ZjP`6yDvwHi&Df`u%6D<{5((7is!_6ZZ&A}w1sUT-?ejB?83}gWQI*tC(g zUK>O5*_^_kS2Kx-5^h{dCU<|c-aKa+I4@x2d8#=e`KNFNxO-}qLG7y2MgNVy2BYWA zE>z4SKOQ8KO$!!nC-*jhU{_*68=McEa{_YDfM88MK`JJ7_mkP2l7Jh)vVF?jX&4LJx0|~z_CRAw=U2O%^@|98NK z47MPL#y~l9-5MyIph8Pb91(5~-%qXOm$v>v9VK7%@z+-!a7}nre-gNm5|B=1p-yHTiZ*zT3XVqUX3O|>5`I?0vh;cuk|boFu;^S(y8YY z4t09Kt!)kmIS;^c00adIYB@jI8-Mj}b=Q=Od<6rtNSFW_Lu-15#samT6%;7>sAq*P zTGpaTv+IwpS%uZlRrl{-oW?`O2`d}s!T8A-e65p4W9!eZw>BjE@#bWYr}rLN7ocQw zzyZgILmKozOpCfL%K+CN0AKV|k2OFviFBKPcuBZMVL_=ZmQv`@$nG|Ch=5^r&*|W~ z1cQrvhWG|nXoWp4kt{w$XOyqd*sVm`{@|0f3_+T+uO2!S6H?i({@x>=2Ui9QlEV=Z zEjrYemVS)JHaZ-QF%UEJrk6P)XJB5dl8O))-{uc94E=>R3^YIWz;b;m49-V>8!)(r zj7&F(x4yZ(cnR5oz;Aox16cQx>$uJ(uY^P!P_4*tFqr0nf#TH$Lwr@0pm+1U)dMWZ z*d}S-xjsBRCHezx{eUJ7RBRU=6^9z!KPCLZ9(<2;y+_7p%TDku@7_@|B&Bc%&pWT9 zOUZ_c2ZKQ6A_lGHox*cD_jR!CXTNe*rEdeR7>-YAHJ97`uZf+VeK7lN0FS|357Z$; z^+XY}_>723)&9YLY5GiBbx7*PH%PqJbzTzY<83Ty0+#}WJr zp9ria6d4#-HX=FGzhb;H%#`i-B-MQb5590329IQVSO+7RaEMPWxOX4aO=<@Di7jDo zPmihhwC(L29f$+fULYfC$TT#?Td-ZXoW0;uMEg**tqMrXi za%?I5ky(Q)49a-w(QA%rl#mbnr?tO-b((RDx0||_&cO`f8uJXyD?v=C9>IqLOW4AM z*bLB1??HZ~d+cXhOZ4A#!XqdkSN#U;NP3jh_p_@Xs(UD^4H)yAQG)H@1gJ4?&xG-N zi*9obRk7d%)^GASr`Gbu*IVVLwBz!DHpnerNg_&=2cSpBdP`rAn?ZaK2j)xi9qMjM8g#N|fNq zb>)p$NhTM2UX(r-)dRE2GIyyuYwRaPx)|nNf7sMt#l6fYgd<}~VPUqw`YbF2usjdK zNoj=`ehC;-8V>z#IwT++wKLy5`KT-#IPtHZV909v6zaKJTEsg|!m1TwVzs03lm>e2 zsN_$kO0`C)7nZ&BixCffIO6-1xnIV(Qm=(T!MQ%9vX(NFA=XU@hz^cQESHWQ!&9i= ztAtUB%BvJBDWuyHvBkou!q!25TuGN3rG>8Io&rHuJAbP^*&&2y2=DZ;CvI2@t+icD zN2y;f7`upv{W&`NRlj@V?3BtN0pRhT2OS7WiDL>6Wr-UTz+Ywu3bL_nf!Q0#P76aa za&o|+z5wAvLlD29c|CUk#&VNxF5}ylWTFrwWA7kT?bi0$dzc92ew7}H!*3GC2#DKh zB;Z*;%A%Gh)u{ixS@Huvem=9$O_)$x;dZf79Jw=@4sICfx%eF4_ftaCG`gv2e- z#=XMUWnk_FtiK6oS~9Ya@89nO7aQxHpB`4Pu(VfJll|pqDIunAxZ_Ip=WKC#$|)y7 zd`5cSFCDb;gkOxxL!2$MR&ds0332!sWYKu4rkzxhy}D&*UP)`K;g1O{xSLkJ3!^wG zp(%K#&|k#y4Ev@uxO#-6n@)>WNbofYxiOlzvh5RT>J%ZJ}I zJ3-4)`qZaY;*E_GoRU~Pi)XoHRv*4E#d@ScDS)tN>&zj8b(ySGY!gTW(fH!pnS$T$ z2N*+w0IKgBfOFJ+K;3RzJ$S~7ndUyYyF`Q;?0j>%d&5iSZwnC=k3@^Dpy%4bsO+2M z-tWzR(><-_SEcAQ+v+9v;@pj$o& z-r_=Z`@{JN6~a;UFaoQF0*pcaRmm@r-!aDWpZ|ILSp?x!;cq%)aaTns^RPlhi9_l| zb`+BaNw8~Wo=Ocmm14%TNK9y2GT^yuv24WCI4#_J(S0kFAYy7{l*XtC60chSjg%o* z5OaCV%pCVf@)j_y!0qz-7sF{@2XXR+r4N@2prv2Jcv}3>VlmgD7^#dY&Te}S;^9eU zk(HXf*r@07mAF(bf_9Br&R(;6EY{D2lo+8B!z=d*0To1SQKLbh5uvg;bc_bQ>koTk zEI;EDKo&~HnnR=Q#-?aH{;>p@zuZmopb7moFu?oApKa~~r>hW|USoo)c;1n}m6#Bg z`k)K_U>k_w*gNAOJVyK^%x}Hlps}_LdPGL?H^KE+F-n@`;xCIQ_Ultn14l{{9T~ zWXwdwrijB?~Vn|4ZrbP@7)Qcbe!+@k4`drc} zY7@aDNBJC^K)TEp2UeO8W^eWD+J0-avW6fOfhR9xNeBf~5TDb{s`U|lAca1g3E>e+ zo1vR}__u&KUIhCxx1(z`I6i+^Xg9?b8-6vYE4o@o&Au!UENdzAkkBvYuIi=O&Y z_YJOH6vE?WSDMX;!{odi4y~@P;>6;t-x@Fz!6&|^ojE+E*ls@- zrKjGrAPUjLe`*bFH(|zD%5e}qpdM8ymMtFO#jC=O6*SP%2faoHeA@l5v(AG;P>u#rRbih<3>)#BlDjF{nR8dNMJysb~OK!KESppAz=saguuEc^;4x5eduVKY6$d6B<(UVUhd z6)ItMym;I7x%8PQo-Tg%=5wg zOh#UQ!Ed`TeHKX$h;Kae+wQX{EYe{%hbmZ5ay@Fn7Y_dxvn)c@34YxoY|oewq7~O% zmaoD011Ko?CUI1asE5}iiO04ku~8PAKD?$@ZILK3^<1Q@ftNUwgVOQnyj71|Cxppu zNJit9dq#1i&g8ncOaBlsec;AxokcLbdkAbqAfA~Em>F1y?&1!K&YhSwYz4SK*TM`z zpc2e|uRykL{MR)Z%u}|~3^iOPEBX~NOsRzcLM8ZAK^zu=31O%9A5mL}(rtW6IO)=V zd^CU|MSwwT-OUqqZ?}@<&3zV#VulVI6?0_2%!3*$nBWP0Zvd79;bn+Q`j333U!Z*K zV##334e7N018kV)(Kau$aJg|q(a*A1d{BsEH4f#ECm8zXiJOFm>Z;zK5n#hOruZ$X z0fHa+=;R$fs~fR2UFoiY3HHC&%0&xCu*A~C!ALX%#KM4=2eLJqgZwcEKmss^)F@fG zhu=?NaYKPnvo>iBd*w{<(PDTo2i)dD%x}pV$eYD^!+GRDf%9O-km3C#{kS+1jm_|x zx({YSq)Bb8zq-Cg+|BnVl#=KExHPQ(d9|NtiFnpPGgm=)Hn9h|IqT|9yWpMi& zG}90Xi`?Uwi(nujAR_R)di;Ja2@1Cbi*UTgq$lV}PTdbENhf1?=j8hF^I|j)XL}zF zKKQ4IspKV1(1$@z@EM!o#j&3i{g{kt9wL&k3XV%)Oq+RXV>b`=pUlCXl148y6mZn2( z{C;b(3gV~NJ)lvheKCAfD0gw#uQVy#6)3HfP=69yr)p+uLESzf^gHUYKc0Tjwv{UZ zV|KPQy+Yku3gIzEe)~v%D%f8y()=Tz8C<<|3vAfWa|?eaUXg^&RS?NDo?iAr(N%ox z!qqQ}u_VY&0Or)B)1~s-=;gg9zw+xM{@8a zO}nrQ-13m0RX*5zmhj-v3cta@z;GM6G%01rAw15ZZvs3h z!7mu$30%gnazZ%kEbwY@n#dvH+_2-@IvE+iYEmdwNA)q58If=6 zj1yEua(LKBq)bq7xuwSQISzRp*c82d#*@M@!fy!n%Q4UXnFb>Z5vwH13e5?}q!`WC zHc9@mfG6mtwlb9*t-C35xbTOnk6CP?h(j^xa8@4QEkbk4E88p90T=p4QOCX15%Wne zM{zLk0vo1Vrb{p8*!iLkB({JPpFrXS!Tyr%Lcub|6Zd2lzsZz~{NW%F^;TvP_lr{; zA$mw{6YUeCZ=yEx#?~PS>Y%Q8D8NRb`vu+bFNL+a6mPDO8|+xOO%9)ePOg}qs?NIQ zcIa|opN0K^qW2LLJW7vlfv@?EC-bGuPftwjDvBiiIBv`VlFD{L)vXAeKVI&$^ioIuHAIr#u$$Q9 zV%oyyd>P$QiDbmL3qfww2rWmQ&q~DvdSR2is;|xkz8!rl z4q|rTCCJPZ854M(p;I}T+QClRi#McjxwInsJMh6Gv2+)`OcGr$H+NnE-##@OJ~pL$ zKld6-LDZzV#y#SDuxAwY9+{T9entZ3Rp3|^=Z7^Iyw{q2$dA@=Rxi5e8wo@ZX;r$c zty}&IdKOh&_&S~r*QCajL1kyEvum0~ZJ59X{MXN|GH-JDCSAi-Y2* zSl~$LU|3;BObiw4!}61mekF)IgOn;bZt?OZ;P&d8TTLYLx`uMOCjoOVp^S#bxmr~k z6An0}-^_@MGNX2~#>+iGwP-FH@SWNw!`;swi+F*WW*cRXmgf|F`)_}uSz)8#Y(5H=G zUgcO{{U{a6!act_L18WUA$$?_(W@uh6lZf(6NQutx&1=MlPpkiuBkT`PENjW*Zjq8 zed-1*`Dttd&+Qsf3!SSBhWTFxfczz?KR5P2PtnJ%RDJMK!~VjrR{m3jsP>C2<(Pm) zl07cYM;6`M@Me$3x9t?Dd)uA)jxj_su{Hq&(dyc8VY46A*ufNX&q5C9UnG^_a(gp> zQO;dqEQE&yb4!yLY2AB`9`nh;?$>g$JZuh`qYwh;q}xIE1!MtQ4tlA;3B)s`{R>9x zI5@}{^Dht@MTVq2{tfJ&`ZXRI(4j-m6gr87soBUlbX67M4oY7W88tr-3m9NR5fc@{ z1E}(hY>%7R=GbtEp8`1=7usbP+d`s8DZ;2gR8$H<2>b+6h~*~Vg8!zejXlS!*cs+z z&A#7HeVi&!LEIq*VUyt}ZL-me)WG?$$V$u8PABLOjj6fT^E}jlISpVPvI=PJ+<0rL3x`13y7Gg$8a+XvLRBNlyz-_m^(0n3&MV>*Khm%|v32-ax{jPO!LkxRF?Q zWK`0$+I4oMA}r*fYFGRS!B6K{^2(lSIYqHsByj8PwhV%EZJ3;#0tuB+2?bQ6g)n8r?+aDVxY`w|A$*&A0U` z+B%E`ow+3sp^Z4A5B*lam|($$g4u5hmQK0Z51It#r337}5rrSv+8_H!ao3_CbUa=; zRMAbcU?`nc-m)#v5OPfE<)NIo74Ptv?T_nwhFOz9+zj|`DQA1Lj*HK<^kfJzp%F4> z&E5WxF1jg{U>KZ23Lh3jXkCk82!BDFqZpn4=AG+*S#bPM;Dj zH|E6^+xNp6fQLT=9?&a)aB#ESu!dPoEMWcPtBdv<;jOG6e?l-RtU=g97u&0IfJ9e5 zbl$lr$(@>Qnf(C3Igtr$70Tv;WZj&zep(| z@7uHX-4f<^WrR^gkZW>uVQ2?T&P#eHS?YO{9Kr~2Qbr12=9oohXTn?vX5%!9s9aIz zQyv_I6WrX7wvv_b4=-+e|00g?IX0NRQRk7kDI@_6l=V0mjQPl@l9P8N#lE9KFowZk zSQx>#4m)L~?BbYgULJcz{vTa`oa?un?nB@dlKEGsPdw*97Jy8P*Ur>IM!F;7p%HD( zeFC%b)_(}~{TV6hQJ&n5pfOt@*|M@1AB6o4J5 zv3u2-K+3nK6=?%V>guUqRkEVs#0sjC^&9h8f*N=kp%EiZaHR_G5{8-ue2X!oNnB*g z=Z9zP=O2|(6ZDZfD3D66k&&z*1}Y5-*|4pyGE*Ue?g80aH>OIo%1*x;Ls#i{o9w($ zYd9JzBzK8!l|*-6QIF9mn4Gou8H5M$Nd`lXm5hK}h1Dt;f}P$?iyoantT>C8eEG3? zA^k>_k{?lM>iE%dvje=jzX-Pe$L^IC8Zb|A`NDCcefszV(cCu?NCqp?CB8+y+Z)8%p2!%>Z8 zH{P9Tq&pXVN}7&2_DlJE_R|p2dFDunkuQc(glTb@vK1In5d}t9QJ`n!Qm9_-yI-wu z&q?_9SVyU|ZP{G;Pv*?GEAhUin>nhpv)ZVK3HU*pg zJzNA^LyXFQ20p?ooM^M^Wv>`N>11sqxVrz9!ok?#>c#03XKn9YvM8aR*`?XV zDE#;?{f(=sHOh4Ic}sV5&Bn7=eEo9nMYG0p&@w3}clXFnozd)MGoT{kJF{=iSW*R3 zQGQyDGl?uZ!gRLnWsU5gOVcM#z8y4er+(DBnjK+OZZVJ{*Rzt7n3xCzVWd>vL&iS+ zwmxf}>b|FrZ%feHQ@UoZxjjrZ<`=h>$$vCFFD%sfh%0FuFY8dtD`tXnFCoJqkU35ZheNG0C>>y?1k8V~Xu|+Ey;P74x;*pQCjxf1MAS|0|s9 zbZdwpPHp?(T=UAKDmq%;@?d;XmA$-c)cSko~Q0>nO21Jc|6A z4%V%0X6GONG4@L=##uZiMaHwWvP-D#rL1}&x&-FXdI|t^6EpJ-UHComc-}e?Pyw0< zLNA6*n<_5ysYg3-SXx>(+MW>>9}{*G>oH;LOz-96FS2GotR{T3mX|jUeLzhe-Koi% z5C2MhSRHt???_MBKFY98J|i}P)fR1O^FKbUdM7V!r^xr{8g234MaL>+Yd}w-`pk+U zj+s#2z1vXOX{_DUEOj%X=@W2N&mpBos*@+?5uq(e7a>J+Bc5NN&_#GVotC!lQQp3M zB|0aygYClJuhU-a`pmw_y}DyCE^goJ%V{h}dJMF-5;yjKj2KVlmghk`mbbUJUaA?4s4IJ=gMb~W_AekMZ^R>WbpOvf`^cH`B}WML^DX13fFlDd%#LFf#}O7pLV*96{7 zEZ9n2lppk!p7nIjhYg;H+HeK?!oMn#SZU^$juL+t^iEw<)6dfnJKpG1009y@dUl|r zy3UAA)BWfY3`!u-^l!dw-u9Dt+C<4grJh@Cl2}UWyDQ2RYxRP}p8j$D=-}-s2|J8?FJ379whJJ2-HhgKUvS|*s2;OVI^b&3@vX9X zEqi(2zjy0gkqo%d+#O-%QdaN|{pjz4E}~{cZi656Hq(XS;zdPea9e2|Wa+|G>o4@> zsB37rm+LNU&z4HNHU99#<1hoQUJ;il?|mQAL_bDU*Th=qm~t{vgv|l2KKyI{e9&P% zrUC184W^vZ$`e#=d9=;+EF(a2yM$xD5bvk$?RWjlyf;QX9-_=a~*Js+bQ-P|W%(89e z7g;zeBr007qU%kIRW5yiqK~NM$86?yNxP3oq2XI# z(rW3Xr|K1^JI~mha7^!v_)hAKFanTQfP!xSsve|-7wP2 z8zH=UmMY)*;5i}G!{h4!j#&w>y1L~~g}F0Z?E``3a> zbZl&?-CZLg*w}pJF1a+OcIosfx4LdCW4o(yA8J)@CiQTT#Hwxhdac_T>zWHlgqZU_ zB0Bs}j&XuxyH$|p)}6~s)_>-yPN4)q;tWQ9bDHD{?%lipp?PZ5oRWz0jq+wO3+Pf_pdy!TINw>o7mYsZuqi(lo_vDFWZCa*>jJt1(|EZyL@i*Bp#?diXU+`EsygQ);%~=6$EA>+Ce*6N~QDJ(eb1+gVADRuj~01kcltaT-#xG_n_tX$r9lW#2Wt zeC7DBi`$5&a$JUmgbwA|&50%~+ixf%OkfN4iV;f~D({Q_2@fKK)NeLS4)%#=;Ef`whi!7|Y@P2caoPveP<8H4n5>^_C| z>FJpEF&^!JzG*{YG~K@s_`)wLEc^<-gh~8I$^^!w9-`&g*~rKU-9eRhttEG!N-_6T zLpM^F>N`KE26@>BpVUIaIG{OqhCe2ED?Klvc!|UpA=MTC`B+KMvx?a-myPHJ8=Izf z9SCUMPTYOHbkOZcj}xJKvMSiNYBu~dQ)NxXgTxC0CuWEC6`u6=7o-hSqI;E8EH@mr zCxUO_(m~cvwjDMhe_ibLsp^_4U`93JT||U})+b2hkAyzl;J39(s^N($ zvO3y&-aj?wNNw9O5d&v2dpkmkqhOP5!uUXs*K_qMk0p|6uw&MFuch!c6HgA_>qBP7 z#+MA7BSfgBY`;_c-rvG37J6xCOZ>S?8gxG8r4~Fmb8BNuzczp51p~emyw# z)V_WDj@#N2JkWx@c=3131VmHyXQ!vmc&QvcI)Hl?J^!z^sYfKL=LEuU&Vz}CmdfC{ ztO14U<=5KRRi_J!clewblr=EEvGp~2nblTug97744#(=6pXFs<7)ZxtT7tDOLa?B`+igSmJQev41DLi+GyF9`2y@d9z z?5@Y1odwm^!%fHR>{e!H{S{6|Imlo5_vh=vzIbg~LQwbZTCY`nZ0xfdO`1H5;!&>K zvEzNmmlq4iT%`Gru0@khm4uYvd2y~%<)@WLni}GO?S+{b-ydfT~C|9k# zA)z{n8zwA-jpc2dA}S*0lq^?#dnX+s%jKu>=Sq=lFdD-$70%KUv7M`s59yeOY2|st z&ZIu+0uI~h11+uqasE7o8v&ZawGNLoiykecXE4+`H_sZw7j`#!QqT0*>x2Ol$&h0| z(n*>pt5!~4-9&G3*T&pdZ`1r{LMBz3@{Q7T!U^|7Osf0KS$my{Hp*6q6R>Eo@_-!ozZ$ z5#q-fS|Z<1RKov@-;nH^<$+9vPlzoK1HZgOThMy&A4p~ip1phbN=Qg3D7=`M*g^b- zh)FL^A|94C!DH|{qGRS5gd#R#5Y`Sw=p`;TZGFgkDZ+|hk-zVa<~5ouszS9i{uki^ zq7O&rPK$;HPFHM%oV#S~`krsE3-lZkNa{v|#0#6RxJ!gx8l^Xp=gWFhd)xS3>hggb z%h{8y>nvmQO+%F@4ylnK;`{coW&l1P*O)t$(eEzzl0Sl@aka|fvS?+!XZct(`_=-Z zAJpH^H^i#S&=|2Lmy!lfM&xoYh}_ur@3wz}^ZT}Ys>XbM(ekFc%0{(&s7(}%%eOjJ z5CofMcM7d8>&Jrfrf*3IX*gS9_A zNlrdVxBvsF!^W@S@*_@ljh;8-5v72sh;SsMP>lZIGe-9wyS)xRC+NxA`(C5ItNXTN-eN%xs~YrId@L%7EM+B zpF7u*tcB8#TXxSbsR_{i-i^p~CPMKS;sTUd%g!sd{;C$7bvqL3?pGD2@ zI*qWW?C4CVAf`|4a(J%(yte4{?c?FDw9qRtSNS}?Nis0?5fHHCX*9`L)?kjMNYuad zerK|TQrtGQQxlDC9gR^OXifoX|4Jn=Y?&! zuPv;)eU*FXo_--@tF-Da^49kYKTp*TGP?9H#plPZRZlGV=Q&H}$w|m%dDE>**KC{X zw_ZJio+L%Hf4{pn(WujtG==4~E3yw$2xW{l@o5P*28Z7;)gdM7t34NUJXITeK)_P> zRk=%~2{oe&dzDPScjHVZLDBh)2s0_Mu8X`LMG|`UY3R~lwOtfp$-+kG{%$j;aF98w z?WLa49%@|k>h+$bAH8La8Oy5-gi+}zkv%fCYFU=XNU7Rm@j#(6pVy9y>qGIZ@^MCb zid>Q=ZzPwrjBW>C`YqIA>_fNL3UM*fun@KVyJGo_WDAU>+g791WDSaIwMn1iIua6V zE7BeO#6vFF-C`hAhaRY@#Z9pgiTXn>-V;0Mwz%DR6C&F;v5fX5B=)xt1dJ{C)^Y8K z*Q)rtpXSrWEqaxnzAL;F|(w44f?V!{&W|XsM zt@06LoHx8wlyBP{9>&2Q$SuSrEGH4H@Q|T~wU5xG=;S%(ph2I{%_~ZkG4$&vLFBsZ zvDBTC)voZWP+`+D^gBRJsd`=P?j2dzVR922t^wRe+;D@lIImHVRC;bag7)#p-EUvj zYs{Qz$no+Xb&PmDxpKTmID({4rwW5U%?`sgLE#|E9dCyU`kDmI`q|3*K38Xk=YbwMZ zn8RI!u?Vojmk&cj`--gewJQ3Da(5(Noas_nQWLi*5RUoBGh99;ZBuT<9DkS_`Rv`< zY5tbUg3^VVYsuZxU7-A#yEq7;#x1;zBpNoq(xXAA>l&_08}kUr-H0hy*M9!;%kQ`q z&Ua!OUb2_1{rhU4@CTHI0Ch|Fs8qp1VdB zP;a`Gdql`@mZbUO=V?uP3WI-nL1oMY4iKXpt(hj{Ut<-W<+7ir{StHLOU7T7@h;Ib z^lNW@Z_2{JkW{}O+^U}Qw70i*iF&}>7LGP>E$YlQ8Sg#&s=5F+LZdI}sltR}a)ri1 zj(?H&ldch0qo33mm#2HHa;#s9S%8s;f%o~xLrjT#&iVyio90?R>~+8-L)OIYbp5CL zGRFu~+o6nr^BSubt^c|X(D$u}QeHCRj~9;+yxuK;KH65|P{{XtlZIqlT?>mbi0CJN ze1B&3?e(XJFb;ajQgBv2^OTHrpX7x&Zx#mkGLCqyg4H_?FOeWziHNvswxQDWvMlG6 zn79w2dX@46_15Dichi(w`i$4x^7$Zw%|x_$6!+rG zf`>!RpH>gc%=aiDmX}*$@uYP|>$tX|AvY*j(}rAO2dfPBKq8wuAxUoTY6Y#;FG0WW z-2Ue0Uw*ptCSUg3N6nCs5Imk**XJ->k%6%pd>UkZsObHUNTk)|(hx3}@-mxW%>Uul z;o;myP3UJ)0GROLH4{mJhZ}PT+~iKeS_vV}^F1wTF~Oufc}aPkF9Qs4uP^{Pq%^Z96=V^NU{>Jsg`vM|-YpUnFQ=QTmfID*9e38GWZ!x)k~O z^B@q{{ei7zAZY4`TK&a|*5En`xpO-M))&nubnDMd!U4@Z)0Fc79Xk0xuW zE*Md`wDg$D@;FJY)wb;u`{B$-qVLyPBRwLw%%Qy*G=Qi@**)=p)BpZ9z+@*ZoS$UN=SQC>Jf>P+dF{r=zua!r65E^Kta3WnWH$H^!Z}femOD0(Wn-1jk(r`f!7Wu@nnl!uMVpyml zH$2|t+uh$^e=vd+jBhkKIaxZ=E7coDL3I%%KJA0npEGlFX-P@Eo|*cv$PPJl=umU2 ztbu#oxI;%&=d_@ZP;}E-MVtO}JNZ|2BU>cCB?w0(yegTc4@v-Vxez({?p=cf}3w^;C4sDF`FmuYhM^pTbC=JlO+$7Q&X=$<97enIOk{osQO`PnXL6@K zm3%~Y;_Ds#0MhQ=4`GJ4eR~>g)?x7TL~YiWfm;0>c|G`pdZsR&^Uy;hFMd@$IJB18 zt);zpMrmO84=-4~3H0MPWYQTwa*`2dW6Y{d^)DK-u6F9ylWe__mGuDLsb|lA(t6OO zU6b4Wl)q~z;vR5cl)a-1zIe)Lg4gyS|9qT`>#nuXP*b{0UG%u!?ks^behi+yvwfM< zfio4NxaKdY*izO7seT|psRACE-M!D`T zOErST(b#GKX4j_x8O%<&ZAeFMr_agBL36ahWbPHnLesqj6n7a+^Vb&KzaI#H0J32? z3NaX~eZezF?4nWH?ZI_6PjfJ^GOniJR-0NUzP+BTVz|IaHSoLW5 zMi*%PR#z1j6`6F8_HY_38F{J&8upgA!3g{qj3s5#q5r>$9u+hx>(vPe3X<)_TwPt` ze^c*d=@kh)SrENb;lVgu5P-GfCi>LOX&-m?_5GYNHl1c}Zf+Ea@uNzoFGmA;^%mn* zzWDolnRQJRGbbeh6sC}e9?Lp3G(>wj2j2->g)p+U^^nh`P|X`shB+OI?JQYW@N>5J zv1;*Pf!v33Bg;t;BI7TU7XZfGAfqe!A^`Q_D-Q>{dV5#B4@$aoClp>6WE(rYEJ2~EbCNpUf;xNFz$D4exRp^>Vm50`TKOe#InhhBiw zeHrGHaWjf)B)476l{nOX8DkakCdD@>`DNXux{Z!{Y36qFBCkHWz?Qf`5UjRy{;o~csIR&ji?mq_G?N7fEaCZPQttJT@n zh2H9W(#O^lFB7cO{NZauEue*KZOSKC!8oI?lk>Q}nfIpo;Hd(>4_0{&95aBdtFd#S zMywGeEr&^=OLOe;Vkyl$viJq=X&Jm zb}nud%mpU!tUUB`R*9)rz3=^LMuQ>#GR_m^pJ_DS={B4AClq=PYfvy$X<>!?#it}H zTUKKXi`=2CNXaIj;-lKyiDvh72bbXmtixz%AuwMLviSR#nPrJu9y7Y`ZDj>p6e4T% zS$HDkr@P@Tm(gUrnTB4uN_In&ij1qw{LO3p~^GTM#c6B zz7FItihuy%nOoK+QI4?}t+|*r(SQpOkKght6w1GYTJ0nYULQFBt;~+>tw<3DtbSqr zr^q@Y{W{VN{F^e2>@9*0d9d7SYHE;>*UIgHBmg)zz)So%I|~xb+{$D(wDa~G%VtKh z%O`vJ-0w12JRKBj{}C8=;wMB#Nx%2^^z=|sQNe=|#lSxdod5=Ii^$a3`GM?!SMOo% zE_YJ-0zE;f1va1Aeet_PNXT!%HZwCbXgq#CI5^lm8VczC=~L~6EwI;`g83(yS2`9h zvrdex@x*mquQvm+Qwyv>=)8OS=^Qy4U86`rAQ=jGvCWH9We`p9ZyDX0A^Xpdzt z*>)G%+6{}#@n{EuOPqsJ`di;{@;_gBb6Uv8&j9LiP(ooMj*WI)}iH0Y@*->QAFpSx&LW<@sd$A{~`Da{Wjd;(&MvfIj=H*bcP;+XS~ zy^?>Qd@BQoPEITEJLN1Z%tQ)E`_?;MWNm6*jK%QK83&0pOcPoldUH6mv7$WIC}JGtKCC*CZk{K*Z1$xKTW*W8r{k( zuxAf$xmmCq*is%COT*$$p`oGi0?F)T9ZQ9$-ufyzs7SqYW9qs&bN`Apy=xQ=QMQLk zl%b*ReO~w*-`8oR1hlM@n|e%KGC#M%n{=|tZwLCCQCX4m5BD*#-MjA~X;`@X%A?}$ z-FxfvJp%)~<=jTl^iK=pKWNXsfB&AJzo)>&Rbk#AA0E>=U?6)?S((7l8@CV7Qjo*p zmoAMIU#~O7(JL_7kBKs4sZ77D^+NukTl*VzdDbeTwpo7lgH55MM0 zBU7lJx83T3k^GUZd2xYLyuqx2sp?aDNDhWvYUNIH2ue$T!Rn+T@c9 zhYsKK;UuK0ogajRGcU-o?P1y4&KYDRc^_7!WN9SwGmN|e19a5DVAp=1Jp?mc)1W-t zDyR>`kte@@teps6C;(nyGf;EgQ6pXX%s|{1}1S+)7h8z9Kgvn--%T*lVWE2R_Md9d2jwc zZ7*GJvuj2YY1hbJ{5PdXH{)IaF`z>(ZZ?8)nrWWe-Ltlm350-l!FUsl+1u@ ziT49!ImoJtIN48)ceuzItEoaer@a*|)!@gDB?Y~Ek^c$8W%kdgk7#glrCiT3ek3l{ zb(ooQbm)3v6ImRaKH(7Oi|Gw3DLUc4#O1dm5H~VIrgEm{gRqXd)cJ4EG zeLbls7+QFJ;tqdV&xf6tnrcniG@FyIuH=-=u3D|oFgrPs!JR5nz1!#_cE1WnA+2iw z<-wN+v!xNmTpZ-Ggr^DnAh_+7whJCO@C#RUU6HH+3ko9GjuJ5ppDtR^A{skqQ<@o$)sU`HI=4i13B40UktPVHbnCg3g6ZTRg z9w%kF3jFQsNx)*k(=ckw{FCn_o@I}NQfvY&m(b6>B zF0cGQ2Eas*_Ob)y*TXAVG>Ehm6ON%z3+}V9@v;wys>C!1JRRkM{~Rv5pRo0=&m0_b ztkQnl@9t7Ect*z~4{mVG{PB@99JqUP0X*~tY z_`rxba|p+^B|Yf;&yU9dxMwe3Y~Ul~{wuY+3g&0Qm-g~oWN-KndfpV>bqE{H8+xBU zeG@db!YevAa7R)^q~sMXp_uRsmsN>k6f&{7sV#zsc%-_3biujsK869XI3wbA_wMMXrQ|8u*@rj=)mMg4gn<468Lb2M(3P`CiBPAP#T!;BGK zSEW@@|3MJwb`PgpCS6}{x|)an;>C+~D(trnF$KdH1Dht)Ax7FuQl~@~Z_67O69fBc zD?mVBULt;AsmS0Eey0r+JgWk;&JF?G!FZ4=jT#boxuCNc6ro$ zBj|JTyfArWF%qB(a(7Gxa9@YPTndl z25QPnpN(eb)m?V%jhwk};upAKUQWJ&L;%L?ciGB0WWh z7y#&iZg&WYmG$krcez6@TJc=wHZ~%!*tTthm!4|ni{|EL$z%2UA}u&=m6eq?<=?)2 zOSpQq(SLay%c*?u;Ck={U`JRL`Lk0yNu)Q6i_fad@G6Y|L&6#ieFJ><0?(fZ@Mryp zS<{$oN&ouwYh`6+OdmR>M#`AA9=U|-57q|3=g&8Iyz;?;K$)d<+py?43-Z9Gi~aUe z$^f$L?CgLF;ohq-yP1;m;nSzeAr}W(xRg>d|Vjx;b`uhw`4mbAn*-PP*yVcp8J$n{~G9vVDl@LWm#g`Kk z&8Sh40E1*hqLOJ?bkf?Q+~Ry-;O}Wb8n_yfz!bk&0z-*g{>r8>&==+g z2$6Vvh>~#cv5&*R5Kb;Gkr=)%vfJLK&6_1rCc`iIWz`HE=SCw2@|}@6kf)8reF5kq z%hiW}i?Qnk1^qy;hn(YM`fg`j(Rey?>H4tz26O|&jIQfDvT7#|7MU`N!%CU7p<+Weaz#I74^z?K`$4O|xk*d)%Fd*uRNJ?UE z%sCts-_A`jJ{B87R-n%2FOU z8K-Idb!`o**=xQo7HeOc zJRvvOJSH2sxrt~RLms$Qa|lHh3dH1R;J>p+-2}eODE3cI9#GqPabP>3J6l( z!ArrIo$lDNEDr{tN5JlJ+m-5`f ztz>3qI!V%p+mv6#FdV6_|EfHbJW?f3B#@pxeVXWBeg%fxw;{99jf7I&yx1&Z?ccP7 z9R1s&t=l*C-X7mm?nc7ZylIm_#3m)#jMP+i90N@Y4SH0RD-cu?VbW8u-h}Fqf(Lmr zJb9IsZIude%_IFI19%-B9jIUO)g>h*A&q76-Li9Mob&?(UL<(`o%bUgUtMA*5~LPTDmgWE48vaPY{ZwNu3R~m>2|?(=M&J)6Dk$JYsIbZ z@yN@MHOU(nn=Se(p}cc_(a~|);U*w7fVsA2 zobr;=)4SJNvLdmp`^C&U zbr~kdxE}$v2?;nStM}ExY4q6#0N-WnWHYDuu8ce$RtWXF)FSWY=Rf{wLr0WbhzbLV&RF`6r3~l2ghCKg~oAbm+_|Jij z!h*XKRz$YYGk?}19(vs109Jgwy&0I8&SS$#cZKt4pGY&8IDPC;Pc>uYBZpA!y35fu z%K;MrwDMUYIQgh%m4zz;xKS z=(Ig>=j%^yWP>A9bay@2(_0q0qIQaFFg~~7QO8D=70dxi#-b3&q#i1W( zXSJT!uKR;o>GifH`!UAGqHG344N3Z&{wD&`E`!;3?+T@!!n6DZ&0%crQ>nOeyQyVw ze1bxQk(Gr7VU~HFX25F*iuhh3+4S)?H+kK5j0yc&elxZu%};9n)e_ zb_SK64Tjv`#%3JpLDT60?i16;7@i9#v;g4MX;wJ%+RM-HIL3D%^rBio*-?X31Jks! z=E{SJDYZ%)2tG&Mn$PYYDdZ%T#1UZIlEU*ZWOmVax`qlf&PAM{^RJ%1a6G)1Cv~* z>*?vjF}a3Cc|sy$Vjscd4>v!ktsU`@M;$w)Qi_V-5!etOnhc9FAs9gUjB*m$A`m>>t-oLzK~vbk(S>~O@*h_8%X3< z-|NIlKk-Jz360Xz?(QJmKR60Y3k!|#C4zVqCw>Fj%9AJL7DXm@F$`yc<@Qm1ecyn9 zYcVkyz#ehCppZs4246fQnM_K)W9;VUhIzK{zfRQtUOMrQOUho=*?AU~#|V7>N-<{S z=hTEYHy!B4f1rN>YxpuxEes3r@bI8cMn4A} zC$7fEu5E0DLV{6w;^CR{MUZU(9gbrH30?!=Tl<)vHJTTP6Or7;r&j{;C4c{IbHPx)nK`Z6G{ zg3u*|>j|oKkAnd?Z20c@LEe2R^lylp+ai+LKY#udm@9zbL7@U@Yz4m_Nd<~mJS8g= zlU2Bb{rvT7V}57`D8^U`W(+DUEEr@d10sC=??OsyDjay?2Zetqxnjwc(l{qy^8#Y=@}wsA45@tv;t?DmhAYB zG6zk`dVcWB_5p`CkzGmtBi0TgUKlZX*)~PA%26D)L_h}l}J7{F^56hnBcPcR!VypYxnYpn!Ts80|(EG^c ze0xYtWXG*LwZ>hhAN;{D2aKW!Di(#{t%K*szCCUhKaFx5A0LZaA4z*zEyw8T2Olc+ zG1dKjn=rdrmEJnlkBhf9etIM#F~=C+fR&Ro9eMWk>r{mDz;0N;Bh`|7dD_{zsi}!l z6-{bDblA2+PdbM{Ji4uxrFihh|Fi)9(Ur_7-_^BwWcT7ec{ekIXWt2=*YK8N6&k}Z z$%gn0o7IiQQN8MPT&gJi8gS}RxuIwbgrznNS9k1SW0M8SftQiZK(RRBJPm^OQipe_ zMkK1bI0LOO1S)p zNHRyXc}N+e?>o}pgphdmkm&s)52x}f3Si6q2cpoxN8%Zwl9AQ*Qi;Zih-eDej*tuA z2jw;XKj#+T%r|lW_jS~hg8%>PWd7gl)W;yl+`@;$kkg-Nl}CL#0((;R?g5UI!%#Zx z_}?4O+*gm5mJk+pU9^zhi*zTmi6McWjM6MH==@`d8d5)8L zLsstQevP+I`hZHnwLemT{KQ(<)NUWzW4`Q8ZwHYs!Bl{n4p zPqwLp=yXY(0+meO52VFS|G_Tlo{zAEfdP2AOZQoSzkIqr=n>1(QMnh`_8)xqYZ^Bw zH!q8SPlvf_1y2tY}&OEKjhLoFi`m_YA#5P z^nTT5rT&>@zJ&bRU-qoC8j;OY=7&)HxwTeY4kIy$Yam^)qL)10#Ky^qnz3i`3bh(C z4bXmCe%G9gPrhV|^DZ}kH4av&)h=}PeRq@H~qi@5$&hWd2=)kwJ8fsO;=BJa8HWAd$A z%BaW-&uE(F&h&_?jg6GM0H4gnvp_|F-|ruYL|L3&&$I!@`>yNH9OLklj_=hH#6JYE zKGNl8Ru9mSB6C~}-l@DV=bGK0UY8V4o7ipmI#I-Mzdk#Ia)^CgH|WF#9(C<| zm%}bi*NsKI*YXJM4eNjKT4XsaUHh#DEnfSdZRjslr8*bGq&t*v@S~^VlHi=9S9fQD zduaCq9m<;rZArU;lws5P3(23{UKLKEX5lqiL2+8T;qKE#6W?lOg*@*}E$}KV%&h9+ zyW*6E4l@za%BNqbzKPuQVJ`m0ErqSuo?M}qIS7O=qm@MF@%>u|0CS-53Oeg2xMvR_ zw#gICD>QN57>a}&K4ldp0mj!UI8*CgC)|d<9!kr)St=4i8RbFM)xslOVAPlWgD(a` zJ`12)rV5WQ@%EEfdOw4MiOH4@DKhI^_Z~0-g5vdVC*t!R%%%i|SkG+(m>UH>1&@M4 z0B{I@Q8rET9O5r)YZ~-GpdZ_0Wn?G;45stj5x|Qd9-cQqXPB9pp=8LZ`;CzqsPRsr z0Pynqj6C{N*~zKt%omBg-xXt1?nwx?#Q44 z6}Y~(77K}7ObqsiDe^JXhNrB&Tv!z@6MEoTyLRtBVQnqEY$KKmdS-oo=p@+N`m>)= z4Y2H1X~9JY1W3Yi?r+2^4>-fDp1gL@`PhB?c1m~c1O)v#7~&qP%FT5|f#bh)m>$Du z&Y|2wxnCu|8?_AVsLiabte(_QVn7iD|BjH3pxj4i*GH%Wd{$oXC!Y58k!9)V;6+;= zS^0d@*K?UTJ0{r zwK=uVc>6uBN=`k=ID28`bJw%;?ng~|V;r&0_)r4N?Ax~0;f+y<%FD~k%CZqI840nm zanWk50QB0S&Go`w~X* z0Tlwz{7iK6DEpi1G~Yi_?wsOvgyRL8K>>D<#eGn50W+m|g8~h?U={{3Eo*Mwx)tB( zX|)&uf8Ay*Fv72ao?hv&C&n;mmX^9>FfHJa$?QUZ%=vRasl^F7Rj!cDUct4sHGy{I zPc}#;%jJVx|AH$DD1Gc9PafC&-m~oZIfnGA!^e{Co_u>v@_Q0~C#m^6TXzRw6tSP1!v1Lx{J>K>8&u&Myg(6U85!P@7u&# z4Rv)y?($TQ8Q`$YI~6~xy*4~|r3|r9fMu&Am|RUDe{f}~PsMyyGWD@MZayA=^=gvV z5fGdBp8VVVp-4p5%>B2w=PDGYVP}60l4o{kYtQ2-YHL4**p&#I`vJ*I2so$YS!>MS zLSm(PA=Aw-a&T##&F{r00?hrbTerBFx!56ip`fD0Xt%%6F~Y`E34EuAhZq6FbQf8! z(sbQ|rU|`=(5isx!ib$Qc|6eta=RawOT4CRg_xwILb^UPl#K?VKQ(AR^0QuZDA8t% z1cNl8F{?{Ognat@_+`s&@kZsEoZ&Ho*JINCytwkxntx-61v~XK-vT@Jzy#UHSdG695}M( zmXiI8)G%y{%!)L@z z^My(hro!OJk7dNj*t0t!um-J(_(ew?HYPV8;|Npm$jJDh8ckNi0oBxul)YwtB{w~+&Fob4rZR}b%QBiRDwk|fKMWszkYqRwA%a?Wz z)aegUA|iA_bY34n4QeMSX#W#$Xh;Tndm+r+TQH7k0$a9jy`E+FLZ|N69CjMGElqlO z`+zkj&lDgq-S#*5ql=&0>By5BP)lF{`!Z~)NTu&(55K4uIS>Zey@AK+prCMz9oB8nf`eSvI*1`Es@u>+V{OXn+zv^mEmZ2!I7 z3EP%HR-(eLm23O@L4?tbju_1GipB| zAe;(kb`mXs3&@gOU~S8F+(GYImtGcvjD&vCb6E-#z>Z*&2-2C@5oS@43uLW1avJcC zjuSd5iul#Igs~>KA+ZJ6S=@l#7K|xk6Rb5_+11rP$RB{OxlJ~$17j;-FizL6M?_zn z8+f?-OcXk>6F?|h7eAVLDKA!TBfOqRGjXN~covO*c`Tvu&t$uurHuWXQtmB*n+Us} z>G5`-nOlNoL+{RnVlnHN)Bu0p1iF@#RD}h@>@15Pw_ozbyaQEN!e+uIhn2z&Y;_=% zxdYd*ikzGu8Hxu&gEgYMe|2^kq5eqq?Gh;j1!2pO!W`MEda}ef_^(+dhT%lru+g5o}%7W|1b6B z>ELI903>{f$2EVJ ze*OHZy8~?qRyZu+I#IZ|ZrElNf;_P)7<7^WTjB{EVk{Y8ss-0eo)Ll%;=O)t4aOW< zde=!b-!wuPk0CEu&T_gZ80xq0)UzA7VnG(_^mKhnzjyB*O7bttl0lp0*+2#|(bK!E zRB2K(+vJ45OF`20{_5U%^dlX#d~)v8EMvTucu{+#WJhk;{IQ4E)%V$o%i54cJ6`91 zTfJQHVI@6YI=BT`6~Hw+_W{u(qzK?)!SNjAlnEh>{E$%Ub<`yx-Ld5MhzgEK96d6^ zUT)#OQQ*J%r6JcV8GO9pA1N>S{OmFh2(S-EYh~mSZMG&ti^r~{-KL8!SwGDD#-V>> z@cc7ZDSr0AO=p-K8fpHOGyW=D|5p<*_14&YV*14SJ4$l>o}8(2GB9(MNL(N_ujx+23an*XOizYSEXX;UXU`p|U(HC2#jn|c7rt5>wqOodiw|0J=TQ9xW z@%nF(Gk^6<>fUO$$b0^s3JjPw&wcUxTR?$yHf0v>`ue>w+eFE&tiW|WrypSEh-Ij1 z)|{vOF4DlMmJDmP)`=oRx{fBqt!wg~NK zq1ABgdw8?pTV6!XtKS&)P-#=QNSgTSePOV^Nr{}@i*C4{QLFr-}4h>!74yS|CGJDM~|ZFXzp`n zn%5)3x}9t=%odQTyVP3n<9nBAS#@4=s6U)Og!`41UyE7+Dr_%^dVVh9w!=(7OO?U7 zHBa)?Y%5Yx`zOtY#R9m}lolE?VbZ4R@g> z4##Yb;JG&V!L5+ZcGoq>8(Tc8OvQSH9IP)u8D;tT zPolHEsf3jvPvk-|5IlP^(p~swTpV-jxXvjkO6$@3{ibc_ZFuYR*dOVL)cQ=g4sy6! zMSVs#ggfJT%?9G+FbMvzZ(lHn1mhh8=7;l?z+r&VokJ+0utye*BYU2Fo2@UdlZReh z3wm)ppwSj_3F!Q&UfLQr@R8jR37R)^?2BY(^m9y|FHYjJqr0Arlyw^Z20{+0@DE^(3i`!VD9%oVC-mEJ>>KV1LR z#klB*h^BlH_P<&vlu$S(`-ASC{>?&8ab;$Q8}CLdrR5HtMxu@HPbH3xO=%flNyu6@qGBDOy}h|Oj1Ewh?^ zl*`GCM{e(0e{ov8uO27_iTI|}lm9Yhb`erNI``$bT2_$gvrl&$|B*TO=QFuM z(z4v9;7UaZ60>a~_u+|;X?sYfRYT9?tQkq}YnZqVR6i-nyW4RC4I!h#w}--{L`HTT z=ChQ)kgF8p_iXL!t$)-Fej!f^kL5TlqRIC)29tQIX=QRb znPpBt4>_fmm(0_W_{U=ClCVtfhwSsMdbGcS_9k}n(1@n%Q9Arsk)H3D=OC=~!~b+j zIU;`~lc-=4AZXn__>r9HlZ!PxdC+~T1JEjlz5l4mm_;4xi*(J>v`AJ|v=kVE+&`{$ zf>&#o;N|E%2Tt{CPxb-7hsgG5mhulg+3SJ^xMFt$q6ew>byL&)w}*e%B?)rg1)>ab zDT@<&;9mnOzx3HU5v*uVze0l)U&ItL?C;+LkDH!Ht`i(>;AAS66u5O|X3F&4vST6c zKacU6tNbo{k{gG2@QT*F9JPJM>zJN(%fe?R;j-x4#bUxf_gPQ8$p4|~y5p&A|Nm`v zvUkVK&dk;@vbQ)mLS@T}jO?t85ZSxzEu_p+c2@RE$cjV}MalYo&hvf!`r~=(c|9uk zx$f)wT<^)b+?*yYSt@~#q&>Vk&Qx_9EKSS54vcHek3Turd=rK}wvQ`b_9cL7a<3BX zX5e|^x4|w50y+D@;H&)n(Nw!YLIMm89td&YHelGV{rVsQc+}moqCQ}vn2$zb-^5)p z;c@~`NeGHkIXDy-LWDr@*x%12eb?mn11kc8FjB+Qfbe!uTkb%y26(^35m@4jkn~us z&ns_oUj_g)xSW_ni|)xj5T4&5whPvem+CgGINbIGXu!-1t1xy{cmf>C!~>Vq1u)&F z7>~ZAIXzE3w)h@-gfI4*W-3CWd%rc8Ar zfvz7D#DnhtdYR1;)+ZCdW_-FMyL#87yH&4hdCwncp<1}DD-1-aG{Tk+Ks?M6!p9pM zFe>EA7k57god*6qME7l0zp0SD0l1{VHeE%qw))Hyh zkr2+aCxQR={uD%RZv||tsawP?KYYdhpkA^x##b5!vj5TG4aLy)r@KQ=dJ79 zexb-O5-6L#XU7*Kv$9<_Y%9`?vI-S*|NJ1c9zh0v)d}E-SR@#QUy|`xzV(ZI%{9aB zNHOv!?N<$Xu`56K7lcp0b$+$6H_BY??>MFoiSp|f4JRfhUeY-()$^6j0a$e6k5EOP zlDsu*LT2UxV5auAwsqjefJuBJj33_KKd`j`xdN$`ZXlGHH2ShDXo*iPHn&ssS!rtY z`tn(1(f0|K8=-n@PJUBJ@~7nY<=I=T!q;B7$dd&!BDUo3p1gY^Cf0G#A2G@zK&QzP zkAzHdKUsaKSEL`yIY6(s@bfZ=%R5^>h)YN~^Jd-@`R^4s7>*PL8U<9y?1D_OvptpbdlJud7Q%cO3R{k4fx}xbxS7K)wW~dVdJ=u9V2q z<5=j9U#F!{J~wL{kmF}E{t9XP$x?b2VgGl`xmHE?QevHZc4B^P;!E3wf1w3t6~4{eauxL3N1xC&d>dy)3MS z!C!VYADn3RE!Vy8!Zs-(dF+?sZ5%7dGjEt!8yrpXo(+{ReH;Eh!SZ$Z!3e2R#M#KM zEJZ@x)46yNC)Fw2EyMw*;AMh6Zi;>a|7fqB*?xE}-uL^A!sFquD}M4HdmV$~-E9Bl zdpTQs?q9JuntDH;RdR5AqRo4qkZ^V*2e#?!+0s=HBirJyoveGm!HGm;-LGiWzn7pnH_UinojG%l+|wieB#Vb+I87p4 zmPiSG6j~V}&?kv0sLgwEr**pWsb19wF&??h-+CUQ^oxdf@m)Oe+cJyTg7==%93@)d z86Mx0pAb-E%2(tzkcre!TLsSpq+XKzsHnhY%>a|76ady70RNN?!XY>dJ`VF8$KS;< zd>At6*%vb;$U`dPZ=XTAYF^_5*a^6W?!3C~Gw%f>r33=H4rx%0j|c;mWHKd)hPgO3 z6`X`+pxgxY$KTK^zvK?Cz$maJBU8SvZcH!B7H|4%(CNwo4|Q%20TT472tUSnUd-S@ds&LxYt`R z)kM6uXrgGT?Y{j7&rJOTU)v&|by6zG^DT%Z$dM3}>X9tEqr~EMqm+&ET|St3B9(<@ zYu-UmD$e2lf*0^(=aFCe(sZ15He4FDtQz5jhCRI79tC`=GV(bCY^n&N`W zVD`H?2*&qIm#rQ3CDU4c^}@xh{R~rRky||GQIB88Zr?cP#&QOsl>HfE{`lk9UvKw6 zIfM61EK?`Rh&Kote)F!I6M-Th01=R^?NPL*o475xzVfq8@?YLKnq>Mdm0dW999q8) z;4`(VV!KPj_*kxg$k8C_^m!~J?Erfu55ASujP0vR`Br(ld{Z)@ybkI9j!%_8>x?cN z8&Jbes?N#Hb+DChu zl6v7!_m(o(JT9iD7dPINZI0H;7sB4o@mb5C7S6eaIJicPn>Vd&elI*IKHyH_^q@Az z|5T=bk1BfNAqQ>|DS_EFL#G7rf^V0$0ObU6mExa!fFg)J`0IB2TQIbv!VLAF*$J+= zI1dAi^OLfPYn}uCp?e!f)rwI|x1HR_azbD{VFNe7p5e0K6Km)*5 z7>5#q0KV1qlR-eLu;C}!-TvxBtQcgHHlHhrr`@-z++y5@&%l>-K-8rKUX~+ zC~adiWR9?Ix7DQ;H{7q8nmx?r%e3Kpp>M z@>+ppgf*vgG8NH%dvY?)N1u*T{~ezIQn?IJ7*Pl)^|MNnleK@nG&D2>;vR1iY`u_N z;cw&NA>JtpR2;>l!dvYG&{QE7ET8D=perj2N zx*D)BW$lP1H{OkY`ZjZ02U9B}_IlYO1XIi>L5dhNnbEP;>0@|?*8Zt$7?xGgEp;+J zjNQY)b#^MKIICpdb65@p=>E6wHO{g=cZSRhsKQ2kW!Z8>W|t%~bwcfrNWQGC;pFQ8 zR)jLoZJw?(O04tBgphn(;eV|7^WZ^Dfzc2(cS{_5QC~sN%BZAnO@F}7y`?>WL7}a0 z+E3E|?bj=KcU(y2E!E)i6!^m8K2=i`w#!+jO&8E)(qSg-a?U|3*Y^Z{QCy!P)t&=wyb>ne>pMo48kz9(2;gEiI|sj4E9~wp4zNlo1O1|9BcyknUsjR`3hTVGW4Md>9IpgD5>zi}}7?-U`0M5^pI{QD% z{boYsm@T82B+|7zB4SrN@uh`QR|4JZ^62xAd6!%1b=kha6-N{2r~%EF@O@9?ZgVS5 z0lMIC3rQCr&oJxhwUFU~U@hl!sM6=cX+oyEfUh+=j9SCF1k4d(2&^jr7dLJ&DU|^z z4S>u!v2ZZAkpW5i{{5#P`vPyS#OUpL9h+v1gci0H9O!Q0>!yizj#Yer?D%eNt}Xbl zKx7DsKn9lDT^1RUOcS%Y@ixfd-z#`sqhAzbl<&{7)09V8@N?Kgk`|a$O&VQqw~^{x zzwUkY84im8KNGSDa}FqBXYumjTLu|@=4X4rX|I<`ym;X6-r`D$ICMAjJb!iLk&`Kr z%4i6G*;~sPQ6(&$&L}c67L)T$lW2b*1#PznlL`;cySM+C{5X5~{W zOHTgSS?oVs@nt+&ue@w|m#cu^gGWLN{9WRZqf|P60QfuHlzBmd2s`P;bit3hjb>Hn zW*m*_?11#fQ$J0+>FNi!dO@FLJH~;aNIn{yG47=}-bVS{;|1CP@1DlZ5UI@e#ctl2 z&FU9-^tm~SZEGx4ND_&@bn=$o`cBOg*!^&f4qRT-yvg5o&)wTRuWa%j9u1K)&Q}`< zzcrA_Q;qfDy8}A+!^`h*DZK=OCP17{L1qRFS=MEDPDBUP7tt4TOzIpkpng5ws|nTx zmbS{=$HvhuSd(4kR&EJS1+ZZ_DnTcy}fe!a;J!0TCU25zIo4 zoHeWElR?&>XHb0g?om?DWf12 zv1Y)lH4$oeCUzwYFKZ~{YconwY02=xue;nl=)dQJv{B7Cy_#HMQmzV1SfXK4VXvo> z0;<>tP?}?)k^XmPcLGSYw+{g~cVN7NETmot@&H|Lb&WbG?Z88I3Qj}Ze}=e|iU-m) zNpps#(AJb^Kt|F|bIW%$jRH=ns5NE!cxCTJ(ML?+3y`` z1(FP^-a^U|_+RM-jl=yJZhUS=BU;q-pGhW%Yz;1Jf8h&>=okve8wwYA_jj>9uvOk; z9PlGSLU*c|v=;L+t@}4Er05BwiLveU^M95zQtl4W(`^Jmsxl~`&f(MsIVZU64~ted z1c0k&pd|#s4UjL3;6q%8Ts#1?L{4wT3Yb6Z@`_fICa%_2S(7zqP(|9ZtXI*GB9uM4 zQD5%HZ{%sS$}@$Xb4Nmk)F}h0uI-;@R?;uA&;TtBS{z)&fFG#eVJ+csF*uLfS#e|= z^Su_F9zzacf!1J+!U#+8#hKHW= zu;I1+Tl#(B(D7}@#Gfajok?cp0UnA80xTXMv|XB)j(zYzqpvvu*Mmp%l^=n090<2Fl05;x*WIry)kjJ= zP$h=Pad0P{M?@Wr46--Q7mvzL-MVqtfc%^yk1TdiF5`tPB6>?zxeN-kplZfb3s2$E zCP8kO-}RfXX57<@}=B&HX{t$_G2@SK-!1s>C58PnAD= zi-zzQ8K+RVX}9HE>uN6u$i60B{PVC@t2`r7zwhn42Xn4IfW3e`<98!aW@C1amElyl z%&%9a5cv%rhtya4DW8l;TSb=X3? zklA@UzJFjKEH6U$QD=UmQJ-KYcLuxUVoSz{d2?%VlpOU;S&N7P)JRpWyCS z=;5x=Ip7PG13$u<<{b%FLQD!Ny{kEKrH0HTO2(>=y z*8ZK+sy^iNqP%(LM}GPcP|8^rD5}+MUG8TRx_l^)iR3DgURCpAppH?qtI9V;M$-?R38GvERFZ(pV0?25Ia!DEY{SFT8&g92^wKkA{$u5b6RvOIzN z56mg}ZD9F*c)Jk+l{7A`44iS5M=2$arQ?i3!$x?q?nLB|ei1dqswjn_xbKqu;w*4* z47~b#BUGtR3#y?~_q~`1@+)p}4(UXj!w?g9v9-C^O}01&#zB&GxYej)+#-0UHi%8b z&;~=Z1F@S%DIl>jG*y1A<4^DE_SE&L*R~ars7>BzCJ^=bt^LeMW*P)R92z{+Yvg$z-&jkH^Ke$8bKI}^KP1&X?uhN6QZ<>;*Z5viTQ_{ zq|WG*<e3toc}|gROGQOa^+e?sQQC zQ3YKbv3yq>xGVRfb&9p^8#xnU#C{f|T6p?y08>=$$7k zD0|rd zb7EO^3$N*uQ)mo+p`J?%D-?f6r5_oOf=_woZ zLu7)na=5i0OP2rr{wL~lpOPq4$5Bkr)cKq(F+{v6t*NP@Yxdqq+vCB~U$-AhHR9pf z-b_LiYJT6uOZ&=)ZD~1>Msb@~=M`yTOtAG4vs#2h6bRa;tnPJ)5z#{xVuo9^ms;xm zzMTBQYZKu&)1V$&3ZWLVfnzJ0gFAf6HhV@#-Qq>BLMntkb8(i4aX%n&W4DnH_wSI7 znR|82i14xV=2ZKZZaProDcDqshYNK&kk50?dA|3Y@`_gd(>(?j5vsP^Jkd}s$+{QPh-tQDTL#YOVSD;q+MJwrH5_6YXd1D9j z?RLe59y8@~&|x#u|DluVl!PtP+L;QXgs|l#X)0Ps$WQEDk=iF8|ClWVGA37%lDzXj zY&(2>@v}OHjy%%tYc>>RW5_a4w>T2uDyl|{^4;vLum}$#P4}1rN!85_nb)neQ2INH^$lNW zWZBdcOpjAHl;jmadYP=;ie|{Hh2of0IG3zY+8)FH2Lf9i>EU1fl3~4so8^wBvV({l z^!o<~2lSu7QVuhmV9exv3@zQF(u9A51iPg%UC|_Cd|5;@z5LsqDKU#n&7qRp`UeU* zBw<%?$jLP5?B9uwSe3l8aP4_uvgsX^UKrP<1{b$8Iui1j*KdB_6nlLIvDD!xb3h5o zjL@lmi_{;j7&(vfNk~+7po$Lf5y5)U3*OTGLVo4R>>DR(M5{Gfx3I2_|G2 z9-dVoB8`Ua%SFuU_&^H@a$HE-!VO845-E8P`MdbYY2zM5(Gs zWbeZhuN~ zGdm=y4EOhc0*V6Q1%MKN!Um7u25M6r(P0;&bAY-(Q7)yovU2BOl^4G7W8Qf)LmZw*b0^ zi9Vf0i$?X$Ess9e_6&!goaVcvI#E|gg(4FpvZLolB=~~19|TCVo|~f){&H^RWvSo| zeMKHtfh#{&GB6LD@9Vzne`rYhMC6XglXRJwJAAr$h^~R;)!khbd8icZJhEgQ8bLE` zX3OCe9VxwLQaof(9sS_Xybn%g3#1t6ucV-B4}n&Ki@S`ieg8> zp@@@l4!L0OTXU2eCs=o2zzrXoNUb&V-szC>yN~|R#?(Y~>R=2K{ zmgO6cC{QUC{24oDLLl+LwehA<8rYJ~(bISL^aQ;9Y^f`h+;=~J?22pSA)xPoqjaHX z4QsTt)qq7B1T-gjQe?Jrn)V*^JuS9b^qAo&}`O-%R&6l6JdC|dFmn&gu_VU zTaBQu;Hl%)Ls5lR1=3OyKeNnRxw=Bjbsj-g(ZtET4qx}~o9LHppIjpI6>Xxd>La`9 z%9D9#hBEoW@FcmF%d}-haDo+Xt-Afqr=c-?P|;(BAG8tadAvp<^TV$B$% zdm~|{_qOc%F*bV;m~6W%+MO4t`m?WS3fO-0nL`Ls6s=mU1ZEfY0GLC>UVbi+)XfQ6#JnC7UT8w+ojOE+x=V z;VG!aeq8KK6cTgSC3!*!FOOT+$5w~KQNRlr)DqFvPc!|tg`Xn74jGWxTvHcN+P^VqwG?Y%0@etzibXjT@TAkb08SY+3Vle zJ2_o>QumDOFWlFZ3|~ze@gCR!DoMt9>NzfQ#G>^CZmqW=mk6BYc(~%TiVFGNUM{!| zy#oO|+$5Oj>Am_!=`dsK34%+Rj=ksD$J1ywLP_or*5)&JgilDm`i>d4I2%O&L1jaE z^~IIqsl-w4CnA4-w~aT&rKHXr+&LCj4?X|tr3GL9b9r)tkRm)%`sr)BbaNSRC{P?R zB>5?1q?BawBLFQqE0^*0gE|Q&%riM(aj7h=5Mg6*rnlqI`IxABPpPK@c+ctACcb~X z8fG^GcLH2k1fWpz06W38_fzE!5yTSBD<}6BqLE?oz;X%#`4(`|y#DkTzc|Uv%LRLu zo&=Q#*I%cO)e`fMb+#g)VAYLX_Q*gF8Zzk!mi@#m`*KuA@czSF9Q3(S|2ubi;Lw{T zj=QT2Q;ab~DX7-5$B2&v5h+{>S5aG~*YYD_>o+Yqm=oZja-Y0FWi%u%C5j5z@Q?oq zhr=&lS-`~URWT6bf!kq=G?Pan&fSzHI;i8#)!G^_DdEj#R}m!tOF@nx(8II;(FPkd z0k$EWBfCHTVmRgHT&XYYvlKjsg<9O6vlsK(_^gc6ut?Je^J@C2Q9-k`TqHz7Z2%H+ z&G%9Inpd(U|mNro`WDX!25J!$2)5yPwmP zX|L>^um5H5Ad1#5Bu>=0&D;TTGvEfqK;^Z6WJhZ{L50PXPi24(jX5bn2K62*NOhuNdiMh5GF)P)O852`2C33UK+^?(r zgF-ADo@$V(hlZmi1a9u7iWQ=f=}h+xC?NFtEE6$K zc0y<{9VvR@LMf=G{y9V2>8qKSuU=J3hC|BWh3ik<*k&6dT$=Y=x9Ql&;rI#oU8Xc- zK}9$+(2b2y8m%iKdB~2!_bQiTR;0?*Q6frt`5Y*N<2b%Hw7 zH-$#I(P9H8yc+z5Pv)dg;kJI#@$LR~fJz}gp6tN{$h&}wH4ZL&wsWIVv}aT7hAZQ9 z$&r+^wqi0XDuS^dWlav+&Br%l6;$p^`0y&kelD<7OYJK02tEBx?dF{%<@;*#cQE#9 z;L zFCliYvih~ah&a$^po)T06K|N^CK;`q2QaE>V+n%s7Fiy zzxiQdY$lp-;O&kfuPO#nNTf#+q%14`;gv@X$v^wGoOrI{NU}vNO%2ptulG@4DfINv zQoeEPV*2!^u8z+0m!&gzA@n6j&ZlAWE`IE21U&^~B;rHVd=JPlhp42kylfn)%y?B+c%=gt?Xl15s| zLsvQI&bDwN$RiO&d@=K`XON7&z4tu}Z))_$;9YI;BRYOLe(E|+FStxiBVqHmcZZ>- zr;u+|HEM|Lb))j;6rM|H&+Lcu>17^A|1LMquIx0)q6iF4{a`a0_~FX6%D{4KTT?)I z4C1jmcJeFm2~ix89FkFz8=t7a4!fKautiN6`t<;pf&)w-FraV$a&Tx`7`yu#Fl%pF zv~FJ>X$;67V7w5!?rDkDiYB=FnPv{auGBQ9b1#2R)?T)Z$WzO8p}HvY9q>OwXU+>jqN@@poaxi;2Afn+>Q zHhI-&ji)q6;>u(fBPLN%Vf@jx#Y?4iv5~VhD)vE^%NQX?OF9^baf_NK`or`M)jDtAY@JpB(3ko=a z(Y5VMf@BR4RQ^s<9({r~zd!gFyVsi+mDKOX5_huuNuA-I)w+{kEg5lREL|QJi-%w_ zwnp6^-4_O3=^|nHj+=*`KR54Go^0Q_q7Dp zHwAZYr_0oAcZXLGzJE!gk1bEzt+m@9j=`S1Kp=J)w+gV%T= zoPuQ)|7e0$|9mgBLlF9t!@*PzH4YFYbB*PgRE89wI?HfQF)oE(V^A6#JV+k5}(4lR)e zL%7rCOKXxwp}(`$P1-7Wh>>bLmQjf!nI^XYiTFOGe_^IgOr;SNOuZIc>KXXqOjtRL z@ea|sdlkIKOi5p4<0zY>2s>Yz_y2D8%!p;a-(e?tMlk#H<-@tJ)vVbse`!l5KbsE6 zURWEL^nS=QbSHhD@vb%IE?in;DzNm7wgvgU7g(dWKEAuzD=tUQ)=35YPvSiko(;Lp zSca^UIsM1oN$bk6%*Yy+X@-*9v>Tzkw8IYlGPO4K#JOxEFO?4s)7EmH3ccbr;H^vz zz1*zPJxR}}7gG=LN7_)c?o|L-1+WZeOqr*i-q+s=?roT*pDPQFl~oGUD56FysZgsp z7uBMbQjwZymUA9^XJsB=e}Dh`n1F5KSa^6wiHCe;-((}-UiU*QVewhY8*<&7G^eA# zKP`FFmLk~Wqo;h?L`X}Dram4bX*ybA#^ka&h_?7UzCV899?R9|eT0a> zJtBlDEb5Ac#e7CuPVG9~>_n$pC?|f1(xTF4?tU#L*;a~?jD)KRI&y>^-;pjdfqlYv z!|9N|sl+ybHJ1(#MQ3l&*+%8TON$^knXrPE$*(@`%VdR_^2fV4N|Er3BYaFF=lEFOg~*?adA-!B&GVBWR7 zzILw+E~2xwjctC)O)LL;vP8$fmjuKkDMR$nYjJ@{RMQJ|wl97(2N+r+b-?G}zN_c5(toX6S^HgfL0;9Dp zRd5JY+=_jyC})=OQ;UUPs7y%L1cf=!*j(X|UID7zUvr+rGk4D=6VM+883v-2`o47S zi~3eC^Djzeestn{blhp_Xu%uz+nP59bzk}1c=_!F4DL?jNH;C1h?0!>JHIEFm;jZ! z>cE0iDIWm}Aqa*cTKfr{s%!${U_u?b_-H9xlT*Pe0e3boPaORp0k zy4VVlVFodDCG7X=D}Nce`o9Pw!enD_1>Im|0UKc3Ec^rfvFYU%{mjo_F1b5$t%VLJN}QZ!Q>?T})r0z(*b{f~Yl0OW%exO)SNZ zj5ATKRvkqbVbm>xYA<<0RrPQ#_Gw_jkiGX=*XGqUh@V;oV>be>$d@o>Y&>^jx`if?6qq77R6-m_SIkZ$7;I5eK4Sd2re$ZpvDzC)Ni`Y)-)G!;3^BtyBc?+rY0k&y}xlaT(O zY)3R(`J$ME8;|JdVyA2(p(dA*tL;|ef3Gqq^KJoc4Q7xO2y%rSB%Ia!li%j@jxT6^ z-hodB()eBGn#4w~!Mz#sQGn70<3$bExkm-o-JXcs*7j{CJcPaCB{a0yWZIcYs2G}d zi>$6X=3zIMN*kc%M0U zb+{PZ&SApii`tLzpxtI1vbdFATJ1yi-)$nnOf(#~SAgygGB}7q&_^B8;ysG6sAl!KQ z*${;Bm{v`lrQI-FF)F$|D)O)dbKhnb9Mu0^vekso3><;80HQt!LV(`|IdEC}9XWQmye6_%HS@JlnFfDXI%H$`>3_O(jI~ zY)7+m2kH#?F2>$-!zC<3Bm`K6S)PdUoxu=*r_vn+t-y(SvNVE^6^v)#sRAuw{SYrZ z=IQ!5K3%o@UX`=zsQ>7417YQi+}u|1Yxe&D&F@);kRUMTKq?Ryo;&?Nk1HER&93Q~u1nOdN`B)}^cqpFvQniO(?rizv<$B`O?D54uFv=yS}z6+1<+@&c8c)70!COOa%U8Mgh~^lzwpJ zJdj@?zciQEI^X18C^P_Y;xXt4&mgcqo=?x*Rs>}Z?sH93LOXBef|2yLA$*f#mtKYpa4Fz*65!n*NmYGAG9^Asd2~#}kT-hPC6~2A(2E<+F z$%#JfSvfm3Mpgn|Js9s#fGs7cxb6MsSwTh9wk6b*w?=W;nwl%7RP&GX-urXqUEie7 zT%g_!OmP;ThNxq=B5u65@mv2GAy(d@x zdJ&Ql+J~ygzkL{dYZ)i3ih;%h7T>2#klX-y=h)_Kp@E7Dff$b+!+^Ku;UmthYabdv zz7QynVR#^S=1=(uw3Jn}_;->O{tE|vys$FB8S3-HZ>Ydc_Y~Bxz;75B8t$ci`C=Qp z0}}bYG%&t?6D)we0RYXhLlzltG6b#%-tB#(b)8F1zLWVIA)-mtSH5oPQP4RANdcBe1HvKamjLvw0QdgH$AM?``kteyg+CoRyK64*~%O1P~uV z*~OgepS|fzB>BmZ)0A7I!wj_OEnDi0l5bMZQzk;islMPiucT9%B zHecb3?3I2~zw6+iyAhQ60-y2h9$busW#@1S(h$I90(lrpN{}3$IQxSb$sUvj@6A+LlWzw2Pq#i3?Gp-{NBJvFr(M|bJgh>N6Dy(bgAYVR0fkn&$h>)UjL4L+djXR z&{|}FcZTZ#_D1NvJPZch;Wo%;c(m!&$lwi6v^#)0HeA~d$f2UeptMW>_VqRuj#e#E z%c;BN1HYzZP$;}2YKOZ@_{532!f0GHUu*w9WYoZ(a(En+T>dm^1~j#R;Tks|_ba}7 zo-01%Pq|iL-IQY6hDKPt-;~8TSzTO>JzVL@RWYSzJ)5((GSNDwXox5bUFn;3HtA^@ z63re2S1Yct2I_=pXgg~btp_d9Yq;hD$gzM>0zyTThP#Zn8?o$aPycrCc74v=Uq0a_ zmrU5uQbeg~aI`VO4?i10!hO;xk*%}dw2Xo=I)7hW18)1}7p^Z(54 zySw+Nv8V{ietuT?X4#G~+J}wG5~)Ie*+E6u44_@Kf6^Z*xxn+91R3>~@61$HP`>$f+@>El$VT;0)SyFVc&aUrGfwIL z8_!`^(+SoPF?}QUr|~w7$-F0f<9biKX($!6**@$Vc?c9V@}4_Cx3jwYm$o(cE(7uK zAq;(xCcp+h*Su9o&ckK#Y`SZC5$KM?l(6UNns$Sz^vRv)l6hQH9-h?2Oz~=Pfx#`5l~!~p4;M&hw|vM@UYUAK}=H8*?A&yG@>uhl5cHK$j;4Hr=zd zyx`vD8iAy7m?q9m?N2+6uxH_^mMAL6xu|A2gw!rkGpV5CR_$Za3}}Y_g$9Q=$=efp zc9)U1aD5>H1jTXpB|c)UYlVrlhD{XAus9(O@FMDO?O<8};vDBze*5NDeG6Ds?B<%> z{nZZO0#*kxhy8^I@Hx=(I+#sb96^T4qF)d^GsyZ2eUCe8z)1Z%&_&2imgi6mL+wgO zLW~#1EkI|FlXjxx>>TM{$r=baS&!64XRL+@4n~&@eJ!xcCP3J)vP}>R7w$mRk)Lc1 zgmA6j12t|PU|*oQbA;p~ea-tf$Lm1MrB{>C0-!ODrU4TfaDU$yT2DdLMKF(Z03*K8 zXhWrhJFwY98m+rY5EBSmaw{CX^JeSyCeG(AxXZ)LT`|K?8$(Rbl*utcnCl?H2n1dD zXohS@f7~5G#Gzy?AydIXnw6daiIvEi+PG)}QT1?`VNGf$uE4wppsLx-suMWK0i&}s zom#;8H8~^1p=PDBqQZQg3mlYCV+5Zy3_u_PhZtulMnG^*ZNRoGExcDijy9@$mrGIS z?xEVB9>;=$_xXWd853Vj|liFgjho{N}f8pml(R9)o=Dtxyv-Uzg87`s3O*#9a7AxEnfzSlH6yhRAdgr-$ZP;veNH7{hW-<*B_EU?;Wu===Y1}?fc z;Vj0Pydl95L-z<=nE5*pQIwLDWZ-XkxDUZ^H*R}P!YxSf{&?~@xVz6K-F4hNUHF{Y zBjw%_AMEkSEnM(cXg@y*sy8sIpI?1)8N(NYuT`bxa%}V%Ti(D%R9^ontszBV8B-oZ zKWa=`fGX?d5KyI3<>z2oqDi9i_^=)C_$T{3dx2`y>+Ng4!pSo;_IG@~&Sd)K*z4%R zNcBf&FRbRt`M)0Vi0ApQAO~t< zVglIqg1p&IU)ue>Jxs2g(tQmLR7}A;XnnftoY+3{?KhOZ*b5)6MyPQbHSR@g)I3WR z{!Sai|966KsFJuEg%_$*TUYOTOsjtqtXkG(JH{!U^j_e#XoFq?cGAQE9p7OAthF`gr-JywJCw;) zRaLrB3ibKn+GL~_{->nsn@rveE5dzf0#&86re|}Ry8XJ_=sDOEdI>9NkPsEdk4*ml zpKSOw;T8i~tB#K4ATWTz4-Wxq?@~iMRT!>HhJe^yOG^tfIY5^{NkTFGtsPDOUAR4fO=z1ya#-%+;Z_!E*|gju>E8KIU8 z(#asy4s^D#-wX~8B1pbI-?d!L!cpRYzi(l0hpRvmvG8r*mH@j2gOm;`^z z2gE);xRMU&N%#q)50vhVO-`m>;{36`j=tMzU}161eOcvz6+MMxERX-S<9GG+z-2lR zm#BxRtM}lUN1`E?0OycNxCVNBS2t@2hmDMU4=})4!j4{YT??l&husia`B1e+m)S_~ z{7;aq2bVHXR}Ke`C|bAy6~l-g@%k*Nl8fr0h1ams%Nk@L6Ji%OdQamY~Lgh zp47VOz~F65!DdbV6-#g<9IDxi^bc&YykXKm&+Iz5e%M^Z{SZxhD#=9NT=%A_3EX>V zTtYO+Jh>7z_)<!UKjmx#W_ZbqUROXi*MkgkIgN*2jb!ZG_ zCKRG4sO`x(h64}$00;z-gu>_2J1W7!f#=t43Ad$lkZwc$DU=%;ws9UxaMbAP4uX(} ziJ4hSQgUtR+2-o%9<-EKR8&0q`Fc#60)u_ltItEr{Wps0D?LFj6A^p|+?ncCQe#XX z`KcUj>Kv`1=?W-ecsw|nDm-!kEksOT5+YP|bSkB|9GleSWLjqC$24Ln!iUw>TfoP> zfU7LE`8uS!pbbcYZH?}>mdpJK_|A*kTEBOm76uOYnUD|-#z)jvP)(4P1%)H5h=Q_m z=lr}Jgcd90;Jm-w+=Q&q+>u8HUszy*K2?;Lr>3OD9=(3i8ZX~XfGE5Vb6sii zSmf#mX0LE0Pwdra%&r{&b{`hP+}y2veFtl61E>+RvI1ZwQ3K*ZA;%QLStvo`MoKCZ zbadI9AyX#^v_|TxA@iz*%A&?x?cyouQp*c{|O0u%%)K)oZ{>y^Qm7v&HFL=D)`YVXA}Q=ID15^XtDQd z6s7MnSVFfjiX&4tOHuoGYTJe;L3V@=@3l!mrW@g>3bwKLpRB7Y@FwFN9~{A;Q-;bX z%B!x<&dkdBZaJtprSC+9yRQ!IPJA@DlUmy8!rj`mpPY2>_S%Z4>`u^%!Ji+hkdS*t zANo;F2Byjv|ET>;+LGtspovn!cYpq%z?{l}CQ-rnz?p*wQD9G0d&RIJDcWSJ_VRAH zAUwX<9?5e<+9VOEE)^1YqqrFLsCVz=(+9dwppyx%56Q!MupLxX^sjngo_<_gyYuBn zVNH#NzCL^Ka`KT2{OMus361u|2o&FvL@067lx~ESUoAAr7gOa+(dXmdg}i%=3U?B9 zv`WABXS=;W$|#Pw5~}*PY1FCJeR36dbC)ue5e+Nqvasis=CaTXqLlv=_B-u&0 z!-;VvfuoQH3eX{#MQdxt1O!MBOD88LM#gWOo6IaM|K((VZaI+J@oI1P6DTZ4L169d z>}*^d-%U?^1YvxtsiJ5UR~wc7K)$u5Wv;CaA^j6uR#~~?(M&->VREbXLgLe>N1zHK zzt$H3g(&dN)VXvd!~gNde@~#nX4Gz{MMJxmQhtIOFE#&! z73ULtgq!AUr~(=?Ih6Pq9_KP;8*$T&I-JJF6d9CvxVi;{VHLuqdb4B5N}%kezTOMY z&CW0IA%GSUe7&@Z$W=!squr4oEy1TJQBhG}8#)37U=vA%3JX)y8L<71xKSZgR8%2E zVfBrT&@&DwlDntpKyPo`18&d{JpyE|5Z-#Y#Y3n1@cmJMP+mjLs+rjnYt{ETpzz4d z$^x5|R}0aB9z=a&U_%-o_r(1Q645oeX@Y}KcNhpmFh=1t(cJ9pxU|5+LIUAe>1k=W z(G$Y^>g($vvlaw&aDtVW*_;iw5%|+=jOhzEb1ugK81rFj%G+1f1hUcLAZp?Kvf~R#4J;&lw0G5s};iJuEDKx_-et z)U#*LEWA}A2Xw%?*4$gw1YRkcXmcsmCP+VZc6Rm~E`q8w;7Q*1^fcDjLvP8It5-j@ zx93CjmW0Hs*RQj>t>MN6`a{b7hfL>CgdL0Pb|k&Y{+@{%D*5{RM>#j%aryntD}*q1 z7#|$ue`vyy22gPuo-3>?7llYb^pVq#u{e<2{?u&g&E4EN&~OKiuDDk!vzi#vuamXwqe z5ejV^8?HFD@ySWmQ#ge{J%u396A*H%8xMhwjr&*M*4ARQol%7Z(JFA#6LEYP98_H! zf|p+T`Xxn_oj7BRrgUt=$At@_YT*RCRH*R8ru_d7)s~`I2l*Ej6(rrlENuWgy4c$O z27ML`ez+0w*2QUfQlVV0sQ~M}H=~&QA67;HdQCEIc|K2DHmhi2r|Ooq0Uf z>D$MTYH~)%NHHSE5-LJPl1e8$A_kG=;>vLWA=c74pTt!2}w!UFy$I-OL&O6)rzW3$b zlcRlug3c_=z9XI5)!EtE)upyAcDUr0SNZsu-!jv~kgdLcOY8n3$Hbp;0B3_Q=?dS~ z3i;=e7g`=Pp}&%$=j`pSA|EHG1C$cBS4iX*EiA%Y_wUmNh3wk3Yv9>h_QLb$zdCoC z{j{3{);?E~Y+POJ9p7!$JuszV$5*{4=4)hShX9^W`1PBl|B}WE-L9W3+_-V0zzTkj z358lbfD7HN>?0kHGD8q2+9$y87|Dx;iN*ZSAlMC5=2+dt{|1pIa0$r%z^_ zxsP<7Nmi-TjE-XA@U;AVvpT&^wynv7O&A*BkIaxEPn(($C(w^hiHobCk8gJm@dW2O zxo1K0G1>bjTF$!R(j=?$s%7sWPtTV3Bc!C)bg4Kv&F#;o_la}+bLQM71qBA62>?c> zK7+$aX6EY9&_4Jwl){nJtwdxd^va-H#gbRpB3n?Udg&|LhfbcyD&Tsq^ZPhvj~9W+$bh^BFITWa;(f+epNekIF@$COJdZu;!~?~2h_@UlZ? zVfII~Eubk6m6u4>TDdl32x})W0h`+n0f$N&o`ZSF&?-Of1}dpW-2rH!VF~QC&U$ zysapjQ``DRMojjEgaizo21JQWO?&C!LUZ^S{(ppaPG3<#se183FUeMxs(E@k&yRK- z=Os&g-QDxhQhlKI4;{QbI6iG)5YX2|Ws3W!Zgug@8RcJpU9w=oy1(j7^IW^y+Q>}y zwiS@}@rl(FYH12PpOdpdVv&Ju+D`GzjXH{ZxTdTN7xMG+mfQ##lVpn^9X@UcZFSf+ zOFd>=TXV3x4GMw;D!>fEutg3Ia>Gko-s5Pv)XfbQ{)nwx%hHB_A4wxLC(n=GxDn3a zMMV{d#!Xb4Hf2gyoGFO+Q-#Y@*v|^&C_T#v*pUG2wL2L3E!k-01;+)EBwEmxpFe+IwtP9# z=`o5BBPf@OMG9Kl+IeT^W>zwG_1A*jmM*M{_tq3BPgoPS1Bo2B93)9u! z-hTf6Lv~_Bd65cMnk5~TuFzhRgR@P=1Iex$8deByv9ojR9@lWswQIkV#UVk+hq1nT z_Wb!IGcz{NqK$0xj~;D9xEt`#Zl*CkWW$EIm>BbjzTBNVXWQAy z?cLPc&k1b=>fXcUEp>IpXKNhQ3a*gngjpVX{Gd>r|;FYof@ z4-{891F(Vtp!BqnLtR-B^1EAFTc6k0v!h~hflm3|oGIT|(-1&$aiWO{UG0bYAX(yE zo&7g%d`38!;~Lw0o>y1jC@4sC=(Du6T-*4koS+=%=9m~xLtN%gwtdArvyYkr*qkx# zgLcbt%^NU9Z$b8Ro;boO*;!fkN6iema7ZJPbaLSjpFYhQCEU7oE8wWAs_O3DyOK6) z1bajC%P(&r2}HL%w>DsWa_6g8m9@1~8WiPhIOvawA^0ZRnANPUJunkv#_2jbCFr_d zy;@aUTL3`HETT7;$#^w4w+6l@v7xf1f^dlHbY$E8;UBwM*?2gXc$gfxM@LAwukRSU zf|&mI*}dc%}1vA$7fLRX8zR%Aze*PNa80XV1Y_Oi(SPZFU9lc3t8Yo ze0Mdu3K-fRMJCju#fyi^%OAeyMbMJuc@{5fYg5H(SFT-~C8QNT2+M)C^_tOC$d+C8 z8-5=@$feGw2UKE?arSKZmrsGhG%L}n38|>lbezHaSXx>-#F8$1N@yXLgiuJ~U~@H? zm$8Q|aIzCNQ^i?edFuQ3Z9;dL02roo=gv8gm18E_*@^#^vGkhIPnDpfQg(0)LW~Nx zN$%l@(=DlYq!4#guHH%{%i6HvgJeB<`ulf2cwqnW8E-*?$6oh$1&K&7CmZ#@W$c?C zn~?DOLw|L3HQOXrBZb>^*H2WD9eaqKPDV3e?b_3h`YiE?>58fd;Yl!# z2muehCRUku^n#wsR{VIMnUOII;e@O#AFI#Ic!}S0h?=r8RC4!BVZpNT@pJrre5~}w zjv2$Gj!(^!vCzVyoemJ|ghW6ltOVh+;|v)jI@JOzC+4#Y`--8U*M1t)5}T^t-7LIS+KH(_NdxP`A#TSXBnmab;E z%PBZ4#-uba4}pa-W1tD#(>)&kB&mZ7g+i;cEDIzodwP418@mrUB9njRiZh*|moAA9 zD3Ts(C6!|?$q|lH>5vTn;Jkl>-+^03{&D*z-6jX?Yj~Ick;DDoE#B@cO zojjaDf<#*#4GoQu0={|1j2R(07#_mJfOYc%_q5w+B`GN@k9!`dKB|Ao%p}|BQQK1O z7rDBcUmw8+al$N6)dJ10O=c|1^zhmabA0QW{)=|p~ z)|ZlX%$ns1F-BY(zQN_AoO28VY zp3$MFzh+w8@`Q>ukG9T^j^Kiq%1hp~x6gf81&xKmD_q?`3F?2caKwE)EuEGxcR2HG ziNWEBmj?Z>#alNsC73$E21?#U+2T{d=jZ!fU|-SPyjOMN^<@_#oQ>^&n|`v${m$U$ z2CEWl)a2Vyr64oziMpQU{C4~BIL_L@B5vBe`ON9l>0?Yk3f<3D%rc83njW%qsgd?I zMy8QTWn&}#jX3b-lCbf~lf+}k_Wr%z&F!eQRhajKFAl8uv5raoClU+}dFWSd2@8YTdKbNIV}yU&sn|q&-3)=HP)R-hPBTd!BC@4b zRZRahM^UtEKHC^qMu7phuKp9MV)Io}FYnwLxbs9k%MZ3LL9s1kynAs?xz{CYt(kii z_q1mJQg=75_~Gn~r;M35z$3iZ&ujRO=OYXGN%IFjOLwLvan-gFd*!Cj*S?<9P} zn~k6U^O^}eKi>6|7=}2-vZ>MgO?P)Bo@>Mu^uio(6xIxgveHT-+lE?@nx7PLPeHtT zbsIwAZsSM^ZE)BmMsW$^xm}n*0>L~7x_*V8?wcacpMJ5{_QN2`6k4@ct zAv1Hdo}RR2+Di4tEor9~WgsGPK_t0$z!$H&vT$S)nZhk3g7xtt!m9e0{feG8DD zq#ReO+PJp#)-5X?#rL6>N)Mv$G}ApO(fOV|d-Swv>R&!4MbcWTsvp>$Cmu*YB=cR8} z9lFO5EH!8A)|;0vW6^#3^kBpGAPSqo`>b^orHj7ztL9(`E-@uBSFioLadtrMdTN0K3kqS*#uR%sHb1B`4Bz%%7D1z1rukL~442~}ob zXh;*4{vkUy-alc5$am%B zWf4WQ+uQ37%Sn|u*g^(%EXCi1vj{48%t8nA90<%wsdLDec@#HqPRmz|&x3-NoDNVB zSUz`dHvEM+w6ogK;`ns@wf0zF3amHV zym>PrKFJmnlx(UFNl8+gU4Q@Wo#zVAqi|b7simZdRvstzK0@3tpuVX{QC0OwVxmA( zDX#R>r%&ZaZQY6IGsKoF6`gL=l!5U+g6yN4P2@pGddXbyk5Y5&P z{RAdbwcQG9YjT^ZQ_Kl_{rKd*6BkaL7^Qn43?o`$GgnD&4f?rj@BEWXw8Cxh7>dSp zsHmvY25X^ZG`WNT=y(E=M=~X}0Lzh=c=1AcOANS&c}33XYEX^x4Nl62Zf^CX=N%>! zrU?XH+z5$?W>l25mWi?P6W$B6!Xjo~lZ=6~$P{O{@mNz*Q-6|{hSsYuDH)Wyf2=O) zCO=I}5Bni7)LQE)`=M#_wQG~_vnl0dWDLU`3Q<2jJ-z8C_fTJ_N=lJ zn`MfGdzN<7T+DFeCCZev)>=p9hH?POejg3Zyw%ggL)Sj#9coGG>(N3DShHp_=WoD` zZ#z315&Vv*6DJfFS{fSWa8F<$?SGz8#a}g4Qf-LN1?podY-}71WlP?W%!t?T_fJtu;KCpUz)Kq)Zn%;u~4`3W&GR&BPK zmAp+_dUtubEk6pv-s`r(QkiNKna?)tfyjICFvg1Ku3LI@ABF<(vzy{fhJ1kdAe_E? z7mTwvv-83AkJNUICr*rG8+!V5riMxEuEHuG8=KwuY@IyW$nzxG$K*DqvTfy$VhyR5 za@tc_?__xHo}R--jY@DfPp&XEF$tr85h8?ICRuIn1D+XAj^~GdSHJ81>?fMlBx3Pu zZ&U4cU;i^uaO&BclouQ3&8tA(isy>i(ViSzQ!_KIB3}YDG;pf@CbTaPA0A<3WMp>K z5YX1sBZ|g%Tym3ukWZh`mt}F$XnK6YYMDz#Vt74DMZz>F9q(<~DZJ@ma`Mq5M=sTN z@ihj=?R7m9t^o&tmtZx_d20$+)0jdkVXK1;`PlVq4abi4^YOvQ-qh6eukP-m(D&(9 zA}U=oP2|WveJ0hBm%1!jG6mi=tSl_amhab75MtN*Wc>0LS{tc0#sXmu9dhyX%=kJV z1k{mAafu()UpRhK^3{AdTTbzCO{yjGkNo8>2-p2fr1=NWj`^2tUi$lgKYHwi z>at({{a|5rQ>+3Bp>+Gz!Hc8KC9jL7|NpBV{uo%Jno?2gaCen}*WB5^Szi#Z+VQ^{ C|9*x5 literal 0 HcmV?d00001 diff --git a/dev/beetle_example_imm/index.html b/dev/beetle_example_imm/index.html index ace05a5b..f4fbb8b4 100644 --- a/dev/beetle_example_imm/index.html +++ b/dev/beetle_example_imm/index.html @@ -17,7 +17,7 @@ @inline ϕ(s) = s[4]

We then define the probability distributions we need. The IMM filter takes a transition-probability matrix, $P$, and an initial mixing probability, $μ$. $P$ is a Markov (stochastic) matrix, where each row sums to one, and P[i, j] is the probability of switching from mode i to mode j. μ is a vector of probabilities, where μ[i] is the probability of starting in mode i. We also define the noise distributions for the dynamics and the measurements. The dynamics noise is modeled as a Gaussian distribution with a standard deviation of dvσ for the velocity and ϕσ for the angle. The measurement noise is modeled as a Gaussian distribution with a standard deviation of dgσ. The initial state is modeled as a Gaussian distribution with a mean at the first measurement and a standard deviation of d0.

dgσ = 1.0 # the deviation of the measurement noise distribution
 dvσ = 0.3 # the deviation of the dynamics noise distribution
 ϕσ  = 0.5
-P = [0.995 0.005; 0.0 1] # Transition probability matrix, we model the search mode as "almost terminal"
+P = [0.995 0.005; 0.0 1] # Transition probability matrix, we model the search mode as "terminal"
 μ = [1.0, 0.0] # Initial mixing probabilities
 R1 = Diagonal([1e-1, 1e-1, dvσ, ϕσ].^2)
 R2 = dgσ^2*I(ny) # Measurement noise covariance matrix
@@ -45,14 +45,14 @@
 sol = forward_trajectory(imm, u, y, interact=true)
 figx = plot(sol, plotu=false, plotRt=true)
 figmode = plot(sol.extra', title="Mode")
-plot(figx, figmode)
Example block output

Tuning by optimization

We will attempt to optimize the dynamics and measurement noise covariance matrices and the modegain parameter. We code this up in two functions, one that takes the parameter vector and returns an IMM filter, and one that calculates the loss given the filter. We will optimize the log-likelihood of the data given the filter.

params = [log10.(diag(R1)); log10(1); log10(10)]
+plot(figx, figmode)
Example block output

If you have followed the particle filter tutorial Smoothing the track of a moving beetle, you will notice that the result here is much worse. We used noise parameters similar to in the particle-gilter example, but those were tuned fo the particle filter. Below, we will attempt to optimize the performance of the IMM filter.

Tuning by optimization

We will attempt to optimize the dynamics and measurement noise covariance matrices and the modegain parameter. We code this up in two functions, one that takes the parameter vector and returns an IMM filter, and one that calculates the loss given the filter. We will optimize the log-likelihood of the data given the filter.

params = [log10.(diag(R1)); log10(1); log10(10)]
 
 function get_opt_kf(p)
     T = eltype(p)
     R1i = Diagonal(SVector{4}(exp10.(p[1:4])))
     R2i = SMatrix{2,2}(exp10(p[5])*R2)
     d0i = MvNormal(SVector{4, T}(T.(d0.μ)), SMatrix{4,4}(T.(d0.Σ)))
-    modegain = 5+exp10(p[6])
+    modegain = 2+exp10(p[6])
     Pi = SMatrix{2,2, Float64,4}(P)
     # sigmoid(x) = 1/(1+exp(-x))
     # switch_prob = sigmoid(p[7])
@@ -65,7 +65,8 @@
 function cost(pars)
     try
         imm = get_opt_kf(pars)
-        ll = loglik(imm, u, y, interact=true) - 1/2*logdet(imm.models[1].R1)
+        T = length(y)
+        ll = loglik(imm, u[1:T], y[1:T], interact=true) - 1/2*logdet(imm.models[1].R1)
         return -ll
     catch e
         # rethrow() # If you only get Inf, you can uncomment this line to see the error message
@@ -78,15 +79,16 @@
 res = Optim.optimize(
     cost,
     params,
-    ParticleSwarm(),
+    ParticleSwarm(), # Use a gradient-free optimizer. ForwardDiff works, but the algorithm is numerically difficult to compute gradients through and may suffer from overflows in the gradient computation
     Optim.Options(
         show_trace        = true,
         show_every        = 5,
-        iterations        = 200,
+        iterations        = 100,
+        time_limit        = 30,
     ),
 )
 
 imm = get_opt_kf(res.minimizer)
 
 sol = forward_trajectory(imm, u, y)
-plot(sol.extra', title="Mode (optimized filter)")
Example block output

If it went well, the filter should be in mode 1 (the false mode) from the start until just before 200 time steps, at which point it should switch to model 2 (true). This method of detecting the mode switch of the beetle appears to be somewhat less robust than the particle filter, but is significantly cheaper computationally.

The IMM filter does not stick in mode 2 perpetually after having reached it since it never actually becomes fully confident that mode 2 has been reached, but detecting the first switch is sufficient to know that the switch has occurred.

+plot(sol.extra', title="Mode (optimized filter)")Example block output

If it went well, the filter should be in mode 1 (the false mode) from the start until around 200 time steps, at which point it should switch to model 2 (true). This method of detecting the mode switch of the beetle appears to be somewhat less robust than the particle filter, but is significantly cheaper computationally.

The IMM filter does not stick in mode 2 perpetually after having reached it since it never actually becomes fully confident that mode 2 has been reached, but detecting the first switch is sufficient to know that the switch has occurred.

The log-likelihood of the solution

sol.ll
-1660.8132416661117

should be similar to that of the particle-filter in the tutorial Smoothing the track of a moving beetle, which was around -1660.

diff --git a/dev/benchmark/index.html b/dev/benchmark/index.html index 69e713b3..235a3ca1 100644 --- a/dev/benchmark/index.html +++ b/dev/benchmark/index.html @@ -36,4 +36,4 @@ particle_count = [10, 20, 50, 100, 200, 500, 1000] nT = length(time_steps) leg = reshape(["$(time_steps[i]) time steps" for i = 1:nT], 1,:) -plot(particle_count,RMSE,xscale=:log10, ylabel="RMS errors", xlabel=" Number of particles", lab=leg)

window

+plot(particle_count,RMSE,xscale=:log10, ylabel="RMS errors", xlabel=" Number of particles", lab=leg)

window

diff --git a/dev/dae/index.html b/dev/dae/index.html index 3e7fa660..f1a35ff9 100644 --- a/dev/dae/index.html +++ b/dev/dae/index.html @@ -1,2 +1,2 @@ -State estimation for DAE systems · LowLevelParticleFilters Documentation +State estimation for DAE systems · LowLevelParticleFilters Documentation diff --git a/dev/discretization/index.html b/dev/discretization/index.html index 0a57ce16..d1180cf5 100644 --- a/dev/discretization/index.html +++ b/dev/discretization/index.html @@ -36,4 +36,4 @@ Nd = sys_wd.B # The discretized noise input matrix R1d = Nd*Nd' # The final discrete-time covariance matrix
2×2 Matrix{Float64}:
  6.25e-6   0.000125
- 0.000125  0.0025

We can verify that the matrix we computed corresponds to the theoretical covariance matrix for a discrete-time double integrator:

R1d ≈ σ1^2*[Ts^2 / 2; Ts]*[Ts^2 / 2; Ts]'
true

For a nonlinear system, we could adopt a similar strategy by first linearizing the system around a suitable operating point. Alternatively, we could make use of the fact that some of the state estimators in this package allows the covariance matrices to be functions of the state, and thus compute a new discretized covariance matrix using a linearization around the current state.

Non-uniform sample rates

Special care is needed if the sample rate is not constant, i.e., the time interval between measurements varies.

Dropped samples

A common case is that the sample rate is constant, but some measurements are lost. This case is very easy to handle; the filter loop iterates between two steps

  1. Prediction using predict!(filter, x, u, p, t)
  2. Correction using
    • correct!(f, u, y, p, t) if using the standard measurement model of the filter
    • correct!(f, mm, u, y, p, t, mm) to use a custom measurement model mm

If a measurement y is lacking, one simply skips the corresponding call to correct! where y is missing. Repeated calls to predict! corresponds to simulating the system without any feedback from measurements, like if an ODE was solved. Internally, the filter will keep track of the covariance of the estimate, which is likely to grow if no measurements are used to inform the filter about the state of the system.

Sensors with different sample rates

For Kalman-type filters, it is possible to construct custom measurement models, and pass an instance of a measurement model as the second argument to correct!. This allows for sensor fusion with sensors operating at different rates, or when parts of the measurement model are linear, and other parts are nonlinear. See examples in Measurement models for how to construct explicit measurement models.

A video demonstrating the use of multiple measurement models running at different rates is available on YouTube:

Stochastic sample rate

In some situations, such as in event-based systems, the sample rate is truly stochastic. There is no single correct way of handling this, and we instead outline some alternative approaches.

  • If the filtering is performed offline on a batch of data, time-varying dynamics can be used, for instance by supplying matrices to a KalmanFilter on the form A[:, :, t]. Each A is then computed as the discretization with the sample time given as the time between measurement t and measurement t+1.
  • A conceptually simple approach is to choose a very small sample interval $T_s$ which is smaller than the smallest occuring sample interval in the data, and approximate each sample interval by rounding it to the nearest integer multiple of $T_s$. This transforms the problem to an instance of the "dropped samples" problem described above.
  • Make use of an adaptive integrator instead of the fixed-step rk4 supplied in this package, and manually keep track of the step length that needs to be taken.
+ 0.000125 0.0025

We can verify that the matrix we computed corresponds to the theoretical covariance matrix for a discrete-time double integrator:

R1d ≈ σ1^2*[Ts^2 / 2; Ts]*[Ts^2 / 2; Ts]'
true

For a nonlinear system, we could adopt a similar strategy by first linearizing the system around a suitable operating point. Alternatively, we could make use of the fact that some of the state estimators in this package allows the covariance matrices to be functions of the state, and thus compute a new discretized covariance matrix using a linearization around the current state.

Non-uniform sample rates

Special care is needed if the sample rate is not constant, i.e., the time interval between measurements varies.

Dropped samples

A common case is that the sample rate is constant, but some measurements are lost. This case is very easy to handle; the filter loop iterates between two steps

  1. Prediction using predict!(filter, x, u, p, t)
  2. Correction using
    • correct!(f, u, y, p, t) if using the standard measurement model of the filter
    • correct!(f, mm, u, y, p, t, mm) to use a custom measurement model mm

If a measurement y is lacking, one simply skips the corresponding call to correct! where y is missing. Repeated calls to predict! corresponds to simulating the system without any feedback from measurements, like if an ODE was solved. Internally, the filter will keep track of the covariance of the estimate, which is likely to grow if no measurements are used to inform the filter about the state of the system.

Sensors with different sample rates

For Kalman-type filters, it is possible to construct custom measurement models, and pass an instance of a measurement model as the second argument to correct!. This allows for sensor fusion with sensors operating at different rates, or when parts of the measurement model are linear, and other parts are nonlinear. See examples in Measurement models for how to construct explicit measurement models.

A video demonstrating the use of multiple measurement models running at different rates is available on YouTube:

Stochastic sample rate

In some situations, such as in event-based systems, the sample rate is truly stochastic. There is no single correct way of handling this, and we instead outline some alternative approaches.

  • If the filtering is performed offline on a batch of data, time-varying dynamics can be used, for instance by supplying matrices to a KalmanFilter on the form A[:, :, t]. Each A is then computed as the discretization with the sample time given as the time between measurement t and measurement t+1.
  • A conceptually simple approach is to choose a very small sample interval $T_s$ which is smaller than the smallest occuring sample interval in the data, and approximate each sample interval by rounding it to the nearest integer multiple of $T_s$. This transforms the problem to an instance of the "dropped samples" problem described above.
  • Make use of an adaptive integrator instead of the fixed-step rk4 supplied in this package, and manually keep track of the step length that needs to be taken.
diff --git a/dev/distributions/index.html b/dev/distributions/index.html index 7a39edb3..5a371cc9 100644 --- a/dev/distributions/index.html +++ b/dev/distributions/index.html @@ -9,4 +9,4 @@ @btime logpdf($dm,$(Vector(sv))) # 11.392 ns (0 allocations: 0 bytes)
@btime logpdf($d,$sv)  # 13.964 ns (0 allocations: 0 bytes)
 @btime logpdf($dt,$sv) # 12.817 ns (0 allocations: 0 bytes)
 @btime logpdf($dm,$sv) # 8.383  ns (0 allocations: 0 bytes)

Without loading LowLevelParticleFilters, the timing for the native distributions are the following

@btime logpdf($d,$sv)  # 18.040 ns (0 allocations: 0 bytes)
-@btime logpdf($dm,$sv) # 9.938  ns (0 allocations: 0 bytes)
+@btime logpdf($dm,$sv) # 9.938 ns (0 allocations: 0 bytes) diff --git a/dev/fault_detection/index.html b/dev/fault_detection/index.html index 4a7f667b..e0a8b4f4 100644 --- a/dev/fault_detection/index.html +++ b/dev/fault_detection/index.html @@ -1,2 +1,2 @@ -Fault detection · LowLevelParticleFilters Documentation +Fault detection · LowLevelParticleFilters Documentation diff --git a/dev/index-33d29abe.png b/dev/index-33d29abe.png new file mode 100644 index 0000000000000000000000000000000000000000..7d830ddc4affe659d9e9dcaf64685f1216681878 GIT binary patch literal 24024 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 X9SB}`-;4p69f7!}tgVDcSv~$QbPkhl literal 0 HcmV?d00001 diff --git a/dev/index-388f16d4.png b/dev/index-388f16d4.png deleted file mode 100644 index d4d58f51f37d9e867bfcc5d40502bbf2f5745ec9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25026 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 literal 0 HcmV?d00001 diff --git a/dev/index-4cc3cda1.svg b/dev/index-4cc3cda1.svg new file mode 100644 index 00000000..e2cc7445 --- /dev/null +++ b/dev/index-4cc3cda1.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/index-62cb66c7.png b/dev/index-62cb66c7.png new file mode 100644 index 0000000000000000000000000000000000000000..5e5d2526ed523997d755ba113fc707aabfac3fc7 GIT binary patch literal 48600 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

k+o+>?5a>y{S4c27iCwE|h1q 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 diff --git a/dev/index-80b9d4e0.png b/dev/index-80b9d4e0.png deleted file mode 100644 index 33909e04a246db38dc6a3c4a1e379198fb8849bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49313 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/index-8fbe54cb.svg b/dev/index-8fbe54cb.svg new file mode 100644 index 00000000..30435dfd --- /dev/null +++ b/dev/index-8fbe54cb.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/index-96104843.svg b/dev/index-96104843.svg deleted file mode 100644 index c4ad4661..00000000 --- a/dev/index-96104843.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/index-b37be692.png b/dev/index-b37be692.png deleted file mode 100644 index c71a121de929c285cb41b9c71bc586d789a520f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63170 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�Y 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

2-element Vector{Float64}:
- -0.9019972897330913
-  0.09993085374393618

If you want to perform batch filtering using an existing trajectory consisting of vectors of inputs and measurements, try any of the functions forward_trajectory, mean_trajectory:

sol = forward_trajectory(pf, u, y) # Filter whole trajectories at once
+ -0.1341748822051022
+ -0.31374513551312594

If you want to perform batch filtering using an existing trajectory consisting of vectors of inputs and measurements, try any of the functions forward_trajectory, mean_trajectory:

sol = forward_trajectory(pf, u, y) # Filter whole trajectories at once
 x̂,ll = mean_trajectory(pf, u, y)
-plot(sol, xreal=xs, markersize=2)
Example block output

u ad y are then assumed to be vectors of vectors. StaticArrays is recommended for maximum performance.

If MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} with the layout T × n_state using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.

For a full usage example, see the benchmark section below or example_lineargaussian.jl

Resampling

The particle filter will perform a resampling step whenever the distribution of the weights has become degenerate. The resampling is triggered when the effective number of samples is smaller than pf.resample_threshold $\in [0, 1]$, this value can be set when constructing the filter. How the resampling is done is governed by pf.resampling_strategy, we currently provide ResampleSystematic <: ResamplingStrategy as the only implemented strategy. See https://en.wikipedia.org/wiki/Particle_filter for more info.

Particle Smoothing

Smoothing is the process of finding the best state estimate given both past and future data. Smoothing is thus only possible in an offline setting. This package provides a particle smoother, based on forward filtering, backward simulation (FFBS), example usage follows:

N     = 2000 # Number of particles
+plot(sol, xreal=xs, markersize=2)
Example block output

u ad y are then assumed to be vectors of vectors. StaticArrays is recommended for maximum performance.

If MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} with the layout T × n_state using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.

For a full usage example, see the benchmark section below or example_lineargaussian.jl

Resampling

The particle filter will perform a resampling step whenever the distribution of the weights has become degenerate. The resampling is triggered when the effective number of samples is smaller than pf.resample_threshold $\in [0, 1]$, this value can be set when constructing the filter. How the resampling is done is governed by pf.resampling_strategy, we currently provide ResampleSystematic <: ResamplingStrategy as the only implemented strategy. See https://en.wikipedia.org/wiki/Particle_filter for more info.

Particle Smoothing

Smoothing is the process of finding the best state estimate given both past and future data. Smoothing is thus only possible in an offline setting. This package provides a particle smoother, based on forward filtering, backward simulation (FFBS), example usage follows:

N     = 2000 # Number of particles
 T     = 80   # Number of time steps
 M     = 100  # Number of smoothed backwards trajectories
 pf    = ParticleFilter(N, dynamics, measurement, df, dg, d0)
@@ -53,10 +53,10 @@
 xbt   = smoothed_trajs(xb)  # Get smoothing trajectories
 xbs   = [diag(xbc) for xbc in xbc] |> vecvec_to_mat .|> sqrt
 plot(xbm', ribbon=2xbs, lab="PF smooth")
-plot!(vecvec_to_mat(x), l=:dash, lab="True")
Example block output

We can plot the particles themselves as well

downsample = 5
+plot!(vecvec_to_mat(x), l=:dash, lab="True")
Example block output

We can plot the particles themselves as well

downsample = 5
 plot(vecvec_to_mat(x), l=(4,), layout=(2,1), show=false)
 scatter!(xbt[1, 1:downsample:end, :]', subplot=1, show=false, m=(1,:black, 0.5), lab="")
-scatter!(xbt[2, 1:downsample:end, :]', subplot=2, m=(1,:black, 0.5), lab="")
Example block output

Kalman filter

The KalmanFilter (wiki) assumes that $f$ and $g$ are linear functions, i.e., that they can be written on the form

\[\begin{aligned} +scatter!(xbt[2, 1:downsample:end, :]', subplot=2, m=(1,:black, 0.5), lab="")Example block output

Kalman filter

The KalmanFilter (wiki) assumes that $f$ and $g$ are linear functions, i.e., that they can be written on the form

\[\begin{aligned} x(t+1) &= Ax(t) + Bu(t) + w(t)\\ y(t) &= Cx(t) + Du(t) + e(t) \end{aligned}\]

for some matrices $A,B,C,D$ where $w \sim N(0, R_1)$ and $e \sim N(0, R_2)$ are zero mean and Gaussian. The Kalman filter represents the posterior distributions over $x$ by the mean and a covariance matrix. The magic behind the Kalman filter is that linear transformations of Gaussian distributions remain Gaussian, and we thus have a very efficient way of representing them.

A Kalman filter is easily created using the constructor KalmanFilter. Many of the functions defined for particle filters, are defined also for Kalman filters, e.g.:

R1 = cov(df)
@@ -72,7 +72,7 @@
 end

The matrices in the Kalman filter may be time varying, such that A[:, :, t] is $A(t)$. They may also be provided as functions on the form $A(t) = A(x, u, p, t)$. This works for both dynamics and covariance matrices.

The numeric type used in the Kalman filter is determined from the mean of the initial state distribution, so make sure that this has the correct type if you intend to use, e.g., Float32 or ForwardDiff.Dual for automatic differentiation.

Smoothing using KF

Kalman filters can also be used for smoothing

kf = KalmanFilter(A, B, C, 0, cov(df), cov(dg), d0)
 xT,R,lls = smooth(kf, u, y) # Returns smoothed state, smoothed cov, loglik

Plot and compare PF and KF

plot(vecvec_to_mat(xT), lab="Kalman smooth", layout=2)
 plot!(xbm', lab="pf smooth")
-plot!(vecvec_to_mat(x), lab="true")
Example block output

Kalman filter tuning tutorial

The tutorial "How to tune a Kalman filter" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model.

Unscented Kalman Filter

The UnscentedKalmanFilter represents posterior distributions over $x$ as Gaussian distributions just like the KalmanFilter, but propagates them through a nonlinear function $f$ by a deterministic sampling of a small number of particles called sigma points (this is referred to as the unscented transform). This UKF thus handles nonlinear functions $f,g$, but only Gaussian disturbances and unimodal posteriors. The UKF will by default treat the noise as additive, but by using the augmented UKF form, non-additive noise may be handled as well. See the docstring of UnscentedKalmanFilter for more details.

The UKF takes the same arguments as a regular KalmanFilter, but the matrices defining the dynamics are replaced by two functions, dynamics and measurement, working in the same way as for the ParticleFilter above (unless the augmented form is used).

ukf = UnscentedKalmanFilter(dynamics, measurement, cov(df), cov(dg), MvNormal(SA[1.,1.]); nu=nu, ny=ny)
UnscentedKalmanFilter{false, false, false, false, typeof(Main.dynamics), UKFMeasurementModel{false, false, typeof(Main.measurement), Matrix{Float64}, typeof(-), typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LowLevelParticleFilters.cross_cov), LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{1, Float64}}}}, Matrix{Float64}, Distributions.MvNormal{Float64, PDMats.PDiagMat{Float64, StaticArraysCore.SVector{2, Float64}}, FillArrays.Zeros{Float64, 1, Tuple{Base.OneTo{Int64}}}}, LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{2, Float64}}}, Vector{Float64}, Matrix{Float64}, LowLevelParticleFilters.NullParameters, Nothing, typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LinearAlgebra.cholesky!)}(Main.dynamics, UKFMeasurementModel{false, false, typeof(Main.measurement), Matrix{Float64}, typeof(-), typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LowLevelParticleFilters.cross_cov), LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{1, Float64}}}}(Main.measurement, [0.04000000000000001;;], 1, 0, -, LowLevelParticleFilters.safe_mean, LowLevelParticleFilters.safe_cov, LowLevelParticleFilters.cross_cov, LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{1, Float64}}}(StaticArraysCore.SVector{2, Float64}[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], StaticArraysCore.SVector{1, Float64}[[0.0], [0.0], [0.0], [0.0], [0.0]])), [0.010000000000000002 0.0; 0.0 0.010000000000000002], Distributions.MvNormal{Float64, PDMats.PDiagMat{Float64, StaticArraysCore.SVector{2, Float64}}, FillArrays.Zeros{Float64, 1, Tuple{Base.OneTo{Int64}}}}(
+plot!(vecvec_to_mat(x), lab="true")
Example block output

Kalman filter tuning tutorial

The tutorial "How to tune a Kalman filter" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model.

Unscented Kalman Filter

The UnscentedKalmanFilter represents posterior distributions over $x$ as Gaussian distributions just like the KalmanFilter, but propagates them through a nonlinear function $f$ by a deterministic sampling of a small number of particles called sigma points (this is referred to as the unscented transform). This UKF thus handles nonlinear functions $f,g$, but only Gaussian disturbances and unimodal posteriors. The UKF will by default treat the noise as additive, but by using the augmented UKF form, non-additive noise may be handled as well. See the docstring of UnscentedKalmanFilter for more details.

The UKF takes the same arguments as a regular KalmanFilter, but the matrices defining the dynamics are replaced by two functions, dynamics and measurement, working in the same way as for the ParticleFilter above (unless the augmented form is used).

ukf = UnscentedKalmanFilter(dynamics, measurement, cov(df), cov(dg), MvNormal(SA[1.,1.]); nu=nu, ny=ny)
UnscentedKalmanFilter{false, false, false, false, typeof(Main.dynamics), UKFMeasurementModel{false, false, typeof(Main.measurement), Matrix{Float64}, typeof(-), typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LowLevelParticleFilters.cross_cov), LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{1, Float64}}}}, Matrix{Float64}, Distributions.MvNormal{Float64, PDMats.PDiagMat{Float64, StaticArraysCore.SVector{2, Float64}}, FillArrays.Zeros{Float64, 1, Tuple{Base.OneTo{Int64}}}}, LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{2, Float64}}}, Vector{Float64}, Matrix{Float64}, LowLevelParticleFilters.NullParameters, Nothing, typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LinearAlgebra.cholesky!)}(Main.dynamics, UKFMeasurementModel{false, false, typeof(Main.measurement), Matrix{Float64}, typeof(-), typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LowLevelParticleFilters.cross_cov), LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{1, Float64}}}}(Main.measurement, [0.04000000000000001;;], 1, 0, -, LowLevelParticleFilters.safe_mean, LowLevelParticleFilters.safe_cov, LowLevelParticleFilters.cross_cov, LowLevelParticleFilters.SigmaPointCache{Vector{StaticArraysCore.SVector{2, Float64}}, Vector{StaticArraysCore.SVector{1, Float64}}}(StaticArraysCore.SVector{2, Float64}[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], StaticArraysCore.SVector{1, Float64}[[0.0], [0.0], [0.0], [0.0], [0.0]])), [0.010000000000000002 0.0; 0.0 0.010000000000000002], Distributions.MvNormal{Float64, PDMats.PDiagMat{Float64, StaticArraysCore.SVector{2, Float64}}, FillArrays.Zeros{Float64, 1, Tuple{Base.OneTo{Int64}}}}(
 dim: 2
 μ: Zeros(2)
 Σ: [1.0 0.0; 0.0 1.0]
@@ -103,27 +103,27 @@
   p: LowLevelParticleFilters.NullParameters LowLevelParticleFilters.NullParameters()
   threads: Bool false
   Ts: Float64 1.0
-, StaticArraysCore.SVector{1, Float64}[[-0.581146869379883], [-1.469770570308081], [-0.4665682508355672], [0.4234924411574639], [-1.2994733710630846], [0.19717030178114028], [0.5781200218992196], [0.06754736822207849], [-1.572069110356176], [0.17227229037093392]  …  [0.2769012811822157], [-0.5043025072555615], [1.0903524694417166], [0.9708346951972306], [0.2376545415920728], [-0.19697645842384984], [-1.276720957403689], [0.3164908801143953], [0.9957909432454998], [0.21073604411718913]], StaticArraysCore.SVector{1, Float64}[[0.5391939827750171], [0.18249931772160993], [0.10087755016317689], [-0.030646125661147258], [-0.06840802251253109], [-0.2754469405850646], [-0.6598459146381536], [-0.08451814678404623], [-0.8487502596864017], [-0.5813112714708646]  …  [0.1506382818748036], [0.6440322824183035], [0.1145393221188427], [0.17567522546691838], [0.46315975412284505], [0.16957810665037654], [-0.3111368843884259], [-0.6698000197360167], [-0.24455231528274332], [-0.1592922241654996]], StaticArraysCore.SVector{2, Float64}[[-3.3153421443122513, -2.4541217991834285] [0.25154080451826155, 0.41265079618577816] … [-0.6604198046223679, -0.2840031842113254] [-0.4858714356475497, -0.20358222568168374]; [0.4416529515995341, 0.47928403107595907] [0.19928333343389698, 0.6284416872336622] … [-0.8097845965671094, -0.5176163851766447] [-0.5381792825321053, -0.49309215041687404]; … ; [1.0298013271664521, -1.7041575966065925] [-1.287666187735087, 0.6136860145828382] … [-0.20231986795731988, -0.2424585032449692] [0.16054112245350213, -0.27018806758351616]; [-2.8475007636855683, -0.2986138941616716] [-1.3831915677243751, 0.835860591189961] … [-0.37642140979492167, -0.23009734942673565] [-0.14349861748985682, -0.35382671254377407]], [-117.36454134010754 -7.342943359561149 … -7.180603797284416 -6.57295337980245; -5.410164237496096 -9.166629533145915 … -8.093198987381932 -8.85380840153896; … ; -68.27312806751331 -9.004846665946825 … -7.161203959654783 -6.6827570903364375; -14.139324691803322 -12.016833992422935 … -7.163760984517893 -7.004636353714595], [1.0696146063254322e-51 0.0006471429406122278 … 0.0007612080879892544 0.0013976634795139352; 0.004470905860662188 0.00010446802302518174 … 0.0003056105474434297 0.00014283671953124513; … ; 2.235410147260729e-30 0.0001228131251115503 … 0.0007761195738376076 0.0012523204477937811; 7.233846826193592e-7 6.041646448073951e-6 … 0.0007741375519101658 0.0009076639438922475], -18.90520087624123)
plot(sol, xreal=x)
Example block output

We can even use this type as an AuxiliaryParticleFilter

apfa = AuxiliaryParticleFilter(apf)
+, StaticArraysCore.SVector{1, Float64}[[2.039129321735416], [1.151597694841343], [0.14053103072265363], [-0.5094480022037171], [-0.3264775442126382], [2.2765002943710693], [-1.0765221156821387], [0.32376782093108836], [-1.1401054540200994], [-1.7487208181298963]  …  [1.610889849566029], [-1.1038081711193932], [1.7951582478483346], [0.3627856246592035], [0.04464316800248958], [0.09932971641987426], [-0.7659901715531249], [0.8365073240852781], [-0.7153055161303419], [0.5024990644200305]], StaticArraysCore.SVector{1, Float64}[[-0.15195378778438828], [-0.136234692260716], [-0.04625962370970575], [-0.2656630013766956], [0.32226659370652505], [0.272079043578301], [0.1454060659305941], [0.9579799076845587], [0.46183980027537025], [0.21177737888290737]  …  [0.04836438156831484], [0.2053723445488685], [-0.19788624438997968], [-0.07036645109882726], [0.2198240373639479], [0.10496125015329888], [0.19987803633018758], [0.32072339879967576], [0.7749932994985786], [0.5883278851737495]], StaticArraysCore.SVector{2, Float64}[[-1.3590046681886658, -0.5237985500240129] [-1.0559797483754867, -0.7007290475151341] … [0.1710352000831514, -0.054895966666212014] [0.2963868760206542, 0.6029967049599272]; [-1.5931213264149418, 0.4188477218246225] [-1.4389746212444192, 0.17196304447145783] … [0.4165559095356379, 0.5554707276650006] [0.7367438753916016, 0.4505937180448987]; … ; [1.1509161965527337, -1.638603245343401] [-2.151531141273438, 0.08093842260054027] … [0.9483243270408499, 0.4595291741033511] [0.7502879718491563, 0.5326993592200591]; [2.9766025218569214, 1.2045253376049334] [0.12361187820727325, -0.6052850800417828] … [1.1354797552083327, 0.7223257093307399] [0.7129216256758648, 0.36275341094432334]], [-7.040807060082262 -10.974429961943297 … -16.717396041544564 -7.308329692607172; -9.385130012168295 -8.178579559602461 … -7.076744685633059 -7.542773774116657; … ; -32.93903309077555 -7.5808085207487865 … -6.9482772958112875 -7.344321675430435; -28.31289569023146 -9.741359826486645 … -12.766698885283327 -7.941688056981706], [0.000875419760736845 1.7134270761816663e-5 … 5.491957242211849e-8 0.00066993511563328; 8.396336273616395e-5 0.0002806002330926794 … 0.0008445178496110321 0.0005299256871800618; … ; 4.951761164623748e-15 0.0005101485905055395 … 0.0009602880217813548 0.0006462515876515632; 5.056681907476915e-13 5.8800521944811705e-5 … 2.8542573100480076e-6 0.00035560568870060826], -6.86404020850312)
plot(sol, xreal=x)
Example block output

We can even use this type as an AuxiliaryParticleFilter

apfa = AuxiliaryParticleFilter(apf)
 sol = forward_trajectory(apfa, u, y, ny)
-plot(sol, dim=1, xreal=x) # Same as above, but only plots a single dimension
Example block output

See the tutorials section for more advanced examples, including state estimation for DAE (Differential-Algebraic Equation) systems.

Troubleshooting and tuning

Tuning a particle filter can be quite the challenge. To assist with this, we provide som visualization tools

debugplot(pf,u[1:20],y[1:20], runall=true, xreal=x[1:20])
Time     Surviving    Effective nbr of particles
+plot(sol, dim=1, xreal=x) # Same as above, but only plots a single dimension
Example block output

See the tutorials section for more advanced examples, including state estimation for DAE (Differential-Algebraic Equation) systems.

Troubleshooting and tuning

Tuning a particle filter can be quite the challenge. To assist with this, we provide som visualization tools

debugplot(pf,u[1:20],y[1:20], runall=true, xreal=x[1:20])
Time     Surviving    Effective nbr of particles
 --------------------------------------------------------------
 t:     1   1.000    2000.0
-t:     2   1.000     296.0
-t:     3   0.147    2000.0
-t:     4   1.000    1468.7
-t:     5   1.000     974.4
-t:     6   1.000     680.1
-t:     7   1.000     514.6
-t:     8   1.000     353.6
-t:     9   0.208    2000.0
-t:    10   1.000    1020.6
-t:    11   1.000    1057.6
-t:    12   1.000     598.1
-t:    13   1.000     535.7
-t:    14   1.000     327.0
-t:    15   0.268    2000.0
-t:    16   1.000    1549.9
-t:    17   1.000     581.9
-t:    18   1.000     554.1
-t:    19   1.000     482.8
-t:    20   1.000     366.4

The plot displays all state variables and all measurements. The heatmap in the background represents the weighted particle distributions per time step. For the measurement sequences, the heatmap represent the distributions of predicted measurements. The blue dots corresponds to measured values. In this case, we simulated the data and we had access to the state as well, if we do not have that, just omit xreal. You can also manually step through the time-series using

  • commandplot(pf,u,y; kwargs...)

For options to the debug plots, see ?pplot.

Tuning noise parameters through optimization

See examples in Parameter Estimation.

Tuning through simulation

It is possible to sample from the Bayesian model implied by a filter and its parameters by calling the function simulate. A simple tuning strategy is to adjust the noise parameters such that a simulation looks "similar" to the data, i.e., the data must not be too unlikely under the model.

Videos

Several video tutorials using this package are available in the playlists

Some examples featuring this package in particular are


Using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:


Estimation of time-varying parameters:


Adaptive control by means of estimation of time-varying parameters:

+t: 2 1.000 278.6 +t: 3 0.149 2000.0 +t: 4 1.000 1462.6 +t: 5 1.000 933.9 +t: 6 1.000 513.5 +t: 7 1.000 346.3 +t: 8 1.000 256.4 +t: 9 0.161 2000.0 +t: 10 1.000 1247.5 +t: 11 1.000 365.6 +t: 12 1.000 274.7 +t: 13 1.000 258.8 +t: 14 0.234 2000.0 +t: 15 1.000 1559.2 +t: 16 1.000 1090.9 +t: 17 1.000 536.3 +t: 18 1.000 300.5 +t: 19 1.000 337.4 +t: 20 0.279 2000.0

The plot displays all state variables and all measurements. The heatmap in the background represents the weighted particle distributions per time step. For the measurement sequences, the heatmap represent the distributions of predicted measurements. The blue dots corresponds to measured values. In this case, we simulated the data and we had access to the state as well, if we do not have that, just omit xreal. You can also manually step through the time-series using

  • commandplot(pf,u,y; kwargs...)

For options to the debug plots, see ?pplot.

Tuning noise parameters through optimization

See examples in Parameter Estimation.

Tuning through simulation

It is possible to sample from the Bayesian model implied by a filter and its parameters by calling the function simulate. A simple tuning strategy is to adjust the noise parameters such that a simulation looks "similar" to the data, i.e., the data must not be too unlikely under the model.

Videos

Several video tutorials using this package are available in the playlists

Some examples featuring this package in particular are


Using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:


Estimation of time-varying parameters:


Adaptive control by means of estimation of time-varying parameters:

diff --git a/dev/measurement_models/index.html b/dev/measurement_models/index.html index 0b67e5eb..5fbc65ed 100644 --- a/dev/measurement_models/index.html +++ b/dev/measurement_models/index.html @@ -24,7 +24,7 @@ R2 = I(ny) mm_kf = LinearMeasurementModel(__C, 0, R2; nx, ny) -ukf = UnscentedKalmanFilter(dynamics_ip, mm_kf, R1; ny, nu)
UnscentedKalmanFilter{true, false, false, false, typeof(Main.dynamics_ip), LinearMeasurementModel{Matrix{Float64}, Int64, LinearAlgebra.Diagonal{Bool, Vector{Bool}}, Nothing}, LinearAlgebra.Diagonal{Bool, Vector{Bool}}, LowLevelParticleFilters.SimpleMvNormal{Vector{Float64}, LinearAlgebra.Diagonal{Bool, Vector{Bool}}}, LowLevelParticleFilters.SigmaPointCache{Vector{Vector{Float64}}, Vector{Vector{Float64}}}, Vector{Float64}, Matrix{Float64}, LowLevelParticleFilters.NullParameters, Nothing, typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LinearAlgebra.cholesky!)}(Main.dynamics_ip, LinearMeasurementModel{Matrix{Float64}, Int64, LinearAlgebra.Diagonal{Bool, Vector{Bool}}, Nothing}([-3.4336509571765053 0.7848257286874997 … 1.7409551744781047 0.28442432033664633; -0.9068377917702121 1.9162540186985246 … 1.8788277264178899 0.7201981001313605; … ; 0.715220244669793 1.5217859431962695 … -0.18597339767327933 1.001546765688925; 1.0692606615098486 0.2156844795608287 … 0.3688366360641461 -1.1181842094069676], 0, Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 0; 0 0 … 0 1], 90, nothing), Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 0; 0 0 … 0 1], LowLevelParticleFilters.SimpleMvNormal{Vector{Float64}, LinearAlgebra.Diagonal{Bool, Vector{Bool}}}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 0; 0 0 … 0 1]), LowLevelParticleFilters.SigmaPointCache{Vector{Vector{Float64}}, Vector{Vector{Float64}}}([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  …  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  …  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0 0.0 … 0.0 0.0; 0.0 1.0 … 0.0 0.0; … ; 0.0 0.0 … 1.0 0.0; 0.0 0.0 … 0.0 1.0], 0, 1.0, 90, 2, LowLevelParticleFilters.NullParameters(), nothing, LowLevelParticleFilters.safe_mean, LowLevelParticleFilters.safe_cov, LinearAlgebra.cholesky!)

When we create the filter with the custom measurement model, we do not pass the arguments that are associated with the measurement model to the filter constructor, i.e., we do not pass any measurement function, and not the measurement covariance matrix $R_2$.

Sensor fusion: Using several different measurement models

Above we constructed a filter with a custom measurement model, we can also pass a custom measurement model when we call correct!. This may be useful when, e.g., performing sensor fusion with sensors operating at different sample rates, or when parts of the measurement model are linear, and other parts are nonlinear.

The following example instantiates three different filters and three different measurement models. Each filter is updated with each measurement model, demonstrating that any combination of filter and measurement model can be used together.

using LowLevelParticleFilters, LinearAlgebra
+ukf = UnscentedKalmanFilter(dynamics_ip, mm_kf, R1; ny, nu)
UnscentedKalmanFilter{true, false, false, false, typeof(Main.dynamics_ip), LinearMeasurementModel{Matrix{Float64}, Int64, LinearAlgebra.Diagonal{Bool, Vector{Bool}}, Nothing}, LinearAlgebra.Diagonal{Bool, Vector{Bool}}, LowLevelParticleFilters.SimpleMvNormal{Vector{Float64}, LinearAlgebra.Diagonal{Bool, Vector{Bool}}}, LowLevelParticleFilters.SigmaPointCache{Vector{Vector{Float64}}, Vector{Vector{Float64}}}, Vector{Float64}, Matrix{Float64}, LowLevelParticleFilters.NullParameters, Nothing, typeof(LowLevelParticleFilters.safe_mean), typeof(LowLevelParticleFilters.safe_cov), typeof(LinearAlgebra.cholesky!)}(Main.dynamics_ip, LinearMeasurementModel{Matrix{Float64}, Int64, LinearAlgebra.Diagonal{Bool, Vector{Bool}}, Nothing}([0.45563868255969786 1.2767221563269395 … 0.5664561128334656 0.633487302084747; -1.0309093438610097 -0.8365799692760448 … -1.2792629123847703 -0.2654701159186893; … ; -0.7528181076204443 0.7769090438716332 … 0.4549191393234413 -0.6703097540313754; 0.8326613494926483 -1.4716719378245975 … 1.1337257013525612 1.0103431316009601], 0, Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 0; 0 0 … 0 1], 90, nothing), Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 0; 0 0 … 0 1], LowLevelParticleFilters.SimpleMvNormal{Vector{Float64}, LinearAlgebra.Diagonal{Bool, Vector{Bool}}}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], Bool[1 0 … 0 0; 0 1 … 0 0; … ; 0 0 … 1 0; 0 0 … 0 1]), LowLevelParticleFilters.SigmaPointCache{Vector{Vector{Float64}}, Vector{Vector{Float64}}}([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  …  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]  …  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [1.0 0.0 … 0.0 0.0; 0.0 1.0 … 0.0 0.0; … ; 0.0 0.0 … 1.0 0.0; 0.0 0.0 … 0.0 1.0], 0, 1.0, 90, 2, LowLevelParticleFilters.NullParameters(), nothing, LowLevelParticleFilters.safe_mean, LowLevelParticleFilters.safe_cov, LinearAlgebra.cholesky!)

When we create the filter with the custom measurement model, we do not pass the arguments that are associated with the measurement model to the filter constructor, i.e., we do not pass any measurement function, and not the measurement covariance matrix $R_2$.

Sensor fusion: Using several different measurement models

Above we constructed a filter with a custom measurement model, we can also pass a custom measurement model when we call correct!. This may be useful when, e.g., performing sensor fusion with sensors operating at different sample rates, or when parts of the measurement model are linear, and other parts are nonlinear.

The following example instantiates three different filters and three different measurement models. Each filter is updated with each measurement model, demonstrating that any combination of filter and measurement model can be used together.

using LowLevelParticleFilters, LinearAlgebra
 nx = 10    # Dimension of state
 nu = 2     # Dimension of input
 ny = 9     # Dimension of measurements
@@ -83,4 +83,4 @@
 [ Info: Updating ExtendedKalmanFilter with measurement model UKFMeasurementModel
 [ Info: Updating UnscentedKalmanFilter with measurement model UKFMeasurementModel

Since the dynamics in this particular example is in fact linear, we should get identical results for all three filters.

using Test
 @test kf.x ≈ ekf.x ≈ ukf.x
-@test kf.R ≈ ekf.R ≈ ukf.R
Test Passed

Video tutorial

A video demonstrating the use of multiple measurement models in a sensor-fusion context is available on YouTube:

+@test kf.R ≈ ekf.R ≈ ukf.R
Test Passed

Video tutorial

A video demonstrating the use of multiple measurement models in a sensor-fusion context is available on YouTube:

diff --git a/dev/neural_network/0c9f13e1.svg b/dev/neural_network/34a9b0f3.svg similarity index 96% rename from dev/neural_network/0c9f13e1.svg rename to dev/neural_network/34a9b0f3.svg index cdf94b11..91f8aff0 100644 --- a/dev/neural_network/0c9f13e1.svg +++ b/dev/neural_network/34a9b0f3.svg @@ -1,396 +1,396 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/neural_network/index.html b/dev/neural_network/index.html index f4c42b52..f3b9f3a8 100644 --- a/dev/neural_network/index.html +++ b/dev/neural_network/index.html @@ -107,7 +107,7 @@ plot(0:Ts:4000, reduce(hcat, xTe)'[:, nx+1:end], title="EKF parameters", c=1, alpha=0.2), plot(0:Ts:4000, reduce(hcat, xTu)'[:, nx+1:end], title="UKF parameters", c=1, alpha=0.2), legend = false, -)Example block output

Benchmarking

The neural network used in this example has

length(parr)
164

parameters, and the length of the data is

length(data.u)
134

Performing the estimation using the Extended Kalman Filter took

using BenchmarkTools
+)
Example block output

Benchmarking

The neural network used in this example has

length(parr)
164

parameters, and the length of the data is

length(data.u)
134

Performing the estimation using the Extended Kalman Filter took

using BenchmarkTools
 @btime forward_trajectory(ekf, data.u, data.x);
   # 46.034 ms (77872 allocations: 123.45 MiB)

and with the Unscented Kalman Filter

@btime forward_trajectory(ukf, data.u, data.x);
-  # 142.608 ms (2134370 allocations: 224.82 MiB)

The EKF is a bit faster, which is to be expected. Both methods are very fast from a neural-network training perspective, but the performance will not scale favorably to very large network sizes.

Closing remarks

We have seen how to estimate train a black-box neural network dynamics model by treating the parameter estimation as a state-estimation problem. This example is very simple and leaves a lot of room for improvement, such as

  • We assumed very little prior knowledge of the dynamics. In practice, we may want to model as much as possible from first principles and add a neural network to capture only the residuals that our first-principles model cannot capture.
  • We started the training of the network weights directly from a random initialization. In practice, we may want to pre-train the network on a large offline dataset before updating the weights adaptively in real-time.
  • We used forward-mode AD to compute the Jacobian. The Jacobian of the dynamics has dense rows, which means that it's theoretically favorable to use reverse-mode AD to compute it. This is possible using Zygote.jl, but Zygote does not handle array mutation, and one must thus avoid the in-place version of the dynamics. Since the number of parameters in this example is small, sparse forward mode AD ended up being slightly faster.
+ # 142.608 ms (2134370 allocations: 224.82 MiB)

The EKF is a bit faster, which is to be expected. Both methods are very fast from a neural-network training perspective, but the performance will not scale favorably to very large network sizes.

Closing remarks

We have seen how to estimate train a black-box neural network dynamics model by treating the parameter estimation as a state-estimation problem. This example is very simple and leaves a lot of room for improvement, such as

  • We assumed very little prior knowledge of the dynamics. In practice, we may want to model as much as possible from first principles and add a neural network to capture only the residuals that our first-principles model cannot capture.
  • We started the training of the network weights directly from a random initialization. In practice, we may want to pre-train the network on a large offline dataset before updating the weights adaptively in real-time.
  • We used forward-mode AD to compute the Jacobian. The Jacobian of the dynamics has dense rows, which means that it's theoretically favorable to use reverse-mode AD to compute it. This is possible using Zygote.jl, but Zygote does not handle array mutation, and one must thus avoid the in-place version of the dynamics. Since the number of parameters in this example is small, sparse forward mode AD ended up being slightly faster.
diff --git a/dev/noisetuning/index.html b/dev/noisetuning/index.html index 53ddff4c..1d30969d 100644 --- a/dev/noisetuning/index.html +++ b/dev/noisetuning/index.html @@ -1,2 +1,2 @@ -Noise tuning and disturbance modeling for Kalman filtering · LowLevelParticleFilters Documentation +Noise tuning and disturbance modeling for Kalman filtering · LowLevelParticleFilters Documentation diff --git a/dev/parameter_estimation/0ce988d8.svg b/dev/parameter_estimation/0ce988d8.svg deleted file mode 100644 index 1db38020..00000000 --- a/dev/parameter_estimation/0ce988d8.svg +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/parameter_estimation/0d315cae.svg b/dev/parameter_estimation/0d315cae.svg deleted file mode 100644 index ed78c4ab..00000000 --- a/dev/parameter_estimation/0d315cae.svg +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/parameter_estimation/1fbc1cbb.svg b/dev/parameter_estimation/1fbc1cbb.svg new file mode 100644 index 00000000..5135cc6e --- /dev/null +++ b/dev/parameter_estimation/1fbc1cbb.svg @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/23dbe7cf.svg b/dev/parameter_estimation/23dbe7cf.svg new file mode 100644 index 00000000..8cc3e7df --- /dev/null +++ b/dev/parameter_estimation/23dbe7cf.svg @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/24f69092.svg b/dev/parameter_estimation/24f69092.svg new file mode 100644 index 00000000..acc5f930 --- /dev/null +++ b/dev/parameter_estimation/24f69092.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/43f4c869.svg b/dev/parameter_estimation/43f4c869.svg deleted file mode 100644 index 5163b124..00000000 --- a/dev/parameter_estimation/43f4c869.svg +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/parameter_estimation/5afd5f48.svg b/dev/parameter_estimation/5afd5f48.svg deleted file mode 100644 index c829b099..00000000 --- a/dev/parameter_estimation/5afd5f48.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/parameter_estimation/99d67e60.svg b/dev/parameter_estimation/99d67e60.svg new file mode 100644 index 00000000..511fee1b --- /dev/null +++ b/dev/parameter_estimation/99d67e60.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/c5d789ad.svg b/dev/parameter_estimation/b3acc360.svg similarity index 93% rename from dev/parameter_estimation/c5d789ad.svg rename to dev/parameter_estimation/b3acc360.svg index d1787a3a..a1e30662 100644 --- a/dev/parameter_estimation/c5d789ad.svg +++ b/dev/parameter_estimation/b3acc360.svg @@ -1,88 +1,88 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/b61366d9.svg b/dev/parameter_estimation/b61366d9.svg new file mode 100644 index 00000000..c5a0a8fb --- /dev/null +++ b/dev/parameter_estimation/b61366d9.svg @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/b91de95b.svg b/dev/parameter_estimation/b69d40b1.svg similarity index 93% rename from dev/parameter_estimation/b91de95b.svg rename to dev/parameter_estimation/b69d40b1.svg index 11c030e7..8c01a774 100644 --- a/dev/parameter_estimation/b91de95b.svg +++ b/dev/parameter_estimation/b69d40b1.svg @@ -1,92 +1,92 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/parameter_estimation/c319f8f0.svg b/dev/parameter_estimation/c319f8f0.svg deleted file mode 100644 index 2b8e2081..00000000 --- a/dev/parameter_estimation/c319f8f0.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/parameter_estimation/175e5dc8.svg b/dev/parameter_estimation/d91b6330.svg similarity index 66% rename from dev/parameter_estimation/175e5dc8.svg rename to dev/parameter_estimation/d91b6330.svg index 55ed63e0..0f393c54 100644 --- a/dev/parameter_estimation/175e5dc8.svg +++ b/dev/parameter_estimation/d91b6330.svg @@ -1,189 +1,149 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - + + + + + + + diff --git a/dev/parameter_estimation/index.html b/dev/parameter_estimation/index.html index 20d544ff..fa62acc6 100644 --- a/dev/parameter_estimation/index.html +++ b/dev/parameter_estimation/index.html @@ -17,7 +17,7 @@ measurement(x,u,p,t) = C*x vecvec_to_mat(x) = copy(reduce(hcat, x)') # Helper function pf = ParticleFilter(N, dynamics, measurement, df, dg, d0) -xs,u,y = simulate(pf,300,df)
([[1.0812304200971112, -0.14562935751734435], [2.3116314798731947, 0.8082328770481344], [2.149967983738722, 2.541312262560706], [2.872559969263048, 3.125774767585316], [1.2847604308632985, 3.594221579226578], [1.7057197186301083, 1.8021199812015898], [1.2521647148100503, 3.7759747591461132], [2.916252681282151, 5.527520598681996], [3.8655354764711896, 5.694599692041501], [3.336783380763536, 5.69541365597537]  …  [-40.057822375546, 0.10357520800534564], [-40.79781396078199, -0.14891820535533207], [-40.998735577498536, -1.3313676138345785], [-42.305070570706356, -2.4752799199342475], [-40.175733821663414, -0.9221917889417495], [-40.83920051568449, -2.3416262383382276], [-41.11639931687991, -2.930835927025443], [-42.65241345816076, -3.8233874837439936], [-44.10458147517731, -2.663071035334208], [-44.9401935069422, -2.5067551899020923]], [[0.5839054062927054, -0.27929477378843304], [0.41007457728427377, 0.9184433161348705], [0.11204639752074251, 0.5631568392262732], [1.1255022555445502, -0.432131932236531], [-1.4609285400734122, -1.0047900574943391], [1.658369563599552, 0.41173127501428186], [0.080280121082907, -1.6750679461296805], [0.47545184209756375, 0.9200875097747347], [-0.8745692970385783, -0.6063211557138892], [-0.6371267005592348, 0.3182510062201885]  …  [-1.2489711048850263, 0.5737070285485795], [-0.5339829136703733, 0.2608634380802061], [-0.24862328178704068, 0.9549561375433364], [-0.16281638770760531, 1.0145987581223301], [-1.9226803890658999, 0.8827977883629121], [-0.858732315998032, -0.8824817581291353], [-0.6331406379760188, 0.42937840647202086], [-0.4115253891654016, -0.3459220491586696], [1.0877107905147378, -1.2027615350296437], [0.5789458507677563, 1.2073250722043054]], [[1.1322693119104885, 1.2029078202705352], [2.415363163655064, 1.695904961850642], [1.615759267659335, 3.5222811498451456], [2.143408989541812, 4.449899931909501], [0.8136966133619441, 4.499992159132988], [1.5599254636028799, 2.3315079458814703], [1.2799763549358372, 4.997067283150275], [2.606702355083542, 5.166990151336355], [3.4065631365369033, 6.56772913959163], [4.298954711495609, 6.490182843053165]  …  [-38.92772845267652, -1.4240826458928186], [-39.247146472512256, -2.3438403741212466], [-38.68000016203556, 0.35067589772821006], [-40.746955577248805, -4.369904724612883], [-39.41991512287349, -0.9956165897938583], [-40.73730497150801, -1.6295350451398427], [-42.87587778055609, -2.542375460317303], [-42.671747208920145, -2.9776133707209542], [-43.409959422929205, -3.849652637003693], [-43.03840912826101, -5.067597518916225]])

Compute likelihood for various values of the parameters

p = nothing
+xs,u,y = simulate(pf,300,df)
([[1.0812304200971112, -0.14562935751734435], [0.4607585860405089, -0.26877726154333453], [0.1746695304331622, 0.8583346015504947], [-0.9214627126928474, 0.8064840415028459], [-0.7914529733164749, 1.2766786662910583], [-0.08231328525055592, -0.12651336412522596], [0.4548121977246394, -0.016090288673307418], [1.1437185445779767, 1.0102618637859997], [0.41378790949518307, 0.9733010427501054], [-0.34959947631249844, 2.0102727426935676]  …  [-396.0793383516089, -7.14883185708867], [-398.1453577469821, -8.978199939476177], [-399.5537380277289, -9.132101219748684], [-400.6604900815941, -9.481225612192988], [-403.42205151747856, -9.940164431721728], [-402.98615320505536, -10.912036937439861], [-403.52125776769185, -12.542770762621664], [-403.7363348486577, -14.491275899498842], [-405.41913093283154, -16.6631983440307], [-406.5442261933284, -15.784503607517209]], [[0.5839054062927054, -0.27929477378843304], [0.41007457728427377, 0.9184433161348705], [0.11204639752074251, 0.5631568392262732], [1.1255022555445502, -0.432131932236531], [-1.4609285400734122, -1.0047900574943391], [1.658369563599552, 0.41173127501428186], [0.080280121082907, -1.6750679461296805], [0.47545184209756375, 0.9200875097747347], [-0.8745692970385783, -0.6063211557138892], [-0.6371267005592348, 0.3182510062201885]  …  [-1.2489711048850263, 0.5737070285485795], [-0.5339829136703733, 0.2608634380802061], [-0.24862328178704068, 0.9549561375433364], [-0.16281638770760531, 1.0145987581223301], [-1.9226803890658999, 0.8827977883629121], [-0.858732315998032, -0.8824817581291353], [-0.6331406379760188, 0.42937840647202086], [-0.4115253891654016, -0.3459220491586696], [1.0877107905147378, -1.2027615350296437], [0.5789458507677563, 1.2073250722043054]], [[3.826379477846361, 1.106346131653314], [-0.5299524866050582, 0.029844978891187146], [-1.9262924115894797, 2.4575180042692497], [-0.335419945580939, 0.4248124748336408], [-1.6779522529226032, 0.48425158180477057], [0.20170143674813212, 1.0435377872168172], [0.832460087218006, -0.9740279880423295], [-0.10327968004895771, 0.8192117715711238], [0.5070534631332806, 0.41553019255392354], [0.4600219090084662, 0.8696004125230792]  …  [-396.74634382146576, -7.151126612740699], [-398.3362017506925, -7.528928595515266], [-399.327259973, -9.310502658656317], [-399.88209093374587, -8.504114595664538], [-403.6130400910793, -8.898714242989328], [-402.87182523413037, -11.642104259408015], [-403.0100033389447, -11.02070063527221], [-404.12759639635897, -15.24432040373154], [-405.39332832867996, -17.435338403058026], [-405.62937020884544, -15.012921996736385]])

Compute likelihood for various values of the parameters

p = nothing
 svec = exp10.(LinRange(-0.8, 1.2, 60))
 llspf = map(svec) do s
     df = MvNormal(nx,s)
@@ -30,13 +30,13 @@
     xlabel = "Dynamics noise standard deviation",
     lab = "PF",
 )
-vline!([svec[findmax(llspf)[2]]], l=(:dash,:blue), primary=false)
Example block output

the correct value for the simulated data is 1 (the simulated system is the same as on the front page of the docs).

We can do the same with a Kalman filter

eye(n) = SMatrix{n,n}(1.0I(n))
+vline!([svec[findmax(llspf)[2]]], l=(:dash,:blue), primary=false)
Example block output

the correct value for the simulated data is 1 (the simulated system is the same as on the front page of the docs).

We can do the same with a Kalman filter

eye(n) = SMatrix{n,n}(1.0I(n))
 llskf = map(svec) do s
     kfs = KalmanFilter(A, B, C, 0, s^2*eye(nx), eye(ny), d0)
     loglik(kfs, u, y, p)
 end
 plot!(svec, llskf, yscale=:identity, xscale=:log10, lab="Kalman", c=:red)
-vline!([svec[findmax(llskf)[2]]], l=(:dash,:red), primary=false)
Example block output

the result can be quite noisy due to the stochastic nature of particle filtering. The particle filter likelihood agrees with the Kalman-filter estimate, which is optimal for the linear example system we are simulating here, apart for when the noise variance is small. Due to particle depletion, particle filters often struggle when dynamics-noise is too small. This problem is mitigated by using a greater number of particles, or simply by not using a too small covariance.

MAP estimation

In this example, we will estimate the variance of the noises in the dynamics and the measurement functions.

To solve a MAP estimation problem, we need to define a function that takes a parameter vector and returns a filter, the parameters are used to construct the covariance matrices:

filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*eye(nx), exp(θ[2])^2*eye(ny), d0) # Works with particle filters as well

The call to exp on the parameters is so that we can define log-normal priors

priors = [Normal(0,2),Normal(0,2)]
2-element Vector{Distributions.Normal{Float64}}:
+vline!([svec[findmax(llskf)[2]]], l=(:dash,:red), primary=false)
Example block output

the result can be quite noisy due to the stochastic nature of particle filtering. The particle filter likelihood agrees with the Kalman-filter estimate, which is optimal for the linear example system we are simulating here, apart for when the noise variance is small. Due to particle depletion, particle filters often struggle when dynamics-noise is too small. This problem is mitigated by using a greater number of particles, or simply by not using a too small covariance.

MAP estimation

In this example, we will estimate the variance of the noises in the dynamics and the measurement functions.

To solve a MAP estimation problem, we need to define a function that takes a parameter vector and returns a filter, the parameters are used to construct the covariance matrices:

filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*eye(nx), exp(θ[2])^2*eye(ny), d0) # Works with particle filters as well

The call to exp on the parameters is so that we can define log-normal priors

priors = [Normal(0,2),Normal(0,2)]
2-element Vector{Distributions.Normal{Float64}}:
  Distributions.Normal{Float64}(μ=0.0, σ=2.0)
  Distributions.Normal{Float64}(μ=0.0, σ=2.0)

Now we call the function log_likelihood_fun that returns a function to be minimized

ll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)

Since this is a low-dimensional problem, we can plot the LL on a 2d-grid

function meshgrid(a,b)
     grid_a = [i for i in a, j in b]
@@ -54,16 +54,16 @@
     yticks = (1:Nv, round.(v, digits = 2)),
     xlabel = "sigma v",
     ylabel = "sigma w",
-) # Yes, labels are reversed
Example block output

For higher-dimensional problems, we may estimate the parameters using an optimizer, e.g., Optim.jl.

Bayesian inference using PMMH

We proceed like we did for MAP above, but when calling the function metropolis, we will get the entire posterior distribution of the parameter vector, for the small cost of a massive increase in the amount of computations. metropolis runs the Metropolis Hastings algorithm, or more precisely if a particle filter is used, the "Particle Marginal Metropolis Hastings" (PMMH) algorithm. Here we use the Kalman filter simply to have the documentation build a bit faster, it can be quite heavy to run.

filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*I(nx), exp(θ[2])^2*I(ny), d0) # Works with particle filters as well

The call to exp on the parameters is so that we can define log-normal priors

priors = [Normal(0,2),Normal(0,2)]
+) # Yes, labels are reversed
Example block output

For higher-dimensional problems, we may estimate the parameters using an optimizer, e.g., Optim.jl.

Bayesian inference using PMMH

We proceed like we did for MAP above, but when calling the function metropolis, we will get the entire posterior distribution of the parameter vector, for the small cost of a massive increase in the amount of computations. metropolis runs the Metropolis Hastings algorithm, or more precisely if a particle filter is used, the "Particle Marginal Metropolis Hastings" (PMMH) algorithm. Here we use the Kalman filter simply to have the documentation build a bit faster, it can be quite heavy to run.

filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*I(nx), exp(θ[2])^2*I(ny), d0) # Works with particle filters as well

The call to exp on the parameters is so that we can define log-normal priors

priors = [Normal(0,2),Normal(0,2)]
 ll     = log_likelihood_fun(filter_from_parameters, priors, u, y, p)
 θ₀     = log.([1.0, 1.0]) # Starting point

We also need to define a function that suggests a new point from the "proposal distribution". This can be pretty much anything, but it has to be symmetric since I was lazy and simplified an equation.

draw   = θ -> θ .+ 0.05 .* randn.() # This function dictates how new proposal parameters are being generated.
 burnin = 200 # remove this many initial samples ("burn-in period")
 @info "Starting Metropolis algorithm"
 @time theta, lls = metropolis(ll, 2200, θ₀, draw) # Run PMMH for 2200  iterations
 thetam = reduce(hcat, theta)'[burnin+1:end,:] # Build a matrix of the output
-histogram(exp.(thetam), layout=(3,1), lab=["R1" "R2"]); plot!(lls[burnin+1:end], subplot=3, lab="log likelihood") # Visualize
Example block output

In this example, we initialize the MH algorithm on the correct value θ₀, in general, you'd see a period in the beginning where the likelihood (bottom plot) is much lower than during the rest of the sampling, this is the reason we remove a number of samples in the beginning, typically referred to as "burn in".

If you are lucky, you can run the above threaded as well. I tried my best to make particle filters thread safe with their own rngs etc., but your milage may vary. For threading to help, the dynamics must be non-allocating, e.g., by using StaticArrays etc.

@time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 2200, θ₀, draw, nthreads=2)
+histogram(exp.(thetam), layout=(3,1), lab=["R1" "R2"]); plot!(lls[burnin+1:end], subplot=3, lab="log likelihood") # Visualize
Example block output

In this example, we initialize the MH algorithm on the correct value θ₀, in general, you'd see a period in the beginning where the likelihood (bottom plot) is much lower than during the rest of the sampling, this is the reason we remove a number of samples in the beginning, typically referred to as "burn in".

If you are lucky, you can run the above threaded as well. I tried my best to make particle filters thread safe with their own rngs etc., but your milage may vary. For threading to help, the dynamics must be non-allocating, e.g., by using StaticArrays etc.

@time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 2200, θ₀, draw, nthreads=2)
 histogram(exp.(thetalls[:,1:2]), layout=3)
-plot!(thetalls[:,3], subplot=3)
Example block output

Bayesian inference using DynamicHMC.jl

The following snippet of code performs the same estimation as above, but uses the much more sophisticated HMC sampler in DynamicHMC.jl rather than the PMMH sampler above. This package requires the log-likelihood function to be wrapped in a custom struct that implements the LogDensityProblems interface, which is done below. We also indicate that we want to use ForwardDiff.jl to compute the gradients for fast sampling.

using DynamicHMC, LogDensityProblemsAD, ForwardDiff, LogDensityProblems, LinearAlgebra, Random
+plot!(thetalls[:,3], subplot=3)
Example block output

Bayesian inference using DynamicHMC.jl

The following snippet of code performs the same estimation as above, but uses the much more sophisticated HMC sampler in DynamicHMC.jl rather than the PMMH sampler above. This package requires the log-likelihood function to be wrapped in a custom struct that implements the LogDensityProblems interface, which is done below. We also indicate that we want to use ForwardDiff.jl to compute the gradients for fast sampling.

using DynamicHMC, LogDensityProblemsAD, ForwardDiff, LogDensityProblems, LinearAlgebra, Random
 
 struct LogTargetDensity{F}
     ll::F
@@ -135,7 +135,7 @@
 plot(
     plot(reduce(hcat, x)', title="State"),
     plot(reduce(hcat, u)', title="Inputs")
-)
Example block output

To perform the joint state and parameter estimation, we define a version of the dynamics that contains an extra state, corresponding to the unknown or time varying parameter, in this case $a_1$. We do not have any apriori information about how this parameter changes, so we say that its derivative is 0 and it's thus only driven by noise:

function quadtank_paramest(h, u, p, t)
+)
Example block output

To perform the joint state and parameter estimation, we define a version of the dynamics that contains an extra state, corresponding to the unknown or time varying parameter, in this case $a_1$. We do not have any apriori information about how this parameter changes, so we say that its derivative is 0 and it's thus only driven by noise:

function quadtank_paramest(h, u, p, t)
     kc = 0.5
     k1, k2, g = 1.6, 1.6, 9.81
     A1 = A3 = A2 = A4 = 4.9
@@ -164,7 +164,7 @@
 
 sol = forward_trajectory(kf, u, y)
 plot(sol, plotx=false, plotxt=true, plotu=false, ploty=true, legend=:bottomright)
-plot!([0,500,500,1000], [0.03, 0.03, 0.06, 0.06], l=(:dash, :black), sp=5, lab="True param")
Example block output

as we can see, the correct value of the parameter is quickly found ($x_5$), and it also adapts at $t=500$ when the parameter value changes. The speed with which the parameter adapts to changes is determined by the covariance matrix $R_1$, a higher value results in faster adaptation, but also higher sensitivity to noise.

If adaptive parameter estimation is coupled with a model-based controller, we get an adaptive controller! Note: the state that corresponds to the estimated parameter is typically not controllable, a fact that may require some special care for some control methods.

We may ask ourselves, what's the difference between a parameter and a state variable if we can add parameters as state variables? Typically, parameters do not vary with time, and if they do, they vary significantly slower than the state variables. State variables also have dynamics associate with them, whereas we often have no idea about how the parameters vary other than that they vary slowly.

Abrupt changes to the dynamics like in the example above can happen in practice, for instance, due to equipment failure or change of operating mode. This can be treated as a scenario with time-varying parameters that are continuously estimated.

Using an optimizer

The state estimators in this package are all statistically motivated and thus compute things like the likelihood of the data as a by-product of the estimation. Maximum-likelihood or prediction-error estimation is thus very straight-forward by simply calling a gradient-based optimizer with gradients provided by differentiating through the state estimator using automatic differentiation. In this example, we will continue the example from above, but now estimate all the parameters of the quad-tank process. This time, they will not vary with time. We will first use a standard optimization algorithm from Optim.jl to minimize the cost function based on the prediction error, and then use a Gauss-Newton optimizer.

We now define the dynamics function such that it takes its parameters from the p input argument. We also define a variable p_true that contains the true values that we will use to simulate some estimation data

function quadtank(h, u, p, t)
+plot!([0,500,500,1000], [0.03, 0.03, 0.06, 0.06], l=(:dash, :black), sp=5, lab="True param")
Example block output

as we can see, the correct value of the parameter is quickly found ($x_5$), and it also adapts at $t=500$ when the parameter value changes. The speed with which the parameter adapts to changes is determined by the covariance matrix $R_1$, a higher value results in faster adaptation, but also higher sensitivity to noise.

If adaptive parameter estimation is coupled with a model-based controller, we get an adaptive controller! Note: the state that corresponds to the estimated parameter is typically not controllable, a fact that may require some special care for some control methods.

We may ask ourselves, what's the difference between a parameter and a state variable if we can add parameters as state variables? Typically, parameters do not vary with time, and if they do, they vary significantly slower than the state variables. State variables also have dynamics associate with them, whereas we often have no idea about how the parameters vary other than that they vary slowly.

Abrupt changes to the dynamics like in the example above can happen in practice, for instance, due to equipment failure or change of operating mode. This can be treated as a scenario with time-varying parameters that are continuously estimated.

Using an optimizer

The state estimators in this package are all statistically motivated and thus compute things like the likelihood of the data as a by-product of the estimation. Maximum-likelihood or prediction-error estimation is thus very straight-forward by simply calling a gradient-based optimizer with gradients provided by differentiating through the state estimator using automatic differentiation. In this example, we will continue the example from above, but now estimate all the parameters of the quad-tank process. This time, they will not vary with time. We will first use a standard optimization algorithm from Optim.jl to minimize the cost function based on the prediction error, and then use a Gauss-Newton optimizer.

We now define the dynamics function such that it takes its parameters from the p input argument. We also define a variable p_true that contains the true values that we will use to simulate some estimation data

function quadtank(h, u, p, t)
     kc = p[1]
     k1, k2, g = p[2], p[3], 9.81
     A1 = A3 = A2 = A4 = p[4]
@@ -195,7 +195,7 @@
 plot(
     plot(reduce(hcat, x)', title="State"),
     plot(reduce(hcat, u)', title="Inputs")
-)
Example block output

This time, we define a cost function for the optimizer to optimize, we'll use the sum of squared errors (sse). It's important to define the UKF with an initial state distribution with the same element type as the parameter vector so that automatic differentiation through the state estimator works, hence the explicit casting T.(x0) and T.(R1). We also make sure to use StaticArrays for the covariance matrices and the initial condition for performance reasons (optional).

nx = 4
+)
Example block output

This time, we define a cost function for the optimizer to optimize, we'll use the sum of squared errors (sse). It's important to define the UKF with an initial state distribution with the same element type as the parameter vector so that automatic differentiation through the state estimator works, hence the explicit casting T.(x0) and T.(R1). We also make sure to use StaticArrays for the covariance matrices and the initial condition for performance reasons (optional).

nx = 4
 R1 = SMatrix{nx,nx}(Diagonal([0.1, 0.1, 0.1, 0.1])) # Use of StaticArrays is generally good for performance
 R2 = SMatrix{ny,ny}(Diagonal((1e-2)^2 * ones(ny)))
 x0 = SA[2.0, 2, 3, 3]
@@ -280,4 +280,4 @@
   h3  => 0
   h1  => 1
   A1  => 0
-  a2  => 0

indicating that we can not hope to resolve all of the parameters. However, using appropriate regularization from prior information, we might still recover a lot of information about the system. Regularization could easily be added to the function cost above, e.g., using a penalty like (p-p_guess)'Γ*(p-p_guess) for some matrix $\Gamma$, to indicate our confidence in the initial guess.

Videos

Examples of parameter estimation are available here

By using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:

Estimation of time-varying parameters:

Adaptive control by means of estimation of time-varying parameters:

+ a2 => 0

indicating that we can not hope to resolve all of the parameters. However, using appropriate regularization from prior information, we might still recover a lot of information about the system. Regularization could easily be added to the function cost above, e.g., using a penalty like (p-p_guess)'Γ*(p-p_guess) for some matrix $\Gamma$, to indicate our confidence in the initial guess.

Videos

Examples of parameter estimation are available here

By using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:

Estimation of time-varying parameters:

Adaptive control by means of estimation of time-varying parameters:

diff --git a/dev/search_index.js b/dev/search_index.js index 290294d7..33c011c9 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"distributions/#Performance-tips","page":"Performance tips","title":"Performance tips","text":"","category":"section"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"Use of StaticArrays.jl is recommended for optimal performance when the state dimension is small, e.g., less than about 10-15 for Kalman filters and less than about 100 for particle filters. In the section Parameter optimization we demonstrate one workflow that makes use of StaticArrays everywhere it is needed for an UnscentedKalmanFilter in order to get a completely allocation free filter. The following arrays must be static for this to hold","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"The initial state distribution (the vector and matrix passed to d0 = MvNormal(μ, Σ) for Kalman filters). If you are performing parameter optimization with gradients derived using ForwardDiff.jl, these must further have the correct element type. How to achieve this is demonstrated in the liked example above.\nInputs u measured outputs y.\nIn case of Kalman filters, the dynamic model matrices A, B, C, D and the covariance matrices R1, R2.\nThe dynamics functions for UnscentedKalmanFilter and particle filters must further return static arrays when passed static arrays as inputs.","category":"page"},{"location":"distributions/#Analysis-using-JET","page":"Performance tips","title":"Analysis using JET","text":"","category":"section"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"All flavors of Kalman filters are analyzed for potential runtime dispatch using JET.jl. This analysis is performed in the tests and generally requires a completely static filter using static arrays internally. See the tests for an example of how to set a filter up this way.","category":"page"},{"location":"distributions/#High-performance-Distributions","page":"Performance tips","title":"High performance Distributions","text":"","category":"section"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"When using LowLevelParticleFilters, a number of methods related to distributions are defined for static arrays, making logpdf etc. faster. We also provide a new kind of distribution: TupleProduct <: MultivariateDistribution that behaves similarly to the Product distribution. The TupleProduct however stores the individual distributions in a tuple, has compile-time known length and supports Mixed <: ValueSupport, meaning that it can be a product of both Continuous and Discrete dimensions, something not supported by the standard Product. Example","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"using BenchmarkTools, LowLevelParticleFilters, Distributions, StaticArrays\ndt = TupleProduct((Normal(0,2), Normal(0,2), Binomial())) # Mixed value support","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"A small benchmark","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"sv = @SVector randn(2)\nd = Distributions.Product([Normal(0,2), Normal(0,2)])\ndt = TupleProduct((Normal(0,2), Normal(0,2)))\ndm = MvNormal(2, 2)\n@btime logpdf($d,$(Vector(sv))) # 19.536 ns (0 allocations: 0 bytes)\n@btime logpdf($dt,$(Vector(sv))) # 13.742 ns (0 allocations: 0 bytes)\n@btime logpdf($dm,$(Vector(sv))) # 11.392 ns (0 allocations: 0 bytes)","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"@btime logpdf($d,$sv) # 13.964 ns (0 allocations: 0 bytes)\n@btime logpdf($dt,$sv) # 12.817 ns (0 allocations: 0 bytes)\n@btime logpdf($dm,$sv) # 8.383 ns (0 allocations: 0 bytes)","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"Without loading LowLevelParticleFilters, the timing for the native distributions are the following","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"@btime logpdf($d,$sv) # 18.040 ns (0 allocations: 0 bytes)\n@btime logpdf($dm,$sv) # 9.938 ns (0 allocations: 0 bytes)","category":"page"},{"location":"parameter_estimation/#Parameter-Estimation","page":"Parameter estimation","title":"Parameter Estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"State estimation is an integral part of many parameter-estimation methods. Below, we will illustrate several different methods of performing parameter estimation. We can roughly divide the methods into two camps","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Methods that optimize prediction error or likelihood by tweaking model parameters.\nMethods that add the parameters to be estimated as state variables in the model and estimate them using standard state estimation. ","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"From the first camp, we provide som basic functionality for maximum-likelihood estimation and MAP estimation, described below. An example of (2), joint state and parameter estimation, is provided in Joint state and parameter estimation.","category":"page"},{"location":"parameter_estimation/#Maximum-likelihood-estimation","page":"Parameter estimation","title":"Maximum-likelihood estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Filters calculate the likelihood and prediction errors while performing filtering, this can be used to perform maximum likelihood estimation or prediction-error minimization. One can estimate all kinds of parameters using this method, in the example below, we will estimate the noise covariance. We may for example plot likelihood as function of the variance of the dynamics noise like this:","category":"page"},{"location":"parameter_estimation/#Generate-data-by-simulation","page":"Parameter estimation","title":"Generate data by simulation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"This simulates the same linear system as on the index page of the documentation","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots\nnx = 2 # Dimension of state\nnu = 2 # Dimension of input\nny = 2 # Dimension of measurements\nN = 2000 # Number of particles\n\nconst dg = MvNormal(ny,1.0) # Measurement noise Distribution\nconst df = MvNormal(nx,1.0) # Dynamics noise Distribution\nconst d0 = MvNormal(@SVector(randn(nx)),2.0) # Initial state Distribution\n\nconst A = SA[1 0.1; 0 1]\nconst B = @SMatrix [0.0 0.1; 1 0.1]\nconst C = @SMatrix [1.0 0; 0 1]\n\ndynamics(x,u,p,t) = A*x .+ B*u \nmeasurement(x,u,p,t) = C*x\nvecvec_to_mat(x) = copy(reduce(hcat, x)') # Helper function\npf = ParticleFilter(N, dynamics, measurement, df, dg, d0)\nxs,u,y = simulate(pf,300,df)","category":"page"},{"location":"parameter_estimation/#Compute-likelihood-for-various-values-of-the-parameters","page":"Parameter estimation","title":"Compute likelihood for various values of the parameters","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"p = nothing\nsvec = exp10.(LinRange(-0.8, 1.2, 60))\nllspf = map(svec) do s\n df = MvNormal(nx,s)\n pfs = ParticleFilter(N, dynamics, measurement, df, dg, d0)\n loglik(pfs, u, y, p)\nend\nplot( svec, llspf,\n xscale = :log10,\n title = \"Log-likelihood\",\n xlabel = \"Dynamics noise standard deviation\",\n lab = \"PF\",\n)\nvline!([svec[findmax(llspf)[2]]], l=(:dash,:blue), primary=false)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"the correct value for the simulated data is 1 (the simulated system is the same as on the front page of the docs).","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We can do the same with a Kalman filter","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"eye(n) = SMatrix{n,n}(1.0I(n))\nllskf = map(svec) do s\n kfs = KalmanFilter(A, B, C, 0, s^2*eye(nx), eye(ny), d0)\n loglik(kfs, u, y, p)\nend\nplot!(svec, llskf, yscale=:identity, xscale=:log10, lab=\"Kalman\", c=:red)\nvline!([svec[findmax(llskf)[2]]], l=(:dash,:red), primary=false)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"the result can be quite noisy due to the stochastic nature of particle filtering. The particle filter likelihood agrees with the Kalman-filter estimate, which is optimal for the linear example system we are simulating here, apart for when the noise variance is small. Due to particle depletion, particle filters often struggle when dynamics-noise is too small. This problem is mitigated by using a greater number of particles, or simply by not using a too small covariance.","category":"page"},{"location":"parameter_estimation/#MAP-estimation","page":"Parameter estimation","title":"MAP estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"In this example, we will estimate the variance of the noises in the dynamics and the measurement functions.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"To solve a MAP estimation problem, we need to define a function that takes a parameter vector and returns a filter, the parameters are used to construct the covariance matrices:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*eye(nx), exp(θ[2])^2*eye(ny), d0) # Works with particle filters as well\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The call to exp on the parameters is so that we can define log-normal priors","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"priors = [Normal(0,2),Normal(0,2)]","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Now we call the function log_likelihood_fun that returns a function to be minimized","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"ll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Since this is a low-dimensional problem, we can plot the LL on a 2d-grid","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"function meshgrid(a,b)\n grid_a = [i for i in a, j in b]\n grid_b = [j for i in a, j in b]\n grid_a, grid_b\nend\nNv = 20\nv = LinRange(-0.7,1,Nv)\nllxy = (x,y) -> ll([x;y])\nVGx, VGy = meshgrid(v,v)\nVGz = llxy.(VGx, VGy)\nheatmap(\n VGz,\n xticks = (1:Nv, round.(v, digits = 2)),\n yticks = (1:Nv, round.(v, digits = 2)),\n xlabel = \"sigma v\",\n ylabel = \"sigma w\",\n) # Yes, labels are reversed","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"For higher-dimensional problems, we may estimate the parameters using an optimizer, e.g., Optim.jl.","category":"page"},{"location":"parameter_estimation/#Bayesian-inference-using-PMMH","page":"Parameter estimation","title":"Bayesian inference using PMMH","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We proceed like we did for MAP above, but when calling the function metropolis, we will get the entire posterior distribution of the parameter vector, for the small cost of a massive increase in the amount of computations. metropolis runs the Metropolis Hastings algorithm, or more precisely if a particle filter is used, the \"Particle Marginal Metropolis Hastings\" (PMMH) algorithm. Here we use the Kalman filter simply to have the documentation build a bit faster, it can be quite heavy to run.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*I(nx), exp(θ[2])^2*I(ny), d0) # Works with particle filters as well\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The call to exp on the parameters is so that we can define log-normal priors","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"priors = [Normal(0,2),Normal(0,2)]\nll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)\nθ₀ = log.([1.0, 1.0]) # Starting point\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We also need to define a function that suggests a new point from the \"proposal distribution\". This can be pretty much anything, but it has to be symmetric since I was lazy and simplified an equation.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"draw = θ -> θ .+ 0.05 .* randn.() # This function dictates how new proposal parameters are being generated. \nburnin = 200 # remove this many initial samples (\"burn-in period\")\n@info \"Starting Metropolis algorithm\"\n@time theta, lls = metropolis(ll, 2200, θ₀, draw) # Run PMMH for 2200 iterations\nthetam = reduce(hcat, theta)'[burnin+1:end,:] # Build a matrix of the output\nhistogram(exp.(thetam), layout=(3,1), lab=[\"R1\" \"R2\"]); plot!(lls[burnin+1:end], subplot=3, lab=\"log likelihood\") # Visualize","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"In this example, we initialize the MH algorithm on the correct value θ₀, in general, you'd see a period in the beginning where the likelihood (bottom plot) is much lower than during the rest of the sampling, this is the reason we remove a number of samples in the beginning, typically referred to as \"burn in\".","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"If you are lucky, you can run the above threaded as well. I tried my best to make particle filters thread safe with their own rngs etc., but your milage may vary. For threading to help, the dynamics must be non-allocating, e.g., by using StaticArrays etc.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"@time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 2200, θ₀, draw, nthreads=2)\nhistogram(exp.(thetalls[:,1:2]), layout=3)\nplot!(thetalls[:,3], subplot=3)","category":"page"},{"location":"parameter_estimation/#Bayesian-inference-using-DynamicHMC.jl","page":"Parameter estimation","title":"Bayesian inference using DynamicHMC.jl","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The following snippet of code performs the same estimation as above, but uses the much more sophisticated HMC sampler in DynamicHMC.jl rather than the PMMH sampler above. This package requires the log-likelihood function to be wrapped in a custom struct that implements the LogDensityProblems interface, which is done below. We also indicate that we want to use ForwardDiff.jl to compute the gradients for fast sampling.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using DynamicHMC, LogDensityProblemsAD, ForwardDiff, LogDensityProblems, LinearAlgebra, Random\n\nstruct LogTargetDensity{F}\n ll::F\n dim::Int\nend\nLogDensityProblems.logdensity(p::LogTargetDensity, θ) = p.ll(θ)\nLogDensityProblems.dimension(p::LogTargetDensity) = p.dim\nLogDensityProblems.capabilities(::Type{LogTargetDensity}) = LogDensityProblems.LogDensityOrder{0}()\n\nfunction filter_from_parameters(θ, pf = nothing)\n # It's important that the distribution of the initial state has the same\n # element type as the parameters. DynamicHMC will use Dual numbers for differentiation,\n # hence, we make sure that d0 has `eltype(d0) = eltype(θ)`\n T = eltype(θ)\n d0 = MvNormal(T.(d0.μ), T.(d0.Σ))\n KalmanFilter(A, B, C, 0, exp(θ[1])^2*eye(nx), exp(θ[2])^2*eye(ny), d0) \nend\nll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)\n\nD = length(θ₀)\nℓπ = LogTargetDensity(ll, D)\n∇P = ADgradient(:ForwardDiff, ℓπ)\n\nresults = mcmc_with_warmup(Random.default_rng(), ∇P, 3000)\nDynamicHMC.Diagnostics.summarize_tree_statistics(results.tree_statistics)\nlls = [ts.π for ts in results.tree_statistics]\n\nhistogram(exp.(results.posterior_matrix)', layout=(3,1), lab=[\"R1\" \"R2\"])\nplot!(lls, subplot=3, lab=\"log likelihood\") # Visualize","category":"page"},{"location":"parameter_estimation/#Joint-state-and-parameter-estimation","page":"Parameter estimation","title":"Joint state and parameter estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"In this example, we'll show how to perform parameter estimation by treating a parameter as a state variable. This method can not only estimate constant parameters, but also time-varying parameters. The system we will consider is a quadruple tank, where two upper tanks feed into two lower tanks. The outlet for tank 1 can vary in size, simulating, e.g., that something partially blocks the outlet. We start by defining the dynamics on a form that changes the outlet area a_1 at time t=500:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LowLevelParticleFilters\nusing SeeToDee\nusing Distributions\nusing StaticArrays\nusing Plots, LinearAlgebra\n\nfunction quadtank(h,u,p,t)\n kc = 0.5\n k1, k2, g = 1.6, 1.6, 9.81\n A1 = A3 = A2 = A4 = 4.9\n a1, a3, a2, a4 = 0.03, 0.03, 0.03, 0.03\n γ1, γ2 = 0.2, 0.2\n\n if t > 500\n a1 *= 2 # Change the parameter at t = 500\n end\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n \n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n ]\nend\n\nnu = 2 # number of control inputs\nnx = 4 # number of state variables\nny = 2 # number of measured outputs\nTs = 1 # sample time\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We then define a measurement function, we measure the levels of tanks 1 and 2, and discretize the continuous-time dynamics using a Runge-Kutta 4 integrator SeeToDee.Rk4:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"measurement(x,u,p,t) = SA[x[1], x[2]]\ndiscrete_dynamics = SeeToDee.Rk4(quadtank, Ts)\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We simulate the system using the rollout function and add some noise to the measurements. The inputs in this case are just square waves.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Tperiod = 200\nt = 0:Ts:1000\nu = vcat.(0.25 .* sign.(sin.(2pi/Tperiod .* t)) .+ 0.25)\nu = SVector{nu}.(vcat.(u,u))\nx0 = Float64[2,2,3,3]\nx = LowLevelParticleFilters.rollout(discrete_dynamics, x0, u)[1:end-1]\ny = measurement.(x, u, 0, 0)\ny = [y .+ 0.01.*randn.() for y in y]\n\nplot(\n plot(reduce(hcat, x)', title=\"State\"),\n plot(reduce(hcat, u)', title=\"Inputs\")\n)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"To perform the joint state and parameter estimation, we define a version of the dynamics that contains an extra state, corresponding to the unknown or time varying parameter, in this case a_1. We do not have any apriori information about how this parameter changes, so we say that its derivative is 0 and it's thus only driven by noise:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"function quadtank_paramest(h, u, p, t)\n kc = 0.5\n k1, k2, g = 1.6, 1.6, 9.81\n A1 = A3 = A2 = A4 = 4.9\n a3, a2, a4 = 0.03, 0.03, 0.03\n γ1, γ2 = 0.2, 0.2\n\n a1 = h[5] # the a1 parameter is a state\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n \n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n 0 # the state is only driven by noise\n ]\nend\n\ndiscrete_dynamics_params = SeeToDee.Rk4(quadtank_paramest, Ts)\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We then define a nonlinear state estimator, we will use the UnscentedKalmanFilter, and solve the filtering problem. We start by an initial state estimate x_0 that is slightly off for the parameter a_1","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"nx = 5\nR1 = SMatrix{nx,nx}(Diagonal([0.1, 0.1, 0.1, 0.1, 0.0001])) # Use of StaticArrays is generally good for performance\nR2 = SMatrix{ny,ny}(Diagonal((1e-2)^2 * ones(ny)))\nx0 = SA[2, 2, 3, 3, 0.02] # The SA prefix makes the array static, which is good for performance\n\nkf = UnscentedKalmanFilter(discrete_dynamics_params, measurement, R1, R2, MvNormal(x0, R1); ny, nu, Ts)\n\nsol = forward_trajectory(kf, u, y)\nplot(sol, plotx=false, plotxt=true, plotu=false, ploty=true, legend=:bottomright)\nplot!([0,500,500,1000], [0.03, 0.03, 0.06, 0.06], l=(:dash, :black), sp=5, lab=\"True param\")","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"as we can see, the correct value of the parameter is quickly found (x_5), and it also adapts at t=500 when the parameter value changes. The speed with which the parameter adapts to changes is determined by the covariance matrix R_1, a higher value results in faster adaptation, but also higher sensitivity to noise. ","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"If adaptive parameter estimation is coupled with a model-based controller, we get an adaptive controller! Note: the state that corresponds to the estimated parameter is typically not controllable, a fact that may require some special care for some control methods.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We may ask ourselves, what's the difference between a parameter and a state variable if we can add parameters as state variables? Typically, parameters do not vary with time, and if they do, they vary significantly slower than the state variables. State variables also have dynamics associate with them, whereas we often have no idea about how the parameters vary other than that they vary slowly.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Abrupt changes to the dynamics like in the example above can happen in practice, for instance, due to equipment failure or change of operating mode. This can be treated as a scenario with time-varying parameters that are continuously estimated. ","category":"page"},{"location":"parameter_estimation/#Using-an-optimizer","page":"Parameter estimation","title":"Using an optimizer","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The state estimators in this package are all statistically motivated and thus compute things like the likelihood of the data as a by-product of the estimation. Maximum-likelihood or prediction-error estimation is thus very straight-forward by simply calling a gradient-based optimizer with gradients provided by differentiating through the state estimator using automatic differentiation. In this example, we will continue the example from above, but now estimate all the parameters of the quad-tank process. This time, they will not vary with time. We will first use a standard optimization algorithm from Optim.jl to minimize the cost function based on the prediction error, and then use a Gauss-Newton optimizer.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We now define the dynamics function such that it takes its parameters from the p input argument. We also define a variable p_true that contains the true values that we will use to simulate some estimation data","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"function quadtank(h, u, p, t)\n kc = p[1]\n k1, k2, g = p[2], p[3], 9.81\n A1 = A3 = A2 = A4 = p[4]\n a1 = a3 = a2 = a4 = p[5]\n γ1 = γ2 = p[6]\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n \n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n ]\nend\n\ndiscrete_dynamics = SeeToDee.Rk4(quadtank, Ts) # Discretize the dynamics using a 4:th order Runge-Kutta integrator\np_true = [0.5, 1.6, 1.6, 4.9, 0.03, 0.2]\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Similar to previous example, we simulate the system, this time using a more exciting input in order to be able to identify several parameters","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using Random; Random.seed!(1) # hide\nTperiod = 200\nt = 0:Ts:1000\nu1 = vcat.(0.25 .* sign.(sin.(2pi/Tperiod .* (t ./ 40).^2)) .+ 0.25)\nu2 = vcat.(0.25 .* sign.(sin.(2pi/Tperiod .* (t ./ 40).^2 .+ pi/2)) .+ 0.25)\nu = SVector{nu}.(vcat.(u1,u2))\nx0 = SA[2.0,2,3,3] # Initial condition, static array for performance\nx = LowLevelParticleFilters.rollout(discrete_dynamics, x0, u, p_true)[1:end-1]\ny = measurement.(x, u, 0, 0)\ny = [y .+ 0.01 .* randn.() for y in y]\n\nplot(\n plot(reduce(hcat, x)', title=\"State\"),\n plot(reduce(hcat, u)', title=\"Inputs\")\n)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"This time, we define a cost function for the optimizer to optimize, we'll use the sum of squared errors (sse). It's important to define the UKF with an initial state distribution with the same element type as the parameter vector so that automatic differentiation through the state estimator works, hence the explicit casting T.(x0) and T.(R1). We also make sure to use StaticArrays for the covariance matrices and the initial condition for performance reasons (optional).","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"nx = 4\nR1 = SMatrix{nx,nx}(Diagonal([0.1, 0.1, 0.1, 0.1])) # Use of StaticArrays is generally good for performance\nR2 = SMatrix{ny,ny}(Diagonal((1e-2)^2 * ones(ny)))\nx0 = SA[2.0, 2, 3, 3]\n\nfunction cost(p::Vector{T}) where T\n kf = UnscentedKalmanFilter(discrete_dynamics, measurement, R1, R2, MvNormal(T.(x0), T.(R1)); ny, nu, Ts)\n LowLevelParticleFilters.sse(kf, u, y, p) # Sum of squared prediction errors\nend\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We generate a random initial guess for the estimation problem","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"p_guess = p_true .+ 0.1*p_true .* randn(length(p_true))","category":"page"},{"location":"parameter_estimation/#Solving-using-Optim","page":"Parameter estimation","title":"Solving using Optim","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We first minimize the cost using the BFGS optimization algorithm from Optim.jl","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using Optim\nres = Optim.optimize(\n cost,\n p_guess,\n BFGS(),\n Optim.Options(\n show_trace = true,\n show_every = 5,\n iterations = 100,\n time_limit = 30,\n ),\n autodiff = :forward, # Indicate that we want to use forward-mode AD to derive gradients\n)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We started out with a normalized parameter error of","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LinearAlgebra\nnorm(p_true - p_guess) / norm(p_true)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"and ended with","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"p_opt = res.minimizer\nnorm(p_true - p_opt) / norm(p_true)","category":"page"},{"location":"parameter_estimation/#Solving-using-Gauss-Newton-optimization","page":"Parameter estimation","title":"Solving using Gauss-Newton optimization","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Below, we optimize the sum of squared residuals again, but this time we do it using a Gauss-Newton style algorithm (Levenberg Marquardt). These algorithms want the entire residual vector rather than the sum of squares of the residuals, so we define an alternative \"cost function\" called residuals that calls the lower-level function LowLevelParticleFilters.prediction_errors!","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LeastSquaresOptim\n\nfunction residuals!(res, p::Vector{T}) where T\n kf = UnscentedKalmanFilter(discrete_dynamics, measurement, R1, R2, MvNormal(T.(x0), T.(R1)); ny, nu, Ts)\n LowLevelParticleFilters.prediction_errors!(res, kf, u, y, p) \nend\n\nres_gn = optimize!(LeastSquaresProblem(x = copy(p_guess), f! = residuals!, output_length = length(y)*ny, autodiff = :forward), LevenbergMarquardt())\n\np_opt_gn = res_gn.minimizer\nnorm(p_true - p_opt_gn) / norm(p_true)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Gauss-Newton algorithms are often more efficient at sum-of-squares minimization than the more generic BFGS optimizer. This form of Gauss-Newton optimization of prediction errors is also available through ControlSystemIdentification.jl, which uses this package undernath the hood.","category":"page"},{"location":"parameter_estimation/#Identifiability","page":"Parameter estimation","title":"Identifiability","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"There is no guarantee that we will recover the true parameters for this system, especially not if the input excitation is poor, but we will generally find parameters that results in a good predictor for the system (this is after all what we're optimizing for). A tool like StructuralIdentifiability.jl may be used to determine the identifiability of parameters and state variables, something that for this system could look like","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using StructuralIdentifiability\n\node = @ODEmodel(\n h1'(t) = -a1/A1 * h1(t) + a3/A1*h3(t) + gam*k1/A1 * u1(t),\n h2'(t) = -a2/A2 * h2(t) + a4/A2*h4(t) + gam*k2/A2 * u2(t),\n h3'(t) = -a3/A3*h3(t) + (1-gam)*k2/A3 * u2(t),\n h4'(t) = -a4/A4*h4(t) + (1-gam)*k1/A4 * u1(t),\n\ty1(t) = h1(t),\n y2(t) = h2(t),\n)\n\nlocal_id = assess_local_identifiability(ode, 0.99)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"where we have made the substitution sqrt h rightarrow h due to a limitation of the tool. The output of the above analysis is ","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"julia> local_id = assess_local_identifiability(ode, 0.99)\nDict{Nemo.fmpq_mpoly, Bool} with 15 entries:\n a3 => 0\n gam => 1\n k2 => 0\n A4 => 0\n h4 => 0\n h2 => 1\n A3 => 0\n a1 => 0\n A2 => 0\n k1 => 0\n a4 => 0\n h3 => 0\n h1 => 1\n A1 => 0\n a2 => 0","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"indicating that we can not hope to resolve all of the parameters. However, using appropriate regularization from prior information, we might still recover a lot of information about the system. Regularization could easily be added to the function cost above, e.g., using a penalty like (p-p_guess)'Γ*(p-p_guess) for some matrix Gamma, to indicate our confidence in the initial guess.","category":"page"},{"location":"parameter_estimation/#Videos","page":"Parameter estimation","title":"Videos","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Examples of parameter estimation are available here","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"By using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Estimation of time-varying parameters:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Adaptive control by means of estimation of time-varying parameters:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"","category":"page"},{"location":"neural_network/#Adaptive-Neural-Network-training","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"In this example, we will demonstrate how we can take the estimation of time-varying parameters to the extreme, and use a nonlinear state estimator to estimate the weights in a neural-network model of a dynamical system. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"In the tutorial Joint state and parameter estimation, we demonstrated how we can add a parameter as a state variable and let the state estimator estimate this alongside the state. In this example, we will try to learn an entire black-box model of the system dynamics using a neural network, and treat the network weights as time-varying parameters by adding them to the state.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We start by generating some data from a simple dynamical system, we will continue to use the quadruple-tank system from Joint state and parameter estimation.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"using LowLevelParticleFilters, Lux, Random, SeeToDee, StaticArrays, Plots, LinearAlgebra, ComponentArrays, DifferentiationInterface, SparseMatrixColorings\nusing SparseConnectivityTracer: TracerSparsityDetector\nusing DisplayAs # hide\n\nusing LowLevelParticleFilters: SimpleMvNormal\n\nfunction quadtank(h,u,p,t)\n kc = 0.5\n k1, k2, g = 1.6, 1.6, 9.81\n A1 = A3 = A2 = A4 = 4.9\n a1, a3, a2, a4 = 0.03, 0.03, 0.03, 0.03\n γ1, γ2 = 0.2, 0.2\n\n if t > 2000\n a1 *= 1.5 # Change the parameter at t = 2000\n end\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n\n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n ]\nend\n\nTs = 30 # sample time\ndiscrete_dynamics = SeeToDee.Rk4(quadtank, Ts) # Discretize dynamics\nnu = 2 # number of control inputs\nnx = 4 # number of state variables\nny = 4 # number of measured outputs\n\nfunction generate_data() \n measurement(x,u,p,t) = x#SA[x[1], x[2]]\n Tperiod = 200\n t = 0:Ts:4000\n u = vcat.((0.25 .* sign.(sin.(2pi/Tperiod .* t)) .+ 0.25) .* sqrt.(rand.()))\n u = SVector{nu, Float32}.(vcat.(u,u))\n x0 = Float32[2,2,3,3]\n x = LowLevelParticleFilters.rollout(discrete_dynamics, x0, u)[1:end-1]\n y = measurement.(x, u, 0, 0)\n y = [Float32.(y .+ 0.01.*randn.()) for y in y] # Add some noise to the measurement\n\n (; x, u, y, nx, nu, ny, Ts)\nend\n\nrng = Random.default_rng()\nRandom.seed!(rng, 1)\ndata = generate_data()\nnothing # hide","category":"page"},{"location":"neural_network/#Neural-network-dynamics","page":"Adaptive Neural-Network training","title":"Neural network dynamics","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"Our neural network will be a small feedforward network built using the package Lux.jl. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"ni = ny + nu\nnhidden = 8\nconst model_ = Chain(Dense(ni, nhidden, tanh), Dense(nhidden, nhidden, tanh), Dense(nhidden, ny))","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"Since the network is rather small, we will train on the CPU only, this will be fast enough for this use case. We may extract the parameters of the network using the function Lux.setup, and convert them to a ComponentArray to make it easier to refer to different parts of the combined state vector.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"dev = cpu_device()\nps, st = Lux.setup(rng, model_) |> dev\nparr = ComponentArray(ps)\nnothing # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The dynamics of our black-box model will call the neural network to predict the next state given the current state and input. We bias the dynamics towards low frequencies by adding a multiple of the current state to the prediction of the next state, 0.95*x. We also add a small amount of weight decay to the parameters of the neural network for regularization, 0.995*p.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"function dynamics(out0, xp0, u, _, t)\n xp = ComponentArray(xp0, getaxes(s0))\n out = ComponentArray(out0, getaxes(s0))\n x = xp.x\n p = xp.p\n xp, _ = Lux.apply(model_, [x; u], p, st)\n @. out.x = 0.95f0*x+xp\n @. out.p = 0.995f0*p\n nothing\nend\n\n@views measurement(out, x, _, _, _) = out .= x[1:nx] # Assume measurement of the full state vector\nnothing # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"For simplicity, we have assumed here that we have access to measurements of the entire state vector of the original process. This is many times unrealistic, and if we do not have such access, we may instead augment the measured signals with delayed versions of themselves (sometimes called a delay embedding). This is a common technique in discrete-time system identification, used in e.g., ControlSystemIdentification.arx and subspaceid.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The initial state of the process x0 and the initial parameters of the neural network parr can now be concatenated to form the initial augmented state s0.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"x0 = Float32[2; 2; 3; 3]\ns0 = ComponentVector(; x=x0, p=parr)\nnothing # hide","category":"page"},{"location":"neural_network/#Kalman-filter-setup","page":"Adaptive Neural-Network training","title":"Kalman filter setup","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We will estimate the parameters using two different nonlinear Kalman filters, the ExtendedKalmanFilter and the UnscentedKalmanFilter. The covariance matrices for the filters, R1, R2, may be tuned such that we get the desired learning speed of the weights, where larger covariance for the network weights will allow for faster learning, but also more noise in the estimates. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"R1 = Diagonal([0.1ones(nx); 0.01ones(length(parr))]) .|> Float32\nR2 = Diagonal((1e-2)^2 * ones(ny)) .|> Float32\nnothing # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The ExtendedKalmanFilter uses Jacobians of the dynamics and measurement model, and if we do not provide those functions they will be automatically computed using ForwardDiff.jl. Since our Jacobians will be relatively large but sparse in this example, we will make use of the sparsity-aware features of DifferentiationInterface.jl in order to get efficient Jacobian computations. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"function Ajacfun(x,u,p,t) # Function that returns a function for the Jacobian of the dynamics\n # For large neural networks, it might be faster to use an OOP formulation with Zygote instead of ForwardDiff. Zygote does not handle the in-place version\n backend = AutoSparse(\n AutoForwardDiff(),\n # AutoZygote(),\n sparsity_detector=TracerSparsityDetector(),\n coloring_algorithm=GreedyColoringAlgorithm(),\n )\n out = similar(getdata(x))\n inner = (out,x)->dynamics(out,x,u,p,t)\n prep = prepare_jacobian(inner, out, backend, getdata(x))\n jac = one(eltype(x)) .* sparsity_pattern(prep)\n function (x,u,p,t)\n inner2 = (out,x)->dynamics(out,x,u,p,t)\n DifferentiationInterface.jacobian!(inner2, out, jac, prep, backend, x)\n end\nend\n\nAjac = Ajacfun(s0, data.u[1], nothing, 0)\n\nconst CJ_ = [I(nx) zeros(Float32, nx, length(parr))] # The jacobian of the measurement model is constant\nCjac(x,u,p,t) = CJ_\nnothing # hide","category":"page"},{"location":"neural_network/#Estimation","page":"Adaptive Neural-Network training","title":"Estimation","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We may now initialize our filters and perform the estimation. Here, we use the function forward_trajectory to perform filtering along the entire data trajectory at once, but we may use this in a streaming fashion as well, as more data becomes available in real time.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We plot the one-step ahead prediction of the outputs and compare to the \"measured\" data.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"ekf = ExtendedKalmanFilter(dynamics, measurement, R1, R2, SimpleMvNormal(s0, 100R1); nu, check=false, Ajac, Cjac, Ts)\nukf = UnscentedKalmanFilter(dynamics, measurement, R1, R2, SimpleMvNormal(s0, 100R1); nu, ny, Ts)\n\n@time sole = forward_trajectory(ekf, data.u, data.x)\n@time solu = forward_trajectory(ukf, data.u, data.x)\n\nplot(sole, plotx=false, plotxt=false, plotyh=true, plotyht=false, plotu=false, plote=true, name=\"EKF\", layout=(nx, 1), size=(1200, 1500))\nplot!(solu, plotx=false, plotxt=false, plotyh=true, plotyht=false, plotu=false, plote=true, name=\"UKF\", ploty=false)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We see that prediction errors, e, are large in the beginning when the network weights are randomly initialized, but after about half the trajectory the errors are significantly reduced. Just like in the tutorial Joint state and parameter estimation, we modified the true dynamics after some time, at t=2000, and we see that the filters are able to adapt to this change after a transient increase in prediction error variance.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We may also plot the evolution of the neural-network weights over time, and see how the filters adapt to the changing dynamics of the system.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"plot(\n plot(0:Ts:4000, reduce(hcat, sole.xt)'[:, nx+1:end], title=\"EKF parameters\"),\n plot(0:Ts:4000, reduce(hcat, solu.xt)'[:, nx+1:end], title=\"UKF parameters\"),\n legend = false,\n)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"neural_network/#Smoothing","page":"Adaptive Neural-Network training","title":"Smoothing","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"@time xTe,RTe = smooth(sole, ekf)\n@time xTu,RTu = smooth(solu, ukf)\nplot(\n plot(0:Ts:4000, reduce(hcat, xTe)'[:, nx+1:end], title=\"EKF parameters\", c=1, alpha=0.2),\n plot(0:Ts:4000, reduce(hcat, xTu)'[:, nx+1:end], title=\"UKF parameters\", c=1, alpha=0.2),\n legend = false,\n)","category":"page"},{"location":"neural_network/#Benchmarking","page":"Adaptive Neural-Network training","title":"Benchmarking","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The neural network used in this example has","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"length(parr)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"parameters, and the length of the data is","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"length(data.u)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"Performing the estimation using the Extended Kalman Filter took","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"using BenchmarkTools\n@btime forward_trajectory(ekf, data.u, data.x);\n # 46.034 ms (77872 allocations: 123.45 MiB)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"and with the Unscented Kalman Filter","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"@btime forward_trajectory(ukf, data.u, data.x);\n # 142.608 ms (2134370 allocations: 224.82 MiB)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The EKF is a bit faster, which is to be expected. Both methods are very fast from a neural-network training perspective, but the performance will not scale favorably to very large network sizes.","category":"page"},{"location":"neural_network/#Closing-remarks","page":"Adaptive Neural-Network training","title":"Closing remarks","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We have seen how to estimate train a black-box neural network dynamics model by treating the parameter estimation as a state-estimation problem. This example is very simple and leaves a lot of room for improvement, such as","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We assumed very little prior knowledge of the dynamics. In practice, we may want to model as much as possible from first principles and add a neural network to capture only the residuals that our first-principles model cannot capture.\nWe started the training of the network weights directly from a random initialization. In practice, we may want to pre-train the network on a large offline dataset before updating the weights adaptively in real-time.\nWe used forward-mode AD to compute the Jacobian. The Jacobian of the dynamics has dense rows, which means that it's theoretically favorable to use reverse-mode AD to compute it. This is possible using Zygote.jl, but Zygote does not handle array mutation, and one must thus avoid the in-place version of the dynamics. Since the number of parameters in this example is small, sparse forward mode AD ended up being slightly faster.","category":"page"},{"location":"adaptive_kalmanfilter/#Noise-adaptive-Kalman-filter","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Noise-adaptive Kalman filter","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"In this tutorial we will consider filtering of a 1D position track, similar in spirit to what one could have obtained from a GPS device, but limited to 1D for easier visualization. We will use a constant-velocity model, i.e., use a double integrator,","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"beginaligned\nx_k+1 = beginbmatrix 1 T_s 0 1 endbmatrix x_k + beginbmatrix T_s^22 T_s endbmatrix w_k \ny_k = beginbmatrix 1 0 endbmatrix x_k + v_k\nendaligned","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"where w_k sim mathcalN(0 σ_w) is the process noise, and v_k sim mathcalN(0 R_2) is the measurement noise, and illustrate how we can make use of an adaptive noise covariance to improve the filter performance.","category":"page"},{"location":"adaptive_kalmanfilter/#Data-generation","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Data generation","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"We start by generating some position data that we want to perform filtering on. The \"object\" we want to track is initially stationary, and transitions to moving with a constant velocity after a while. ","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"using LowLevelParticleFilters, Plots, Random\nRandom.seed!(1)\n\n# Create a time series for filtering\nx = [zeros(50); 0:100]\nT = length(x)\nY = x + randn(T)\nplot([Y x], lab=[\"Measurement\" \"True state to be tracked\"], c=[1 :purple])","category":"page"},{"location":"adaptive_kalmanfilter/#Simple-Kalman-filtering","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Simple Kalman filtering","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"We will use a Kalman filter to perform the filtering. The model is a double integrator, i.e., a constant-acceleration model. The state vector is thus x = p v^T, where p is the position and v is the velocity. When designing a Kalman filter, we need to specify the noise covariances R_1 and R_2. While it's often easy to measure the covariance of the measurement noise, R_2, it can be quite difficult to know ahead of time what the dynamics noise covariance, R_1, should be. In this example, we will use an adaptive filter, where we will increase the dynamics noise covariance if the filter prediction error is too large. However, we first run the filter twice, once with a large R_1 and once with a small R_1 to illustrate the difference.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"y = [[y] for y in Y] # create a vector of vectors for the KF\nu = fill([], T) # No inputs in this example :(\n\n# Define the model\nTs = 1\nA = [1 Ts; 0 1]\nB = zeros(2, 0)\nC = [1 0]\nD = zeros(0, 0)\nR2 = [1;;]\n\nσws = [1e-2, 1e-5] # Dynamics noise standard deviations\n\nfig = plot(Y, lab=\"Measurement\")\nfor σw in σws\n R1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts] # The dynamics noise covariance matrix is σw*Bw*Bw' where Bw = [Ts^2/2; Ts]\n kf = KalmanFilter(A, B, C, D, R1, R2)\n yh = []\n measure = LowLevelParticleFilters.measurement(kf)\n for t = 1:T # Main filter loop\n kf(u[t], y[t]) # Performs both prediction and correction\n xh = state(kf)\n yht = measure(xh, u[t], nothing, t)\n push!(yh, yht)\n end\n\n Yh = reduce(hcat, yh)\n plot!(Yh', lab=\"Estimate \\$σ_w\\$ = $σw\")\nend\nfig","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"When R_1 is small (controlled by σ_w), we get a nice and smooth filter estimate, but this estimate clearly lags behind the true state. When R_1 is large, the filter estimate is much more responsive, but it also has a lot of noise.","category":"page"},{"location":"adaptive_kalmanfilter/#Adaptive-noise-covariance","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Adaptive noise covariance","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Below, we will implement an adaptive filter, where we keep the dynamics noise covariance low by default, but increase it if the filter prediction error is too large. We will use a Z-score to determine if the prediction error is too large. The Z-score is defined as the number of standard deviations the prediction error is away from the estimated mean. This time around we use separate correct! and predict! calls, so that we can access the prediction error as well as the prior covariance of the prediction error, S. S (or the Cholesky factor Sᵪ) will be used to compute the Z-score.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"σw = 1e-5 # Set the covariance to a low value by default\nR1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts]\nkf = KalmanFilter(A, B, C, D, R1, R2)\nmeasure = LowLevelParticleFilters.measurement(kf)\n\n# Some arrays to store simulation data\nyh = []\nes = Float64[]\nσs = Float64[]\nfor t = 1:T # Main filter loop\n ll, e, S, Sᵪ = correct!(kf, u[t], y[t], nothing, t) # Manually call the prediction step\n σ = √(e'*(Sᵪ\\e)) # Compute the Z-score\n push!(es, e[]) # Save for plotting\n push!(σs, σ)\n if σ > 3 # If the Z-score is too high\n # we temporarily increase the dynamics noise covariance by 1000x to adapt faster\n predict!(kf, u[t], nothing, t; R1 = 1000kf.R1) \n else\n predict!(kf, u[t], nothing, t)\n end\n xh = state(kf)\n yht = measure(xh, u[t], nothing, t)\n push!(yh, yht)\nend\n\nYh = reduce(hcat, yh)\nplot([Y Yh'], lab=[\"Measurement\" \"Adaptive estimate\"])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Not too bad! This time the filter estimate is much more responsive during the transition, but exhibits favorable noise properties during the stationary phases. We can also plot the prediction error and the Z-score to see how the filter adapts to the dynamics noise covariance.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"plot([es σs], lab=[\"Prediction error\" \"Z-score\"])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Notice how the prediction errors, that should ideally be centered around zero, remain predominantly negative for a long time interval after the transition. This can be attributed to an overshoot in the velocity state of the estimator, but the rapid decrease of the covariance after the transition makes the filter slow at correcting its overshoot. If we want, we could mitigate this and make the adaptation even more sophisticated by letting the covariance remain large for a while after a transition in operating mode has been detected. Below, we implement a simple version of this, where we use a multiplier σ_wt that defaults to 1, but is increase to a very large value of 1000 if a transition is detected. When no transition is detected, σ_wt is decreased exponentially back down to 1.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"σw = 1e-5 # Set the covariance to a low value by default\nσwt = 1.0\nR1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts]\nkf = KalmanFilter(A, B, C, D, R1, R2)\nmeasure = LowLevelParticleFilters.measurement(kf)\n\n# Some arrays to store simulation data\nyh = []\nes = Float64[]\nσs = Float64[]\nσwts = Float64[]\nfor t = 1:T # Main filter loop\n global σwt # Note, do not make use of global variables in performance critical code\n ll, e, S, Sᵪ = correct!(kf, u[t], y[t], nothing, t) # Manually call the prediction step\n σ = √(e'*(Sᵪ\\e)) # Compute the Z-score\n push!(es, e[]) # Save for plotting\n push!(σs, σ)\n if σ > 3 # If the Z-score is too high\n σwt = 1000.0 # Set the R1 multiplier to a very large value\n else\n σwt = max(0.7σwt, 1.0) # Decrease exponentially back to 1\n end\n push!(σwts, σwt)\n predict!(kf, u[t], nothing, t; R1 = σwt*kf.R1) \n xh = state(kf)\n yht = measure(xh, u[t], nothing, t)\n push!(yh, yht)\nend\n\nYh = reduce(hcat, yh)\nplot([Y Yh'], lab=[\"Measurement\" \"Adaptive estimate\"])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"plot([es σs σwts], lab=[\"Prediction error\" \"Z-score\" \"\\$σ_{wt}\\$ multiplier\"], layout=2, sp=[1 1 2])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"This time, the prediction errors look more like white noise centered around zero after the initial transient caused by the transition.","category":"page"},{"location":"adaptive_kalmanfilter/#Summary","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Summary","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"This tutorial demonstrated simple Kalman filtering for a double integrator without control inputs. We saw how the filtering estimate could be improved by playing around with the covariance matrices of the estimator, helping it catch up to fast changes in the behavior of the system without sacrificing steady-state noise properties.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"In this case, we handled the modification of R_1 outside of the filter, implementing our own filtering loop. Some applications get away with instead providing time-varying matrices in the form of a 3-dimension array, where the third dimension corresponds to time, or instead of providing a matrix, providing a function R_1(x u p t) allows the matrix to be a function of state, input, parameters and time. These options apply to all matrices in the filter, including the dynamics matrices, ABCD.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Lastly, we mention the ability of the KalmanFilter to act like a recursive least-squares estimator, by setting the \"forgetting factor α1 when creating the KalmanFilter. α1 will cause the filter will exhibit exponential forgetting similar to an RLS estimator, in addition to the covariance inflation due to R1. It is thus possible to get a RLS-like algorithm by setting R_1 = 0 R_2 = 1α and α 1.","category":"page"},{"location":"adaptive_kalmanfilter/#Disturbance-modeling-and-noise-tuning","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Disturbance modeling and noise tuning","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"See this notebook for a blog post about disturbance modeling and noise tuning using LowLevelParticleFilter.jl","category":"page"},{"location":"dae/#State-estimation-for-high-index-DAEs","page":"State estimation for DAE systems","title":"State estimation for high-index DAEs","text":"","category":"section"},{"location":"dae/","page":"State estimation for DAE systems","title":"State estimation for DAE systems","text":"This tutorial is hosted as a notebook.","category":"page"},{"location":"measurement_models/#measurement_models","page":"Multiple measurement models","title":"Measurement models","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"The Kalman-type filters","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"KalmanFilter\nExtendedKalmanFilter\nUnscentedKalmanFilter","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"each come with their own built-in measurement model, e.g., the standard KalmanFilter uses the linear measurement model y = Cx + Du + e, while the ExtendedKalmanFilter and UnscentedKalmanFilter use the nonlinear measurement model y = h(xupt) + e or y = h(xupte). For covariance propagation, the ExtendedKalmanFilter uses linearization to approximate the nonlinear measurement model, while the UnscentedKalmanFilter uses the unscented transform.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"It is sometimes useful to mix and match dynamics and measurement models. For example, using the unscented transform from the UKF for the dynamics update (predict!), but the linear measurement model from the standard KalmanFilter for the measurement update (correct!) if the measurement model is linear.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"This is possible by constructing a filter with an explicitly created measurement model. The available measurement models are","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"LinearMeasurementModel performs linear propagation of covariance (as is done in KalmanFilter).\nEKFMeasurementModel uses linearization to propagate covariance (as is done in ExtendedKalmanFilter).\nUKFMeasurementModel uses the unscented transform to propagate covariance (as is done in UnscentedKalmanFilter).\nCompositeMeasurementModel combines multiple measurement models.","category":"page"},{"location":"measurement_models/#Constructing-a-filter-with-a-custom-measurement-model","page":"Multiple measurement models","title":"Constructing a filter with a custom measurement model","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"Constructing a Kalman-type filter automatically creates a measurement model of the corresponding type, given the functions/matrices passed to the filter constructor. To construct a filter with a non-standard measurement model, e.g., and UKF with a KF measurement model, manually create the desired measurement model and pass it as the second argument to the constructor. For example, to construct an UKF with a linear measurement model, we do","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"using LowLevelParticleFilters, LinearAlgebra\nnx = 100 # Dimension of state\nnu = 2 # Dimension of input\nny = 90 # Dimension of measurements\n\n# Define linear state-space system\nconst __A = 0.1*randn(nx, nx)\nconst __B = randn(nx, nu)\nconst __C = randn(ny,nx)\nfunction dynamics_ip(dx,x,u,p,t)\n # __A*x .+ __B*u\n mul!(dx, __A, x)\n mul!(dx, __B, u, 1.0, 1.0)\n nothing\nend\nfunction measurement_ip(y,x,u,p,t)\n # __C*x\n mul!(y, __C, x)\n nothing\nend\n\nR1 = I(nx)\nR2 = I(ny)\n\nmm_kf = LinearMeasurementModel(__C, 0, R2; nx, ny)\nukf = UnscentedKalmanFilter(dynamics_ip, mm_kf, R1; ny, nu)","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"When we create the filter with the custom measurement model, we do not pass the arguments that are associated with the measurement model to the filter constructor, i.e., we do not pass any measurement function, and not the measurement covariance matrix R_2.","category":"page"},{"location":"measurement_models/#Sensor-fusion:-Using-several-different-measurement-models","page":"Multiple measurement models","title":"Sensor fusion: Using several different measurement models","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"Above we constructed a filter with a custom measurement model, we can also pass a custom measurement model when we call correct!. This may be useful when, e.g., performing sensor fusion with sensors operating at different sample rates, or when parts of the measurement model are linear, and other parts are nonlinear.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"The following example instantiates three different filters and three different measurement models. Each filter is updated with each measurement model, demonstrating that any combination of filter and measurement model can be used together.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"using LowLevelParticleFilters, LinearAlgebra\nnx = 10 # Dimension of state\nnu = 2 # Dimension of input\nny = 9 # Dimension of measurements\n\n# Define linear state-space system\nconst __A = 0.1*randn(nx, nx)\nconst __B = randn(nx, nu)\nconst __C = randn(ny,nx)\nfunction dynamics_ip(dx,x,u,p,t)\n # __A*x .+ __B*u\n mul!(dx, __A, x)\n mul!(dx, __B, u, 1.0, 1.0)\n nothing\nend\nfunction measurement_ip(y,x,u,p,t)\n # __C*x\n mul!(y, __C, x)\n nothing\nend\n\nR1 = I(nx) # Covariance matrices\nR2 = I(ny)\n\n# Construct three different filters\nkf = KalmanFilter(__A, __B, __C, 0, R1, R2)\nukf = UnscentedKalmanFilter(dynamics_ip, measurement_ip, R1, R2; ny, nu)\nekf = ExtendedKalmanFilter(dynamics_ip, measurement_ip, R1, R2; nu)\n\n# Simulate some data\nT = 200 # Number of time steps\nU = [randn(nu) for _ in 1:T]\nx,u,y = LowLevelParticleFilters.simulate(kf, U) # Simulate trajectory using the model in the filter\n\n# Construct three different measurement models\nmm_kf = LinearMeasurementModel(__C, 0, R2; nx, ny)\nmm_ekf = EKFMeasurementModel{Float64, true}(measurement_ip, R2; nx, ny)\nmm_ukf = UKFMeasurementModel{Float64, true, false}(measurement_ip, R2; nx, ny)\n\n\nmms = [mm_kf, mm_ekf, mm_ukf]\nfilters = [kf, ekf, ukf]\n\nfor mm in mms, filter in filters\n @info \"Updating $(nameof(typeof(filter))) with measurement model $(nameof(typeof(mm)))\"\n correct!(filter, mm, u[1], y[1]) # Pass the measurement model as the second argument to the correct! function if not using the measurement model built into the filter\nend\nnothing # hide","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"Since the dynamics in this particular example is in fact linear, we should get identical results for all three filters.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"using Test\n@test kf.x ≈ ekf.x ≈ ukf.x\n@test kf.R ≈ ekf.R ≈ ukf.R","category":"page"},{"location":"measurement_models/#Video-tutorial","page":"Multiple measurement models","title":"Video tutorial","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"A video demonstrating the use of multiple measurement models in a sensor-fusion context is available on YouTube:","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"","category":"page"},{"location":"api/#Exported-functions-and-types","page":"API","title":"Exported functions and types","text":"","category":"section"},{"location":"api/#Index","page":"API","title":"Index","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"","category":"page"},{"location":"api/","page":"API","title":"API","text":"Modules = [LowLevelParticleFilters]\nPrivate = false","category":"page"},{"location":"api/#LowLevelParticleFilters.AdvancedParticleFilter-Tuple{Integer, Function, Function, Any, Any, Any}","page":"API","title":"LowLevelParticleFilters.AdvancedParticleFilter","text":"AdvancedParticleFilter(N::Integer, dynamics::Function, measurement::Function, measurement_likelihood, dynamics_density, initial_density; p = NullParameters(), threads = false, kwargs...)\n\nThis type represents a standard particle filter but affords extra flexibility compared to the ParticleFilter type, e.g., non-additive noise in the dynamics and measurement functions.\n\nSee the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#AdvancedParticleFilter-1\n\nArguments:\n\nN: Number of particles\ndynamics: A discrete-time dynamics function (x, u, p, t, noise=false) -> x⁺. It's important that the noise argument defaults to false.\nmeasurement: A measurement function (x, u, p, t, noise=false) -> y. It's important that the noise argument defaults to false.\nmeasurement_likelihood: A function (x, u, y, p, t)->logl to evaluate the log-likelihood of a measurement.\ndynamics_density: This field is not used by the advanced filter and can be set to nothing.\ninitial_density: The distribution of the initial state.\nthreads: use threads to propagate particles in parallel. Only activate this if your dynamics is thread-safe. SeeToDee.SimpleColloc is not thread-safe by default due to the use of internal caches, but SeeToDee.Rk4 is.\n\nExtended help\n\nMultiple measurement models\n\nThe measurement_likelihood function is used to evaluate the likelihood of a measurement. If you have multiple sensors and want to perform individual correct! steps for each, call correct!(..., g = custom_likelihood_function).\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.AuxiliaryParticleFilter-Tuple","page":"API","title":"LowLevelParticleFilters.AuxiliaryParticleFilter","text":"AuxiliaryParticleFilter(args...; kwargs...)\n\nTakes exactly the same arguments as ParticleFilter, or an instance of ParticleFilter.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.CompositeMeasurementModel-Tuple{Any, Vararg{Any}}","page":"API","title":"LowLevelParticleFilters.CompositeMeasurementModel","text":"CompositeMeasurementModel(model1, model2, ...)\n\nA composite measurement model that combines multiple measurement models. This model acts as all component models concatenated. The tuple returned from correct! will be\n\nll: The sum of the log-likelihood of all component models\ne: The concatenated innovation vector\nS: A vector of the innovation covariance matrices of the component models\nSᵪ: A vector of the Cholesky factorizations of the innovation covariance matrices of the component models\nK: A vector of the Kalman gains of the component models\n\nIf all sensors operate on at the same rate, and all measurement models are of the same type, it's more efficient to use a single measurement model with a vector-valued measurement function.\n\nFields:\n\nmodels: A tuple of measurement models\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.EKFMeasurementModel-Union{Tuple{IPM}, NTuple{4, Any}, NTuple{5, Any}} where IPM","page":"API","title":"LowLevelParticleFilters.EKFMeasurementModel","text":"EKFMeasurementModel{IPM}(measurement, R2, ny, Cjac, cache = nothing)\n\nA measurement model for the Extended Kalman Filter.\n\nArguments:\n\nIPM: A boolean indicating if the measurement function is inplace\nmeasurement: The measurement function y = h(x, u, p, t)\nR2: The measurement noise covariance matrix\nny: The number of measurement variables\nCjac: The Jacobian of the measurement function Cjac(x, u, p, t). If none is provided, ForwardDiff will be used.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.EKFMeasurementModel-Union{Tuple{M}, Tuple{IPM}, Tuple{T}, Tuple{M, Any}} where {T, IPM, M}","page":"API","title":"LowLevelParticleFilters.EKFMeasurementModel","text":"EKFMeasurementModel{T,IPM}(measurement::M, R2; nx, ny, Cjac = nothing)\n\nT is the element type used for arrays\nIPM is a boolean indicating if the measurement function is inplace\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.ExtendedKalmanFilter","page":"API","title":"LowLevelParticleFilters.ExtendedKalmanFilter","text":"ExtendedKalmanFilter(kf, dynamics, measurement; Ajac, Cjac)\nExtendedKalmanFilter(dynamics, measurement, R1,R2,d0=MvNormal(Matrix(R1)); nu::Int, p = NullParameters(), α = 1.0, check = true)\n\nA nonlinear state estimator propagating uncertainty using linearization.\n\nThe constructor to the extended Kalman filter takes dynamics and measurement functions, and either covariance matrices, or a KalmanFilter. If the former constructor is used, the number of inputs to the system dynamics, nu, must be explicitly provided with a keyword argument.\n\nBy default, the filter will internally linearize the dynamics using ForwardDiff. User provided Jacobian functions can be provided as keyword arguments Ajac and Cjac. These functions should have the signature (x,u,p,t)::AbstractMatrix where x is the state, u is the input, p is the parameters, and t is the time.\n\nThe dynamics and measurement function are on the following form\n\nx(t+1) = dynamics(x, u, p, t) + w\ny = measurement(x, u, p, t) + e\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0\n\nSee also UnscentedKalmanFilter which is typically more accurate than ExtendedKalmanFilter. See KalmanFilter for detailed instructions on how to set up a Kalman filter kf.\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.IMM-Tuple{Any, AbstractMatrix, AbstractVector}","page":"API","title":"LowLevelParticleFilters.IMM","text":"IMM(models, P, μ; check = true, p = NullParameters(), interact = true)\n\nInteracting Multiple Model (IMM) filter. This filter is a combination of multiple Kalman-type filters, each with its own state and covariance. The IMM filter is a probabilistically weighted average of the states and covariances of the individual filters. The weights are determined by the probability matrix P and the mixing probabilities μ.\n\nwarning: Experimental\nThis filter is currently considered experimental and the user interface may change in the future without respecting semantic versioning.\n\nIn addition to the predict! and correct! steps, the IMM filter has an interact! method that updates the states and covariances of the individual filters based on the mixing probabilities. The combine! method combines the states and covariances of the individual filters into a single state and covariance. These four functions are typically called in either of the orders\n\ncorrect!, combine!, interact!, predict! (as is done in update!)\ninteract!, predict!, correct!, combine! (as is done in the reference cited below)\n\nThese two orders are cyclic permutations of each other, and the order used in update! is chosen to align with the order used in the other filters, where the initial condition is corrected using the first measurement, i.e., we assume the first measurement updates x(0-1) to x(00).\n\nThe initial (combined) state and covariance of the IMM filter is made up of the weighted average of the states and covariances of the individual filters. The weights are the initial mixing probabilities μ.\n\nRef: \"Interacting multiple model methods in target tracking: a survey\", E. Mazor; A. Averbuch; Y. Bar-Shalom; J. Dayan\n\nArguments:\n\nmodels: An array of Kalman-type filters, such as KalmanFilter, ExtendedKalmanFilter, UnscentedKalmanFilter, etc. The state of each model must have the same meaning, such that forming a weighted average makes sense.\nP: The mode-transition probability matrix. P[i,j] is the probability of transitioning from mode i to mode j (each row must sum to one).\nμ: The initial mixing probabilities. μ[i] is the probability of being in mode i at the initial contidion (must sum to one).\ncheck: If true, check that the inputs are valid. If false, skip the checks.\np: Parameters for the filter. NOTE: this p is shared among all internal filters. The internal p of each filter will be overridden by this one.\ninteract: If true, the filter will run the interaction as part of update! and forward_trajectory. If false, the filter will not run the interaction step. This choice can be overridden by passing the keyword argument interact to the respective functions.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.KalmanFilter","page":"API","title":"LowLevelParticleFilters.KalmanFilter","text":"KalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1, check=true)\n\nThe matrices A,B,C,D define the dynamics\n\nx' = Ax + Bu + w\ny = Cx + Du + e\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0\n\nThe matrices can be time varying such that, e.g., A[:, :, t] contains the A matrix at time index t. They can also be given as functions on the form\n\nAfun(x, u, p, t) -> A\n\nFor maximum performance, provide statically sized matrices from StaticArrays.jl\n\nα is an optional \"forgetting factor\", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to R_1, exhibit \"exponential forgetting\" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting R_1=0 R_2 = 1α and α 1 (α is the inverse of the traditional RLS parameter α = 1λ). The exact form of the covariance update is\n\nR(t+1t) = α AR(t)A^T + R_1\n\nIf check = true (default) the function will check that the eigenvalues of A are less than 2 in absolute value. Large eigenvalues may be an indication that the system matrices are representing a continuous-time system and the user has forgotten to discretize it. Turn off this check by setting check = false.\n\nTutorials on Kalman filtering\n\nThe tutorial \"How to tune a Kalman filter\" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model. See also the tutorial in the documentation\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.KalmanFilteringSolution","page":"API","title":"LowLevelParticleFilters.KalmanFilteringSolution","text":"KalmanFilteringSolution{Tx,Txt,TR,TRt,Tll} <: AbstractFilteringSolution\n\nFields\n\nx: predictions x(t+1t) (plotted if plotx=true)\nxt: filtered estimates x(tt) (plotted if plotxt=true)\nR: predicted covariance matrices R(t+1t) (plotted if plotR=true)\nRt: filter covariances R(tt) (plotted if plotRt=true)\nll: loglikelihood\ne: prediction errors e(tt-1) = y - y(tt-1) (plotted if plote=true)\n\nPlot\n\nThe solution object can be plotted\n\nplot(sol, plotx=true, plotxt=true, plotR=true, plotRt=true, plote=true, plotu=true, ploty=true, plotyh=true, plotyht=true, name=\"\")\n\nwhere\n\nplotx: Plot the predictions x(t|t-1)\nplotxt: Plot the filtered estimates x(t|t)\nplotR: Plot the predicted covariances R(t|t-1) as ribbons at ±2σ (1.96 σ to be precise)\nplotRt: Plot the filter covariances R(t|t) as ribbons at ±2σ (1.96 σ to be precise)\nplote: Plot the prediction errors e(t|t-1) = y - ŷ(t|t-1)\nplotu: Plot the input\nploty: Plot the measurements\nplotyh: Plot the predicted measurements ŷ(t|t-1)\nplotyht: Plot the filtered measurements ŷ(t|t)\nname: a string that is prepended to the labels of the plots, which is useful when plotting multiple solutions in the same plot.\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.LinearMeasurementModel","page":"API","title":"LowLevelParticleFilters.LinearMeasurementModel","text":"LinearMeasurementModel{CT, DT, RT, CAT}\n\nA linear measurement model y = C*x + D*u + e.\n\nFields:\n\nC \nD\nR2: The measurement noise covariance matrix\nny: The number of measurement variables\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.ParticleFilter-Tuple{Integer, Function, Function, Any, Any, Any}","page":"API","title":"LowLevelParticleFilters.ParticleFilter","text":"ParticleFilter(N::Integer, dynamics, measurement, dynamics_density, measurement_density, initial_density; threads = false, p = NullParameters(), kwargs...)\n\nSee the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#Particle-filter-1\n\nArguments:\n\nN: Number of particles\ndynamics: A discrete-time dynamics function (x, u, p, t) -> x⁺\nmeasurement: A measurement function (x, u, p, t) -> y\ndynamics_density: A probability-density function for additive noise in the dynamics. Use AdvancedParticleFilter for non-additive noise.\nmeasurement_density: A probability-density function for additive measurement noise. Use AdvancedParticleFilter for non-additive noise.\ninitial_density: Distribution of the initial state.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.ParticleFilteringSolution","page":"API","title":"LowLevelParticleFilters.ParticleFilteringSolution","text":"ParticleFilteringSolution{F, Tu, Ty, Tx, Tw, Twe, Tll} <: AbstractFilteringSolution\n\nFields:\n\nf: The filter used to produce the solution.\nu: Input\ny: Output / measurements\nx: Particles, the size of this array is (N,T), where N is the number of particles and T is the number of time steps. Each element represents a weighted state hypothesis with weight given by we.\nw: Weights (log space). These are used for internal computations.\nwe: Weights (exponentiated / original space). These are the ones to use to compute weighted means etc., they sum to one for each time step.\nll: Log likelihood\n\nPlot\n\nThe solution object can be plotted\n\nplot(sol; nbinsy=30, xreal=nothing, dim=nothing, ploty=true)\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.SqKalmanFilter","page":"API","title":"LowLevelParticleFilters.SqKalmanFilter","text":"SqKalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1)\n\nA standard Kalman filter on square-root form. This filter may have better numerical performance when the covariance matrices are ill-conditioned.\n\nThe matrices A,B,C,D define the dynamics\n\nx' = Ax + Bu + w\ny = Cx + Du + e\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0\n\nThe matrices can be time varying such that, e.g., A[:, :, t] contains the A matrix at time index t. They can also be given as functions on the form\n\nAfun(x, u, p, t) -> A\n\nThe internal fields storing covariance matrices are for this filter storing the upper-triangular Cholesky factor.\n\nα is an optional \"forgetting factor\", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to R_1, exhibit \"exponential forgetting\" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting R_1=0 R_2 = 1α and α 1 (α is the inverse of the traditional RLS parameter α = 1λ). The form of the covariance update is\n\nR(t+1t) = α AR(t)A^T + R_1\n\nRef: \"A Square-Root Kalman Filter Using Only QR Decompositions\", Kevin Tracy https://arxiv.org/abs/2208.06452\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.UKFMeasurementModel-Union{Tuple{AUGM}, Tuple{IPM}, NTuple{8, Any}, NTuple{9, Any}} where {IPM, AUGM}","page":"API","title":"LowLevelParticleFilters.UKFMeasurementModel","text":"UKFMeasurementModel{inplace_measurement,augmented_measurement}(measurement, R2, ny, ne, innovation, mean, cov, cross_cov, cache = nothing)\n\nA measurement model for the Unscented Kalman Filter.\n\nArguments:\n\nmeasurement: The measurement function y = h(x, u, p, t)\nR2: The measurement noise covariance matrix\nny: The number of measurement variables\nne: If augmented_measurement is true, the number of measurement noise variables\ninnovation(y::AbstractVector, yh::AbstractVector) where the arguments represent (measured output, predicted output)\nmean(ys::AbstractVector{<:AbstractVector}): computes the mean of the vector of vectors of output sigma points.\ncov(ys::AbstractVector{<:AbstractVector}, y::AbstractVector): computes the covariance matrix of the output sigma points.\ncross_cov(xs::AbstractVector{<:AbstractVector}, x::AbstractVector, ys::AbstractVector{<:AbstractVector}, y::AbstractVector) where the arguments represents (state sigma points, mean state, output sigma points, mean output). The function should return the cross-covariance matrix between the state and output sigma points.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.UKFMeasurementModel-Union{Tuple{AUGM}, Tuple{IPM}, Tuple{T}, Tuple{Any, Any}} where {T, IPM, AUGM}","page":"API","title":"LowLevelParticleFilters.UKFMeasurementModel","text":"UKFMeasurementModel{T,IPM,AUGM}(measurement, R2; nx, ny, ne = nothing, innovation = -, mean = safe_mean, cov = safe_cov, cross_cov = cross_cov, static = nothing)\n\nT is the element type used for arrays\nIPM is a boolean indicating if the measurement function is inplace\nAUGM is a boolean indicating if the measurement model is augmented\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.UnscentedKalmanFilter-Union{Tuple{AUGM}, Tuple{AUGD}, Tuple{IPM}, Tuple{IPD}, Tuple{Any, LowLevelParticleFilters.AbstractMeasurementModel, Any}, Tuple{Any, LowLevelParticleFilters.AbstractMeasurementModel, Any, Any}} where {IPD, IPM, AUGD, AUGM}","page":"API","title":"LowLevelParticleFilters.UnscentedKalmanFilter","text":"UnscentedKalmanFilter(dynamics, measurement, R1, R2, d0=MvNormal(Matrix(R1)); p = NullParameters(), ny, nu)\nUnscentedKalmanFilter{IPD,IPM,AUGD,AUGM}(dynamics, measurement_model::AbstractMeasurementModel, R1, d0=SimpleMvNormal(R1); p=NullParameters(), nu)\n\nA nonlinear state estimator propagating uncertainty using the unscented transform.\n\nThe dynamics and measurement function are on either of the following forms\n\nx' = dynamics(x, u, p, t) + w\ny = measurement(x, u, p, t) + e\n\nx' = dynamics(x, u, p, t, w)\ny = measurement(x, u, p, t, e)\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0. The former (default) assums that the noise is additive and added after the dynamics and measurement updates, while the latter assumes that the dynamics functions take an additional argument corresponding to the noise term. The latter form (sometimes refered to as the \"augmented\" form) is useful when the noise is multiplicative or when the noise is added before the dynamics and measurement updates. See \"Augmented UKF\" below for more details on how to use this form.\n\nThe matrices R1, R2 can be time varying such that, e.g., R1[:, :, t] contains the R_1 matrix at time index t. They can also be given as functions on the form\n\nRfun(x, u, p, t) -> R\n\nFor maximum performance, provide statically sized matrices from StaticArrays.jl\n\nny, nu indicate the number of outputs and inputs.\n\nCustom type of u\n\nThe input u may be of any type, e.g., a named tuple or a custom struct. The u provided in the input data is passed directly to the dynamics and measurement functions, so as long as the type is compatible with the dynamics it will work out. The one exception where this will not work is when calling simulate, which assumes that u is an array.\n\nAugmented UKF\n\nIf the noise is not additive, one may use the augmented form of the UKF. In this form, the dynamics functions take additional input arguments that correspond to the noise terms. To enable this form, the typed constructor\n\nUnscentedKalmanFilter{inplace_dynamics,inplace_measurement,augmented_dynamics,augmented_measurement}(...)\n\nis used, where the Boolean type parameters have the following meaning\n\ninplace_dynamics: If true, the dynamics function operates in-place, i.e., it modifies the first argument in dynamics(dx, x, u, p, t). Default is false.\ninplace_measurement: If true, the measurement function operates in-place, i.e., it modifies the first argument in measurement(y, x, u, p, t). Default is false.\naugmented_dynamics: If true the dynamics function is augmented with an additional noise input w, i.e., dynamics(x, u, p, t, w). Default is false.\naugmented_measurement: If true the measurement function is agumented with an additional noise input e, i.e., measurement(x, u, p, t, e). Default is false. (If the measurement noise has fewer degrees of freedom than the number of measurements, you may failure in Cholesky factorizations, see \"Custom Cholesky factorization\" below).\n\nUse of augmented dynamics incurs extra computational cost. The number of sigma points used is 2L+1 where L is the length of the augmented state vector. Without augmentation, L = nx, with augmentation L = nx + nw and L = nx + ne for dynamics and measurement, respectively.\n\nSigma-point rejection\n\nFor problems with challenging dynamics, a mechanism for rejection of sigma points after the dynamics update is provided. A function reject(x) -> Bool can be provided through the keyword argument reject that returns true if a sigma point for x(t+1) should be rejected, e.g., if an instability or non-finite number is detected. A rejected point is replaced by the propagated mean point (the mean point cannot be rejected). This function may be provided either to the constructor of the UKF or passed to the predict! function.\n\nCustom measurement models\n\nBy default, standard arithmetic mean and e(y, yh) = y - yh are used as mean and innovation functions.\n\nBy passing and explicitly created UKFMeasurementModel, one may provide custom functions that compute the mean, the covariance and the innovation. This is useful in situations where the state or a measurement lives on a manifold. One may further override the mean and covariance functions for the state sigma points by passing the keyword arguments state_mean and state_cov to the constructor.\n\nstate_mean(xs::AbstractVector{<:AbstractVector}) computes the mean of the vector of vectors of state sigma points.\nstate_cov(xs::AbstractVector{<:AbstractVector}, m = mean(xs)) where the first argument represent state sigma points and the second argument, which must be optional, represents the mean of those points. The function should return the covariance matrix of the state sigma points.\n\nSee UKFMeasurementModel for more details on how to set up a custom measurement model. Pass the custom measurement model as the second argument to the UKF constructor.\n\nCustom Cholesky factorization\n\nThe UnscentedKalmanFilter supports providing a custom function to compute the Cholesky factorization of the covariance matrices for use in sigma-point generation.\n\nIf either of the following conditions are met, you may experience failure in internal Cholesky factorizations:\n\nThe dynamics noise or measurement noise covariance matrices (R_1 R_2) are singular\nThe measurement is augmented and the measurement noise has fewer degrees of freedom than the number of measurements\n(Under specific technical conditions) The dynamics is augmented and the dynamics noise has fewer degrees of freedom than the number of state variables. The technical conditions are easiest to understand in the linear-systems case, where it corresponds to the Riccati equation associated with the Kalman gain not having a solution. This may happen when the pair (A R1) has uncontrollable modes on the unit circle, for example, when there are integrating modes that are not affected through the noise.\n\nThe error message may look like\n\nERROR: PosDefException: matrix is not positive definite; Factorization failed.\n\nIn such situations, it is advicable to reconsider the noise model and covariance matrices, alternatively, you may provide a custom Cholesky factorization function to the UKF constructor through the keyword argument cholesky!. The function should have the signature cholesky!(A::AbstractMatrix)::Cholesky. A useful alternative factorizaiton when covariance matrices are expected to be singular is cholesky! = R->cholesky!(Positive, Matrix(R)) where the \"positive\" Cholesky factorization is provided by the package PositiveFactorizations.jl, which must be manually installed and loaded by the user.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.combine!-Tuple{IMM}","page":"API","title":"LowLevelParticleFilters.combine!","text":"combine!(imm::IMM)\n\nCombine the models of the IMM filter into a single state imm.x and covariance imm.R. This is done by taking a weighted average of the states and covariances of the individual models, where the weights are the mixing probabilities μ.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.commandplot","page":"API","title":"LowLevelParticleFilters.commandplot","text":"commandplot(pf, u, y, p=parameters(pf); kwargs...)\n\nProduce a helpful plot. For customization options (kwargs...), see ?pplot. After each time step, a command from the user is requested.\n\nq: quit\ns n: step n steps\n\nnote: Note\nThis function requires using Plots to be called before it is used.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!","page":"API","title":"LowLevelParticleFilters.correct!","text":"(; ll, e, S, Sᵪ, K) = correct!(kf::AbstractKalmanFilter, u, y, p = parameters(kf), t::Integer = index(kf), R2)\n\nThe correct step for a Kalman filter returns not only the log likelihood ll and the prediction error e, but also the covariance of the output S, its Cholesky factor Sᵪ and the Kalman gain K.\n\nIf R2 stored in kf is a function R2(x, u, p, t), this function is evaluated at the state before the correction is performed. The measurement noise covariance matrix R2 stored in the filter object can optionally be overridden by passing the argument R2, in this case R2 must be a matrix.\n\nExtended help\n\nTo perform separate measurement updates for different sensors, see the \"Measurement models\" in the documentation.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!-2","page":"API","title":"LowLevelParticleFilters.correct!","text":"ll, e = correct!(pf, u, y, p = parameters(f), t = index(f))\n\nUpdate state/weights based on measurement y, returns log-likelihood and prediction error (the error is always 0 for particle filters).\n\nExtended help\n\nTo perform separate measurement updates for different sensors, see the \"Measurement models\" in the documentation. For AdvancedParticleFilter, this can be realized by passing a custom measurement_likelihood function as the keyword argument g to correct!, or by calling the lower-level function measurement_equation! with a custom measurement_likelihood.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!-3","page":"API","title":"LowLevelParticleFilters.correct!","text":"correct!(kf::SqKalmanFilter, u, y, p = parameters(kf), t::Real = index(kf); R2 = get_mat(kf.R2, kf.x, u, p, t))\n\nFor the square-root Kalman filter, a custom provided R2 must be the upper triangular Cholesky factor of the covariance matrix of the measurement noise.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!-Tuple{IMM, Any, Any, Vararg{Any}}","page":"API","title":"LowLevelParticleFilters.correct!","text":"ll, lls, rest = correct!(imm::IMM, u, y, args; kwargs)\n\nThe correct step of the IMM filter corrects each model with the measurements y and control input u. The mixing probabilities imm.μ are updated based on the likelihood of each model given the measurements and the transition probability matrix P.\n\nThe returned tuple consists of the sum of the log-likelihood of all models, the vector of individual log-likelihoods and an array of the rest of the return values from the correct step of each model.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.correct!-Tuple{UnscentedKalmanFilter, Any, Any, Any, Real}","page":"API","title":"LowLevelParticleFilters.correct!","text":"correct!(ukf::UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, u, y, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R2 = get_mat(ukf.R2, ukf.x, u, p, t), mean, cross_cov, innovation)\n\nThe correction step for an UnscentedKalmanFilter allows the user to override, R2, mean, cross_cov, innovation.\n\nArguments:\n\nu: The input\ny: The measurement\np: The parameters\nt: The current time\nR2: The measurement noise covariance matrix, or a function that returns the covariance matrix (x,u,p,t)->R2.\nmean: The function that computes the mean of the output sigma points.\ncross_cov: The function that computes the cross-covariance of the state and output sigma points.\ninnovation: The function that computes the innovation between the measured output and the predicted output.\n\nExtended help\n\nTo perform separate measurement updates for different sensors, see the \"Measurement models\" in the documentation\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.debugplot","page":"API","title":"LowLevelParticleFilters.debugplot","text":"debugplot(pf, u, y, p=parameters(pf); runall=false, kwargs...)\n\nProduce a helpful plot. For customization options (kwargs...), see ?pplot.\n\nrunall=false: if true, runs all time steps befor displaying (faster), if false, displays the plot after each time step.\n\nThe generated plot becomes quite heavy. Initially, try limiting your input to 100 time steps to verify that it doesn't crash.\n\nnote: Note\nThis function requires using Plots to be called before it is used.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.densityplot","page":"API","title":"LowLevelParticleFilters.densityplot","text":"densityplot(x,[w])\n\nPlot (weighted) particles densities\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.forward_trajectory","page":"API","title":"LowLevelParticleFilters.forward_trajectory","text":"sol = forward_trajectory(pf, u::AbstractVector, y::AbstractVector, p=parameters(pf))\n\nRun the particle filter for a sequence of inputs and measurements (offline / batch filtering). Return a solution with x,w,we,ll = particles, weights, expweights and loglikelihood\n\nIf MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.\n\nsol can be plotted\n\nplot(sol::ParticleFilteringSolution; nbinsy=30, xreal=nothing, dim=nothing)\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.forward_trajectory-2","page":"API","title":"LowLevelParticleFilters.forward_trajectory","text":"forward_trajectory(imm::IMM, u, y, p = parameters(imm); interact = true)\n\nWhen performing batch filtering using an IMM filter, one may\n\nOverride the interact parameter of the filter\nAccess the mode probabilities along the trajectory as the sol.extra field. This is a matrix of size (n_modes, T) where T is the length of the trajectory (length of u and y).\n\nThe returned solution object is of type KalmanFilteringSolution and has the following fields:\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.forward_trajectory-3","page":"API","title":"LowLevelParticleFilters.forward_trajectory","text":"sol = forward_trajectory(kf::AbstractKalmanFilter, u::Vector, y::Vector, p=parameters(kf))\n\nRun a Kalman filter forward to perform (offline / batch) filtering along an entire trajectory u, y.\n\nReturns a KalmanFilteringSolution: with the following\n\nx: predictions x(tt-1)\nxt: filtered estimates x(tt)\nR: predicted covariance matrices R(tt-1)\nRt: filter covariances R(tt)\nll: loglik\n\nsol can be plotted\n\nplot(sol::KalmanFilteringSolution; plotx = true, plotxt=true, plotu=true, ploty=true)\n\nSee KalmanFilteringSolution for more details.\n\nExtended help\n\nVery large systems\n\nIf your system is very large, i.e., the dimension of the state is very large, and the arrays u,y are long, this function may use a lot of memory to store all covariance matrices R, Rt. If you do not need all the information retained by this function, you may opt to call one of the functions\n\nloglik\nLowLevelParticleFilters.sse\nLowLevelParticleFilters.prediction_errors!\n\nThat store significantly less information. The amount of computation performed by all of these functions is identical, the only difference lies in what is stored and returned.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.interact!-Tuple{IMM}","page":"API","title":"LowLevelParticleFilters.interact!","text":"interact!(imm::IMM)\n\nThe interaction step of the IMM filter updates the state and covariance of each internal model based on the mixing probabilities imm.μ and the transition probability matrix imm.P.\n\nModels with small mixing probabilities will have their states and covariances updated more towards the states and covariances of models with higher mixing probabilities, and vice versa.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.log_likelihood_fun-Tuple{Any, AbstractVector, Any, Any, Any}","page":"API","title":"LowLevelParticleFilters.log_likelihood_fun","text":"ll(θ) = log_likelihood_fun(filter_from_parameters(θ::Vector)::Function, priors::Vector{Distribution}, u, y, p)\n\nreturns function θ -> p(y|θ)p(θ)\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.loglik","page":"API","title":"LowLevelParticleFilters.loglik","text":"ll = loglik(filter, u, y, p=parameters(filter))\n\nCalculate log-likelihood for entire sequences u,y\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.logsumexp!","page":"API","title":"LowLevelParticleFilters.logsumexp!","text":"ll = logsumexp!(w, we [, maxw])\n\nNormalizes the weight vector w and returns the weighted log-likelihood\n\nhttps://arxiv.org/pdf/1412.8695.pdf eq 3.8 for p(y) https://discourse.julialang.org/t/fast-logsumexp/22827/7?u=baggepinnen for stable logsumexp\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.mean_trajectory-Tuple{Any, Vector, Vector}","page":"API","title":"LowLevelParticleFilters.mean_trajectory","text":"x,ll = mean_trajectory(pf, u::Vector{Vector}, y::Vector{Vector}, p=parameters(pf))\n\nThis method resets the particle filter to the initial state distribution upon start\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.mean_trajectory-Tuple{ParticleFilteringSolution}","page":"API","title":"LowLevelParticleFilters.mean_trajectory","text":"mean_trajectory(sol::ParticleFilteringSolution)\nmean_trajectory(x::AbstractMatrix, we::AbstractMatrix)\n\nCompute the weighted mean along the trajectory of a particle-filter solution. Returns a matrix of size T × nx. If x and we are supplied, the weights are expected to be in the original space (not log space).\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.metropolis","page":"API","title":"LowLevelParticleFilters.metropolis","text":"metropolis(ll::Function(θ), R::Int, θ₀::Vector, draw::Function(θ) = naive_sampler(θ₀))\n\nPerforms MCMC sampling using the marginal Metropolis (-Hastings) algorithm draw = θ -> θ' samples a new parameter vector given an old parameter vector. The distribution must be symmetric, e.g., a Gaussian. R is the number of iterations. See log_likelihood_fun\n\nExample:\n\nfilter_from_parameters(θ) = ParticleFilter(N, dynamics, measurement, MvNormal(n,exp(θ[1])), MvNormal(p,exp(θ[2])), d0)\npriors = [Normal(0,0.1),Normal(0,0.1)]\nll = log_likelihood_fun(filter_from_parameters,priors,u,y,1)\nθ₀ = log.([1.,1.]) # Initial point\ndraw = θ -> θ .+ rand(MvNormal(0.1ones(2))) # Function that proposes new parameters (has to be symmetric)\nburnin = 200 # If using threaded call, provide number of burnin iterations\n# @time theta, lls = metropolis(ll, 2000, θ₀, draw) # Run single threaded\n# thetam = reduce(hcat, theta)'\n@time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 5000, θ₀, draw) # run on all threads, will provide (2000-burnin)*nthreads() samples\nhistogram(exp.(thetalls[:,1:2]), layout=3)\nplot!(thetalls[:,3], subplot=3) # if threaded call, log likelihoods are in the last column\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.reset!-Tuple{LowLevelParticleFilters.AbstractKalmanFilter}","page":"API","title":"LowLevelParticleFilters.reset!","text":"reset!(kf::AbstractKalmanFilter; x0)\n\nReset the initial distribution of the state. Optionally, a new mean vector x0 can be provided.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.reset!-Tuple{LowLevelParticleFilters.AbstractParticleFilter}","page":"API","title":"LowLevelParticleFilters.reset!","text":"Reset the filter to initial state and covariance/distribution\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.reset!-Tuple{SqKalmanFilter}","page":"API","title":"LowLevelParticleFilters.reset!","text":"reset!(kf::SqKalmanFilter; x0)\n\nReset the initial distribution of the state. Optionally, a new mean vector x0 can be provided.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.simulate","page":"API","title":"LowLevelParticleFilters.simulate","text":"x,u,y = simulate(f::AbstractFilter, T::Int, du::Distribution, p=parameters(f), [N]; dynamics_noise=true, measurement_noise=true)\nx,u,y = simulate(f::AbstractFilter, u, p=parameters(f); dynamics_noise=true, measurement_noise=true)\n\nSimulate dynamical system forward in time T steps, or for the duration of u. Returns state sequence, inputs and measurements.\n\nu is an input-signal trajectory, alternatively, du is a distribution of random inputs.\n\nA simulation can be considered a draw from the prior distribution over the evolution of the system implied by the selected noise models. Such a simulation is useful in order to evaluate whether or not the noise models are reasonable.\n\nIf MonteCarloMeasurements.jl is loaded, the argument N::Int can be supplied, in which case N simulations are done and the result is returned in the form of Vector{MonteCarloMeasurements.Particles}.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.smooth","page":"API","title":"LowLevelParticleFilters.smooth","text":"xb,ll = smooth(pf, M, u, y, p=parameters(pf))\nxb,ll = smooth(pf, xf, wf, wef, ll, M, u, y, p=parameters(pf))\n\nPerform particle smoothing using forward-filtering, backward simulation. Return smoothed particles and loglikelihood. See also smoothed_trajs, smoothed_mean, smoothed_cov\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.smooth-2","page":"API","title":"LowLevelParticleFilters.smooth","text":"xT,RT,ll = smooth(sol, kf)\nxT,RT,ll = smooth(kf::KalmanFilter, u::Vector, y::Vector, p=parameters(kf))\nxT,RT,ll = smooth(kf::ExtendedKalmanFilter, u::Vector, y::Vector, p=parameters(kf))\n\nReturns smoothed estimates of state x and covariance R given all input output data u,y or an existing solution sol obtained from forward_trajectory.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.smoothed_cov-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.smoothed_cov","text":"smoothed_cov(xb)\n\nHelper function to calculate the covariance of smoothed particle trajectories\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.smoothed_mean-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.smoothed_mean","text":"smoothed_mean(xb)\n\nHelper function to calculate the mean of smoothed particle trajectories\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.smoothed_trajs-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.smoothed_trajs","text":"smoothed_trajs(xb)\n\nHelper function to get particle trajectories as a 3-dimensions array (N,M,T) instead of matrix of vectors.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.update!","page":"API","title":"LowLevelParticleFilters.update!","text":"ll, e = update!(f::AbstractFilter, u, y, p = parameters(f), t = index(f))\n\nPerform one step of predict! and correct!, returns log-likelihood and prediction error\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.update!-Tuple{IMM, Any, Any, Vararg{Any}}","page":"API","title":"LowLevelParticleFilters.update!","text":"update!(imm::IMM, u, y, p, t; correct_kwargs = (;), predict_kwargs = (;), interact = true)\n\nThe combined udpate for an IMM filter performs the following steps:\n\nCorrect each model with the measurements y and control input u.\nCombine the models into a single state and covariance.\nInteract the models to update their respective state and covariance.\nPredict each model to the next time step.\n\nThis differs slightly from the udpate step of other filters, where at the end of an update the state of the filter is the one-step ahead predicted value, whereas here each individual filter has a predicted state, but the combine! step of the IMM filter hasn't been performed on the predictions yet. The state of the IMM filter is thus x(tt) and not x(t+1t) like it is for other filters, and each filter internal to the IMM.\n\nArguments:\n\ncorrect_kwargs: An optional named tuple of keyword arguments that are sent to correct!.\npredict_kwargs: An optional named tuple of keyword arguments that are sent to predict!.\ninteract: Whether or not to run the interaction step.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.weighted_cov-Tuple{Any, Any}","page":"API","title":"LowLevelParticleFilters.weighted_cov","text":"weighted_cov(x,we)\n\nSimilar to weighted_mean, but returns covariances\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.weighted_mean-Tuple{Any, AbstractVector}","page":"API","title":"LowLevelParticleFilters.weighted_mean","text":"x̂ = weighted_mean(x,we)\n\nCalculated weighted mean of particle trajectories. we are expweights.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.weighted_mean-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.weighted_mean","text":"x̂ = weighted_mean(pf)\nx̂ = weighted_mean(s::PFstate)\n\n\n\n\n\n","category":"method"},{"location":"api/#StatsAPI.predict!","page":"API","title":"StatsAPI.predict!","text":"predict!(f, u, p = parameters(f), t = index(f))\n\nMove filter state forward in time using dynamics equation and input vector u.\n\n\n\n\n\n","category":"function"},{"location":"api/#StatsAPI.predict!-2","page":"API","title":"StatsAPI.predict!","text":"predict!(kf::SqKalmanFilter, u, p = parameters(kf), t::Real = index(kf); R1 = get_mat(kf.R1, kf.x, u, p, t), α = kf.α)\n\nFor the square-root Kalman filter, a custom provided R1 must be the upper triangular Cholesky factor of the covariance matrix of the process noise.\n\n\n\n\n\n","category":"function"},{"location":"api/#StatsAPI.predict!-3","page":"API","title":"StatsAPI.predict!","text":"predict!(kf::AbstractKalmanFilter, u, p = parameters(kf), t::Integer = index(kf); R1, α = kf.α)\n\nPerform the prediction step (updating the state estimate to x(t+1t)). If R1 stored in kf is a function R1(x, u, p, t), this function is evaluated at the state before the prediction is performed. The dynamics noise covariance matrix R1 stored in kf can optionally be overridden by passing the argument R1, in this case R1 must be a matrix.\n\n\n\n\n\n","category":"function"},{"location":"api/#StatsAPI.predict!-Union{Tuple{AUGM}, Tuple{AUGD}, Tuple{IPM}, Tuple{IPD}, Tuple{UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, Any}, Tuple{UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, Any, Any}, Tuple{UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, Any, Any, Real}} where {IPD, IPM, AUGD, AUGM}","page":"API","title":"StatsAPI.predict!","text":"predict!(ukf::UnscentedKalmanFilter, u, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R1 = get_mat(ukf.R1, ukf.x, u, p, t), reject, mean, cov, dynamics)\n\nThe prediction step for an UnscentedKalmanFilter allows the user to override, R1 and any of the functions, reject, mean, cov, dynamics`.\n\nArguments:\n\nu: The input\np: The parameters\nt: The current time\nR1: The dynamics noise covariance matrix, or a function that returns the covariance matrix.\nreject: A function that takes a sigma point and returns true if it should be rejected.\nmean: The function that computes the mean of the state sigma points.\ncov: The function that computes the covariance of the state sigma points.\n\n\n\n\n\n","category":"method"},{"location":"api/","page":"API","title":"API","text":"LowLevelParticleFilters.prediction_errors!","category":"page"},{"location":"api/#LowLevelParticleFilters.prediction_errors!","page":"API","title":"LowLevelParticleFilters.prediction_errors!","text":"prediction_errors!(res, f::AbstractFilter, u, y, p = parameters(f), λ = 1)\n\nCalculate the prediction errors and store the result in res. Similar to sse, this function is useful for sum-of-squares optimization. In contrast to sse, this function returns the residuals themselves rather than their sum of squares. This is useful for Gauss-Newton style optimizers, such as LeastSquaresOptim.LevenbergMarquardt.\n\nArguments:\n\nres: A vector of length ny*length(y). Note, for each datapoint in u and u, there are ny outputs, and thus ny residuals.\nf: Any filter\nλ: A weighting factor to minimize dot(e, λ, e). A commonly used metric is λ = Diagonal(1 ./ (mag.^2)), where mag is a vector of the \"typical magnitude\" of each output. Internally, the square root of W = sqrt(λ) is calculated so that the residuals stored in res are W*e.\n\nSee example in Solving using Gauss-Newton optimization.\n\n\n\n\n\n","category":"function"},{"location":"beetle_example/#Smoothing-the-track-of-a-moving-beetle","page":"Particle-filter tutorial","title":"Smoothing the track of a moving beetle","text":"","category":"section"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"This is an example of smoothing the 2-dimensional trajectory of a moving dung beetle. The example spurred off of this Discourse topic. For more information about the research behind this example, see Artificial light disrupts dung beetles’ sense of direction and A dung beetle that path integrates without the use of landmarks. Special thanks to Yakir Gagnon for providing this example.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"In this example we will describe the position coordinates, x and y, of the beetle as functions of its velocity, v_t, and direction, θ_t:","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"beginaligned\nx_t+1 = x_t + cos(θ_t)v_t \ny_t+1 = y_t + sin(θ_t)v_t \nv_t+1 = v_t + e_t \nθ_t+1 = θ_t + w_t\nendaligned","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"where e_t N(0σ_e) w_t N(0σ_w) The beetle further has two \"modes\", one where it's moving towards a goal, and one where it's searching in a more erratic manner. Figuring out when this mode switch occurs is the goal of the filtering. The mode will be encoded as a state variable, and used to determine the amount of dynamic noise affecting the angle of the beetle, i.e., in the searching mode, the beetle has more angle noise. The mode switching is modeled as a stochastic process with a binomial distribution (coin flip) describing the likelihood of a switch from mode 0 (moving to goal) and mode 1 (searching). Once the beetle has started searching, it stays in that mode, i.e., the searching mode is \"sticky\" or \"terminal\".","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"The image below shows an example video from which the data is obtained (Image: Bettle)","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We load a single experiment from file for the purpose of this example (in practice, there may be hundreds of experiments)","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots, Random\nusing DisplayAs # hide\nusing DelimitedFiles\npath = \"../track.csv\"\nxyt = readdlm(path)\ntosvec(y) = reinterpret(SVector{length(y[1]),Float64}, reduce(hcat,y))[:] |> copy # helper function\ny = tosvec(collect(eachrow(xyt[:,1:2])))\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We then define some properties of the dynamics and the filter. We will use an AdvancedParticleFilter since we want to have fine-grained control over the noise sampling for the mode switch.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"N = 2000 # Number of particles in the particle filter\nn = 4 # Dimension of state: we have position (2D), speed and angle\np = 2 # Dimension of measurements, we can measure the x and the y\n@inline pos(s) = s[SVector(1,2)]\n@inline vel(s) = s[3]\n@inline ϕ(s) = s[4]\n@inline mode(s) = s[5]\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We then define the probability distributions we need.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"dgσ = 1 # the deviation of the measurement noise distribution\ndvσ = 0.3 # the deviation of the dynamics noise distribution\nϕσ = 0.5\nconst switch_prob = 0.03 # Probability of mode switch\nconst dg = MvNormal(@SVector(zeros(p)), dgσ^2) # Measurement noise Distribution\nconst df = LowLevelParticleFilters.TupleProduct((Normal.(0,[1e-1, 1e-1, dvσ, ϕσ])...,Binomial(1,switch_prob)))\nd0 = MvNormal(SVector(y[1]..., 0.5, atan((y[2]-y[1])...), 0), [3.,3,2,2,0])\nconst noisevec = zeros(5) # cache vector\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We now define the dynamics, since we use the advanced filter, we include the noise=false argument. The dynamics is directly defined in discrete time.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"@inline function dynamics(s,u,p,t,noise=false)\n # current state\n m = mode(s)\n v = vel(s)\n a = ϕ(s)\n p = pos(s)\n # get noise\n if noise\n y_noise, x_noise, v_noise, ϕ_noise,_ = rand!(df, noisevec)\n else\n y_noise, x_noise, v_noise, ϕ_noise = 0.,0.,0.,0.\n end\n # next state\n v⁺ = max(0.999v + v_noise, 0.0)\n m⁺ = Float64(m == 0 ? rand() < switch_prob : true)\n a⁺ = a + (ϕ_noise*(1 + m*10))/(1 + v⁺) # next state velocity is used here\n p⁺ = p + SVector(y_noise, x_noise) + SVector(sincos(a))*v⁺ # current angle but next velocity\n SVector{5,Float64}(p⁺[1], p⁺[2], v⁺, a⁺, m⁺) # all next state\nend\nfunction measurement_likelihood(s,u,y,p,t)\n logpdf(dg, pos(s)-y) # A simple linear measurement model with normal additive noise\nend\n@inline measurement(s,u,p,t,noise=false) = s[SVector(1,2)] + noise*rand(dg) # We observe the position coordinates with the measurement\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"In this example, we have no control inputs, we thus define a vector of only zeros. We then solve the forward filtering problem and plot the results.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"u = zeros(length(y))\npf = AuxiliaryParticleFilter(AdvancedParticleFilter(N, dynamics, measurement, measurement_likelihood, df, d0))\nT = length(y)\nsol = forward_trajectory(pf,u[1:T],y[1:T])\n(; x,w,we,ll) = sol\nplot(sol, markerstrokecolor=:auto, m=(2,0.5))\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We can clearly see when the beetle switched mode (state variable 5). This corresponds well to annotations provided by a biologist and is the fundamental question we want to answer with the filtering procedure.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We can plot the mean of the filtered trajectory as well","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"xh = mean_trajectory(x,we)\n\n\"plotting helper function\"\nfunction to1series(x::AbstractVector, y)\n r,c = size(y)\n y2 = vec([y; fill(Inf, 1, c)])\n x2 = repeat([x; Inf], c)\n x2,y2\nend\nto1series(y) = to1series(1:size(y,1),y)\n\nfig1 = plot(xh[:,1],xh[:,2], c=:blue, lab=\"estimate\", legend=:bottomleft)\nplot!(xyt[:,1],xyt[:,2], c=:red, lab=\"measurement\")","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"as well as the angle state variable (we subsample the particles to not get sluggish plots)","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"fig2 = scatter(to1series(ϕ.(x)'[:,1:2:end])..., m=(:black, 0.03, 2), lab=\"\", size=(500,300))\nplot!(identity.(xh[:,4]), lab=\"Filtered angle\", legend=:topleft, ylims=(-30, 70))\nDisplayAs.PNG(fig2) # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"The particle plot above indicate that the posterior is multimodal. This phenomenon arises due to the simple model that uses an angle that is allowed to leave the interval 0-2π rad. In this example, we are not interested in the angle, but rather when the beetle switches mode. The filtering distribution above gives a hint at when this happens, but we will not plot the mode trajectory until we have explored smoothing as well.","category":"page"},{"location":"beetle_example/#Smoothing","page":"Particle-filter tutorial","title":"Smoothing","text":"","category":"section"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"The filtering results above does not use all the available information when trying to figure out the state trajectory. To do this, we may call a smoother. We use a particle smoother and compute 10 smoothing trajectories.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"M = 10 # Number of smoothing trajectories, NOTE: if this is set higher, the result will be better at the expense of linear scaling of the computational cost.\nsb,ll = smooth(pf, M, u, y) # Sample smoothing particles (b for backward-trajectory)\nsbm = smoothed_mean(sb) # Calculate the mean of smoothing trajectories\nsbt = smoothed_trajs(sb) # Get smoothing trajectories\nplot!(fig1, sbm[1,:],sbm[2,:], lab=\"xs\")","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"plot!(fig2, identity.(sbm'[:,4]), lab=\"smoothed\")\nDisplayAs.PNG(fig2) # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We see that the smoothed trajectory may look very different from the filter trajectory. This is an indication that it's hard to tell what state the beetle is currently in, but easier to look back and tell what state the beetle must have been in at a historical point. ","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We can also visualize the mode state","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"plot(xh[:,5], lab=\"Filtering\")\nplot!(to1series(sbt[5,:,:]')..., lab=\"Smoothing\", title=\"Mode trajectories\", l=(:black,0.2))","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"also this state variable indicates that it's hard to tell what state the beetle is in during filtering, but obvious with hindsight (smoothing). The mode switch occurs when the filtering distribution of the angle becomes drastically wider, indicating that increased dynamics noise is required in order to describe the motion of the beetle.","category":"page"},{"location":"beetle_example/#Summary","page":"Particle-filter tutorial","title":"Summary","text":"","category":"section"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"This example has demonstrated filtering and smoothing in an advanced application that includes manual control over noise, mixed continuous and discrete state.","category":"page"},{"location":"beetle_example_imm/#Filtering-the-track-of-a-moving-beetle-using-IMM","page":"IMM-filter tutorial","title":"Filtering the track of a moving beetle using IMM","text":"","category":"section"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"This tutorial is very similar to Smoothing the track of a moving beetle, but uses an Interacting Multiple Models (IMM) filter to model the mode switching of the beetle. The IMM filter is a mixture model, in this case with internal Unscented Kalman filters, where each Kalman filter represents a different mode of the system. The IMM filter is able to switch between these modes based on the likelihood of the mode given the data.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"This is an example of smoothing the 2-dimensional trajectory of a moving dung beetle. The example spurred off of this Discourse topic. For more information about the research behind this example, see Artificial light disrupts dung beetles’ sense of direction and A dung beetle that path integrates without the use of landmarks. Special thanks to Yakir Gagnon for providing this example.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"In this example we will describe the position coordinates, x and y, of the beetle as functions of its velocity, v_t, and direction, θ_t:","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"beginaligned\nx_t+1 = x_t + cos(θ_t)v_t \ny_t+1 = y_t + sin(θ_t)v_t \nv_t+1 = v_t + e_t \nθ_t+1 = θ_t + w_t\nendaligned","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"where e_t N(0σ_e) w_t N(0σ_w) The beetle further has two \"modes\", one where it's moving towards a goal, and one where it's searching in a more erratic manner. Figuring out when this mode switch occurs is the goal of the filtering. The mode will be encoded as two different models, where the difference between the models lies in the amount of dynamic noise affecting the angle of the beetle, i.e., in the searching mode, the beetle has more angle noise. The mode switching is modeled as a stochastic process with a binomial distribution (coin flip) describing the likelihood of a switch from mode 0 (moving to goal) and mode 1 (searching). Once the beetle has started searching, it stays in that mode, i.e., the searching mode is \"sticky\" or \"terminal\".","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"The image below shows an example video from which the data is obtained (Image: Bettle)","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We load a single experiment from file for the purpose of this example (in practice, there may be hundreds of experiments)","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots, Random\nusing DisplayAs # hide\nusing DelimitedFiles\ncd(@__DIR__)\npath = \"../track.csv\"\nxyt = readdlm(path)\ntosvec(y) = reinterpret(SVector{length(y[1]),Float64}, reduce(hcat,y))[:] |> copy # helper function\ny = tosvec(collect(eachrow(xyt[:,1:2])))\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We then define some properties of the dynamics and the filter. We will use an AdvancedParticleFilter since we want to have fine-grained control over the noise sampling for the mode switch.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"nx = 4 # Dimension of state: we have position (2d), speed and angle\nny = 2 # Dimension of measurements, we can measure the x and the y\n@inline pos(s) = s[SVector(1,2)]\n@inline vel(s) = s[3]\n@inline ϕ(s) = s[4]\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We then define the probability distributions we need. The IMM filter takes a transition-probability matrix, P, and an initial mixing probability, μ. P is a Markov (stochastic) matrix, where each row sums to one, and P[i, j] is the probability of switching from mode i to mode j. μ is a vector of probabilities, where μ[i] is the probability of starting in mode i. We also define the noise distributions for the dynamics and the measurements. The dynamics noise is modeled as a Gaussian distribution with a standard deviation of dvσ for the velocity and ϕσ for the angle. The measurement noise is modeled as a Gaussian distribution with a standard deviation of dgσ. The initial state is modeled as a Gaussian distribution with a mean at the first measurement and a standard deviation of d0.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"dgσ = 1.0 # the deviation of the measurement noise distribution\ndvσ = 0.3 # the deviation of the dynamics noise distribution\nϕσ = 0.5\nP = [0.995 0.005; 0.0 1] # Transition probability matrix, we model the search mode as \"almost terminal\"\nμ = [1.0, 0.0] # Initial mixing probabilities\nR1 = Diagonal([1e-1, 1e-1, dvσ, ϕσ].^2)\nR2 = dgσ^2*I(ny) # Measurement noise covariance matrix\nd0 = MvNormal(SVector(y[1]..., 0.5, atan((y[2]-y[1])...)), [3.,3,2,2])\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We now define the dynamics, which is directly defined in discrete time. The third argument is a parameter we call modegain, which is used to scale the amount of noise in the angle of the beetle depending on the mode in which it is in. The last argument is a boolean that tells the dynamics function which mode it is in, we will close over this argument when defining the dynamics for the individual Kalman filters that are part of the IMM, one will use m = false and one will use m = true.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"@inline function dynamics(s,_,modegain,t,w,m)\n # current state\n v = vel(s)\n a = ϕ(s)\n p = pos(s)\n\n y_noise, x_noise, v_noise, ϕ_noise = w\n\n # next state\n v⁺ = max(0.999v + v_noise, 0.0)\n a⁺ = a + (ϕ_noise*(1 + m*modegain))/(1 + v⁺) # next state velocity is used here\n p⁺ = p + SVector(y_noise, x_noise) + SVector(sincos(a))*v⁺ # current angle but next velocity\n SVector(p⁺[1], p⁺[2], v⁺, a⁺) # all next state\nend\n@inline measurement(s,u,p,t) = s[SVector(1,2)] # We observe the position coordinates with the measurement\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"In this example, we have no control inputs, we thus define a vector of only zeros. We then solve the forward filtering problem and plot the results.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"u = zeros(length(y)) # no control inputs\nkffalse = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,false), measurement, R1, R2, d0; ny, nu=0, p=10)\nkftrue = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,true), measurement, R1, R2, d0; ny, nu=0, p=10)\n\nimm = IMM([kffalse, kftrue], P, μ; p = 10)\n\nT = length(y)\nsol = forward_trajectory(imm, u, y, interact=true)\nfigx = plot(sol, plotu=false, plotRt=true)\nfigmode = plot(sol.extra', title=\"Mode\")\nplot(figx, figmode)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"If you have followed the particle filter tutorial Smoothing the track of a moving beetle, you will notice that the result here is much worse. We used noise parameters similar to in the particle-gilter example, but those were tuned fo the particle filter. Below, we will attempt to optimize the performance of the IMM filter.","category":"page"},{"location":"beetle_example_imm/#Tuning-by-optimization","page":"IMM-filter tutorial","title":"Tuning by optimization","text":"","category":"section"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We will attempt to optimize the dynamics and measurement noise covariance matrices and the modegain parameter. We code this up in two functions, one that takes the parameter vector and returns an IMM filter, and one that calculates the loss given the filter. We will optimize the log-likelihood of the data given the filter.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"params = [log10.(diag(R1)); log10(1); log10(10)]\n\nfunction get_opt_kf(p)\n T = eltype(p)\n R1i = Diagonal(SVector{4}(exp10.(p[1:4])))\n R2i = SMatrix{2,2}(exp10(p[5])*R2)\n d0i = MvNormal(SVector{4, T}(T.(d0.μ)), SMatrix{4,4}(T.(d0.Σ)))\n modegain = 5+exp10(p[6])\n Pi = SMatrix{2,2, Float64,4}(P)\n # sigmoid(x) = 1/(1+exp(-x))\n # switch_prob = sigmoid(p[7])\n # Pi = [1-switch_prob switch_prob; 0 1]\n kffalse = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,false), measurement, R1i, R2i, d0i; ny, nu=0)\n kftrue = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,true), measurement, R1i, R2i, d0i; ny, nu=0)\n\n IMM([kffalse, kftrue], Pi, T.(μ), p=modegain)\nend\nfunction cost(pars)\n try\n imm = get_opt_kf(pars)\n ll = loglik(imm, u, y, interact=true) - 1/2*logdet(imm.models[1].R1)\n return -ll\n catch e\n # rethrow() # If you only get Inf, you can uncomment this line to see the error message\n return eltype(pars)(Inf)\n\tend\nend\n\nusing Optim\nRandom.seed!(0)\nres = Optim.optimize(\n cost,\n params,\n ParticleSwarm(),\n Optim.Options(\n show_trace = true,\n show_every = 5,\n iterations = 200,\n ),\n)\n\nimm = get_opt_kf(res.minimizer)\nimm = get_opt_kf([-0.23848249020342335, 0.09510413594186848, -2.7540206342539832, -0.026720713351238334, -5.596193009305194, -25.37645648820617]) #make sure it goes well # hide\n\nsol = forward_trajectory(imm, u, y)\nplot(sol.extra', title=\"Mode (optimized filter)\")","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"If it went well, the filter should be in mode 1 (the false mode) from the start until just before 200 time steps, at which point it should switch to model 2 (true). This method of detecting the mode switch of the beetle appears to be somewhat less robust than the particle filter, but is significantly cheaper computationally. ","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"The IMM filter does not stick in mode 2 perpetually after having reached it since it never actually becomes fully confident that mode 2 has been reached, but detecting the first switch is sufficient to know that the switch has occurred. ","category":"page"},{"location":"noisetuning/#How-to-tune-a-Kalman-filter","page":"Noise tuning and disturbance modeling for Kalman filtering","title":"How to tune a Kalman filter","text":"","category":"section"},{"location":"noisetuning/","page":"Noise tuning and disturbance modeling for Kalman filtering","title":"Noise tuning and disturbance modeling for Kalman filtering","text":"This tutorial is hosted as a notebook.","category":"page"},{"location":"fault_detection/#Fault-detection","page":"Fault detection","title":"Fault detection","text":"","category":"section"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"This is a video tutorial, available below:","category":"page"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"","category":"page"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"The notebook used in the tutorial is available here:","category":"page"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"identification_12_fault_detection.jl on JuliaHub\nidentification_12_fault_detection.jl on GitHub","category":"page"},{"location":"discretization/#Discretization","page":"Discretization","title":"Discretization","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"This package operates exclusively on discrete-time dynamics, and dynamics describing, e.g., ODE systems must thus be discretized. This page describes the details around discretization for nonlinear and linear systems, as well as how to discretize continuous-time noise processes. ","category":"page"},{"location":"discretization/#Nonlinear-ODEs","page":"Discretization","title":"Nonlinear ODEs","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Continuous-time dynamics functions on the form (x,u,p,t) -> ẋ can be discretized (integrated) using the function SeeToDee.Rk4, e.g.,","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"using SeeToDee\ndiscrete_dynamics = SeeToDee.Rk4(continuous_dynamics, sampletime; supersample=1)","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"where the integer supersample determines the number of RK4 steps that is taken internally for each change of the control signal (1 is often sufficient and is the default). The returned function discrete_dynamics is on the form (x,u,p,t) -> x⁺.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"note: Note\nWhen solving state-estimation problems, accurate integration is often less important than during simulation. The motivations for this are severalThe dynamics model is often inaccurate, and solving an inaccurate model to high accuracy can be a waste of effort.\nThe performance is often dictated by the disturbances acting on the system.\nState-estimation enjoys feedback from measurements that corrects for slight errors due to integration.","category":"page"},{"location":"discretization/#Linear-systems","page":"Discretization","title":"Linear systems","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"A linear system on the form ","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"beginaligned\ndotx(t) = Ax(t) + Bu(t)\ny(t) = Cx(t) + Du(t)\nendaligned","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"can be discretized using ControlSystems.c2d, which defaults to a zero-order hold discretization. See the example below for more info.","category":"page"},{"location":"discretization/#Covariance-matrices","page":"Discretization","title":"Covariance matrices","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Covariance matrices for continuous-time noise processes can also be discretized using ControlSystems.c2d","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"using ControlSystemIdentification\nR1d = c2d(sys::StateSpace{<:Discrete}, R1::Matrix)\nR1d, R2d = c2d(sys::StateSpace{<:Discrete}, R1::Matrix, R2::Matrix)","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"This samples a continuous-time covariance matrix to fit the provided discrete-time system sys.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"The method used comes from theorem 5 in the reference below.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Ref: \"Discrete-time Solutions to the Continuous-time Differential Lyapunov Equation With Applications to Kalman Filtering\", Patrik Axelsson and Fredrik Gustafsson","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"On singular covariance matrices: The traditional double integrator with covariance matrix Q = diagm([0,σ²]) can not be sampled with this method. Instead, the input matrix (\"Cholesky factor\") of Q must be manually kept track of, e.g., the noise of variance σ² enters like N = [0, 1] which is sampled using ZoH and becomes Nd = [Ts^2 / 2; Ts] which results in the covariance matrix σ² * Nd * Nd' (see example below).","category":"page"},{"location":"discretization/#Example","page":"Discretization","title":"Example","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"The following example will discretize a linear double integrator system. Double integrators arise when the position of an object is controlled by a force, i.e., when Newtons second law f = ma governs the dynamics. The system can be written on the form","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"beginaligned\ndot x(t) = Ax(t) + Bu(t) + Nw(t)\ny(t) = Cx(t) + e(t)\nendaligned","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"where N = B are both equal to [0, 1], indicating that the noise w(t) enters like a force (this could be for instance due to air resistance or friction).","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"We start by defining the system that takes u as an input and discretize that with a sample time of T_s = 01.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"using ControlSystemsBase\nA = [0 1; 0 0]\nB = [0; 1;;]\nC = [1 0]\nD = 0\nTs = 0.1 # Sample time\n\nsys = ss(A,B,C,D)\nsysd = c2d(sys, Ts) # Discretize the dynamics","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"We then form another system, this time with w(t) as the input, and thus N as the input matrix instead of B. We assume that the noise has a standard deviation of sigma_1 = 05","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"σ1 = 0.5\nN = σ1*[0; 1;;]\nsys_w = ss(A,N,C,D)\nsys_wd = c2d(sys_w, Ts) # Discretize the noise system\nNd = sys_wd.B # The discretized noise input matrix\nR1d = Nd*Nd' # The final discrete-time covariance matrix","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"We can verify that the matrix we computed corresponds to the theoretical covariance matrix for a discrete-time double integrator:","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"R1d ≈ σ1^2*[Ts^2 / 2; Ts]*[Ts^2 / 2; Ts]'","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"For a nonlinear system, we could adopt a similar strategy by first linearizing the system around a suitable operating point. Alternatively, we could make use of the fact that some of the state estimators in this package allows the covariance matrices to be functions of the state, and thus compute a new discretized covariance matrix using a linearization around the current state.","category":"page"},{"location":"discretization/#Non-uniform-sample-rates","page":"Discretization","title":"Non-uniform sample rates","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Special care is needed if the sample rate is not constant, i.e., the time interval between measurements varies. ","category":"page"},{"location":"discretization/#Dropped-samples","page":"Discretization","title":"Dropped samples","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"A common case is that the sample rate is constant, but some measurements are lost. This case is very easy to handle; the filter loop iterates between two steps","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Prediction using predict!(filter, x, u, p, t)\nCorrection using\ncorrect!(f, u, y, p, t) if using the standard measurement model of the filter\ncorrect!(f, mm, u, y, p, t, mm) to use a custom measurement model mm","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"If a measurement y is lacking, one simply skips the corresponding call to correct! where y is missing. Repeated calls to predict! corresponds to simulating the system without any feedback from measurements, like if an ODE was solved. Internally, the filter will keep track of the covariance of the estimate, which is likely to grow if no measurements are used to inform the filter about the state of the system.","category":"page"},{"location":"discretization/#Sensors-with-different-sample-rates","page":"Discretization","title":"Sensors with different sample rates","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"For Kalman-type filters, it is possible to construct custom measurement models, and pass an instance of a measurement model as the second argument to correct!. This allows for sensor fusion with sensors operating at different rates, or when parts of the measurement model are linear, and other parts are nonlinear. See examples in Measurement models for how to construct explicit measurement models.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"A video demonstrating the use of multiple measurement models running at different rates is available on YouTube:","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"","category":"page"},{"location":"discretization/#Stochastic-sample-rate","page":"Discretization","title":"Stochastic sample rate","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"In some situations, such as in event-based systems, the sample rate is truly stochastic. There is no single correct way of handling this, and we instead outline some alternative approaches.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"If the filtering is performed offline on a batch of data, time-varying dynamics can be used, for instance by supplying matrices to a KalmanFilter on the form A[:, :, t]. Each A is then computed as the discretization with the sample time given as the time between measurement t and measurement t+1.\nA conceptually simple approach is to choose a very small sample interval T_s which is smaller than the smallest occuring sample interval in the data, and approximate each sample interval by rounding it to the nearest integer multiple of T_s. This transforms the problem to an instance of the \"dropped samples\" problem described above.\nMake use of an adaptive integrator instead of the fixed-step rk4 supplied in this package, and manually keep track of the step length that needs to be taken.","category":"page"},{"location":"benchmark/#Benchmark-test","page":"Benchmark","title":"Benchmark test","text":"","category":"section"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"To see how the performance varies with the number of particles, we simulate several times. The following code simulates the system and performs filtering using the simulated measurements. We do this for varying number of time steps and varying number of particles.","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"note: Note\nTo run this code, see the bottom of src/example_lineargaussian.jl.","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"function run_test()\n particle_count = [10, 20, 50, 100, 200, 500, 1000]\n time_steps = [20, 100, 200]\n RMSE = zeros(length(particle_count),length(time_steps)) # Store the RMS errors\n propagated_particles = 0\n t = @elapsed for (Ti,T) = enumerate(time_steps)\n for (Ni,N) = enumerate(particle_count)\n montecarlo_runs = 2*maximum(particle_count)*maximum(time_steps) ÷ T ÷ N\n E = sum(1:montecarlo_runs) do mc_run\n pf = ParticleFilter(N, dynamics, measurement, df, dg, d0) # Create filter\n u = @SVector randn(2)\n x = SVector{2,Float64}(rand(rng, d0))\n y = SVector{2,Float64}(sample_measurement(pf,x,u,0,1))\n error = 0.0\n @inbounds for t = 1:T-1\n pf(u, y) # Update the particle filter\n x = dynamics(x,u,t) + SVector{2,Float64}(rand(rng, df)) # Simulate the true dynamics and add some noise\n y = SVector{2,Float64}(sample_measurement(pf,x,u,0,t)) # Simulate a measuerment\n u = @SVector randn(2) # draw a random control input\n error += sum(abs2,x-weighted_mean(pf))\n end # t\n √(error/T)\n end # MC\n RMSE[Ni,Ti] = E/montecarlo_runs\n propagated_particles += montecarlo_runs*N*T\n @show N\n end # N\n @show T\n end # T\n println(\"Propagated $propagated_particles particles in $t seconds for an average of $(propagated_particles/t/1000) particles per millisecond\")\n return RMSE\nend\n\n@time RMSE = run_test()","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"Propagated 8400000 particles in 1.140468043 seconds for an average of 7365.397085484139 particles per millisecond","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"We then plot the results","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"time_steps = [20, 100, 200]\nparticle_count = [10, 20, 50, 100, 200, 500, 1000]\nnT = length(time_steps)\nleg = reshape([\"$(time_steps[i]) time steps\" for i = 1:nT], 1,:)\nplot(particle_count,RMSE,xscale=:log10, ylabel=\"RMS errors\", xlabel=\" Number of particles\", lab=leg)","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"(Image: window)","category":"page"},{"location":"#LowLevelParticleFilters","page":"Home","title":"LowLevelParticleFilters","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: CI) (Image: codecov)","category":"page"},{"location":"","page":"Home","title":"Home","text":"This is a library for state estimation, that is, given measurements y(t) from a dynamical system, estimate the state vector x(t). Throughout, we assume dynamics on the form","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nx(t+1) = f(x(t) u(t) p t w(t))\ny(t) = g(x(t) u(t) p t e(t))\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"or the linear version","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nx(t+1) = Ax(t) + Bu(t) + w(t)\ny(t) = Cx(t) + Du(t) + e(t)\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"where x is the state vector, u an input, p some form of parameters, t is the time and we are disturbances (noise). Throughout the documentation, we often call the function f dynamics and the function g measurement.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The dynamics above describe a discrete-time system, i.e., the function f takes the current state and produces the next state. This is in contrast to a continuous-time system, where f takes the current state but produces the time derivative of the state. A continuous-time system can be discretized, described in detail in Discretization.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The parameters p can be anything, or left out. You may write the dynamics functions such that they depend on p and include parameters when you create a filter object. You may also override the parameters stored in the filter object when you call any function on the filter object. This behavior is modeled after the SciML ecosystem.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Depending on the nature of f and g, the best method of estimating the state may vary. If fg are linear and the disturbances are additive and Gaussian, the KalmanFilter is an optimal state estimator. If any of the above assumptions fail to hold, we may need to resort to more advanced estimators. This package provides several filter types, outlined below.","category":"page"},{"location":"#Estimator-types","page":"Home","title":"Estimator types","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"We provide a number of filter types","category":"page"},{"location":"","page":"Home","title":"Home","text":"KalmanFilter. A standard Kalman filter. Is restricted to linear dynamics (possibly time varying) and Gaussian noise.\nSqKalmanFilter. A standard Kalman filter on square-root form (slightly slower but more numerically stable with ill-conditioned covariance).\nExtendedKalmanFilter: For nonlinear systems, the EKF runs a regular Kalman filter on linearized dynamics. Uses ForwardDiff.jl for linearization (or user provided). The noise model must still be Gaussian and additive.\nUnscentedKalmanFilter: The Unscented Kalman filter often performs slightly better than the Extended Kalman filter but may be slightly more computationally expensive. The UKF handles nonlinear dynamics and measurement models, but still requires a Gaussian noise model (may be non additive) and still assumes that all posterior distributions are Gaussian, i.e., can not handle multi-modal posteriors.\nParticleFilter: The particle filter is a nonlinear estimator. This version of the particle filter is simple to use and assumes that both dynamics noise and measurement noise are additive. Particle filters handle multi-modal posteriors.\nAdvancedParticleFilter: This filter gives you more flexibility, at the expense of having to define a few more functions. This filter does not require the noise to be additive and is thus the most flexible filter type.\nAuxiliaryParticleFilter: This filter is identical to ParticleFilter, but uses a slightly different proposal mechanism for new particles.\nIMM: (Currently considered experimental) The Interacting Multiple Models filter switches between multiple internal filters based on a hidden Markov model. This filter is useful when the system dynamics change over time and the change can be modeled as a discrete Markov chain, i.e., the system may switch between a small number of discrete \"modes\".","category":"page"},{"location":"#Functionality","page":"Home","title":"Functionality","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package provides ","category":"page"},{"location":"","page":"Home","title":"Home","text":"Filtering, estimating x(t) given measurements up to and including time t. We call the filtered estimate x(tt) (read as x at t given t).\nSmoothing, estimating x(t) given data up to T t, i.e., x(tT).\nParameter estimation.","category":"page"},{"location":"","page":"Home","title":"Home","text":"All filters work in two distinct steps.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The prediction step (predict!). During prediction, we use the dynamics model to form x(tt-1) = f(x(t-1) )\nThe correction step (correct!). In this step, we adjust the predicted state x(tt-1) using the measurement y(t) to form x(tt).","category":"page"},{"location":"","page":"Home","title":"Home","text":"(The IMM filter is an exception to the above and has two additional steps, combine! and interact!)","category":"page"},{"location":"","page":"Home","title":"Home","text":"In general, all filters represent not only a point estimate of x(t), but a representation of the complete posterior probability distribution over x given all the data available up to time t. One major difference between different filter types is how they represent these probability distributions.","category":"page"},{"location":"#Particle-filter","page":"Home","title":"Particle filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"A particle filter represents the probability distribution over the state as a collection of samples, each sample is propagated through the dynamics function f individually. When a measurement becomes available, the samples, called particles, are given a weight based on how likely the particle is given the measurement. Each particle can thus be seen as representing a hypothesis about the current state of the system. After a few time steps, most weights are inevitably going to be extremely small, a manifestation of the curse of dimensionality, and a resampling step is incorporated to refresh the particle distribution and focus the particles on areas of the state space with high posterior probability.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Defining a particle filter (ParticleFilter) is straightforward, one must define the distribution of the noise df in the dynamics function, dynamics(x,u,p,t) and the noise distribution dg in the measurement function measurement(x,u,p,t). Both of these noise sources are assumed to be additive, but can have any distribution (see AdvancedParticleFilter for non-additive noise). The distribution of the initial state estimate d0 must also be provided. In the example below, we use linear Gaussian dynamics so that we can easily compare both particle and Kalman filters. (If we have something close to linear Gaussian dynamics in practice, we should of course use a Kalman filter and not a particle filter.)","category":"page"},{"location":"","page":"Home","title":"Home","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots\nusing DisplayAs # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Define problem","category":"page"},{"location":"","page":"Home","title":"Home","text":"nx = 2 # Dimension of state\nnu = 1 # Dimension of input\nny = 1 # Dimension of measurements\nN = 500 # Number of particles\n\nconst dg = MvNormal(ny,0.2) # Measurement noise Distribution\nconst df = MvNormal(nx,0.1) # Dynamics noise Distribution\nconst d0 = MvNormal(randn(nx),2.0) # Initial state Distribution\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Define linear state-space system (using StaticArrays for maximum performance)","category":"page"},{"location":"","page":"Home","title":"Home","text":"const A = SA[0.97043 -0.097368\n 0.09736 0.970437]\nconst B = SA[0.1; 0;;]\nconst C = SA[0 1.0]\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Next, we define the dynamics and measurement equations, they both take the signature (x,u,p,t) = (state, input, parameters, time) ","category":"page"},{"location":"","page":"Home","title":"Home","text":"dynamics(x,u,p,t) = A*x .+ B*u\nmeasurement(x,u,p,t) = C*x\nvecvec_to_mat(x) = copy(reduce(hcat, x)') # Helper function\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"the parameter p can be anything, and is often optional. If p is not provided when performing operations on filters, any p stored in the filter objects (if supported) is used. The default if none is provided and none is stored in the filter is p = LowLevelParticleFilters.NullParameters().","category":"page"},{"location":"","page":"Home","title":"Home","text":"We are now ready to define and use a filter","category":"page"},{"location":"","page":"Home","title":"Home","text":"pf = ParticleFilter(N, dynamics, measurement, df, dg, d0)","category":"page"},{"location":"","page":"Home","title":"Home","text":"With the filter in hand, we can simulate from its dynamics and query some properties","category":"page"},{"location":"","page":"Home","title":"Home","text":"du = MvNormal(nu,1.0) # Random input distribution for simulation\nxs,u,y = simulate(pf,200,du) # We can simulate the model that the pf represents\npf(u[1], y[1]) # Perform one filtering step using input u and measurement y\nparticles(pf) # Query the filter for particles, try weights(pf) or expweights(pf) as well\nx̂ = weighted_mean(pf) # using the current state","category":"page"},{"location":"","page":"Home","title":"Home","text":"If you want to perform batch filtering using an existing trajectory consisting of vectors of inputs and measurements, try any of the functions forward_trajectory, mean_trajectory:","category":"page"},{"location":"","page":"Home","title":"Home","text":"sol = forward_trajectory(pf, u, y) # Filter whole trajectories at once\nx̂,ll = mean_trajectory(pf, u, y)\nplot(sol, xreal=xs, markersize=2)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"u ad y are then assumed to be vectors of vectors. StaticArrays is recommended for maximum performance.","category":"page"},{"location":"","page":"Home","title":"Home","text":"If MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} with the layout T × n_state using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For a full usage example, see the benchmark section below or example_lineargaussian.jl","category":"page"},{"location":"#Resampling","page":"Home","title":"Resampling","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The particle filter will perform a resampling step whenever the distribution of the weights has become degenerate. The resampling is triggered when the effective number of samples is smaller than pf.resample_threshold in 0 1, this value can be set when constructing the filter. How the resampling is done is governed by pf.resampling_strategy, we currently provide ResampleSystematic <: ResamplingStrategy as the only implemented strategy. See https://en.wikipedia.org/wiki/Particle_filter for more info.","category":"page"},{"location":"#Particle-Smoothing","page":"Home","title":"Particle Smoothing","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Smoothing is the process of finding the best state estimate given both past and future data. Smoothing is thus only possible in an offline setting. This package provides a particle smoother, based on forward filtering, backward simulation (FFBS), example usage follows:","category":"page"},{"location":"","page":"Home","title":"Home","text":"N = 2000 # Number of particles\nT = 80 # Number of time steps\nM = 100 # Number of smoothed backwards trajectories\npf = ParticleFilter(N, dynamics, measurement, df, dg, d0)\ndu = MvNormal(nu,1) # Control input distribution\nx,u,y = simulate(pf,T,du) # Simulate trajectory using the model in the filter\ntosvec(y) = reinterpret(SVector{length(y[1]),Float64}, reduce(hcat,y))[:] |> copy\nx,u,y = tosvec.((x,u,y)) # It's good for performance to use StaticArrays to the extent possible\n\nxb,ll = smooth(pf, M, u, y) # Sample smoothing particles\nxbm = smoothed_mean(xb) # Calculate the mean of smoothing trajectories\nxbc = smoothed_cov(xb) # And covariance\nxbt = smoothed_trajs(xb) # Get smoothing trajectories\nxbs = [diag(xbc) for xbc in xbc] |> vecvec_to_mat .|> sqrt\nplot(xbm', ribbon=2xbs, lab=\"PF smooth\")\nplot!(vecvec_to_mat(x), l=:dash, lab=\"True\")","category":"page"},{"location":"","page":"Home","title":"Home","text":"We can plot the particles themselves as well","category":"page"},{"location":"","page":"Home","title":"Home","text":"downsample = 5\nplot(vecvec_to_mat(x), l=(4,), layout=(2,1), show=false)\nscatter!(xbt[1, 1:downsample:end, :]', subplot=1, show=false, m=(1,:black, 0.5), lab=\"\")\nscatter!(xbt[2, 1:downsample:end, :]', subplot=2, m=(1,:black, 0.5), lab=\"\")\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"#Kalman-filter","page":"Home","title":"Kalman filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The KalmanFilter (wiki) assumes that f and g are linear functions, i.e., that they can be written on the form","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nx(t+1) = Ax(t) + Bu(t) + w(t)\ny(t) = Cx(t) + Du(t) + e(t)\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"for some matrices ABCD where w sim N(0 R_1) and e sim N(0 R_2) are zero mean and Gaussian. The Kalman filter represents the posterior distributions over x by the mean and a covariance matrix. The magic behind the Kalman filter is that linear transformations of Gaussian distributions remain Gaussian, and we thus have a very efficient way of representing them.","category":"page"},{"location":"","page":"Home","title":"Home","text":"A Kalman filter is easily created using the constructor KalmanFilter. Many of the functions defined for particle filters, are defined also for Kalman filters, e.g.:","category":"page"},{"location":"","page":"Home","title":"Home","text":"R1 = cov(df)\nR2 = cov(dg)\nkf = KalmanFilter(A, B, C, 0, R1, R2, d0)\nsol = forward_trajectory(kf, u, y) # sol contains filtered state, predictions, pred cov, filter cov, loglik\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"It can also be called in a loop like the pf above","category":"page"},{"location":"","page":"Home","title":"Home","text":"for t = 1:T\n kf(u,y) # Performs both correct! and predict!\n # alternatively\n ll, e = correct!(kf, y, nothing, t) # Returns loglikelihood and prediction error (plus other things if you want)\n x = state(kf) # Access the state estimate\n R = covariance(kf) # Access the covariance of the estimate\n predict!(kf, u, nothing, t)\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"The matrices in the Kalman filter may be time varying, such that A[:, :, t] is A(t). They may also be provided as functions on the form A(t) = A(x u p t). This works for both dynamics and covariance matrices.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The numeric type used in the Kalman filter is determined from the mean of the initial state distribution, so make sure that this has the correct type if you intend to use, e.g., Float32 or ForwardDiff.Dual for automatic differentiation.","category":"page"},{"location":"#Smoothing-using-KF","page":"Home","title":"Smoothing using KF","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Kalman filters can also be used for smoothing ","category":"page"},{"location":"","page":"Home","title":"Home","text":"kf = KalmanFilter(A, B, C, 0, cov(df), cov(dg), d0)\nxT,R,lls = smooth(kf, u, y) # Returns smoothed state, smoothed cov, loglik\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Plot and compare PF and KF","category":"page"},{"location":"","page":"Home","title":"Home","text":"plot(vecvec_to_mat(xT), lab=\"Kalman smooth\", layout=2)\nplot!(xbm', lab=\"pf smooth\")\nplot!(vecvec_to_mat(x), lab=\"true\")","category":"page"},{"location":"#Kalman-filter-tuning-tutorial","page":"Home","title":"Kalman filter tuning tutorial","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The tutorial \"How to tune a Kalman filter\" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model.","category":"page"},{"location":"#Unscented-Kalman-Filter","page":"Home","title":"Unscented Kalman Filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The UnscentedKalmanFilter represents posterior distributions over x as Gaussian distributions just like the KalmanFilter, but propagates them through a nonlinear function f by a deterministic sampling of a small number of particles called sigma points (this is referred to as the unscented transform). This UKF thus handles nonlinear functions fg, but only Gaussian disturbances and unimodal posteriors. The UKF will by default treat the noise as additive, but by using the augmented UKF form, non-additive noise may be handled as well. See the docstring of UnscentedKalmanFilter for more details.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The UKF takes the same arguments as a regular KalmanFilter, but the matrices defining the dynamics are replaced by two functions, dynamics and measurement, working in the same way as for the ParticleFilter above (unless the augmented form is used).","category":"page"},{"location":"","page":"Home","title":"Home","text":"ukf = UnscentedKalmanFilter(dynamics, measurement, cov(df), cov(dg), MvNormal(SA[1.,1.]); nu=nu, ny=ny)","category":"page"},{"location":"","page":"Home","title":"Home","text":"info: Info\nIf your function dynamics describes a continuous-time ODE, do not forget to discretize it before passing it to the UKF. See Discretization for more information.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The UnscentedKalmanFilter has many customization options, see the docstring for more details. In particular, the UKF may be created with a linear measurement model as an optimization.","category":"page"},{"location":"#Extended-Kalman-Filter","page":"Home","title":"Extended Kalman Filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The ExtendedKalmanFilter (EKF) is similar to the UKF, but propagates Gaussian distributions by linearizing the dynamics and using the formulas for linear systems similar to the standard Kalman filter. This can be slightly faster than the UKF (not always), but also less accurate for strongly nonlinear systems. The linearization is performed automatically using ForwardDiff.jl unless the user provides Jacobian functions that compute A and C. In general, the UKF is recommended over the EKF unless the EKF is faster and computational performance is the top priority.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The EKF constructor has the following two signatures","category":"page"},{"location":"","page":"Home","title":"Home","text":"ExtendedKalmanFilter(dynamics, measurement, R1, R2, d0=MvNormal(R1); nu::Int, p = LowLevelParticleFilters.NullParameters(), α = 1.0, check = true, Ajac = nothing, Cjac = nothing)\nExtendedKalmanFilter(kf, dynamics, measurement; Ajac = nothing, Cjac = nothing)","category":"page"},{"location":"","page":"Home","title":"Home","text":"The first constructor takes all the arguments required to initialize the extended Kalman filter, while the second one takes an already defined standard Kalman filter. using the first constructor, the user must provide the number of inputs to the system, nu.","category":"page"},{"location":"","page":"Home","title":"Home","text":"where kf is a standard KalmanFilter from which the covariance properties are taken.","category":"page"},{"location":"","page":"Home","title":"Home","text":"info: Info\nIf your function dynamics describes a continuous-time ODE, do not forget to discretize it before passing it to the UKF. See Discretization for more information.","category":"page"},{"location":"#AdvancedParticleFilter","page":"Home","title":"AdvancedParticleFilter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The AdvancedParticleFilter works very much like the ParticleFilter, but admits more flexibility in its noise models.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The AdvancedParticleFilter type requires you to implement the same functions as the regular ParticleFilter, but in this case you also need to handle sampling from the noise distributions yourself. The function dynamics must have a method signature like below. It must provide one method that accepts state vector, control vector, parameter, time and noise::Bool that indicates whether or not to add noise to the state. If noise should be added, this should be done inside dynamics An example is given below","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Random\nconst rng = Random.Xoshiro()\nfunction dynamics(x, u, p, t, noise=false) # It's important that `noise` defaults to false\n x = A*x .+ B*u # A simple linear dynamics model in discrete time\n if noise\n x += rand(rng, df) # it's faster to supply your own rng\n end\n x\nend\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"The measurement_likelihood function must have a method accepting state, input, measurement, parameter and time, and returning the log-likelihood of the measurement given the state, a simple example below:","category":"page"},{"location":"","page":"Home","title":"Home","text":"function measurement_likelihood(x, u, y, p, t)\n logpdf(dg, C*x-y) # An example of a simple linear measurement model with normal additive noise\nend\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"This gives you very high flexibility. The noise model in either function can, for instance, be a function of the state, something that is not possible for the simple ParticleFilter. To be able to simulate the AdvancedParticleFilter like we did with the simple filter above, the measurement method with the signature measurement(x,u,p,t,noise=false) must be available and return a sample measurement given state (and possibly time). For our example measurement model above, this would look like this","category":"page"},{"location":"","page":"Home","title":"Home","text":"# This function is only required for simulation\nmeasurement(x, u, p, t, noise=false) = C*x + noise*rand(rng, dg)\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"We now create the AdvancedParticleFilter and use it in the same way as the other filters:","category":"page"},{"location":"","page":"Home","title":"Home","text":"apf = AdvancedParticleFilter(N, dynamics, measurement, measurement_likelihood, df, d0)\nsol = forward_trajectory(apf, u, y, ny) # Perform batch filtering","category":"page"},{"location":"","page":"Home","title":"Home","text":"plot(sol, xreal=x)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"We can even use this type as an AuxiliaryParticleFilter","category":"page"},{"location":"","page":"Home","title":"Home","text":"apfa = AuxiliaryParticleFilter(apf)\nsol = forward_trajectory(apfa, u, y, ny)\nplot(sol, dim=1, xreal=x) # Same as above, but only plots a single dimension\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"See the tutorials section for more advanced examples, including state estimation for DAE (Differential-Algebraic Equation) systems.","category":"page"},{"location":"#Troubleshooting-and-tuning","page":"Home","title":"Troubleshooting and tuning","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Tuning a particle filter can be quite the challenge. To assist with this, we provide som visualization tools","category":"page"},{"location":"","page":"Home","title":"Home","text":"debugplot(pf,u[1:20],y[1:20], runall=true, xreal=x[1:20])","category":"page"},{"location":"","page":"Home","title":"Home","text":"The plot displays all state variables and all measurements. The heatmap in the background represents the weighted particle distributions per time step. For the measurement sequences, the heatmap represent the distributions of predicted measurements. The blue dots corresponds to measured values. In this case, we simulated the data and we had access to the state as well, if we do not have that, just omit xreal. You can also manually step through the time-series using","category":"page"},{"location":"","page":"Home","title":"Home","text":"commandplot(pf,u,y; kwargs...)","category":"page"},{"location":"","page":"Home","title":"Home","text":"For options to the debug plots, see ?pplot.","category":"page"},{"location":"#Tuning-noise-parameters-through-optimization","page":"Home","title":"Tuning noise parameters through optimization","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"See examples in Parameter Estimation.","category":"page"},{"location":"#Tuning-through-simulation","page":"Home","title":"Tuning through simulation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"It is possible to sample from the Bayesian model implied by a filter and its parameters by calling the function simulate. A simple tuning strategy is to adjust the noise parameters such that a simulation looks \"similar\" to the data, i.e., the data must not be too unlikely under the model.","category":"page"},{"location":"#Videos","page":"Home","title":"Videos","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Several video tutorials using this package are available in the playlists","category":"page"},{"location":"","page":"Home","title":"Home","text":"System identification in Julia\nControl systems in Julia","category":"page"},{"location":"","page":"Home","title":"Home","text":"Some examples featuring this package in particular are","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Estimation of time-varying parameters:","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Adaptive control by means of estimation of time-varying parameters:","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"}] +[{"location":"distributions/#Performance-tips","page":"Performance tips","title":"Performance tips","text":"","category":"section"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"Use of StaticArrays.jl is recommended for optimal performance when the state dimension is small, e.g., less than about 10-15 for Kalman filters and less than about 100 for particle filters. In the section Parameter optimization we demonstrate one workflow that makes use of StaticArrays everywhere it is needed for an UnscentedKalmanFilter in order to get a completely allocation free filter. The following arrays must be static for this to hold","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"The initial state distribution (the vector and matrix passed to d0 = MvNormal(μ, Σ) for Kalman filters). If you are performing parameter optimization with gradients derived using ForwardDiff.jl, these must further have the correct element type. How to achieve this is demonstrated in the liked example above.\nInputs u measured outputs y.\nIn case of Kalman filters, the dynamic model matrices A, B, C, D and the covariance matrices R1, R2.\nThe dynamics functions for UnscentedKalmanFilter and particle filters must further return static arrays when passed static arrays as inputs.","category":"page"},{"location":"distributions/#Analysis-using-JET","page":"Performance tips","title":"Analysis using JET","text":"","category":"section"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"All flavors of Kalman filters are analyzed for potential runtime dispatch using JET.jl. This analysis is performed in the tests and generally requires a completely static filter using static arrays internally. See the tests for an example of how to set a filter up this way.","category":"page"},{"location":"distributions/#High-performance-Distributions","page":"Performance tips","title":"High performance Distributions","text":"","category":"section"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"When using LowLevelParticleFilters, a number of methods related to distributions are defined for static arrays, making logpdf etc. faster. We also provide a new kind of distribution: TupleProduct <: MultivariateDistribution that behaves similarly to the Product distribution. The TupleProduct however stores the individual distributions in a tuple, has compile-time known length and supports Mixed <: ValueSupport, meaning that it can be a product of both Continuous and Discrete dimensions, something not supported by the standard Product. Example","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"using BenchmarkTools, LowLevelParticleFilters, Distributions, StaticArrays\ndt = TupleProduct((Normal(0,2), Normal(0,2), Binomial())) # Mixed value support","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"A small benchmark","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"sv = @SVector randn(2)\nd = Distributions.Product([Normal(0,2), Normal(0,2)])\ndt = TupleProduct((Normal(0,2), Normal(0,2)))\ndm = MvNormal(2, 2)\n@btime logpdf($d,$(Vector(sv))) # 19.536 ns (0 allocations: 0 bytes)\n@btime logpdf($dt,$(Vector(sv))) # 13.742 ns (0 allocations: 0 bytes)\n@btime logpdf($dm,$(Vector(sv))) # 11.392 ns (0 allocations: 0 bytes)","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"@btime logpdf($d,$sv) # 13.964 ns (0 allocations: 0 bytes)\n@btime logpdf($dt,$sv) # 12.817 ns (0 allocations: 0 bytes)\n@btime logpdf($dm,$sv) # 8.383 ns (0 allocations: 0 bytes)","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"Without loading LowLevelParticleFilters, the timing for the native distributions are the following","category":"page"},{"location":"distributions/","page":"Performance tips","title":"Performance tips","text":"@btime logpdf($d,$sv) # 18.040 ns (0 allocations: 0 bytes)\n@btime logpdf($dm,$sv) # 9.938 ns (0 allocations: 0 bytes)","category":"page"},{"location":"parameter_estimation/#Parameter-Estimation","page":"Parameter estimation","title":"Parameter Estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"State estimation is an integral part of many parameter-estimation methods. Below, we will illustrate several different methods of performing parameter estimation. We can roughly divide the methods into two camps","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Methods that optimize prediction error or likelihood by tweaking model parameters.\nMethods that add the parameters to be estimated as state variables in the model and estimate them using standard state estimation. ","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"From the first camp, we provide som basic functionality for maximum-likelihood estimation and MAP estimation, described below. An example of (2), joint state and parameter estimation, is provided in Joint state and parameter estimation.","category":"page"},{"location":"parameter_estimation/#Maximum-likelihood-estimation","page":"Parameter estimation","title":"Maximum-likelihood estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Filters calculate the likelihood and prediction errors while performing filtering, this can be used to perform maximum likelihood estimation or prediction-error minimization. One can estimate all kinds of parameters using this method, in the example below, we will estimate the noise covariance. We may for example plot likelihood as function of the variance of the dynamics noise like this:","category":"page"},{"location":"parameter_estimation/#Generate-data-by-simulation","page":"Parameter estimation","title":"Generate data by simulation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"This simulates the same linear system as on the index page of the documentation","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots\nnx = 2 # Dimension of state\nnu = 2 # Dimension of input\nny = 2 # Dimension of measurements\nN = 2000 # Number of particles\n\nconst dg = MvNormal(ny,1.0) # Measurement noise Distribution\nconst df = MvNormal(nx,1.0) # Dynamics noise Distribution\nconst d0 = MvNormal(@SVector(randn(nx)),2.0) # Initial state Distribution\n\nconst A = SA[1 0.1; 0 1]\nconst B = @SMatrix [0.0 0.1; 1 0.1]\nconst C = @SMatrix [1.0 0; 0 1]\n\ndynamics(x,u,p,t) = A*x .+ B*u \nmeasurement(x,u,p,t) = C*x\nvecvec_to_mat(x) = copy(reduce(hcat, x)') # Helper function\npf = ParticleFilter(N, dynamics, measurement, df, dg, d0)\nxs,u,y = simulate(pf,300,df)","category":"page"},{"location":"parameter_estimation/#Compute-likelihood-for-various-values-of-the-parameters","page":"Parameter estimation","title":"Compute likelihood for various values of the parameters","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"p = nothing\nsvec = exp10.(LinRange(-0.8, 1.2, 60))\nllspf = map(svec) do s\n df = MvNormal(nx,s)\n pfs = ParticleFilter(N, dynamics, measurement, df, dg, d0)\n loglik(pfs, u, y, p)\nend\nplot( svec, llspf,\n xscale = :log10,\n title = \"Log-likelihood\",\n xlabel = \"Dynamics noise standard deviation\",\n lab = \"PF\",\n)\nvline!([svec[findmax(llspf)[2]]], l=(:dash,:blue), primary=false)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"the correct value for the simulated data is 1 (the simulated system is the same as on the front page of the docs).","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We can do the same with a Kalman filter","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"eye(n) = SMatrix{n,n}(1.0I(n))\nllskf = map(svec) do s\n kfs = KalmanFilter(A, B, C, 0, s^2*eye(nx), eye(ny), d0)\n loglik(kfs, u, y, p)\nend\nplot!(svec, llskf, yscale=:identity, xscale=:log10, lab=\"Kalman\", c=:red)\nvline!([svec[findmax(llskf)[2]]], l=(:dash,:red), primary=false)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"the result can be quite noisy due to the stochastic nature of particle filtering. The particle filter likelihood agrees with the Kalman-filter estimate, which is optimal for the linear example system we are simulating here, apart for when the noise variance is small. Due to particle depletion, particle filters often struggle when dynamics-noise is too small. This problem is mitigated by using a greater number of particles, or simply by not using a too small covariance.","category":"page"},{"location":"parameter_estimation/#MAP-estimation","page":"Parameter estimation","title":"MAP estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"In this example, we will estimate the variance of the noises in the dynamics and the measurement functions.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"To solve a MAP estimation problem, we need to define a function that takes a parameter vector and returns a filter, the parameters are used to construct the covariance matrices:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*eye(nx), exp(θ[2])^2*eye(ny), d0) # Works with particle filters as well\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The call to exp on the parameters is so that we can define log-normal priors","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"priors = [Normal(0,2),Normal(0,2)]","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Now we call the function log_likelihood_fun that returns a function to be minimized","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"ll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Since this is a low-dimensional problem, we can plot the LL on a 2d-grid","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"function meshgrid(a,b)\n grid_a = [i for i in a, j in b]\n grid_b = [j for i in a, j in b]\n grid_a, grid_b\nend\nNv = 20\nv = LinRange(-0.7,1,Nv)\nllxy = (x,y) -> ll([x;y])\nVGx, VGy = meshgrid(v,v)\nVGz = llxy.(VGx, VGy)\nheatmap(\n VGz,\n xticks = (1:Nv, round.(v, digits = 2)),\n yticks = (1:Nv, round.(v, digits = 2)),\n xlabel = \"sigma v\",\n ylabel = \"sigma w\",\n) # Yes, labels are reversed","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"For higher-dimensional problems, we may estimate the parameters using an optimizer, e.g., Optim.jl.","category":"page"},{"location":"parameter_estimation/#Bayesian-inference-using-PMMH","page":"Parameter estimation","title":"Bayesian inference using PMMH","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We proceed like we did for MAP above, but when calling the function metropolis, we will get the entire posterior distribution of the parameter vector, for the small cost of a massive increase in the amount of computations. metropolis runs the Metropolis Hastings algorithm, or more precisely if a particle filter is used, the \"Particle Marginal Metropolis Hastings\" (PMMH) algorithm. Here we use the Kalman filter simply to have the documentation build a bit faster, it can be quite heavy to run.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"filter_from_parameters(θ, pf = nothing) = KalmanFilter(A, B, C, 0, exp(θ[1])^2*I(nx), exp(θ[2])^2*I(ny), d0) # Works with particle filters as well\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The call to exp on the parameters is so that we can define log-normal priors","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"priors = [Normal(0,2),Normal(0,2)]\nll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)\nθ₀ = log.([1.0, 1.0]) # Starting point\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We also need to define a function that suggests a new point from the \"proposal distribution\". This can be pretty much anything, but it has to be symmetric since I was lazy and simplified an equation.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"draw = θ -> θ .+ 0.05 .* randn.() # This function dictates how new proposal parameters are being generated. \nburnin = 200 # remove this many initial samples (\"burn-in period\")\n@info \"Starting Metropolis algorithm\"\n@time theta, lls = metropolis(ll, 2200, θ₀, draw) # Run PMMH for 2200 iterations\nthetam = reduce(hcat, theta)'[burnin+1:end,:] # Build a matrix of the output\nhistogram(exp.(thetam), layout=(3,1), lab=[\"R1\" \"R2\"]); plot!(lls[burnin+1:end], subplot=3, lab=\"log likelihood\") # Visualize","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"In this example, we initialize the MH algorithm on the correct value θ₀, in general, you'd see a period in the beginning where the likelihood (bottom plot) is much lower than during the rest of the sampling, this is the reason we remove a number of samples in the beginning, typically referred to as \"burn in\".","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"If you are lucky, you can run the above threaded as well. I tried my best to make particle filters thread safe with their own rngs etc., but your milage may vary. For threading to help, the dynamics must be non-allocating, e.g., by using StaticArrays etc.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"@time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 2200, θ₀, draw, nthreads=2)\nhistogram(exp.(thetalls[:,1:2]), layout=3)\nplot!(thetalls[:,3], subplot=3)","category":"page"},{"location":"parameter_estimation/#Bayesian-inference-using-DynamicHMC.jl","page":"Parameter estimation","title":"Bayesian inference using DynamicHMC.jl","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The following snippet of code performs the same estimation as above, but uses the much more sophisticated HMC sampler in DynamicHMC.jl rather than the PMMH sampler above. This package requires the log-likelihood function to be wrapped in a custom struct that implements the LogDensityProblems interface, which is done below. We also indicate that we want to use ForwardDiff.jl to compute the gradients for fast sampling.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using DynamicHMC, LogDensityProblemsAD, ForwardDiff, LogDensityProblems, LinearAlgebra, Random\n\nstruct LogTargetDensity{F}\n ll::F\n dim::Int\nend\nLogDensityProblems.logdensity(p::LogTargetDensity, θ) = p.ll(θ)\nLogDensityProblems.dimension(p::LogTargetDensity) = p.dim\nLogDensityProblems.capabilities(::Type{LogTargetDensity}) = LogDensityProblems.LogDensityOrder{0}()\n\nfunction filter_from_parameters(θ, pf = nothing)\n # It's important that the distribution of the initial state has the same\n # element type as the parameters. DynamicHMC will use Dual numbers for differentiation,\n # hence, we make sure that d0 has `eltype(d0) = eltype(θ)`\n T = eltype(θ)\n d0 = MvNormal(T.(d0.μ), T.(d0.Σ))\n KalmanFilter(A, B, C, 0, exp(θ[1])^2*eye(nx), exp(θ[2])^2*eye(ny), d0) \nend\nll = log_likelihood_fun(filter_from_parameters, priors, u, y, p)\n\nD = length(θ₀)\nℓπ = LogTargetDensity(ll, D)\n∇P = ADgradient(:ForwardDiff, ℓπ)\n\nresults = mcmc_with_warmup(Random.default_rng(), ∇P, 3000)\nDynamicHMC.Diagnostics.summarize_tree_statistics(results.tree_statistics)\nlls = [ts.π for ts in results.tree_statistics]\n\nhistogram(exp.(results.posterior_matrix)', layout=(3,1), lab=[\"R1\" \"R2\"])\nplot!(lls, subplot=3, lab=\"log likelihood\") # Visualize","category":"page"},{"location":"parameter_estimation/#Joint-state-and-parameter-estimation","page":"Parameter estimation","title":"Joint state and parameter estimation","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"In this example, we'll show how to perform parameter estimation by treating a parameter as a state variable. This method can not only estimate constant parameters, but also time-varying parameters. The system we will consider is a quadruple tank, where two upper tanks feed into two lower tanks. The outlet for tank 1 can vary in size, simulating, e.g., that something partially blocks the outlet. We start by defining the dynamics on a form that changes the outlet area a_1 at time t=500:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LowLevelParticleFilters\nusing SeeToDee\nusing Distributions\nusing StaticArrays\nusing Plots, LinearAlgebra\n\nfunction quadtank(h,u,p,t)\n kc = 0.5\n k1, k2, g = 1.6, 1.6, 9.81\n A1 = A3 = A2 = A4 = 4.9\n a1, a3, a2, a4 = 0.03, 0.03, 0.03, 0.03\n γ1, γ2 = 0.2, 0.2\n\n if t > 500\n a1 *= 2 # Change the parameter at t = 500\n end\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n \n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n ]\nend\n\nnu = 2 # number of control inputs\nnx = 4 # number of state variables\nny = 2 # number of measured outputs\nTs = 1 # sample time\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We then define a measurement function, we measure the levels of tanks 1 and 2, and discretize the continuous-time dynamics using a Runge-Kutta 4 integrator SeeToDee.Rk4:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"measurement(x,u,p,t) = SA[x[1], x[2]]\ndiscrete_dynamics = SeeToDee.Rk4(quadtank, Ts)\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We simulate the system using the rollout function and add some noise to the measurements. The inputs in this case are just square waves.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Tperiod = 200\nt = 0:Ts:1000\nu = vcat.(0.25 .* sign.(sin.(2pi/Tperiod .* t)) .+ 0.25)\nu = SVector{nu}.(vcat.(u,u))\nx0 = Float64[2,2,3,3]\nx = LowLevelParticleFilters.rollout(discrete_dynamics, x0, u)[1:end-1]\ny = measurement.(x, u, 0, 0)\ny = [y .+ 0.01.*randn.() for y in y]\n\nplot(\n plot(reduce(hcat, x)', title=\"State\"),\n plot(reduce(hcat, u)', title=\"Inputs\")\n)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"To perform the joint state and parameter estimation, we define a version of the dynamics that contains an extra state, corresponding to the unknown or time varying parameter, in this case a_1. We do not have any apriori information about how this parameter changes, so we say that its derivative is 0 and it's thus only driven by noise:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"function quadtank_paramest(h, u, p, t)\n kc = 0.5\n k1, k2, g = 1.6, 1.6, 9.81\n A1 = A3 = A2 = A4 = 4.9\n a3, a2, a4 = 0.03, 0.03, 0.03\n γ1, γ2 = 0.2, 0.2\n\n a1 = h[5] # the a1 parameter is a state\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n \n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n 0 # the state is only driven by noise\n ]\nend\n\ndiscrete_dynamics_params = SeeToDee.Rk4(quadtank_paramest, Ts)\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We then define a nonlinear state estimator, we will use the UnscentedKalmanFilter, and solve the filtering problem. We start by an initial state estimate x_0 that is slightly off for the parameter a_1","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"nx = 5\nR1 = SMatrix{nx,nx}(Diagonal([0.1, 0.1, 0.1, 0.1, 0.0001])) # Use of StaticArrays is generally good for performance\nR2 = SMatrix{ny,ny}(Diagonal((1e-2)^2 * ones(ny)))\nx0 = SA[2, 2, 3, 3, 0.02] # The SA prefix makes the array static, which is good for performance\n\nkf = UnscentedKalmanFilter(discrete_dynamics_params, measurement, R1, R2, MvNormal(x0, R1); ny, nu, Ts)\n\nsol = forward_trajectory(kf, u, y)\nplot(sol, plotx=false, plotxt=true, plotu=false, ploty=true, legend=:bottomright)\nplot!([0,500,500,1000], [0.03, 0.03, 0.06, 0.06], l=(:dash, :black), sp=5, lab=\"True param\")","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"as we can see, the correct value of the parameter is quickly found (x_5), and it also adapts at t=500 when the parameter value changes. The speed with which the parameter adapts to changes is determined by the covariance matrix R_1, a higher value results in faster adaptation, but also higher sensitivity to noise. ","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"If adaptive parameter estimation is coupled with a model-based controller, we get an adaptive controller! Note: the state that corresponds to the estimated parameter is typically not controllable, a fact that may require some special care for some control methods.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We may ask ourselves, what's the difference between a parameter and a state variable if we can add parameters as state variables? Typically, parameters do not vary with time, and if they do, they vary significantly slower than the state variables. State variables also have dynamics associate with them, whereas we often have no idea about how the parameters vary other than that they vary slowly.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Abrupt changes to the dynamics like in the example above can happen in practice, for instance, due to equipment failure or change of operating mode. This can be treated as a scenario with time-varying parameters that are continuously estimated. ","category":"page"},{"location":"parameter_estimation/#Using-an-optimizer","page":"Parameter estimation","title":"Using an optimizer","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"The state estimators in this package are all statistically motivated and thus compute things like the likelihood of the data as a by-product of the estimation. Maximum-likelihood or prediction-error estimation is thus very straight-forward by simply calling a gradient-based optimizer with gradients provided by differentiating through the state estimator using automatic differentiation. In this example, we will continue the example from above, but now estimate all the parameters of the quad-tank process. This time, they will not vary with time. We will first use a standard optimization algorithm from Optim.jl to minimize the cost function based on the prediction error, and then use a Gauss-Newton optimizer.","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We now define the dynamics function such that it takes its parameters from the p input argument. We also define a variable p_true that contains the true values that we will use to simulate some estimation data","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"function quadtank(h, u, p, t)\n kc = p[1]\n k1, k2, g = p[2], p[3], 9.81\n A1 = A3 = A2 = A4 = p[4]\n a1 = a3 = a2 = a4 = p[5]\n γ1 = γ2 = p[6]\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n \n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n ]\nend\n\ndiscrete_dynamics = SeeToDee.Rk4(quadtank, Ts) # Discretize the dynamics using a 4:th order Runge-Kutta integrator\np_true = [0.5, 1.6, 1.6, 4.9, 0.03, 0.2]\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Similar to previous example, we simulate the system, this time using a more exciting input in order to be able to identify several parameters","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using Random; Random.seed!(1) # hide\nTperiod = 200\nt = 0:Ts:1000\nu1 = vcat.(0.25 .* sign.(sin.(2pi/Tperiod .* (t ./ 40).^2)) .+ 0.25)\nu2 = vcat.(0.25 .* sign.(sin.(2pi/Tperiod .* (t ./ 40).^2 .+ pi/2)) .+ 0.25)\nu = SVector{nu}.(vcat.(u1,u2))\nx0 = SA[2.0,2,3,3] # Initial condition, static array for performance\nx = LowLevelParticleFilters.rollout(discrete_dynamics, x0, u, p_true)[1:end-1]\ny = measurement.(x, u, 0, 0)\ny = [y .+ 0.01 .* randn.() for y in y]\n\nplot(\n plot(reduce(hcat, x)', title=\"State\"),\n plot(reduce(hcat, u)', title=\"Inputs\")\n)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"This time, we define a cost function for the optimizer to optimize, we'll use the sum of squared errors (sse). It's important to define the UKF with an initial state distribution with the same element type as the parameter vector so that automatic differentiation through the state estimator works, hence the explicit casting T.(x0) and T.(R1). We also make sure to use StaticArrays for the covariance matrices and the initial condition for performance reasons (optional).","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"nx = 4\nR1 = SMatrix{nx,nx}(Diagonal([0.1, 0.1, 0.1, 0.1])) # Use of StaticArrays is generally good for performance\nR2 = SMatrix{ny,ny}(Diagonal((1e-2)^2 * ones(ny)))\nx0 = SA[2.0, 2, 3, 3]\n\nfunction cost(p::Vector{T}) where T\n kf = UnscentedKalmanFilter(discrete_dynamics, measurement, R1, R2, MvNormal(T.(x0), T.(R1)); ny, nu, Ts)\n LowLevelParticleFilters.sse(kf, u, y, p) # Sum of squared prediction errors\nend\nnothing # hide","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We generate a random initial guess for the estimation problem","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"p_guess = p_true .+ 0.1*p_true .* randn(length(p_true))","category":"page"},{"location":"parameter_estimation/#Solving-using-Optim","page":"Parameter estimation","title":"Solving using Optim","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We first minimize the cost using the BFGS optimization algorithm from Optim.jl","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using Optim\nres = Optim.optimize(\n cost,\n p_guess,\n BFGS(),\n Optim.Options(\n show_trace = true,\n show_every = 5,\n iterations = 100,\n time_limit = 30,\n ),\n autodiff = :forward, # Indicate that we want to use forward-mode AD to derive gradients\n)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"We started out with a normalized parameter error of","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LinearAlgebra\nnorm(p_true - p_guess) / norm(p_true)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"and ended with","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"p_opt = res.minimizer\nnorm(p_true - p_opt) / norm(p_true)","category":"page"},{"location":"parameter_estimation/#Solving-using-Gauss-Newton-optimization","page":"Parameter estimation","title":"Solving using Gauss-Newton optimization","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Below, we optimize the sum of squared residuals again, but this time we do it using a Gauss-Newton style algorithm (Levenberg Marquardt). These algorithms want the entire residual vector rather than the sum of squares of the residuals, so we define an alternative \"cost function\" called residuals that calls the lower-level function LowLevelParticleFilters.prediction_errors!","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using LeastSquaresOptim\n\nfunction residuals!(res, p::Vector{T}) where T\n kf = UnscentedKalmanFilter(discrete_dynamics, measurement, R1, R2, MvNormal(T.(x0), T.(R1)); ny, nu, Ts)\n LowLevelParticleFilters.prediction_errors!(res, kf, u, y, p) \nend\n\nres_gn = optimize!(LeastSquaresProblem(x = copy(p_guess), f! = residuals!, output_length = length(y)*ny, autodiff = :forward), LevenbergMarquardt())\n\np_opt_gn = res_gn.minimizer\nnorm(p_true - p_opt_gn) / norm(p_true)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Gauss-Newton algorithms are often more efficient at sum-of-squares minimization than the more generic BFGS optimizer. This form of Gauss-Newton optimization of prediction errors is also available through ControlSystemIdentification.jl, which uses this package undernath the hood.","category":"page"},{"location":"parameter_estimation/#Identifiability","page":"Parameter estimation","title":"Identifiability","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"There is no guarantee that we will recover the true parameters for this system, especially not if the input excitation is poor, but we will generally find parameters that results in a good predictor for the system (this is after all what we're optimizing for). A tool like StructuralIdentifiability.jl may be used to determine the identifiability of parameters and state variables, something that for this system could look like","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"using StructuralIdentifiability\n\node = @ODEmodel(\n h1'(t) = -a1/A1 * h1(t) + a3/A1*h3(t) + gam*k1/A1 * u1(t),\n h2'(t) = -a2/A2 * h2(t) + a4/A2*h4(t) + gam*k2/A2 * u2(t),\n h3'(t) = -a3/A3*h3(t) + (1-gam)*k2/A3 * u2(t),\n h4'(t) = -a4/A4*h4(t) + (1-gam)*k1/A4 * u1(t),\n\ty1(t) = h1(t),\n y2(t) = h2(t),\n)\n\nlocal_id = assess_local_identifiability(ode, 0.99)","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"where we have made the substitution sqrt h rightarrow h due to a limitation of the tool. The output of the above analysis is ","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"julia> local_id = assess_local_identifiability(ode, 0.99)\nDict{Nemo.fmpq_mpoly, Bool} with 15 entries:\n a3 => 0\n gam => 1\n k2 => 0\n A4 => 0\n h4 => 0\n h2 => 1\n A3 => 0\n a1 => 0\n A2 => 0\n k1 => 0\n a4 => 0\n h3 => 0\n h1 => 1\n A1 => 0\n a2 => 0","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"indicating that we can not hope to resolve all of the parameters. However, using appropriate regularization from prior information, we might still recover a lot of information about the system. Regularization could easily be added to the function cost above, e.g., using a penalty like (p-p_guess)'Γ*(p-p_guess) for some matrix Gamma, to indicate our confidence in the initial guess.","category":"page"},{"location":"parameter_estimation/#Videos","page":"Parameter estimation","title":"Videos","text":"","category":"section"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Examples of parameter estimation are available here","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"By using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Estimation of time-varying parameters:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"Adaptive control by means of estimation of time-varying parameters:","category":"page"},{"location":"parameter_estimation/","page":"Parameter estimation","title":"Parameter estimation","text":"","category":"page"},{"location":"neural_network/#Adaptive-Neural-Network-training","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"In this example, we will demonstrate how we can take the estimation of time-varying parameters to the extreme, and use a nonlinear state estimator to estimate the weights in a neural-network model of a dynamical system. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"In the tutorial Joint state and parameter estimation, we demonstrated how we can add a parameter as a state variable and let the state estimator estimate this alongside the state. In this example, we will try to learn an entire black-box model of the system dynamics using a neural network, and treat the network weights as time-varying parameters by adding them to the state.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We start by generating some data from a simple dynamical system, we will continue to use the quadruple-tank system from Joint state and parameter estimation.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"using LowLevelParticleFilters, Lux, Random, SeeToDee, StaticArrays, Plots, LinearAlgebra, ComponentArrays, DifferentiationInterface, SparseMatrixColorings\nusing SparseConnectivityTracer: TracerSparsityDetector\nusing DisplayAs # hide\n\nusing LowLevelParticleFilters: SimpleMvNormal\n\nfunction quadtank(h,u,p,t)\n kc = 0.5\n k1, k2, g = 1.6, 1.6, 9.81\n A1 = A3 = A2 = A4 = 4.9\n a1, a3, a2, a4 = 0.03, 0.03, 0.03, 0.03\n γ1, γ2 = 0.2, 0.2\n\n if t > 2000\n a1 *= 1.5 # Change the parameter at t = 2000\n end\n\n ssqrt(x) = √(max(x, zero(x)) + 1e-3) # For numerical robustness at x = 0\n\n SA[\n -a1/A1 * ssqrt(2g*h[1]) + a3/A1*ssqrt(2g*h[3]) + γ1*k1/A1 * u[1]\n -a2/A2 * ssqrt(2g*h[2]) + a4/A2*ssqrt(2g*h[4]) + γ2*k2/A2 * u[2]\n -a3/A3*ssqrt(2g*h[3]) + (1-γ2)*k2/A3 * u[2]\n -a4/A4*ssqrt(2g*h[4]) + (1-γ1)*k1/A4 * u[1]\n ]\nend\n\nTs = 30 # sample time\ndiscrete_dynamics = SeeToDee.Rk4(quadtank, Ts) # Discretize dynamics\nnu = 2 # number of control inputs\nnx = 4 # number of state variables\nny = 4 # number of measured outputs\n\nfunction generate_data() \n measurement(x,u,p,t) = x#SA[x[1], x[2]]\n Tperiod = 200\n t = 0:Ts:4000\n u = vcat.((0.25 .* sign.(sin.(2pi/Tperiod .* t)) .+ 0.25) .* sqrt.(rand.()))\n u = SVector{nu, Float32}.(vcat.(u,u))\n x0 = Float32[2,2,3,3]\n x = LowLevelParticleFilters.rollout(discrete_dynamics, x0, u)[1:end-1]\n y = measurement.(x, u, 0, 0)\n y = [Float32.(y .+ 0.01.*randn.()) for y in y] # Add some noise to the measurement\n\n (; x, u, y, nx, nu, ny, Ts)\nend\n\nrng = Random.default_rng()\nRandom.seed!(rng, 1)\ndata = generate_data()\nnothing # hide","category":"page"},{"location":"neural_network/#Neural-network-dynamics","page":"Adaptive Neural-Network training","title":"Neural network dynamics","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"Our neural network will be a small feedforward network built using the package Lux.jl. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"ni = ny + nu\nnhidden = 8\nconst model_ = Chain(Dense(ni, nhidden, tanh), Dense(nhidden, nhidden, tanh), Dense(nhidden, ny))","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"Since the network is rather small, we will train on the CPU only, this will be fast enough for this use case. We may extract the parameters of the network using the function Lux.setup, and convert them to a ComponentArray to make it easier to refer to different parts of the combined state vector.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"dev = cpu_device()\nps, st = Lux.setup(rng, model_) |> dev\nparr = ComponentArray(ps)\nnothing # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The dynamics of our black-box model will call the neural network to predict the next state given the current state and input. We bias the dynamics towards low frequencies by adding a multiple of the current state to the prediction of the next state, 0.95*x. We also add a small amount of weight decay to the parameters of the neural network for regularization, 0.995*p.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"function dynamics(out0, xp0, u, _, t)\n xp = ComponentArray(xp0, getaxes(s0))\n out = ComponentArray(out0, getaxes(s0))\n x = xp.x\n p = xp.p\n xp, _ = Lux.apply(model_, [x; u], p, st)\n @. out.x = 0.95f0*x+xp\n @. out.p = 0.995f0*p\n nothing\nend\n\n@views measurement(out, x, _, _, _) = out .= x[1:nx] # Assume measurement of the full state vector\nnothing # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"For simplicity, we have assumed here that we have access to measurements of the entire state vector of the original process. This is many times unrealistic, and if we do not have such access, we may instead augment the measured signals with delayed versions of themselves (sometimes called a delay embedding). This is a common technique in discrete-time system identification, used in e.g., ControlSystemIdentification.arx and subspaceid.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The initial state of the process x0 and the initial parameters of the neural network parr can now be concatenated to form the initial augmented state s0.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"x0 = Float32[2; 2; 3; 3]\ns0 = ComponentVector(; x=x0, p=parr)\nnothing # hide","category":"page"},{"location":"neural_network/#Kalman-filter-setup","page":"Adaptive Neural-Network training","title":"Kalman filter setup","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We will estimate the parameters using two different nonlinear Kalman filters, the ExtendedKalmanFilter and the UnscentedKalmanFilter. The covariance matrices for the filters, R1, R2, may be tuned such that we get the desired learning speed of the weights, where larger covariance for the network weights will allow for faster learning, but also more noise in the estimates. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"R1 = Diagonal([0.1ones(nx); 0.01ones(length(parr))]) .|> Float32\nR2 = Diagonal((1e-2)^2 * ones(ny)) .|> Float32\nnothing # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The ExtendedKalmanFilter uses Jacobians of the dynamics and measurement model, and if we do not provide those functions they will be automatically computed using ForwardDiff.jl. Since our Jacobians will be relatively large but sparse in this example, we will make use of the sparsity-aware features of DifferentiationInterface.jl in order to get efficient Jacobian computations. ","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"function Ajacfun(x,u,p,t) # Function that returns a function for the Jacobian of the dynamics\n # For large neural networks, it might be faster to use an OOP formulation with Zygote instead of ForwardDiff. Zygote does not handle the in-place version\n backend = AutoSparse(\n AutoForwardDiff(),\n # AutoZygote(),\n sparsity_detector=TracerSparsityDetector(),\n coloring_algorithm=GreedyColoringAlgorithm(),\n )\n out = similar(getdata(x))\n inner = (out,x)->dynamics(out,x,u,p,t)\n prep = prepare_jacobian(inner, out, backend, getdata(x))\n jac = one(eltype(x)) .* sparsity_pattern(prep)\n function (x,u,p,t)\n inner2 = (out,x)->dynamics(out,x,u,p,t)\n DifferentiationInterface.jacobian!(inner2, out, jac, prep, backend, x)\n end\nend\n\nAjac = Ajacfun(s0, data.u[1], nothing, 0)\n\nconst CJ_ = [I(nx) zeros(Float32, nx, length(parr))] # The jacobian of the measurement model is constant\nCjac(x,u,p,t) = CJ_\nnothing # hide","category":"page"},{"location":"neural_network/#Estimation","page":"Adaptive Neural-Network training","title":"Estimation","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We may now initialize our filters and perform the estimation. Here, we use the function forward_trajectory to perform filtering along the entire data trajectory at once, but we may use this in a streaming fashion as well, as more data becomes available in real time.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We plot the one-step ahead prediction of the outputs and compare to the \"measured\" data.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"ekf = ExtendedKalmanFilter(dynamics, measurement, R1, R2, SimpleMvNormal(s0, 100R1); nu, check=false, Ajac, Cjac, Ts)\nukf = UnscentedKalmanFilter(dynamics, measurement, R1, R2, SimpleMvNormal(s0, 100R1); nu, ny, Ts)\n\n@time sole = forward_trajectory(ekf, data.u, data.x)\n@time solu = forward_trajectory(ukf, data.u, data.x)\n\nplot(sole, plotx=false, plotxt=false, plotyh=true, plotyht=false, plotu=false, plote=true, name=\"EKF\", layout=(nx, 1), size=(1200, 1500))\nplot!(solu, plotx=false, plotxt=false, plotyh=true, plotyht=false, plotu=false, plote=true, name=\"UKF\", ploty=false)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We see that prediction errors, e, are large in the beginning when the network weights are randomly initialized, but after about half the trajectory the errors are significantly reduced. Just like in the tutorial Joint state and parameter estimation, we modified the true dynamics after some time, at t=2000, and we see that the filters are able to adapt to this change after a transient increase in prediction error variance.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We may also plot the evolution of the neural-network weights over time, and see how the filters adapt to the changing dynamics of the system.","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"plot(\n plot(0:Ts:4000, reduce(hcat, sole.xt)'[:, nx+1:end], title=\"EKF parameters\"),\n plot(0:Ts:4000, reduce(hcat, solu.xt)'[:, nx+1:end], title=\"UKF parameters\"),\n legend = false,\n)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"neural_network/#Smoothing","page":"Adaptive Neural-Network training","title":"Smoothing","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"@time xTe,RTe = smooth(sole, ekf)\n@time xTu,RTu = smooth(solu, ukf)\nplot(\n plot(0:Ts:4000, reduce(hcat, xTe)'[:, nx+1:end], title=\"EKF parameters\", c=1, alpha=0.2),\n plot(0:Ts:4000, reduce(hcat, xTu)'[:, nx+1:end], title=\"UKF parameters\", c=1, alpha=0.2),\n legend = false,\n)","category":"page"},{"location":"neural_network/#Benchmarking","page":"Adaptive Neural-Network training","title":"Benchmarking","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The neural network used in this example has","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"length(parr)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"parameters, and the length of the data is","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"length(data.u)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"Performing the estimation using the Extended Kalman Filter took","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"using BenchmarkTools\n@btime forward_trajectory(ekf, data.u, data.x);\n # 46.034 ms (77872 allocations: 123.45 MiB)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"and with the Unscented Kalman Filter","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"@btime forward_trajectory(ukf, data.u, data.x);\n # 142.608 ms (2134370 allocations: 224.82 MiB)","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"The EKF is a bit faster, which is to be expected. Both methods are very fast from a neural-network training perspective, but the performance will not scale favorably to very large network sizes.","category":"page"},{"location":"neural_network/#Closing-remarks","page":"Adaptive Neural-Network training","title":"Closing remarks","text":"","category":"section"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We have seen how to estimate train a black-box neural network dynamics model by treating the parameter estimation as a state-estimation problem. This example is very simple and leaves a lot of room for improvement, such as","category":"page"},{"location":"neural_network/","page":"Adaptive Neural-Network training","title":"Adaptive Neural-Network training","text":"We assumed very little prior knowledge of the dynamics. In practice, we may want to model as much as possible from first principles and add a neural network to capture only the residuals that our first-principles model cannot capture.\nWe started the training of the network weights directly from a random initialization. In practice, we may want to pre-train the network on a large offline dataset before updating the weights adaptively in real-time.\nWe used forward-mode AD to compute the Jacobian. The Jacobian of the dynamics has dense rows, which means that it's theoretically favorable to use reverse-mode AD to compute it. This is possible using Zygote.jl, but Zygote does not handle array mutation, and one must thus avoid the in-place version of the dynamics. Since the number of parameters in this example is small, sparse forward mode AD ended up being slightly faster.","category":"page"},{"location":"adaptive_kalmanfilter/#Noise-adaptive-Kalman-filter","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Noise-adaptive Kalman filter","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"In this tutorial we will consider filtering of a 1D position track, similar in spirit to what one could have obtained from a GPS device, but limited to 1D for easier visualization. We will use a constant-velocity model, i.e., use a double integrator,","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"beginaligned\nx_k+1 = beginbmatrix 1 T_s 0 1 endbmatrix x_k + beginbmatrix T_s^22 T_s endbmatrix w_k \ny_k = beginbmatrix 1 0 endbmatrix x_k + v_k\nendaligned","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"where w_k sim mathcalN(0 σ_w) is the process noise, and v_k sim mathcalN(0 R_2) is the measurement noise, and illustrate how we can make use of an adaptive noise covariance to improve the filter performance.","category":"page"},{"location":"adaptive_kalmanfilter/#Data-generation","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Data generation","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"We start by generating some position data that we want to perform filtering on. The \"object\" we want to track is initially stationary, and transitions to moving with a constant velocity after a while. ","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"using LowLevelParticleFilters, Plots, Random\nRandom.seed!(1)\n\n# Create a time series for filtering\nx = [zeros(50); 0:100]\nT = length(x)\nY = x + randn(T)\nplot([Y x], lab=[\"Measurement\" \"True state to be tracked\"], c=[1 :purple])","category":"page"},{"location":"adaptive_kalmanfilter/#Simple-Kalman-filtering","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Simple Kalman filtering","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"We will use a Kalman filter to perform the filtering. The model is a double integrator, i.e., a constant-acceleration model. The state vector is thus x = p v^T, where p is the position and v is the velocity. When designing a Kalman filter, we need to specify the noise covariances R_1 and R_2. While it's often easy to measure the covariance of the measurement noise, R_2, it can be quite difficult to know ahead of time what the dynamics noise covariance, R_1, should be. In this example, we will use an adaptive filter, where we will increase the dynamics noise covariance if the filter prediction error is too large. However, we first run the filter twice, once with a large R_1 and once with a small R_1 to illustrate the difference.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"y = [[y] for y in Y] # create a vector of vectors for the KF\nu = fill([], T) # No inputs in this example :(\n\n# Define the model\nTs = 1\nA = [1 Ts; 0 1]\nB = zeros(2, 0)\nC = [1 0]\nD = zeros(0, 0)\nR2 = [1;;]\n\nσws = [1e-2, 1e-5] # Dynamics noise standard deviations\n\nfig = plot(Y, lab=\"Measurement\")\nfor σw in σws\n R1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts] # The dynamics noise covariance matrix is σw*Bw*Bw' where Bw = [Ts^2/2; Ts]\n kf = KalmanFilter(A, B, C, D, R1, R2)\n yh = []\n measure = LowLevelParticleFilters.measurement(kf)\n for t = 1:T # Main filter loop\n kf(u[t], y[t]) # Performs both prediction and correction\n xh = state(kf)\n yht = measure(xh, u[t], nothing, t)\n push!(yh, yht)\n end\n\n Yh = reduce(hcat, yh)\n plot!(Yh', lab=\"Estimate \\$σ_w\\$ = $σw\")\nend\nfig","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"When R_1 is small (controlled by σ_w), we get a nice and smooth filter estimate, but this estimate clearly lags behind the true state. When R_1 is large, the filter estimate is much more responsive, but it also has a lot of noise.","category":"page"},{"location":"adaptive_kalmanfilter/#Adaptive-noise-covariance","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Adaptive noise covariance","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Below, we will implement an adaptive filter, where we keep the dynamics noise covariance low by default, but increase it if the filter prediction error is too large. We will use a Z-score to determine if the prediction error is too large. The Z-score is defined as the number of standard deviations the prediction error is away from the estimated mean. This time around we use separate correct! and predict! calls, so that we can access the prediction error as well as the prior covariance of the prediction error, S. S (or the Cholesky factor Sᵪ) will be used to compute the Z-score.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"σw = 1e-5 # Set the covariance to a low value by default\nR1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts]\nkf = KalmanFilter(A, B, C, D, R1, R2)\nmeasure = LowLevelParticleFilters.measurement(kf)\n\n# Some arrays to store simulation data\nyh = []\nes = Float64[]\nσs = Float64[]\nfor t = 1:T # Main filter loop\n ll, e, S, Sᵪ = correct!(kf, u[t], y[t], nothing, t) # Manually call the prediction step\n σ = √(e'*(Sᵪ\\e)) # Compute the Z-score\n push!(es, e[]) # Save for plotting\n push!(σs, σ)\n if σ > 3 # If the Z-score is too high\n # we temporarily increase the dynamics noise covariance by 1000x to adapt faster\n predict!(kf, u[t], nothing, t; R1 = 1000kf.R1) \n else\n predict!(kf, u[t], nothing, t)\n end\n xh = state(kf)\n yht = measure(xh, u[t], nothing, t)\n push!(yh, yht)\nend\n\nYh = reduce(hcat, yh)\nplot([Y Yh'], lab=[\"Measurement\" \"Adaptive estimate\"])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Not too bad! This time the filter estimate is much more responsive during the transition, but exhibits favorable noise properties during the stationary phases. We can also plot the prediction error and the Z-score to see how the filter adapts to the dynamics noise covariance.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"plot([es σs], lab=[\"Prediction error\" \"Z-score\"])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Notice how the prediction errors, that should ideally be centered around zero, remain predominantly negative for a long time interval after the transition. This can be attributed to an overshoot in the velocity state of the estimator, but the rapid decrease of the covariance after the transition makes the filter slow at correcting its overshoot. If we want, we could mitigate this and make the adaptation even more sophisticated by letting the covariance remain large for a while after a transition in operating mode has been detected. Below, we implement a simple version of this, where we use a multiplier σ_wt that defaults to 1, but is increase to a very large value of 1000 if a transition is detected. When no transition is detected, σ_wt is decreased exponentially back down to 1.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"σw = 1e-5 # Set the covariance to a low value by default\nσwt = 1.0\nR1 = σw*[Ts^3/3 Ts^2/2; Ts^2/2 Ts]\nkf = KalmanFilter(A, B, C, D, R1, R2)\nmeasure = LowLevelParticleFilters.measurement(kf)\n\n# Some arrays to store simulation data\nyh = []\nes = Float64[]\nσs = Float64[]\nσwts = Float64[]\nfor t = 1:T # Main filter loop\n global σwt # Note, do not make use of global variables in performance critical code\n ll, e, S, Sᵪ = correct!(kf, u[t], y[t], nothing, t) # Manually call the prediction step\n σ = √(e'*(Sᵪ\\e)) # Compute the Z-score\n push!(es, e[]) # Save for plotting\n push!(σs, σ)\n if σ > 3 # If the Z-score is too high\n σwt = 1000.0 # Set the R1 multiplier to a very large value\n else\n σwt = max(0.7σwt, 1.0) # Decrease exponentially back to 1\n end\n push!(σwts, σwt)\n predict!(kf, u[t], nothing, t; R1 = σwt*kf.R1) \n xh = state(kf)\n yht = measure(xh, u[t], nothing, t)\n push!(yh, yht)\nend\n\nYh = reduce(hcat, yh)\nplot([Y Yh'], lab=[\"Measurement\" \"Adaptive estimate\"])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"plot([es σs σwts], lab=[\"Prediction error\" \"Z-score\" \"\\$σ_{wt}\\$ multiplier\"], layout=2, sp=[1 1 2])","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"This time, the prediction errors look more like white noise centered around zero after the initial transient caused by the transition.","category":"page"},{"location":"adaptive_kalmanfilter/#Summary","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Summary","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"This tutorial demonstrated simple Kalman filtering for a double integrator without control inputs. We saw how the filtering estimate could be improved by playing around with the covariance matrices of the estimator, helping it catch up to fast changes in the behavior of the system without sacrificing steady-state noise properties.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"In this case, we handled the modification of R_1 outside of the filter, implementing our own filtering loop. Some applications get away with instead providing time-varying matrices in the form of a 3-dimension array, where the third dimension corresponds to time, or instead of providing a matrix, providing a function R_1(x u p t) allows the matrix to be a function of state, input, parameters and time. These options apply to all matrices in the filter, including the dynamics matrices, ABCD.","category":"page"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"Lastly, we mention the ability of the KalmanFilter to act like a recursive least-squares estimator, by setting the \"forgetting factor α1 when creating the KalmanFilter. α1 will cause the filter will exhibit exponential forgetting similar to an RLS estimator, in addition to the covariance inflation due to R1. It is thus possible to get a RLS-like algorithm by setting R_1 = 0 R_2 = 1α and α 1.","category":"page"},{"location":"adaptive_kalmanfilter/#Disturbance-modeling-and-noise-tuning","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Disturbance modeling and noise tuning","text":"","category":"section"},{"location":"adaptive_kalmanfilter/","page":"Kalman-filter tutorial with LowLevelParticleFilters","title":"Kalman-filter tutorial with LowLevelParticleFilters","text":"See this notebook for a blog post about disturbance modeling and noise tuning using LowLevelParticleFilter.jl","category":"page"},{"location":"dae/#State-estimation-for-high-index-DAEs","page":"State estimation for DAE systems","title":"State estimation for high-index DAEs","text":"","category":"section"},{"location":"dae/","page":"State estimation for DAE systems","title":"State estimation for DAE systems","text":"This tutorial is hosted as a notebook.","category":"page"},{"location":"measurement_models/#measurement_models","page":"Multiple measurement models","title":"Measurement models","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"The Kalman-type filters","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"KalmanFilter\nExtendedKalmanFilter\nUnscentedKalmanFilter","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"each come with their own built-in measurement model, e.g., the standard KalmanFilter uses the linear measurement model y = Cx + Du + e, while the ExtendedKalmanFilter and UnscentedKalmanFilter use the nonlinear measurement model y = h(xupt) + e or y = h(xupte). For covariance propagation, the ExtendedKalmanFilter uses linearization to approximate the nonlinear measurement model, while the UnscentedKalmanFilter uses the unscented transform.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"It is sometimes useful to mix and match dynamics and measurement models. For example, using the unscented transform from the UKF for the dynamics update (predict!), but the linear measurement model from the standard KalmanFilter for the measurement update (correct!) if the measurement model is linear.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"This is possible by constructing a filter with an explicitly created measurement model. The available measurement models are","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"LinearMeasurementModel performs linear propagation of covariance (as is done in KalmanFilter).\nEKFMeasurementModel uses linearization to propagate covariance (as is done in ExtendedKalmanFilter).\nUKFMeasurementModel uses the unscented transform to propagate covariance (as is done in UnscentedKalmanFilter).\nCompositeMeasurementModel combines multiple measurement models.","category":"page"},{"location":"measurement_models/#Constructing-a-filter-with-a-custom-measurement-model","page":"Multiple measurement models","title":"Constructing a filter with a custom measurement model","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"Constructing a Kalman-type filter automatically creates a measurement model of the corresponding type, given the functions/matrices passed to the filter constructor. To construct a filter with a non-standard measurement model, e.g., and UKF with a KF measurement model, manually create the desired measurement model and pass it as the second argument to the constructor. For example, to construct an UKF with a linear measurement model, we do","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"using LowLevelParticleFilters, LinearAlgebra\nnx = 100 # Dimension of state\nnu = 2 # Dimension of input\nny = 90 # Dimension of measurements\n\n# Define linear state-space system\nconst __A = 0.1*randn(nx, nx)\nconst __B = randn(nx, nu)\nconst __C = randn(ny,nx)\nfunction dynamics_ip(dx,x,u,p,t)\n # __A*x .+ __B*u\n mul!(dx, __A, x)\n mul!(dx, __B, u, 1.0, 1.0)\n nothing\nend\nfunction measurement_ip(y,x,u,p,t)\n # __C*x\n mul!(y, __C, x)\n nothing\nend\n\nR1 = I(nx)\nR2 = I(ny)\n\nmm_kf = LinearMeasurementModel(__C, 0, R2; nx, ny)\nukf = UnscentedKalmanFilter(dynamics_ip, mm_kf, R1; ny, nu)","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"When we create the filter with the custom measurement model, we do not pass the arguments that are associated with the measurement model to the filter constructor, i.e., we do not pass any measurement function, and not the measurement covariance matrix R_2.","category":"page"},{"location":"measurement_models/#Sensor-fusion:-Using-several-different-measurement-models","page":"Multiple measurement models","title":"Sensor fusion: Using several different measurement models","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"Above we constructed a filter with a custom measurement model, we can also pass a custom measurement model when we call correct!. This may be useful when, e.g., performing sensor fusion with sensors operating at different sample rates, or when parts of the measurement model are linear, and other parts are nonlinear.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"The following example instantiates three different filters and three different measurement models. Each filter is updated with each measurement model, demonstrating that any combination of filter and measurement model can be used together.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"using LowLevelParticleFilters, LinearAlgebra\nnx = 10 # Dimension of state\nnu = 2 # Dimension of input\nny = 9 # Dimension of measurements\n\n# Define linear state-space system\nconst __A = 0.1*randn(nx, nx)\nconst __B = randn(nx, nu)\nconst __C = randn(ny,nx)\nfunction dynamics_ip(dx,x,u,p,t)\n # __A*x .+ __B*u\n mul!(dx, __A, x)\n mul!(dx, __B, u, 1.0, 1.0)\n nothing\nend\nfunction measurement_ip(y,x,u,p,t)\n # __C*x\n mul!(y, __C, x)\n nothing\nend\n\nR1 = I(nx) # Covariance matrices\nR2 = I(ny)\n\n# Construct three different filters\nkf = KalmanFilter(__A, __B, __C, 0, R1, R2)\nukf = UnscentedKalmanFilter(dynamics_ip, measurement_ip, R1, R2; ny, nu)\nekf = ExtendedKalmanFilter(dynamics_ip, measurement_ip, R1, R2; nu)\n\n# Simulate some data\nT = 200 # Number of time steps\nU = [randn(nu) for _ in 1:T]\nx,u,y = LowLevelParticleFilters.simulate(kf, U) # Simulate trajectory using the model in the filter\n\n# Construct three different measurement models\nmm_kf = LinearMeasurementModel(__C, 0, R2; nx, ny)\nmm_ekf = EKFMeasurementModel{Float64, true}(measurement_ip, R2; nx, ny)\nmm_ukf = UKFMeasurementModel{Float64, true, false}(measurement_ip, R2; nx, ny)\n\n\nmms = [mm_kf, mm_ekf, mm_ukf]\nfilters = [kf, ekf, ukf]\n\nfor mm in mms, filter in filters\n @info \"Updating $(nameof(typeof(filter))) with measurement model $(nameof(typeof(mm)))\"\n correct!(filter, mm, u[1], y[1]) # Pass the measurement model as the second argument to the correct! function if not using the measurement model built into the filter\nend\nnothing # hide","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"Since the dynamics in this particular example is in fact linear, we should get identical results for all three filters.","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"using Test\n@test kf.x ≈ ekf.x ≈ ukf.x\n@test kf.R ≈ ekf.R ≈ ukf.R","category":"page"},{"location":"measurement_models/#Video-tutorial","page":"Multiple measurement models","title":"Video tutorial","text":"","category":"section"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"A video demonstrating the use of multiple measurement models in a sensor-fusion context is available on YouTube:","category":"page"},{"location":"measurement_models/","page":"Multiple measurement models","title":"Multiple measurement models","text":"","category":"page"},{"location":"api/#Exported-functions-and-types","page":"API","title":"Exported functions and types","text":"","category":"section"},{"location":"api/#Index","page":"API","title":"Index","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"","category":"page"},{"location":"api/","page":"API","title":"API","text":"Modules = [LowLevelParticleFilters]\nPrivate = false","category":"page"},{"location":"api/#LowLevelParticleFilters.AdvancedParticleFilter-Tuple{Integer, Function, Function, Any, Any, Any}","page":"API","title":"LowLevelParticleFilters.AdvancedParticleFilter","text":"AdvancedParticleFilter(N::Integer, dynamics::Function, measurement::Function, measurement_likelihood, dynamics_density, initial_density; p = NullParameters(), threads = false, kwargs...)\n\nThis type represents a standard particle filter but affords extra flexibility compared to the ParticleFilter type, e.g., non-additive noise in the dynamics and measurement functions.\n\nSee the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#AdvancedParticleFilter-1\n\nArguments:\n\nN: Number of particles\ndynamics: A discrete-time dynamics function (x, u, p, t, noise=false) -> x⁺. It's important that the noise argument defaults to false.\nmeasurement: A measurement function (x, u, p, t, noise=false) -> y. It's important that the noise argument defaults to false.\nmeasurement_likelihood: A function (x, u, y, p, t)->logl to evaluate the log-likelihood of a measurement.\ndynamics_density: This field is not used by the advanced filter and can be set to nothing.\ninitial_density: The distribution of the initial state.\nthreads: use threads to propagate particles in parallel. Only activate this if your dynamics is thread-safe. SeeToDee.SimpleColloc is not thread-safe by default due to the use of internal caches, but SeeToDee.Rk4 is.\n\nExtended help\n\nMultiple measurement models\n\nThe measurement_likelihood function is used to evaluate the likelihood of a measurement. If you have multiple sensors and want to perform individual correct! steps for each, call correct!(..., g = custom_likelihood_function).\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.AuxiliaryParticleFilter-Tuple","page":"API","title":"LowLevelParticleFilters.AuxiliaryParticleFilter","text":"AuxiliaryParticleFilter(args...; kwargs...)\n\nTakes exactly the same arguments as ParticleFilter, or an instance of ParticleFilter.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.CompositeMeasurementModel-Tuple{Any, Vararg{Any}}","page":"API","title":"LowLevelParticleFilters.CompositeMeasurementModel","text":"CompositeMeasurementModel(model1, model2, ...)\n\nA composite measurement model that combines multiple measurement models. This model acts as all component models concatenated. The tuple returned from correct! will be\n\nll: The sum of the log-likelihood of all component models\ne: The concatenated innovation vector\nS: A vector of the innovation covariance matrices of the component models\nSᵪ: A vector of the Cholesky factorizations of the innovation covariance matrices of the component models\nK: A vector of the Kalman gains of the component models\n\nIf all sensors operate on at the same rate, and all measurement models are of the same type, it's more efficient to use a single measurement model with a vector-valued measurement function.\n\nFields:\n\nmodels: A tuple of measurement models\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.EKFMeasurementModel-Union{Tuple{IPM}, NTuple{4, Any}, NTuple{5, Any}} where IPM","page":"API","title":"LowLevelParticleFilters.EKFMeasurementModel","text":"EKFMeasurementModel{IPM}(measurement, R2, ny, Cjac, cache = nothing)\n\nA measurement model for the Extended Kalman Filter.\n\nArguments:\n\nIPM: A boolean indicating if the measurement function is inplace\nmeasurement: The measurement function y = h(x, u, p, t)\nR2: The measurement noise covariance matrix\nny: The number of measurement variables\nCjac: The Jacobian of the measurement function Cjac(x, u, p, t). If none is provided, ForwardDiff will be used.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.EKFMeasurementModel-Union{Tuple{M}, Tuple{IPM}, Tuple{T}, Tuple{M, Any}} where {T, IPM, M}","page":"API","title":"LowLevelParticleFilters.EKFMeasurementModel","text":"EKFMeasurementModel{T,IPM}(measurement::M, R2; nx, ny, Cjac = nothing)\n\nT is the element type used for arrays\nIPM is a boolean indicating if the measurement function is inplace\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.ExtendedKalmanFilter","page":"API","title":"LowLevelParticleFilters.ExtendedKalmanFilter","text":"ExtendedKalmanFilter(kf, dynamics, measurement; Ajac, Cjac)\nExtendedKalmanFilter(dynamics, measurement, R1,R2,d0=MvNormal(Matrix(R1)); nu::Int, p = NullParameters(), α = 1.0, check = true)\n\nA nonlinear state estimator propagating uncertainty using linearization.\n\nThe constructor to the extended Kalman filter takes dynamics and measurement functions, and either covariance matrices, or a KalmanFilter. If the former constructor is used, the number of inputs to the system dynamics, nu, must be explicitly provided with a keyword argument.\n\nBy default, the filter will internally linearize the dynamics using ForwardDiff. User provided Jacobian functions can be provided as keyword arguments Ajac and Cjac. These functions should have the signature (x,u,p,t)::AbstractMatrix where x is the state, u is the input, p is the parameters, and t is the time.\n\nThe dynamics and measurement function are on the following form\n\nx(t+1) = dynamics(x, u, p, t) + w\ny = measurement(x, u, p, t) + e\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0\n\nSee also UnscentedKalmanFilter which is typically more accurate than ExtendedKalmanFilter. See KalmanFilter for detailed instructions on how to set up a Kalman filter kf.\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.IMM-Tuple{Any, AbstractMatrix, AbstractVector}","page":"API","title":"LowLevelParticleFilters.IMM","text":"IMM(models, P, μ; check = true, p = NullParameters(), interact = true)\n\nInteracting Multiple Model (IMM) filter. This filter is a combination of multiple Kalman-type filters, each with its own state and covariance. The IMM filter is a probabilistically weighted average of the states and covariances of the individual filters. The weights are determined by the probability matrix P and the mixing probabilities μ.\n\nwarning: Experimental\nThis filter is currently considered experimental and the user interface may change in the future without respecting semantic versioning.\n\nIn addition to the predict! and correct! steps, the IMM filter has an interact! method that updates the states and covariances of the individual filters based on the mixing probabilities. The combine! method combines the states and covariances of the individual filters into a single state and covariance. These four functions are typically called in either of the orders\n\ncorrect!, combine!, interact!, predict! (as is done in update!)\ninteract!, predict!, correct!, combine! (as is done in the reference cited below)\n\nThese two orders are cyclic permutations of each other, and the order used in update! is chosen to align with the order used in the other filters, where the initial condition is corrected using the first measurement, i.e., we assume the first measurement updates x(0-1) to x(00).\n\nThe initial (combined) state and covariance of the IMM filter is made up of the weighted average of the states and covariances of the individual filters. The weights are the initial mixing probabilities μ.\n\nRef: \"Interacting multiple model methods in target tracking: a survey\", E. Mazor; A. Averbuch; Y. Bar-Shalom; J. Dayan\n\nArguments:\n\nmodels: An array of Kalman-type filters, such as KalmanFilter, ExtendedKalmanFilter, UnscentedKalmanFilter, etc. The state of each model must have the same meaning, such that forming a weighted average makes sense.\nP: The mode-transition probability matrix. P[i,j] is the probability of transitioning from mode i to mode j (each row must sum to one).\nμ: The initial mixing probabilities. μ[i] is the probability of being in mode i at the initial contidion (must sum to one).\ncheck: If true, check that the inputs are valid. If false, skip the checks.\np: Parameters for the filter. NOTE: this p is shared among all internal filters. The internal p of each filter will be overridden by this one.\ninteract: If true, the filter will run the interaction as part of update! and forward_trajectory. If false, the filter will not run the interaction step. This choice can be overridden by passing the keyword argument interact to the respective functions.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.KalmanFilter","page":"API","title":"LowLevelParticleFilters.KalmanFilter","text":"KalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1, check=true)\n\nThe matrices A,B,C,D define the dynamics\n\nx' = Ax + Bu + w\ny = Cx + Du + e\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0\n\nThe matrices can be time varying such that, e.g., A[:, :, t] contains the A matrix at time index t. They can also be given as functions on the form\n\nAfun(x, u, p, t) -> A\n\nFor maximum performance, provide statically sized matrices from StaticArrays.jl\n\nα is an optional \"forgetting factor\", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to R_1, exhibit \"exponential forgetting\" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting R_1=0 R_2 = 1α and α 1 (α is the inverse of the traditional RLS parameter α = 1λ). The exact form of the covariance update is\n\nR(t+1t) = α AR(t)A^T + R_1\n\nIf check = true (default) the function will check that the eigenvalues of A are less than 2 in absolute value. Large eigenvalues may be an indication that the system matrices are representing a continuous-time system and the user has forgotten to discretize it. Turn off this check by setting check = false.\n\nTutorials on Kalman filtering\n\nThe tutorial \"How to tune a Kalman filter\" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model. See also the tutorial in the documentation\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.KalmanFilteringSolution","page":"API","title":"LowLevelParticleFilters.KalmanFilteringSolution","text":"KalmanFilteringSolution{Tx,Txt,TR,TRt,Tll} <: AbstractFilteringSolution\n\nFields\n\nx: predictions x(t+1t) (plotted if plotx=true)\nxt: filtered estimates x(tt) (plotted if plotxt=true)\nR: predicted covariance matrices R(t+1t) (plotted if plotR=true)\nRt: filter covariances R(tt) (plotted if plotRt=true)\nll: loglikelihood\ne: prediction errors e(tt-1) = y - y(tt-1) (plotted if plote=true)\n\nPlot\n\nThe solution object can be plotted\n\nplot(sol, plotx=true, plotxt=true, plotR=true, plotRt=true, plote=true, plotu=true, ploty=true, plotyh=true, plotyht=true, name=\"\")\n\nwhere\n\nplotx: Plot the predictions x(t|t-1)\nplotxt: Plot the filtered estimates x(t|t)\nplotR: Plot the predicted covariances R(t|t-1) as ribbons at ±2σ (1.96 σ to be precise)\nplotRt: Plot the filter covariances R(t|t) as ribbons at ±2σ (1.96 σ to be precise)\nplote: Plot the prediction errors e(t|t-1) = y - ŷ(t|t-1)\nplotu: Plot the input\nploty: Plot the measurements\nplotyh: Plot the predicted measurements ŷ(t|t-1)\nplotyht: Plot the filtered measurements ŷ(t|t)\nname: a string that is prepended to the labels of the plots, which is useful when plotting multiple solutions in the same plot.\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.LinearMeasurementModel","page":"API","title":"LowLevelParticleFilters.LinearMeasurementModel","text":"LinearMeasurementModel{CT, DT, RT, CAT}\n\nA linear measurement model y = C*x + D*u + e.\n\nFields:\n\nC \nD\nR2: The measurement noise covariance matrix\nny: The number of measurement variables\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.ParticleFilter-Tuple{Integer, Function, Function, Any, Any, Any}","page":"API","title":"LowLevelParticleFilters.ParticleFilter","text":"ParticleFilter(N::Integer, dynamics, measurement, dynamics_density, measurement_density, initial_density; threads = false, p = NullParameters(), kwargs...)\n\nSee the docs for more information: https://baggepinnen.github.io/LowLevelParticleFilters.jl/stable/#Particle-filter-1\n\nArguments:\n\nN: Number of particles\ndynamics: A discrete-time dynamics function (x, u, p, t) -> x⁺\nmeasurement: A measurement function (x, u, p, t) -> y\ndynamics_density: A probability-density function for additive noise in the dynamics. Use AdvancedParticleFilter for non-additive noise.\nmeasurement_density: A probability-density function for additive measurement noise. Use AdvancedParticleFilter for non-additive noise.\ninitial_density: Distribution of the initial state.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.ParticleFilteringSolution","page":"API","title":"LowLevelParticleFilters.ParticleFilteringSolution","text":"ParticleFilteringSolution{F, Tu, Ty, Tx, Tw, Twe, Tll} <: AbstractFilteringSolution\n\nFields:\n\nf: The filter used to produce the solution.\nu: Input\ny: Output / measurements\nx: Particles, the size of this array is (N,T), where N is the number of particles and T is the number of time steps. Each element represents a weighted state hypothesis with weight given by we.\nw: Weights (log space). These are used for internal computations.\nwe: Weights (exponentiated / original space). These are the ones to use to compute weighted means etc., they sum to one for each time step.\nll: Log likelihood\n\nPlot\n\nThe solution object can be plotted\n\nplot(sol; nbinsy=30, xreal=nothing, dim=nothing, ploty=true)\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.SqKalmanFilter","page":"API","title":"LowLevelParticleFilters.SqKalmanFilter","text":"SqKalmanFilter(A,B,C,D,R1,R2,d0=MvNormal(R1); p = NullParameters(), α=1)\n\nA standard Kalman filter on square-root form. This filter may have better numerical performance when the covariance matrices are ill-conditioned.\n\nThe matrices A,B,C,D define the dynamics\n\nx' = Ax + Bu + w\ny = Cx + Du + e\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0\n\nThe matrices can be time varying such that, e.g., A[:, :, t] contains the A matrix at time index t. They can also be given as functions on the form\n\nAfun(x, u, p, t) -> A\n\nThe internal fields storing covariance matrices are for this filter storing the upper-triangular Cholesky factor.\n\nα is an optional \"forgetting factor\", if this is set to a value > 1, such as 1.01-1.2, the filter will, in addition to the covariance inflation due to R_1, exhibit \"exponential forgetting\" similar to a Recursive Least-Squares (RLS) estimator. It is thus possible to get a RLS-like algorithm by setting R_1=0 R_2 = 1α and α 1 (α is the inverse of the traditional RLS parameter α = 1λ). The form of the covariance update is\n\nR(t+1t) = α AR(t)A^T + R_1\n\nRef: \"A Square-Root Kalman Filter Using Only QR Decompositions\", Kevin Tracy https://arxiv.org/abs/2208.06452\n\n\n\n\n\n","category":"type"},{"location":"api/#LowLevelParticleFilters.UKFMeasurementModel-Union{Tuple{AUGM}, Tuple{IPM}, NTuple{8, Any}, NTuple{9, Any}} where {IPM, AUGM}","page":"API","title":"LowLevelParticleFilters.UKFMeasurementModel","text":"UKFMeasurementModel{inplace_measurement,augmented_measurement}(measurement, R2, ny, ne, innovation, mean, cov, cross_cov, cache = nothing)\n\nA measurement model for the Unscented Kalman Filter.\n\nArguments:\n\nmeasurement: The measurement function y = h(x, u, p, t)\nR2: The measurement noise covariance matrix\nny: The number of measurement variables\nne: If augmented_measurement is true, the number of measurement noise variables\ninnovation(y::AbstractVector, yh::AbstractVector) where the arguments represent (measured output, predicted output)\nmean(ys::AbstractVector{<:AbstractVector}): computes the mean of the vector of vectors of output sigma points.\ncov(ys::AbstractVector{<:AbstractVector}, y::AbstractVector): computes the covariance matrix of the output sigma points.\ncross_cov(xs::AbstractVector{<:AbstractVector}, x::AbstractVector, ys::AbstractVector{<:AbstractVector}, y::AbstractVector) where the arguments represents (state sigma points, mean state, output sigma points, mean output). The function should return the cross-covariance matrix between the state and output sigma points.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.UKFMeasurementModel-Union{Tuple{AUGM}, Tuple{IPM}, Tuple{T}, Tuple{Any, Any}} where {T, IPM, AUGM}","page":"API","title":"LowLevelParticleFilters.UKFMeasurementModel","text":"UKFMeasurementModel{T,IPM,AUGM}(measurement, R2; nx, ny, ne = nothing, innovation = -, mean = safe_mean, cov = safe_cov, cross_cov = cross_cov, static = nothing)\n\nT is the element type used for arrays\nIPM is a boolean indicating if the measurement function is inplace\nAUGM is a boolean indicating if the measurement model is augmented\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.UnscentedKalmanFilter-Union{Tuple{AUGM}, Tuple{AUGD}, Tuple{IPM}, Tuple{IPD}, Tuple{Any, LowLevelParticleFilters.AbstractMeasurementModel, Any}, Tuple{Any, LowLevelParticleFilters.AbstractMeasurementModel, Any, Any}} where {IPD, IPM, AUGD, AUGM}","page":"API","title":"LowLevelParticleFilters.UnscentedKalmanFilter","text":"UnscentedKalmanFilter(dynamics, measurement, R1, R2, d0=MvNormal(Matrix(R1)); p = NullParameters(), ny, nu)\nUnscentedKalmanFilter{IPD,IPM,AUGD,AUGM}(dynamics, measurement_model::AbstractMeasurementModel, R1, d0=SimpleMvNormal(R1); p=NullParameters(), nu)\n\nA nonlinear state estimator propagating uncertainty using the unscented transform.\n\nThe dynamics and measurement function are on either of the following forms\n\nx' = dynamics(x, u, p, t) + w\ny = measurement(x, u, p, t) + e\n\nx' = dynamics(x, u, p, t, w)\ny = measurement(x, u, p, t, e)\n\nwhere w ~ N(0, R1), e ~ N(0, R2) and x(0) ~ d0. The former (default) assums that the noise is additive and added after the dynamics and measurement updates, while the latter assumes that the dynamics functions take an additional argument corresponding to the noise term. The latter form (sometimes refered to as the \"augmented\" form) is useful when the noise is multiplicative or when the noise is added before the dynamics and measurement updates. See \"Augmented UKF\" below for more details on how to use this form.\n\nThe matrices R1, R2 can be time varying such that, e.g., R1[:, :, t] contains the R_1 matrix at time index t. They can also be given as functions on the form\n\nRfun(x, u, p, t) -> R\n\nFor maximum performance, provide statically sized matrices from StaticArrays.jl\n\nny, nu indicate the number of outputs and inputs.\n\nCustom type of u\n\nThe input u may be of any type, e.g., a named tuple or a custom struct. The u provided in the input data is passed directly to the dynamics and measurement functions, so as long as the type is compatible with the dynamics it will work out. The one exception where this will not work is when calling simulate, which assumes that u is an array.\n\nAugmented UKF\n\nIf the noise is not additive, one may use the augmented form of the UKF. In this form, the dynamics functions take additional input arguments that correspond to the noise terms. To enable this form, the typed constructor\n\nUnscentedKalmanFilter{inplace_dynamics,inplace_measurement,augmented_dynamics,augmented_measurement}(...)\n\nis used, where the Boolean type parameters have the following meaning\n\ninplace_dynamics: If true, the dynamics function operates in-place, i.e., it modifies the first argument in dynamics(dx, x, u, p, t). Default is false.\ninplace_measurement: If true, the measurement function operates in-place, i.e., it modifies the first argument in measurement(y, x, u, p, t). Default is false.\naugmented_dynamics: If true the dynamics function is augmented with an additional noise input w, i.e., dynamics(x, u, p, t, w). Default is false.\naugmented_measurement: If true the measurement function is agumented with an additional noise input e, i.e., measurement(x, u, p, t, e). Default is false. (If the measurement noise has fewer degrees of freedom than the number of measurements, you may failure in Cholesky factorizations, see \"Custom Cholesky factorization\" below).\n\nUse of augmented dynamics incurs extra computational cost. The number of sigma points used is 2L+1 where L is the length of the augmented state vector. Without augmentation, L = nx, with augmentation L = nx + nw and L = nx + ne for dynamics and measurement, respectively.\n\nSigma-point rejection\n\nFor problems with challenging dynamics, a mechanism for rejection of sigma points after the dynamics update is provided. A function reject(x) -> Bool can be provided through the keyword argument reject that returns true if a sigma point for x(t+1) should be rejected, e.g., if an instability or non-finite number is detected. A rejected point is replaced by the propagated mean point (the mean point cannot be rejected). This function may be provided either to the constructor of the UKF or passed to the predict! function.\n\nCustom measurement models\n\nBy default, standard arithmetic mean and e(y, yh) = y - yh are used as mean and innovation functions.\n\nBy passing and explicitly created UKFMeasurementModel, one may provide custom functions that compute the mean, the covariance and the innovation. This is useful in situations where the state or a measurement lives on a manifold. One may further override the mean and covariance functions for the state sigma points by passing the keyword arguments state_mean and state_cov to the constructor.\n\nstate_mean(xs::AbstractVector{<:AbstractVector}) computes the mean of the vector of vectors of state sigma points.\nstate_cov(xs::AbstractVector{<:AbstractVector}, m = mean(xs)) where the first argument represent state sigma points and the second argument, which must be optional, represents the mean of those points. The function should return the covariance matrix of the state sigma points.\n\nSee UKFMeasurementModel for more details on how to set up a custom measurement model. Pass the custom measurement model as the second argument to the UKF constructor.\n\nCustom Cholesky factorization\n\nThe UnscentedKalmanFilter supports providing a custom function to compute the Cholesky factorization of the covariance matrices for use in sigma-point generation.\n\nIf either of the following conditions are met, you may experience failure in internal Cholesky factorizations:\n\nThe dynamics noise or measurement noise covariance matrices (R_1 R_2) are singular\nThe measurement is augmented and the measurement noise has fewer degrees of freedom than the number of measurements\n(Under specific technical conditions) The dynamics is augmented and the dynamics noise has fewer degrees of freedom than the number of state variables. The technical conditions are easiest to understand in the linear-systems case, where it corresponds to the Riccati equation associated with the Kalman gain not having a solution. This may happen when the pair (A R1) has uncontrollable modes on the unit circle, for example, when there are integrating modes that are not affected through the noise.\n\nThe error message may look like\n\nERROR: PosDefException: matrix is not positive definite; Factorization failed.\n\nIn such situations, it is advicable to reconsider the noise model and covariance matrices, alternatively, you may provide a custom Cholesky factorization function to the UKF constructor through the keyword argument cholesky!. The function should have the signature cholesky!(A::AbstractMatrix)::Cholesky. A useful alternative factorizaiton when covariance matrices are expected to be singular is cholesky! = R->cholesky!(Positive, Matrix(R)) where the \"positive\" Cholesky factorization is provided by the package PositiveFactorizations.jl, which must be manually installed and loaded by the user.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.combine!-Tuple{IMM}","page":"API","title":"LowLevelParticleFilters.combine!","text":"combine!(imm::IMM)\n\nCombine the models of the IMM filter into a single state imm.x and covariance imm.R. This is done by taking a weighted average of the states and covariances of the individual models, where the weights are the mixing probabilities μ.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.commandplot","page":"API","title":"LowLevelParticleFilters.commandplot","text":"commandplot(pf, u, y, p=parameters(pf); kwargs...)\n\nProduce a helpful plot. For customization options (kwargs...), see ?pplot. After each time step, a command from the user is requested.\n\nq: quit\ns n: step n steps\n\nnote: Note\nThis function requires using Plots to be called before it is used.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!","page":"API","title":"LowLevelParticleFilters.correct!","text":"(; ll, e, S, Sᵪ, K) = correct!(kf::AbstractKalmanFilter, u, y, p = parameters(kf), t::Integer = index(kf), R2)\n\nThe correct step for a Kalman filter returns not only the log likelihood ll and the prediction error e, but also the covariance of the output S, its Cholesky factor Sᵪ and the Kalman gain K.\n\nIf R2 stored in kf is a function R2(x, u, p, t), this function is evaluated at the state before the correction is performed. The measurement noise covariance matrix R2 stored in the filter object can optionally be overridden by passing the argument R2, in this case R2 must be a matrix.\n\nExtended help\n\nTo perform separate measurement updates for different sensors, see the \"Measurement models\" in the documentation.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!-2","page":"API","title":"LowLevelParticleFilters.correct!","text":"ll, e = correct!(pf, u, y, p = parameters(f), t = index(f))\n\nUpdate state/weights based on measurement y, returns log-likelihood and prediction error (the error is always 0 for particle filters).\n\nExtended help\n\nTo perform separate measurement updates for different sensors, see the \"Measurement models\" in the documentation. For AdvancedParticleFilter, this can be realized by passing a custom measurement_likelihood function as the keyword argument g to correct!, or by calling the lower-level function measurement_equation! with a custom measurement_likelihood.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!-3","page":"API","title":"LowLevelParticleFilters.correct!","text":"correct!(kf::SqKalmanFilter, u, y, p = parameters(kf), t::Real = index(kf); R2 = get_mat(kf.R2, kf.x, u, p, t))\n\nFor the square-root Kalman filter, a custom provided R2 must be the upper triangular Cholesky factor of the covariance matrix of the measurement noise.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.correct!-Tuple{IMM, Any, Any, Vararg{Any}}","page":"API","title":"LowLevelParticleFilters.correct!","text":"ll, lls, rest = correct!(imm::IMM, u, y, args; kwargs)\n\nThe correct step of the IMM filter corrects each model with the measurements y and control input u. The mixing probabilities imm.μ are updated based on the likelihood of each model given the measurements and the transition probability matrix P.\n\nThe returned tuple consists of the sum of the log-likelihood of all models, the vector of individual log-likelihoods and an array of the rest of the return values from the correct step of each model.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.correct!-Tuple{UnscentedKalmanFilter, Any, Any, Any, Real}","page":"API","title":"LowLevelParticleFilters.correct!","text":"correct!(ukf::UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, u, y, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R2 = get_mat(ukf.R2, ukf.x, u, p, t), mean, cross_cov, innovation)\n\nThe correction step for an UnscentedKalmanFilter allows the user to override, R2, mean, cross_cov, innovation.\n\nArguments:\n\nu: The input\ny: The measurement\np: The parameters\nt: The current time\nR2: The measurement noise covariance matrix, or a function that returns the covariance matrix (x,u,p,t)->R2.\nmean: The function that computes the mean of the output sigma points.\ncross_cov: The function that computes the cross-covariance of the state and output sigma points.\ninnovation: The function that computes the innovation between the measured output and the predicted output.\n\nExtended help\n\nTo perform separate measurement updates for different sensors, see the \"Measurement models\" in the documentation\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.debugplot","page":"API","title":"LowLevelParticleFilters.debugplot","text":"debugplot(pf, u, y, p=parameters(pf); runall=false, kwargs...)\n\nProduce a helpful plot. For customization options (kwargs...), see ?pplot.\n\nrunall=false: if true, runs all time steps befor displaying (faster), if false, displays the plot after each time step.\n\nThe generated plot becomes quite heavy. Initially, try limiting your input to 100 time steps to verify that it doesn't crash.\n\nnote: Note\nThis function requires using Plots to be called before it is used.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.densityplot","page":"API","title":"LowLevelParticleFilters.densityplot","text":"densityplot(x,[w])\n\nPlot (weighted) particles densities\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.forward_trajectory","page":"API","title":"LowLevelParticleFilters.forward_trajectory","text":"sol = forward_trajectory(kf::AbstractKalmanFilter, u::Vector, y::Vector, p=parameters(kf))\n\nRun a Kalman filter forward to perform (offline / batch) filtering along an entire trajectory u, y.\n\nReturns a KalmanFilteringSolution: with the following\n\nx: predictions x(tt-1)\nxt: filtered estimates x(tt)\nR: predicted covariance matrices R(tt-1)\nRt: filter covariances R(tt)\nll: loglik\n\nsol can be plotted\n\nplot(sol::KalmanFilteringSolution; plotx = true, plotxt=true, plotu=true, ploty=true)\n\nSee KalmanFilteringSolution for more details.\n\nExtended help\n\nVery large systems\n\nIf your system is very large, i.e., the dimension of the state is very large, and the arrays u,y are long, this function may use a lot of memory to store all covariance matrices R, Rt. If you do not need all the information retained by this function, you may opt to call one of the functions\n\nloglik\nLowLevelParticleFilters.sse\nLowLevelParticleFilters.prediction_errors!\n\nThat store significantly less information. The amount of computation performed by all of these functions is identical, the only difference lies in what is stored and returned.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.forward_trajectory-2","page":"API","title":"LowLevelParticleFilters.forward_trajectory","text":"sol = forward_trajectory(pf, u::AbstractVector, y::AbstractVector, p=parameters(pf))\n\nRun the particle filter for a sequence of inputs and measurements (offline / batch filtering). Return a solution with x,w,we,ll = particles, weights, expweights and loglikelihood\n\nIf MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.\n\nsol can be plotted\n\nplot(sol::ParticleFilteringSolution; nbinsy=30, xreal=nothing, dim=nothing)\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.forward_trajectory-3","page":"API","title":"LowLevelParticleFilters.forward_trajectory","text":"forward_trajectory(imm::IMM, u, y, p = parameters(imm); interact = true)\n\nWhen performing batch filtering using an IMM filter, one may\n\nOverride the interact parameter of the filter\nAccess the mode probabilities along the trajectory as the sol.extra field. This is a matrix of size (n_modes, T) where T is the length of the trajectory (length of u and y).\n\nThe returned solution object is of type KalmanFilteringSolution and has the following fields:\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.interact!-Tuple{IMM}","page":"API","title":"LowLevelParticleFilters.interact!","text":"interact!(imm::IMM)\n\nThe interaction step of the IMM filter updates the state and covariance of each internal model based on the mixing probabilities imm.μ and the transition probability matrix imm.P.\n\nModels with small mixing probabilities will have their states and covariances updated more towards the states and covariances of models with higher mixing probabilities, and vice versa.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.log_likelihood_fun-Tuple{Any, AbstractVector, Any, Any, Any}","page":"API","title":"LowLevelParticleFilters.log_likelihood_fun","text":"ll(θ) = log_likelihood_fun(filter_from_parameters(θ::Vector)::Function, priors::Vector{Distribution}, u, y, p)\n\nreturns function θ -> p(y|θ)p(θ)\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.loglik","page":"API","title":"LowLevelParticleFilters.loglik","text":"ll = loglik(filter, u, y, p=parameters(filter))\n\nCalculate log-likelihood for entire sequences u,y\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.logsumexp!","page":"API","title":"LowLevelParticleFilters.logsumexp!","text":"ll = logsumexp!(w, we [, maxw])\n\nNormalizes the weight vector w and returns the weighted log-likelihood\n\nhttps://arxiv.org/pdf/1412.8695.pdf eq 3.8 for p(y) https://discourse.julialang.org/t/fast-logsumexp/22827/7?u=baggepinnen for stable logsumexp\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.mean_trajectory-Tuple{Any, Vector, Vector}","page":"API","title":"LowLevelParticleFilters.mean_trajectory","text":"x,ll = mean_trajectory(pf, u::Vector{Vector}, y::Vector{Vector}, p=parameters(pf))\n\nThis method resets the particle filter to the initial state distribution upon start\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.mean_trajectory-Tuple{ParticleFilteringSolution}","page":"API","title":"LowLevelParticleFilters.mean_trajectory","text":"mean_trajectory(sol::ParticleFilteringSolution)\nmean_trajectory(x::AbstractMatrix, we::AbstractMatrix)\n\nCompute the weighted mean along the trajectory of a particle-filter solution. Returns a matrix of size T × nx. If x and we are supplied, the weights are expected to be in the original space (not log space).\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.metropolis","page":"API","title":"LowLevelParticleFilters.metropolis","text":"metropolis(ll::Function(θ), R::Int, θ₀::Vector, draw::Function(θ) = naive_sampler(θ₀))\n\nPerforms MCMC sampling using the marginal Metropolis (-Hastings) algorithm draw = θ -> θ' samples a new parameter vector given an old parameter vector. The distribution must be symmetric, e.g., a Gaussian. R is the number of iterations. See log_likelihood_fun\n\nExample:\n\nfilter_from_parameters(θ) = ParticleFilter(N, dynamics, measurement, MvNormal(n,exp(θ[1])), MvNormal(p,exp(θ[2])), d0)\npriors = [Normal(0,0.1),Normal(0,0.1)]\nll = log_likelihood_fun(filter_from_parameters,priors,u,y,1)\nθ₀ = log.([1.,1.]) # Initial point\ndraw = θ -> θ .+ rand(MvNormal(0.1ones(2))) # Function that proposes new parameters (has to be symmetric)\nburnin = 200 # If using threaded call, provide number of burnin iterations\n# @time theta, lls = metropolis(ll, 2000, θ₀, draw) # Run single threaded\n# thetam = reduce(hcat, theta)'\n@time thetalls = LowLevelParticleFilters.metropolis_threaded(burnin, ll, 5000, θ₀, draw) # run on all threads, will provide (2000-burnin)*nthreads() samples\nhistogram(exp.(thetalls[:,1:2]), layout=3)\nplot!(thetalls[:,3], subplot=3) # if threaded call, log likelihoods are in the last column\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.reset!-Tuple{LowLevelParticleFilters.AbstractKalmanFilter}","page":"API","title":"LowLevelParticleFilters.reset!","text":"reset!(kf::AbstractKalmanFilter; x0)\n\nReset the initial distribution of the state. Optionally, a new mean vector x0 can be provided.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.reset!-Tuple{LowLevelParticleFilters.AbstractParticleFilter}","page":"API","title":"LowLevelParticleFilters.reset!","text":"Reset the filter to initial state and covariance/distribution\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.reset!-Tuple{SqKalmanFilter}","page":"API","title":"LowLevelParticleFilters.reset!","text":"reset!(kf::SqKalmanFilter; x0)\n\nReset the initial distribution of the state. Optionally, a new mean vector x0 can be provided.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.simulate","page":"API","title":"LowLevelParticleFilters.simulate","text":"x,u,y = simulate(f::AbstractFilter, T::Int, du::Distribution, p=parameters(f), [N]; dynamics_noise=true, measurement_noise=true)\nx,u,y = simulate(f::AbstractFilter, u, p=parameters(f); dynamics_noise=true, measurement_noise=true)\n\nSimulate dynamical system forward in time T steps, or for the duration of u. Returns state sequence, inputs and measurements.\n\nu is an input-signal trajectory, alternatively, du is a distribution of random inputs.\n\nA simulation can be considered a draw from the prior distribution over the evolution of the system implied by the selected noise models. Such a simulation is useful in order to evaluate whether or not the noise models are reasonable.\n\nIf MonteCarloMeasurements.jl is loaded, the argument N::Int can be supplied, in which case N simulations are done and the result is returned in the form of Vector{MonteCarloMeasurements.Particles}.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.smooth","page":"API","title":"LowLevelParticleFilters.smooth","text":"xT,RT,ll = smooth(sol, kf)\nxT,RT,ll = smooth(kf::KalmanFilter, u::Vector, y::Vector, p=parameters(kf))\nxT,RT,ll = smooth(kf::ExtendedKalmanFilter, u::Vector, y::Vector, p=parameters(kf))\n\nReturns smoothed estimates of state x and covariance R given all input output data u,y or an existing solution sol obtained from forward_trajectory.\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.smooth-2","page":"API","title":"LowLevelParticleFilters.smooth","text":"xb,ll = smooth(pf, M, u, y, p=parameters(pf))\nxb,ll = smooth(pf, xf, wf, wef, ll, M, u, y, p=parameters(pf))\n\nPerform particle smoothing using forward-filtering, backward simulation. Return smoothed particles and loglikelihood. See also smoothed_trajs, smoothed_mean, smoothed_cov\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.smoothed_cov-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.smoothed_cov","text":"smoothed_cov(xb)\n\nHelper function to calculate the covariance of smoothed particle trajectories\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.smoothed_mean-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.smoothed_mean","text":"smoothed_mean(xb)\n\nHelper function to calculate the mean of smoothed particle trajectories\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.smoothed_trajs-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.smoothed_trajs","text":"smoothed_trajs(xb)\n\nHelper function to get particle trajectories as a 3-dimensions array (N,M,T) instead of matrix of vectors.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.update!","page":"API","title":"LowLevelParticleFilters.update!","text":"ll, e = update!(f::AbstractFilter, u, y, p = parameters(f), t = index(f))\n\nPerform one step of predict! and correct!, returns log-likelihood and prediction error\n\n\n\n\n\n","category":"function"},{"location":"api/#LowLevelParticleFilters.update!-Tuple{IMM, Any, Any, Vararg{Any}}","page":"API","title":"LowLevelParticleFilters.update!","text":"update!(imm::IMM, u, y, p, t; correct_kwargs = (;), predict_kwargs = (;), interact = true)\n\nThe combined udpate for an IMM filter performs the following steps:\n\nCorrect each model with the measurements y and control input u.\nCombine the models into a single state and covariance.\nInteract the models to update their respective state and covariance.\nPredict each model to the next time step.\n\nThis differs slightly from the udpate step of other filters, where at the end of an update the state of the filter is the one-step ahead predicted value, whereas here each individual filter has a predicted state, but the combine! step of the IMM filter hasn't been performed on the predictions yet. The state of the IMM filter is thus x(tt) and not x(t+1t) like it is for other filters, and each filter internal to the IMM.\n\nArguments:\n\ncorrect_kwargs: An optional named tuple of keyword arguments that are sent to correct!.\npredict_kwargs: An optional named tuple of keyword arguments that are sent to predict!.\ninteract: Whether or not to run the interaction step.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.weighted_cov-Tuple{Any, Any}","page":"API","title":"LowLevelParticleFilters.weighted_cov","text":"weighted_cov(x,we)\n\nSimilar to weighted_mean, but returns covariances\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.weighted_mean-Tuple{Any, AbstractVector}","page":"API","title":"LowLevelParticleFilters.weighted_mean","text":"x̂ = weighted_mean(x,we)\n\nCalculated weighted mean of particle trajectories. we are expweights.\n\n\n\n\n\n","category":"method"},{"location":"api/#LowLevelParticleFilters.weighted_mean-Tuple{Any}","page":"API","title":"LowLevelParticleFilters.weighted_mean","text":"x̂ = weighted_mean(pf)\nx̂ = weighted_mean(s::PFstate)\n\n\n\n\n\n","category":"method"},{"location":"api/#StatsAPI.predict!","page":"API","title":"StatsAPI.predict!","text":"predict!(f, u, p = parameters(f), t = index(f))\n\nMove filter state forward in time using dynamics equation and input vector u.\n\n\n\n\n\n","category":"function"},{"location":"api/#StatsAPI.predict!-2","page":"API","title":"StatsAPI.predict!","text":"predict!(kf::SqKalmanFilter, u, p = parameters(kf), t::Real = index(kf); R1 = get_mat(kf.R1, kf.x, u, p, t), α = kf.α)\n\nFor the square-root Kalman filter, a custom provided R1 must be the upper triangular Cholesky factor of the covariance matrix of the process noise.\n\n\n\n\n\n","category":"function"},{"location":"api/#StatsAPI.predict!-3","page":"API","title":"StatsAPI.predict!","text":"predict!(kf::AbstractKalmanFilter, u, p = parameters(kf), t::Integer = index(kf); R1, α = kf.α)\n\nPerform the prediction step (updating the state estimate to x(t+1t)). If R1 stored in kf is a function R1(x, u, p, t), this function is evaluated at the state before the prediction is performed. The dynamics noise covariance matrix R1 stored in kf can optionally be overridden by passing the argument R1, in this case R1 must be a matrix.\n\n\n\n\n\n","category":"function"},{"location":"api/#StatsAPI.predict!-Union{Tuple{AUGM}, Tuple{AUGD}, Tuple{IPM}, Tuple{IPD}, Tuple{UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, Any}, Tuple{UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, Any, Any}, Tuple{UnscentedKalmanFilter{IPD, IPM, AUGD, AUGM}, Any, Any, Real}} where {IPD, IPM, AUGD, AUGM}","page":"API","title":"StatsAPI.predict!","text":"predict!(ukf::UnscentedKalmanFilter, u, p = parameters(ukf), t::Real = index(ukf) * ukf.Ts; R1 = get_mat(ukf.R1, ukf.x, u, p, t), reject, mean, cov, dynamics)\n\nThe prediction step for an UnscentedKalmanFilter allows the user to override, R1 and any of the functions, reject, mean, cov, dynamics`.\n\nArguments:\n\nu: The input\np: The parameters\nt: The current time\nR1: The dynamics noise covariance matrix, or a function that returns the covariance matrix.\nreject: A function that takes a sigma point and returns true if it should be rejected.\nmean: The function that computes the mean of the state sigma points.\ncov: The function that computes the covariance of the state sigma points.\n\n\n\n\n\n","category":"method"},{"location":"api/","page":"API","title":"API","text":"LowLevelParticleFilters.prediction_errors!","category":"page"},{"location":"api/#LowLevelParticleFilters.prediction_errors!","page":"API","title":"LowLevelParticleFilters.prediction_errors!","text":"prediction_errors!(res, f::AbstractFilter, u, y, p = parameters(f), λ = 1)\n\nCalculate the prediction errors and store the result in res. Similar to sse, this function is useful for sum-of-squares optimization. In contrast to sse, this function returns the residuals themselves rather than their sum of squares. This is useful for Gauss-Newton style optimizers, such as LeastSquaresOptim.LevenbergMarquardt.\n\nArguments:\n\nres: A vector of length ny*length(y). Note, for each datapoint in u and u, there are ny outputs, and thus ny residuals.\nf: Any filter\nλ: A weighting factor to minimize dot(e, λ, e). A commonly used metric is λ = Diagonal(1 ./ (mag.^2)), where mag is a vector of the \"typical magnitude\" of each output. Internally, the square root of W = sqrt(λ) is calculated so that the residuals stored in res are W*e.\n\nSee example in Solving using Gauss-Newton optimization.\n\n\n\n\n\n","category":"function"},{"location":"beetle_example/#Smoothing-the-track-of-a-moving-beetle","page":"Particle-filter tutorial","title":"Smoothing the track of a moving beetle","text":"","category":"section"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"This is an example of smoothing the 2-dimensional trajectory of a moving dung beetle. The example spurred off of this Discourse topic. For more information about the research behind this example, see Artificial light disrupts dung beetles’ sense of direction and A dung beetle that path integrates without the use of landmarks. Special thanks to Yakir Gagnon for providing this example.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"In this example we will describe the position coordinates, x and y, of the beetle as functions of its velocity, v_t, and direction, θ_t:","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"beginaligned\nx_t+1 = x_t + cos(θ_t)v_t \ny_t+1 = y_t + sin(θ_t)v_t \nv_t+1 = v_t + e_t \nθ_t+1 = θ_t + w_t\nendaligned","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"where e_t N(0σ_e) w_t N(0σ_w) The beetle further has two \"modes\", one where it's moving towards a goal, and one where it's searching in a more erratic manner. Figuring out when this mode switch occurs is the goal of the filtering. The mode will be encoded as a state variable, and used to determine the amount of dynamic noise affecting the angle of the beetle, i.e., in the searching mode, the beetle has more angle noise. The mode switching is modeled as a stochastic process with a binomial distribution (coin flip) describing the likelihood of a switch from mode 0 (moving to goal) and mode 1 (searching). Once the beetle has started searching, it stays in that mode, i.e., the searching mode is \"sticky\" or \"terminal\".","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"The image below shows an example video from which the data is obtained (Image: Bettle)","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We load a single experiment from file for the purpose of this example (in practice, there may be hundreds of experiments)","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots, Random\nusing DisplayAs # hide\nusing DelimitedFiles\npath = \"../track.csv\"\nxyt = readdlm(path)\ntosvec(y) = reinterpret(SVector{length(y[1]),Float64}, reduce(hcat,y))[:] |> copy # helper function\ny = tosvec(collect(eachrow(xyt[:,1:2])))\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We then define some properties of the dynamics and the filter. We will use an AdvancedParticleFilter since we want to have fine-grained control over the noise sampling for the mode switch.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"N = 2000 # Number of particles in the particle filter\nn = 4 # Dimension of state: we have position (2D), speed and angle\np = 2 # Dimension of measurements, we can measure the x and the y\n@inline pos(s) = s[SVector(1,2)]\n@inline vel(s) = s[3]\n@inline ϕ(s) = s[4]\n@inline mode(s) = s[5]\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We then define the probability distributions we need.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"dgσ = 1 # the deviation of the measurement noise distribution\ndvσ = 0.3 # the deviation of the dynamics noise distribution\nϕσ = 0.5\nconst switch_prob = 0.03 # Probability of mode switch\nconst dg = MvNormal(@SVector(zeros(p)), dgσ^2) # Measurement noise Distribution\nconst df = LowLevelParticleFilters.TupleProduct((Normal.(0,[1e-1, 1e-1, dvσ, ϕσ])...,Binomial(1,switch_prob)))\nd0 = MvNormal(SVector(y[1]..., 0.5, atan((y[2]-y[1])...), 0), [3.,3,2,2,0])\nconst noisevec = zeros(5) # cache vector\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We now define the dynamics, since we use the advanced filter, we include the noise=false argument. The dynamics is directly defined in discrete time.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"@inline function dynamics(s,u,p,t,noise=false)\n # current state\n m = mode(s)\n v = vel(s)\n a = ϕ(s)\n p = pos(s)\n # get noise\n if noise\n y_noise, x_noise, v_noise, ϕ_noise,_ = rand!(df, noisevec)\n else\n y_noise, x_noise, v_noise, ϕ_noise = 0.,0.,0.,0.\n end\n # next state\n v⁺ = max(0.999v + v_noise, 0.0)\n m⁺ = Float64(m == 0 ? rand() < switch_prob : true)\n a⁺ = a + (ϕ_noise*(1 + m*10))/(1 + v⁺) # next state velocity is used here\n p⁺ = p + SVector(y_noise, x_noise) + SVector(sincos(a))*v⁺ # current angle but next velocity\n SVector{5,Float64}(p⁺[1], p⁺[2], v⁺, a⁺, m⁺) # all next state\nend\nfunction measurement_likelihood(s,u,y,p,t)\n logpdf(dg, pos(s)-y) # A simple linear measurement model with normal additive noise\nend\n@inline measurement(s,u,p,t,noise=false) = s[SVector(1,2)] + noise*rand(dg) # We observe the position coordinates with the measurement\nnothing # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"In this example, we have no control inputs, we thus define a vector of only zeros. We then solve the forward filtering problem and plot the results.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"u = zeros(length(y))\npf = AuxiliaryParticleFilter(AdvancedParticleFilter(N, dynamics, measurement, measurement_likelihood, df, d0))\nT = length(y)\nsol = forward_trajectory(pf,u[1:T],y[1:T])\n(; x,w,we,ll) = sol\nplot(sol, markerstrokecolor=:auto, m=(2,0.5))\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We can clearly see when the beetle switched mode (state variable 5). This corresponds well to annotations provided by a biologist and is the fundamental question we want to answer with the filtering procedure.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We can plot the mean of the filtered trajectory as well","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"xh = mean_trajectory(x,we)\n\n\"plotting helper function\"\nfunction to1series(x::AbstractVector, y)\n r,c = size(y)\n y2 = vec([y; fill(Inf, 1, c)])\n x2 = repeat([x; Inf], c)\n x2,y2\nend\nto1series(y) = to1series(1:size(y,1),y)\n\nfig1 = plot(xh[:,1],xh[:,2], c=:blue, lab=\"estimate\", legend=:bottomleft)\nplot!(xyt[:,1],xyt[:,2], c=:red, lab=\"measurement\")","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"as well as the angle state variable (we subsample the particles to not get sluggish plots)","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"fig2 = scatter(to1series(ϕ.(x)'[:,1:2:end])..., m=(:black, 0.03, 2), lab=\"\", size=(500,300))\nplot!(identity.(xh[:,4]), lab=\"Filtered angle\", legend=:topleft, ylims=(-30, 70))\nDisplayAs.PNG(fig2) # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"The particle plot above indicate that the posterior is multimodal. This phenomenon arises due to the simple model that uses an angle that is allowed to leave the interval 0-2π rad. In this example, we are not interested in the angle, but rather when the beetle switches mode. The filtering distribution above gives a hint at when this happens, but we will not plot the mode trajectory until we have explored smoothing as well.","category":"page"},{"location":"beetle_example/#Smoothing","page":"Particle-filter tutorial","title":"Smoothing","text":"","category":"section"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"The filtering results above does not use all the available information when trying to figure out the state trajectory. To do this, we may call a smoother. We use a particle smoother and compute 10 smoothing trajectories.","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"M = 10 # Number of smoothing trajectories, NOTE: if this is set higher, the result will be better at the expense of linear scaling of the computational cost.\nsb,ll = smooth(pf, M, u, y) # Sample smoothing particles (b for backward-trajectory)\nsbm = smoothed_mean(sb) # Calculate the mean of smoothing trajectories\nsbt = smoothed_trajs(sb) # Get smoothing trajectories\nplot!(fig1, sbm[1,:],sbm[2,:], lab=\"xs\")","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"plot!(fig2, identity.(sbm'[:,4]), lab=\"smoothed\")\nDisplayAs.PNG(fig2) # hide","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We see that the smoothed trajectory may look very different from the filter trajectory. This is an indication that it's hard to tell what state the beetle is currently in, but easier to look back and tell what state the beetle must have been in at a historical point. ","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"We can also visualize the mode state","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"plot(xh[:,5], lab=\"Filtering\")\nplot!(to1series(sbt[5,:,:]')..., lab=\"Smoothing\", title=\"Mode trajectories\", l=(:black,0.2))","category":"page"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"also this state variable indicates that it's hard to tell what state the beetle is in during filtering, but obvious with hindsight (smoothing). The mode switch occurs when the filtering distribution of the angle becomes drastically wider, indicating that increased dynamics noise is required in order to describe the motion of the beetle.","category":"page"},{"location":"beetle_example/#Summary","page":"Particle-filter tutorial","title":"Summary","text":"","category":"section"},{"location":"beetle_example/","page":"Particle-filter tutorial","title":"Particle-filter tutorial","text":"This example has demonstrated filtering and smoothing in an advanced application that includes manual control over noise, mixed continuous and discrete state.","category":"page"},{"location":"beetle_example_imm/#Filtering-the-track-of-a-moving-beetle-using-IMM","page":"IMM-filter tutorial","title":"Filtering the track of a moving beetle using IMM","text":"","category":"section"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"This tutorial is very similar to Smoothing the track of a moving beetle, but uses an Interacting Multiple Models (IMM) filter to model the mode switching of the beetle. The IMM filter is a mixture model, in this case with internal Unscented Kalman filters, where each Kalman filter represents a different mode of the system. The IMM filter is able to switch between these modes based on the likelihood of the mode given the data.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"This is an example of smoothing the 2-dimensional trajectory of a moving dung beetle. The example spurred off of this Discourse topic. For more information about the research behind this example, see Artificial light disrupts dung beetles’ sense of direction and A dung beetle that path integrates without the use of landmarks. Special thanks to Yakir Gagnon for providing this example.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"In this example we will describe the position coordinates, x and y, of the beetle as functions of its velocity, v_t, and direction, θ_t:","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"beginaligned\nx_t+1 = x_t + cos(θ_t)v_t \ny_t+1 = y_t + sin(θ_t)v_t \nv_t+1 = v_t + e_t \nθ_t+1 = θ_t + w_t\nendaligned","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"where e_t N(0σ_e) w_t N(0σ_w) The beetle further has two \"modes\", one where it's moving towards a goal, and one where it's searching in a more erratic manner. Figuring out when this mode switch occurs is the goal of the filtering. The mode will be encoded as two different models, where the difference between the models lies in the amount of dynamic noise affecting the angle of the beetle, i.e., in the searching mode, the beetle has more angle noise. The mode switching is modeled as a stochastic process with a binomial distribution (coin flip) describing the likelihood of a switch from mode 0 (moving to goal) and mode 1 (searching). Once the beetle has started searching, it stays in that mode, i.e., the searching mode is \"sticky\" or \"terminal\".","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"The image below shows an example video from which the data is obtained (Image: Bettle)","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We load a single experiment from file for the purpose of this example (in practice, there may be hundreds of experiments)","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots, Random\nusing DisplayAs # hide\nusing DelimitedFiles\ncd(@__DIR__)\npath = \"../track.csv\"\nxyt = readdlm(path)\ntosvec(y) = reinterpret(SVector{length(y[1]),Float64}, reduce(hcat,y))[:] |> copy # helper function\ny = tosvec(collect(eachrow(xyt[:,1:2])))\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We then define some properties of the dynamics and the filter. We will use an AdvancedParticleFilter since we want to have fine-grained control over the noise sampling for the mode switch.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"nx = 4 # Dimension of state: we have position (2d), speed and angle\nny = 2 # Dimension of measurements, we can measure the x and the y\n@inline pos(s) = s[SVector(1,2)]\n@inline vel(s) = s[3]\n@inline ϕ(s) = s[4]\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We then define the probability distributions we need. The IMM filter takes a transition-probability matrix, P, and an initial mixing probability, μ. P is a Markov (stochastic) matrix, where each row sums to one, and P[i, j] is the probability of switching from mode i to mode j. μ is a vector of probabilities, where μ[i] is the probability of starting in mode i. We also define the noise distributions for the dynamics and the measurements. The dynamics noise is modeled as a Gaussian distribution with a standard deviation of dvσ for the velocity and ϕσ for the angle. The measurement noise is modeled as a Gaussian distribution with a standard deviation of dgσ. The initial state is modeled as a Gaussian distribution with a mean at the first measurement and a standard deviation of d0.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"dgσ = 1.0 # the deviation of the measurement noise distribution\ndvσ = 0.3 # the deviation of the dynamics noise distribution\nϕσ = 0.5\nP = [0.995 0.005; 0.0 1] # Transition probability matrix, we model the search mode as \"terminal\"\nμ = [1.0, 0.0] # Initial mixing probabilities\nR1 = Diagonal([1e-1, 1e-1, dvσ, ϕσ].^2)\nR2 = dgσ^2*I(ny) # Measurement noise covariance matrix\nd0 = MvNormal(SVector(y[1]..., 0.5, atan((y[2]-y[1])...)), [3.,3,2,2])\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We now define the dynamics, which is directly defined in discrete time. The third argument is a parameter we call modegain, which is used to scale the amount of noise in the angle of the beetle depending on the mode in which it is in. The last argument is a boolean that tells the dynamics function which mode it is in, we will close over this argument when defining the dynamics for the individual Kalman filters that are part of the IMM, one will use m = false and one will use m = true.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"@inline function dynamics(s,_,modegain,t,w,m)\n # current state\n v = vel(s)\n a = ϕ(s)\n p = pos(s)\n\n y_noise, x_noise, v_noise, ϕ_noise = w\n\n # next state\n v⁺ = max(0.999v + v_noise, 0.0)\n a⁺ = a + (ϕ_noise*(1 + m*modegain))/(1 + v⁺) # next state velocity is used here\n p⁺ = p + SVector(y_noise, x_noise) + SVector(sincos(a))*v⁺ # current angle but next velocity\n SVector(p⁺[1], p⁺[2], v⁺, a⁺) # all next state\nend\n@inline measurement(s,u,p,t) = s[SVector(1,2)] # We observe the position coordinates with the measurement\nnothing # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"In this example, we have no control inputs, we thus define a vector of only zeros. We then solve the forward filtering problem and plot the results.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"u = zeros(length(y)) # no control inputs\nkffalse = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,false), measurement, R1, R2, d0; ny, nu=0, p=10)\nkftrue = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,true), measurement, R1, R2, d0; ny, nu=0, p=10)\n\nimm = IMM([kffalse, kftrue], P, μ; p = 10)\n\nT = length(y)\nsol = forward_trajectory(imm, u, y, interact=true)\nfigx = plot(sol, plotu=false, plotRt=true)\nfigmode = plot(sol.extra', title=\"Mode\")\nplot(figx, figmode)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"If you have followed the particle filter tutorial Smoothing the track of a moving beetle, you will notice that the result here is much worse. We used noise parameters similar to in the particle-gilter example, but those were tuned fo the particle filter. Below, we will attempt to optimize the performance of the IMM filter.","category":"page"},{"location":"beetle_example_imm/#Tuning-by-optimization","page":"IMM-filter tutorial","title":"Tuning by optimization","text":"","category":"section"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"We will attempt to optimize the dynamics and measurement noise covariance matrices and the modegain parameter. We code this up in two functions, one that takes the parameter vector and returns an IMM filter, and one that calculates the loss given the filter. We will optimize the log-likelihood of the data given the filter.","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"params = [log10.(diag(R1)); log10(1); log10(10)]\n\nfunction get_opt_kf(p)\n T = eltype(p)\n R1i = Diagonal(SVector{4}(exp10.(p[1:4])))\n R2i = SMatrix{2,2}(exp10(p[5])*R2)\n d0i = MvNormal(SVector{4, T}(T.(d0.μ)), SMatrix{4,4}(T.(d0.Σ)))\n modegain = 2+exp10(p[6])\n Pi = SMatrix{2,2, Float64,4}(P)\n # sigmoid(x) = 1/(1+exp(-x))\n # switch_prob = sigmoid(p[7])\n # Pi = [1-switch_prob switch_prob; 0 1]\n kffalse = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,false), measurement, R1i, R2i, d0i; ny, nu=0)\n kftrue = UnscentedKalmanFilter{false,false,true,false}((x,u,p,t,w)->dynamics(x,u,p,t,w,true), measurement, R1i, R2i, d0i; ny, nu=0)\n\n IMM([kffalse, kftrue], Pi, T.(μ), p=modegain)\nend\nfunction cost(pars)\n try\n imm = get_opt_kf(pars)\n T = length(y)\n ll = loglik(imm, u[1:T], y[1:T], interact=true) - 1/2*logdet(imm.models[1].R1)\n return -ll\n catch e\n # rethrow() # If you only get Inf, you can uncomment this line to see the error message\n return eltype(pars)(Inf)\n\tend\nend\n\nusing Optim\nRandom.seed!(0)\nres = Optim.optimize(\n cost,\n params,\n ParticleSwarm(), # Use a gradient-free optimizer. ForwardDiff works, but the algorithm is numerically difficult to compute gradients through and may suffer from overflows in the gradient computation\n Optim.Options(\n show_trace = true,\n show_every = 5,\n iterations = 100,\n time_limit = 30,\n ),\n)\n\nimm = get_opt_kf(res.minimizer)\nimm = get_opt_kf([-0.1981314138910982, -0.18626406669394405, -2.7342979645906547, 0.17994244691004058, -11.706419070755908, -54.16703441089562]) #make sure it goes well # hide\n\nsol = forward_trajectory(imm, u, y)\nplot(sol.extra', title=\"Mode (optimized filter)\")","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"If it went well, the filter should be in mode 1 (the false mode) from the start until around 200 time steps, at which point it should switch to model 2 (true). This method of detecting the mode switch of the beetle appears to be somewhat less robust than the particle filter, but is significantly cheaper computationally. ","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"The IMM filter does not stick in mode 2 perpetually after having reached it since it never actually becomes fully confident that mode 2 has been reached, but detecting the first switch is sufficient to know that the switch has occurred. ","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"The log-likelihood of the solution","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"sol.ll","category":"page"},{"location":"beetle_example_imm/","page":"IMM-filter tutorial","title":"IMM-filter tutorial","text":"should be similar to that of the particle-filter in the tutorial Smoothing the track of a moving beetle, which was around -1660.","category":"page"},{"location":"noisetuning/#How-to-tune-a-Kalman-filter","page":"Noise tuning and disturbance modeling for Kalman filtering","title":"How to tune a Kalman filter","text":"","category":"section"},{"location":"noisetuning/","page":"Noise tuning and disturbance modeling for Kalman filtering","title":"Noise tuning and disturbance modeling for Kalman filtering","text":"This tutorial is hosted as a notebook.","category":"page"},{"location":"fault_detection/#Fault-detection","page":"Fault detection","title":"Fault detection","text":"","category":"section"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"This is a video tutorial, available below:","category":"page"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"","category":"page"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"The notebook used in the tutorial is available here:","category":"page"},{"location":"fault_detection/","page":"Fault detection","title":"Fault detection","text":"identification_12_fault_detection.jl on JuliaHub\nidentification_12_fault_detection.jl on GitHub","category":"page"},{"location":"discretization/#Discretization","page":"Discretization","title":"Discretization","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"This package operates exclusively on discrete-time dynamics, and dynamics describing, e.g., ODE systems must thus be discretized. This page describes the details around discretization for nonlinear and linear systems, as well as how to discretize continuous-time noise processes. ","category":"page"},{"location":"discretization/#Nonlinear-ODEs","page":"Discretization","title":"Nonlinear ODEs","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Continuous-time dynamics functions on the form (x,u,p,t) -> ẋ can be discretized (integrated) using the function SeeToDee.Rk4, e.g.,","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"using SeeToDee\ndiscrete_dynamics = SeeToDee.Rk4(continuous_dynamics, sampletime; supersample=1)","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"where the integer supersample determines the number of RK4 steps that is taken internally for each change of the control signal (1 is often sufficient and is the default). The returned function discrete_dynamics is on the form (x,u,p,t) -> x⁺.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"note: Note\nWhen solving state-estimation problems, accurate integration is often less important than during simulation. The motivations for this are severalThe dynamics model is often inaccurate, and solving an inaccurate model to high accuracy can be a waste of effort.\nThe performance is often dictated by the disturbances acting on the system.\nState-estimation enjoys feedback from measurements that corrects for slight errors due to integration.","category":"page"},{"location":"discretization/#Linear-systems","page":"Discretization","title":"Linear systems","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"A linear system on the form ","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"beginaligned\ndotx(t) = Ax(t) + Bu(t)\ny(t) = Cx(t) + Du(t)\nendaligned","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"can be discretized using ControlSystems.c2d, which defaults to a zero-order hold discretization. See the example below for more info.","category":"page"},{"location":"discretization/#Covariance-matrices","page":"Discretization","title":"Covariance matrices","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Covariance matrices for continuous-time noise processes can also be discretized using ControlSystems.c2d","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"using ControlSystemIdentification\nR1d = c2d(sys::StateSpace{<:Discrete}, R1::Matrix)\nR1d, R2d = c2d(sys::StateSpace{<:Discrete}, R1::Matrix, R2::Matrix)","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"This samples a continuous-time covariance matrix to fit the provided discrete-time system sys.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"The method used comes from theorem 5 in the reference below.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Ref: \"Discrete-time Solutions to the Continuous-time Differential Lyapunov Equation With Applications to Kalman Filtering\", Patrik Axelsson and Fredrik Gustafsson","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"On singular covariance matrices: The traditional double integrator with covariance matrix Q = diagm([0,σ²]) can not be sampled with this method. Instead, the input matrix (\"Cholesky factor\") of Q must be manually kept track of, e.g., the noise of variance σ² enters like N = [0, 1] which is sampled using ZoH and becomes Nd = [Ts^2 / 2; Ts] which results in the covariance matrix σ² * Nd * Nd' (see example below).","category":"page"},{"location":"discretization/#Example","page":"Discretization","title":"Example","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"The following example will discretize a linear double integrator system. Double integrators arise when the position of an object is controlled by a force, i.e., when Newtons second law f = ma governs the dynamics. The system can be written on the form","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"beginaligned\ndot x(t) = Ax(t) + Bu(t) + Nw(t)\ny(t) = Cx(t) + e(t)\nendaligned","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"where N = B are both equal to [0, 1], indicating that the noise w(t) enters like a force (this could be for instance due to air resistance or friction).","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"We start by defining the system that takes u as an input and discretize that with a sample time of T_s = 01.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"using ControlSystemsBase\nA = [0 1; 0 0]\nB = [0; 1;;]\nC = [1 0]\nD = 0\nTs = 0.1 # Sample time\n\nsys = ss(A,B,C,D)\nsysd = c2d(sys, Ts) # Discretize the dynamics","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"We then form another system, this time with w(t) as the input, and thus N as the input matrix instead of B. We assume that the noise has a standard deviation of sigma_1 = 05","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"σ1 = 0.5\nN = σ1*[0; 1;;]\nsys_w = ss(A,N,C,D)\nsys_wd = c2d(sys_w, Ts) # Discretize the noise system\nNd = sys_wd.B # The discretized noise input matrix\nR1d = Nd*Nd' # The final discrete-time covariance matrix","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"We can verify that the matrix we computed corresponds to the theoretical covariance matrix for a discrete-time double integrator:","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"R1d ≈ σ1^2*[Ts^2 / 2; Ts]*[Ts^2 / 2; Ts]'","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"For a nonlinear system, we could adopt a similar strategy by first linearizing the system around a suitable operating point. Alternatively, we could make use of the fact that some of the state estimators in this package allows the covariance matrices to be functions of the state, and thus compute a new discretized covariance matrix using a linearization around the current state.","category":"page"},{"location":"discretization/#Non-uniform-sample-rates","page":"Discretization","title":"Non-uniform sample rates","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Special care is needed if the sample rate is not constant, i.e., the time interval between measurements varies. ","category":"page"},{"location":"discretization/#Dropped-samples","page":"Discretization","title":"Dropped samples","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"A common case is that the sample rate is constant, but some measurements are lost. This case is very easy to handle; the filter loop iterates between two steps","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"Prediction using predict!(filter, x, u, p, t)\nCorrection using\ncorrect!(f, u, y, p, t) if using the standard measurement model of the filter\ncorrect!(f, mm, u, y, p, t, mm) to use a custom measurement model mm","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"If a measurement y is lacking, one simply skips the corresponding call to correct! where y is missing. Repeated calls to predict! corresponds to simulating the system without any feedback from measurements, like if an ODE was solved. Internally, the filter will keep track of the covariance of the estimate, which is likely to grow if no measurements are used to inform the filter about the state of the system.","category":"page"},{"location":"discretization/#Sensors-with-different-sample-rates","page":"Discretization","title":"Sensors with different sample rates","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"For Kalman-type filters, it is possible to construct custom measurement models, and pass an instance of a measurement model as the second argument to correct!. This allows for sensor fusion with sensors operating at different rates, or when parts of the measurement model are linear, and other parts are nonlinear. See examples in Measurement models for how to construct explicit measurement models.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"A video demonstrating the use of multiple measurement models running at different rates is available on YouTube:","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"","category":"page"},{"location":"discretization/#Stochastic-sample-rate","page":"Discretization","title":"Stochastic sample rate","text":"","category":"section"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"In some situations, such as in event-based systems, the sample rate is truly stochastic. There is no single correct way of handling this, and we instead outline some alternative approaches.","category":"page"},{"location":"discretization/","page":"Discretization","title":"Discretization","text":"If the filtering is performed offline on a batch of data, time-varying dynamics can be used, for instance by supplying matrices to a KalmanFilter on the form A[:, :, t]. Each A is then computed as the discretization with the sample time given as the time between measurement t and measurement t+1.\nA conceptually simple approach is to choose a very small sample interval T_s which is smaller than the smallest occuring sample interval in the data, and approximate each sample interval by rounding it to the nearest integer multiple of T_s. This transforms the problem to an instance of the \"dropped samples\" problem described above.\nMake use of an adaptive integrator instead of the fixed-step rk4 supplied in this package, and manually keep track of the step length that needs to be taken.","category":"page"},{"location":"benchmark/#Benchmark-test","page":"Benchmark","title":"Benchmark test","text":"","category":"section"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"To see how the performance varies with the number of particles, we simulate several times. The following code simulates the system and performs filtering using the simulated measurements. We do this for varying number of time steps and varying number of particles.","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"note: Note\nTo run this code, see the bottom of src/example_lineargaussian.jl.","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"function run_test()\n particle_count = [10, 20, 50, 100, 200, 500, 1000]\n time_steps = [20, 100, 200]\n RMSE = zeros(length(particle_count),length(time_steps)) # Store the RMS errors\n propagated_particles = 0\n t = @elapsed for (Ti,T) = enumerate(time_steps)\n for (Ni,N) = enumerate(particle_count)\n montecarlo_runs = 2*maximum(particle_count)*maximum(time_steps) ÷ T ÷ N\n E = sum(1:montecarlo_runs) do mc_run\n pf = ParticleFilter(N, dynamics, measurement, df, dg, d0) # Create filter\n u = @SVector randn(2)\n x = SVector{2,Float64}(rand(rng, d0))\n y = SVector{2,Float64}(sample_measurement(pf,x,u,0,1))\n error = 0.0\n @inbounds for t = 1:T-1\n pf(u, y) # Update the particle filter\n x = dynamics(x,u,t) + SVector{2,Float64}(rand(rng, df)) # Simulate the true dynamics and add some noise\n y = SVector{2,Float64}(sample_measurement(pf,x,u,0,t)) # Simulate a measuerment\n u = @SVector randn(2) # draw a random control input\n error += sum(abs2,x-weighted_mean(pf))\n end # t\n √(error/T)\n end # MC\n RMSE[Ni,Ti] = E/montecarlo_runs\n propagated_particles += montecarlo_runs*N*T\n @show N\n end # N\n @show T\n end # T\n println(\"Propagated $propagated_particles particles in $t seconds for an average of $(propagated_particles/t/1000) particles per millisecond\")\n return RMSE\nend\n\n@time RMSE = run_test()","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"Propagated 8400000 particles in 1.140468043 seconds for an average of 7365.397085484139 particles per millisecond","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"We then plot the results","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"time_steps = [20, 100, 200]\nparticle_count = [10, 20, 50, 100, 200, 500, 1000]\nnT = length(time_steps)\nleg = reshape([\"$(time_steps[i]) time steps\" for i = 1:nT], 1,:)\nplot(particle_count,RMSE,xscale=:log10, ylabel=\"RMS errors\", xlabel=\" Number of particles\", lab=leg)","category":"page"},{"location":"benchmark/","page":"Benchmark","title":"Benchmark","text":"(Image: window)","category":"page"},{"location":"#LowLevelParticleFilters","page":"Home","title":"LowLevelParticleFilters","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"(Image: CI) (Image: codecov)","category":"page"},{"location":"","page":"Home","title":"Home","text":"This is a library for state estimation, that is, given measurements y(t) from a dynamical system, estimate the state vector x(t). Throughout, we assume dynamics on the form","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nx(t+1) = f(x(t) u(t) p t w(t))\ny(t) = g(x(t) u(t) p t e(t))\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"or the linear version","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nx(t+1) = Ax(t) + Bu(t) + w(t)\ny(t) = Cx(t) + Du(t) + e(t)\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"where x is the state vector, u an input, p some form of parameters, t is the time and we are disturbances (noise). Throughout the documentation, we often call the function f dynamics and the function g measurement.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The dynamics above describe a discrete-time system, i.e., the function f takes the current state and produces the next state. This is in contrast to a continuous-time system, where f takes the current state but produces the time derivative of the state. A continuous-time system can be discretized, described in detail in Discretization.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The parameters p can be anything, or left out. You may write the dynamics functions such that they depend on p and include parameters when you create a filter object. You may also override the parameters stored in the filter object when you call any function on the filter object. This behavior is modeled after the SciML ecosystem.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Depending on the nature of f and g, the best method of estimating the state may vary. If fg are linear and the disturbances are additive and Gaussian, the KalmanFilter is an optimal state estimator. If any of the above assumptions fail to hold, we may need to resort to more advanced estimators. This package provides several filter types, outlined below.","category":"page"},{"location":"#Estimator-types","page":"Home","title":"Estimator types","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"We provide a number of filter types","category":"page"},{"location":"","page":"Home","title":"Home","text":"KalmanFilter. A standard Kalman filter. Is restricted to linear dynamics (possibly time varying) and Gaussian noise.\nSqKalmanFilter. A standard Kalman filter on square-root form (slightly slower but more numerically stable with ill-conditioned covariance).\nExtendedKalmanFilter: For nonlinear systems, the EKF runs a regular Kalman filter on linearized dynamics. Uses ForwardDiff.jl for linearization (or user provided). The noise model must still be Gaussian and additive.\nUnscentedKalmanFilter: The Unscented Kalman filter often performs slightly better than the Extended Kalman filter but may be slightly more computationally expensive. The UKF handles nonlinear dynamics and measurement models, but still requires a Gaussian noise model (may be non additive) and still assumes that all posterior distributions are Gaussian, i.e., can not handle multi-modal posteriors.\nParticleFilter: The particle filter is a nonlinear estimator. This version of the particle filter is simple to use and assumes that both dynamics noise and measurement noise are additive. Particle filters handle multi-modal posteriors.\nAdvancedParticleFilter: This filter gives you more flexibility, at the expense of having to define a few more functions. This filter does not require the noise to be additive and is thus the most flexible filter type.\nAuxiliaryParticleFilter: This filter is identical to ParticleFilter, but uses a slightly different proposal mechanism for new particles.\nIMM: (Currently considered experimental) The Interacting Multiple Models filter switches between multiple internal filters based on a hidden Markov model. This filter is useful when the system dynamics change over time and the change can be modeled as a discrete Markov chain, i.e., the system may switch between a small number of discrete \"modes\".","category":"page"},{"location":"#Functionality","page":"Home","title":"Functionality","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package provides ","category":"page"},{"location":"","page":"Home","title":"Home","text":"Filtering, estimating x(t) given measurements up to and including time t. We call the filtered estimate x(tt) (read as x at t given t).\nSmoothing, estimating x(t) given data up to T t, i.e., x(tT).\nParameter estimation.","category":"page"},{"location":"","page":"Home","title":"Home","text":"All filters work in two distinct steps.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The prediction step (predict!). During prediction, we use the dynamics model to form x(tt-1) = f(x(t-1) )\nThe correction step (correct!). In this step, we adjust the predicted state x(tt-1) using the measurement y(t) to form x(tt).","category":"page"},{"location":"","page":"Home","title":"Home","text":"(The IMM filter is an exception to the above and has two additional steps, combine! and interact!)","category":"page"},{"location":"","page":"Home","title":"Home","text":"In general, all filters represent not only a point estimate of x(t), but a representation of the complete posterior probability distribution over x given all the data available up to time t. One major difference between different filter types is how they represent these probability distributions.","category":"page"},{"location":"#Particle-filter","page":"Home","title":"Particle filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"A particle filter represents the probability distribution over the state as a collection of samples, each sample is propagated through the dynamics function f individually. When a measurement becomes available, the samples, called particles, are given a weight based on how likely the particle is given the measurement. Each particle can thus be seen as representing a hypothesis about the current state of the system. After a few time steps, most weights are inevitably going to be extremely small, a manifestation of the curse of dimensionality, and a resampling step is incorporated to refresh the particle distribution and focus the particles on areas of the state space with high posterior probability.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Defining a particle filter (ParticleFilter) is straightforward, one must define the distribution of the noise df in the dynamics function, dynamics(x,u,p,t) and the noise distribution dg in the measurement function measurement(x,u,p,t). Both of these noise sources are assumed to be additive, but can have any distribution (see AdvancedParticleFilter for non-additive noise). The distribution of the initial state estimate d0 must also be provided. In the example below, we use linear Gaussian dynamics so that we can easily compare both particle and Kalman filters. (If we have something close to linear Gaussian dynamics in practice, we should of course use a Kalman filter and not a particle filter.)","category":"page"},{"location":"","page":"Home","title":"Home","text":"using LowLevelParticleFilters, LinearAlgebra, StaticArrays, Distributions, Plots\nusing DisplayAs # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Define problem","category":"page"},{"location":"","page":"Home","title":"Home","text":"nx = 2 # Dimension of state\nnu = 1 # Dimension of input\nny = 1 # Dimension of measurements\nN = 500 # Number of particles\n\nconst dg = MvNormal(ny,0.2) # Measurement noise Distribution\nconst df = MvNormal(nx,0.1) # Dynamics noise Distribution\nconst d0 = MvNormal(randn(nx),2.0) # Initial state Distribution\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Define linear state-space system (using StaticArrays for maximum performance)","category":"page"},{"location":"","page":"Home","title":"Home","text":"const A = SA[0.97043 -0.097368\n 0.09736 0.970437]\nconst B = SA[0.1; 0;;]\nconst C = SA[0 1.0]\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Next, we define the dynamics and measurement equations, they both take the signature (x,u,p,t) = (state, input, parameters, time) ","category":"page"},{"location":"","page":"Home","title":"Home","text":"dynamics(x,u,p,t) = A*x .+ B*u\nmeasurement(x,u,p,t) = C*x\nvecvec_to_mat(x) = copy(reduce(hcat, x)') # Helper function\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"the parameter p can be anything, and is often optional. If p is not provided when performing operations on filters, any p stored in the filter objects (if supported) is used. The default if none is provided and none is stored in the filter is p = LowLevelParticleFilters.NullParameters().","category":"page"},{"location":"","page":"Home","title":"Home","text":"We are now ready to define and use a filter","category":"page"},{"location":"","page":"Home","title":"Home","text":"pf = ParticleFilter(N, dynamics, measurement, df, dg, d0)","category":"page"},{"location":"","page":"Home","title":"Home","text":"With the filter in hand, we can simulate from its dynamics and query some properties","category":"page"},{"location":"","page":"Home","title":"Home","text":"du = MvNormal(nu,1.0) # Random input distribution for simulation\nxs,u,y = simulate(pf,200,du) # We can simulate the model that the pf represents\npf(u[1], y[1]) # Perform one filtering step using input u and measurement y\nparticles(pf) # Query the filter for particles, try weights(pf) or expweights(pf) as well\nx̂ = weighted_mean(pf) # using the current state","category":"page"},{"location":"","page":"Home","title":"Home","text":"If you want to perform batch filtering using an existing trajectory consisting of vectors of inputs and measurements, try any of the functions forward_trajectory, mean_trajectory:","category":"page"},{"location":"","page":"Home","title":"Home","text":"sol = forward_trajectory(pf, u, y) # Filter whole trajectories at once\nx̂,ll = mean_trajectory(pf, u, y)\nplot(sol, xreal=xs, markersize=2)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"u ad y are then assumed to be vectors of vectors. StaticArrays is recommended for maximum performance.","category":"page"},{"location":"","page":"Home","title":"Home","text":"If MonteCarloMeasurements.jl is loaded, you may transform the output particles to Matrix{MonteCarloMeasurements.Particles} with the layout T × n_state using Particles(x,we). Internally, the particles are then resampled such that they all have unit weight. This is conventient for making use of the plotting facilities of MonteCarloMeasurements.jl.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For a full usage example, see the benchmark section below or example_lineargaussian.jl","category":"page"},{"location":"#Resampling","page":"Home","title":"Resampling","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The particle filter will perform a resampling step whenever the distribution of the weights has become degenerate. The resampling is triggered when the effective number of samples is smaller than pf.resample_threshold in 0 1, this value can be set when constructing the filter. How the resampling is done is governed by pf.resampling_strategy, we currently provide ResampleSystematic <: ResamplingStrategy as the only implemented strategy. See https://en.wikipedia.org/wiki/Particle_filter for more info.","category":"page"},{"location":"#Particle-Smoothing","page":"Home","title":"Particle Smoothing","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Smoothing is the process of finding the best state estimate given both past and future data. Smoothing is thus only possible in an offline setting. This package provides a particle smoother, based on forward filtering, backward simulation (FFBS), example usage follows:","category":"page"},{"location":"","page":"Home","title":"Home","text":"N = 2000 # Number of particles\nT = 80 # Number of time steps\nM = 100 # Number of smoothed backwards trajectories\npf = ParticleFilter(N, dynamics, measurement, df, dg, d0)\ndu = MvNormal(nu,1) # Control input distribution\nx,u,y = simulate(pf,T,du) # Simulate trajectory using the model in the filter\ntosvec(y) = reinterpret(SVector{length(y[1]),Float64}, reduce(hcat,y))[:] |> copy\nx,u,y = tosvec.((x,u,y)) # It's good for performance to use StaticArrays to the extent possible\n\nxb,ll = smooth(pf, M, u, y) # Sample smoothing particles\nxbm = smoothed_mean(xb) # Calculate the mean of smoothing trajectories\nxbc = smoothed_cov(xb) # And covariance\nxbt = smoothed_trajs(xb) # Get smoothing trajectories\nxbs = [diag(xbc) for xbc in xbc] |> vecvec_to_mat .|> sqrt\nplot(xbm', ribbon=2xbs, lab=\"PF smooth\")\nplot!(vecvec_to_mat(x), l=:dash, lab=\"True\")","category":"page"},{"location":"","page":"Home","title":"Home","text":"We can plot the particles themselves as well","category":"page"},{"location":"","page":"Home","title":"Home","text":"downsample = 5\nplot(vecvec_to_mat(x), l=(4,), layout=(2,1), show=false)\nscatter!(xbt[1, 1:downsample:end, :]', subplot=1, show=false, m=(1,:black, 0.5), lab=\"\")\nscatter!(xbt[2, 1:downsample:end, :]', subplot=2, m=(1,:black, 0.5), lab=\"\")\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"#Kalman-filter","page":"Home","title":"Kalman filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The KalmanFilter (wiki) assumes that f and g are linear functions, i.e., that they can be written on the form","category":"page"},{"location":"","page":"Home","title":"Home","text":"beginaligned\nx(t+1) = Ax(t) + Bu(t) + w(t)\ny(t) = Cx(t) + Du(t) + e(t)\nendaligned","category":"page"},{"location":"","page":"Home","title":"Home","text":"for some matrices ABCD where w sim N(0 R_1) and e sim N(0 R_2) are zero mean and Gaussian. The Kalman filter represents the posterior distributions over x by the mean and a covariance matrix. The magic behind the Kalman filter is that linear transformations of Gaussian distributions remain Gaussian, and we thus have a very efficient way of representing them.","category":"page"},{"location":"","page":"Home","title":"Home","text":"A Kalman filter is easily created using the constructor KalmanFilter. Many of the functions defined for particle filters, are defined also for Kalman filters, e.g.:","category":"page"},{"location":"","page":"Home","title":"Home","text":"R1 = cov(df)\nR2 = cov(dg)\nkf = KalmanFilter(A, B, C, 0, R1, R2, d0)\nsol = forward_trajectory(kf, u, y) # sol contains filtered state, predictions, pred cov, filter cov, loglik\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"It can also be called in a loop like the pf above","category":"page"},{"location":"","page":"Home","title":"Home","text":"for t = 1:T\n kf(u,y) # Performs both correct! and predict!\n # alternatively\n ll, e = correct!(kf, y, nothing, t) # Returns loglikelihood and prediction error (plus other things if you want)\n x = state(kf) # Access the state estimate\n R = covariance(kf) # Access the covariance of the estimate\n predict!(kf, u, nothing, t)\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"The matrices in the Kalman filter may be time varying, such that A[:, :, t] is A(t). They may also be provided as functions on the form A(t) = A(x u p t). This works for both dynamics and covariance matrices.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The numeric type used in the Kalman filter is determined from the mean of the initial state distribution, so make sure that this has the correct type if you intend to use, e.g., Float32 or ForwardDiff.Dual for automatic differentiation.","category":"page"},{"location":"#Smoothing-using-KF","page":"Home","title":"Smoothing using KF","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Kalman filters can also be used for smoothing ","category":"page"},{"location":"","page":"Home","title":"Home","text":"kf = KalmanFilter(A, B, C, 0, cov(df), cov(dg), d0)\nxT,R,lls = smooth(kf, u, y) # Returns smoothed state, smoothed cov, loglik\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"Plot and compare PF and KF","category":"page"},{"location":"","page":"Home","title":"Home","text":"plot(vecvec_to_mat(xT), lab=\"Kalman smooth\", layout=2)\nplot!(xbm', lab=\"pf smooth\")\nplot!(vecvec_to_mat(x), lab=\"true\")","category":"page"},{"location":"#Kalman-filter-tuning-tutorial","page":"Home","title":"Kalman filter tuning tutorial","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The tutorial \"How to tune a Kalman filter\" details how to figure out appropriate covariance matrices for the Kalman filter, as well as how to add disturbance models to the system model.","category":"page"},{"location":"#Unscented-Kalman-Filter","page":"Home","title":"Unscented Kalman Filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The UnscentedKalmanFilter represents posterior distributions over x as Gaussian distributions just like the KalmanFilter, but propagates them through a nonlinear function f by a deterministic sampling of a small number of particles called sigma points (this is referred to as the unscented transform). This UKF thus handles nonlinear functions fg, but only Gaussian disturbances and unimodal posteriors. The UKF will by default treat the noise as additive, but by using the augmented UKF form, non-additive noise may be handled as well. See the docstring of UnscentedKalmanFilter for more details.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The UKF takes the same arguments as a regular KalmanFilter, but the matrices defining the dynamics are replaced by two functions, dynamics and measurement, working in the same way as for the ParticleFilter above (unless the augmented form is used).","category":"page"},{"location":"","page":"Home","title":"Home","text":"ukf = UnscentedKalmanFilter(dynamics, measurement, cov(df), cov(dg), MvNormal(SA[1.,1.]); nu=nu, ny=ny)","category":"page"},{"location":"","page":"Home","title":"Home","text":"info: Info\nIf your function dynamics describes a continuous-time ODE, do not forget to discretize it before passing it to the UKF. See Discretization for more information.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The UnscentedKalmanFilter has many customization options, see the docstring for more details. In particular, the UKF may be created with a linear measurement model as an optimization.","category":"page"},{"location":"#Extended-Kalman-Filter","page":"Home","title":"Extended Kalman Filter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The ExtendedKalmanFilter (EKF) is similar to the UKF, but propagates Gaussian distributions by linearizing the dynamics and using the formulas for linear systems similar to the standard Kalman filter. This can be slightly faster than the UKF (not always), but also less accurate for strongly nonlinear systems. The linearization is performed automatically using ForwardDiff.jl unless the user provides Jacobian functions that compute A and C. In general, the UKF is recommended over the EKF unless the EKF is faster and computational performance is the top priority.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The EKF constructor has the following two signatures","category":"page"},{"location":"","page":"Home","title":"Home","text":"ExtendedKalmanFilter(dynamics, measurement, R1, R2, d0=MvNormal(R1); nu::Int, p = LowLevelParticleFilters.NullParameters(), α = 1.0, check = true, Ajac = nothing, Cjac = nothing)\nExtendedKalmanFilter(kf, dynamics, measurement; Ajac = nothing, Cjac = nothing)","category":"page"},{"location":"","page":"Home","title":"Home","text":"The first constructor takes all the arguments required to initialize the extended Kalman filter, while the second one takes an already defined standard Kalman filter. using the first constructor, the user must provide the number of inputs to the system, nu.","category":"page"},{"location":"","page":"Home","title":"Home","text":"where kf is a standard KalmanFilter from which the covariance properties are taken.","category":"page"},{"location":"","page":"Home","title":"Home","text":"info: Info\nIf your function dynamics describes a continuous-time ODE, do not forget to discretize it before passing it to the UKF. See Discretization for more information.","category":"page"},{"location":"#AdvancedParticleFilter","page":"Home","title":"AdvancedParticleFilter","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The AdvancedParticleFilter works very much like the ParticleFilter, but admits more flexibility in its noise models.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The AdvancedParticleFilter type requires you to implement the same functions as the regular ParticleFilter, but in this case you also need to handle sampling from the noise distributions yourself. The function dynamics must have a method signature like below. It must provide one method that accepts state vector, control vector, parameter, time and noise::Bool that indicates whether or not to add noise to the state. If noise should be added, this should be done inside dynamics An example is given below","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Random\nconst rng = Random.Xoshiro()\nfunction dynamics(x, u, p, t, noise=false) # It's important that `noise` defaults to false\n x = A*x .+ B*u # A simple linear dynamics model in discrete time\n if noise\n x += rand(rng, df) # it's faster to supply your own rng\n end\n x\nend\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"The measurement_likelihood function must have a method accepting state, input, measurement, parameter and time, and returning the log-likelihood of the measurement given the state, a simple example below:","category":"page"},{"location":"","page":"Home","title":"Home","text":"function measurement_likelihood(x, u, y, p, t)\n logpdf(dg, C*x-y) # An example of a simple linear measurement model with normal additive noise\nend\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"This gives you very high flexibility. The noise model in either function can, for instance, be a function of the state, something that is not possible for the simple ParticleFilter. To be able to simulate the AdvancedParticleFilter like we did with the simple filter above, the measurement method with the signature measurement(x,u,p,t,noise=false) must be available and return a sample measurement given state (and possibly time). For our example measurement model above, this would look like this","category":"page"},{"location":"","page":"Home","title":"Home","text":"# This function is only required for simulation\nmeasurement(x, u, p, t, noise=false) = C*x + noise*rand(rng, dg)\nnothing # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"We now create the AdvancedParticleFilter and use it in the same way as the other filters:","category":"page"},{"location":"","page":"Home","title":"Home","text":"apf = AdvancedParticleFilter(N, dynamics, measurement, measurement_likelihood, df, d0)\nsol = forward_trajectory(apf, u, y, ny) # Perform batch filtering","category":"page"},{"location":"","page":"Home","title":"Home","text":"plot(sol, xreal=x)\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"We can even use this type as an AuxiliaryParticleFilter","category":"page"},{"location":"","page":"Home","title":"Home","text":"apfa = AuxiliaryParticleFilter(apf)\nsol = forward_trajectory(apfa, u, y, ny)\nplot(sol, dim=1, xreal=x) # Same as above, but only plots a single dimension\nDisplayAs.PNG(Plots.current()) # hide","category":"page"},{"location":"","page":"Home","title":"Home","text":"See the tutorials section for more advanced examples, including state estimation for DAE (Differential-Algebraic Equation) systems.","category":"page"},{"location":"#Troubleshooting-and-tuning","page":"Home","title":"Troubleshooting and tuning","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Tuning a particle filter can be quite the challenge. To assist with this, we provide som visualization tools","category":"page"},{"location":"","page":"Home","title":"Home","text":"debugplot(pf,u[1:20],y[1:20], runall=true, xreal=x[1:20])","category":"page"},{"location":"","page":"Home","title":"Home","text":"The plot displays all state variables and all measurements. The heatmap in the background represents the weighted particle distributions per time step. For the measurement sequences, the heatmap represent the distributions of predicted measurements. The blue dots corresponds to measured values. In this case, we simulated the data and we had access to the state as well, if we do not have that, just omit xreal. You can also manually step through the time-series using","category":"page"},{"location":"","page":"Home","title":"Home","text":"commandplot(pf,u,y; kwargs...)","category":"page"},{"location":"","page":"Home","title":"Home","text":"For options to the debug plots, see ?pplot.","category":"page"},{"location":"#Tuning-noise-parameters-through-optimization","page":"Home","title":"Tuning noise parameters through optimization","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"See examples in Parameter Estimation.","category":"page"},{"location":"#Tuning-through-simulation","page":"Home","title":"Tuning through simulation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"It is possible to sample from the Bayesian model implied by a filter and its parameters by calling the function simulate. A simple tuning strategy is to adjust the noise parameters such that a simulation looks \"similar\" to the data, i.e., the data must not be too unlikely under the model.","category":"page"},{"location":"#Videos","page":"Home","title":"Videos","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Several video tutorials using this package are available in the playlists","category":"page"},{"location":"","page":"Home","title":"Home","text":"System identification in Julia\nControl systems in Julia","category":"page"},{"location":"","page":"Home","title":"Home","text":"Some examples featuring this package in particular are","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Using an optimizer to optimize the likelihood of an UnscentedKalmanFilter:","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Estimation of time-varying parameters:","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Adaptive control by means of estimation of time-varying parameters:","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"}] }

If you have followed the particle filter tutorial Smoothing the track of a moving beetle, you will notice that the result here is much worse. We used noise parameters similar to in the particle-gilter example, but those were tuned fo the particle filter. Below, we will attempt to optimize the performance of the IMM filter.

Smoothing