Skip to content

Commit 08afb83

Browse files
Merge pull request #295 from LAMPSPUC/gb/veh-track2
Vehicle Tracking model
2 parents dc6101b + e92beef commit 08afb83

File tree

7 files changed

+124
-0
lines changed

7 files changed

+124
-0
lines changed

docs/src/examples.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,44 @@ smoother_output = kalman_smoother(model)
193193
plot(df.date, get_smoothed_state(smoother_output)[:, 2], label = "slope")
194194
```
195195

196+
## Vehicle tracking
197+
198+
This example illustrates how to perform vehicle tracking from noisy data.
199+
200+
```@setup bt
201+
using StateSpaceModels, Random
202+
using Plots
203+
```
204+
205+
```@example vehicle_tracking
206+
using Random
207+
Random.seed!(1)
208+
209+
# Define a random trajectory
210+
n = 100
211+
H = [1 0; 0 1.0]
212+
Q = [1 0; 0 1.0]
213+
rho = 0.1
214+
model = VehicleTracking(rand(n, 2), rho, H, Q)
215+
initial_state = [0.0, 0, 0, 0]
216+
sim = StateSpaceModels.simulate(model.system, initial_state, n)
217+
218+
# Use a Kalman filter to get the predictive and filtered states
219+
model = VehicleTracking(sim, 0.1, H, Q)
220+
kalman_filter(model)
221+
pos_pred = get_predictive_state(model)
222+
pos_filtered = get_filtered_state(model)
223+
224+
# Plot a gif illustrating the result
225+
using Plots
226+
anim = @animate for i in 1:n
227+
plot(sim[1:i, 1], sim[1:i, 2], label="Measured position", line=:scatter, lw=2, markeralpha=0.2, color=:black, title="Vehicle tracking")
228+
plot!(pos_pred[1:i+1, 1], pos_pred[1:i+1, 3], label = "Predicted position", lw=2, color=:forestgreen)
229+
plot!(pos_filtered[1:i, 1], pos_filtered[1:i, 3], label = "Filtered position", lw=2, color=:indianred)
230+
end
231+
gif(anim, "anim_fps15.gif", fps = 15)
232+
```
233+
196234
## Cross validation of the forecasts of a model
197235

198236
Often times users would like to compare the forecasting skill of different models. The function

docs/src/manual.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ LocalLevelCycle
5555
LocalLevelExplanatory
5656
LocalLinearTrend
5757
MultivariateBasicStructural
58+
VehicleTracking
5859
```
5960

6061
## Naive models

src/StateSpaceModels.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ include("models/unobserved_components.jl")
5353
include("models/exponential_smoothing.jl")
5454
include("models/naive_models.jl")
5555
include("models/dar.jl")
56+
include("models/vehicle_tracking.jl")
5657

5758
include("visualization/forecast.jl")
5859
include("visualization/components.jl")
@@ -86,6 +87,7 @@ export SparseUnivariateKalmanFilter
8687
export StateSpaceModel
8788
export UnivariateKalmanFilter
8889
export UnobservedComponents
90+
export VehicleTracking
8991

9092
# Exported functions
9193
export auto_arima

src/models/locallineartrend.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@doc raw"""
2+
LocalLinearTrend(y::Vector{Fl}) where Fl
3+
24
The linear trend model is defined by:
35
```math
46
\begin{gather*}

src/models/vehicle_tracking.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
@doc raw"""
2+
VehicleTracking(y::Matrix{Fl}, ρ::Fl, H::Matrix{Fl}, Q::Matrix{Fl}) where Fl
3+
4+
The vehicle tracking example illustrates a model where there are no hyperparameters,
5+
the user defines the parameters ``\rho``, ``H`` and ``Q`` and the model gives the predicted and filtered speed and
6+
position. In this case, $y_t$ is a $2 \times 1$ observation vector representing the corrupted measurements
7+
of the vehicle's position on the two-dimensional plane in instant $t$.
8+
9+
The position and speed in each dimension compose the state of the vehicle. Let us refer to ``x_t^{(d)}`` as
10+
the position on the axis $d$ and to ``\dot{x}^{(d)}_t`` as the speed on the axis $d$ in instant ``t``. Additionally,
11+
let ``\eta^{(d)}_t`` be the input drive force on the axis ``d``, which acts as state noise. For a single dimension,
12+
we can describe the vehicle dynamics as
13+
14+
```math
15+
\begin{equation}
16+
\begin{aligned}
17+
& x_{t+1}^{(d)} = x_t^{(d)} + \Big( 1 - \frac{\rho \Delta_t}{2} \Big) \Delta_t \dot{x}^{(d)}_t + \frac{\Delta^2_t}{2} \eta_t^{(d)}, \\
18+
& \dot{x}^{(d)}_{t+1} = (1 - \rho) \dot{x}^{(d)}_{t} + \Delta_t \eta^{(d)}_t,
19+
\end{aligned}\label{eq_control}
20+
\end{equation}
21+
```
22+
23+
We can cast the dynamical system as a state-space model in the following manner:
24+
```math
25+
\begin{align*}
26+
y_t &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} \alpha_{t+1} + \varepsilon_t, \\
27+
\alpha_{t+1} &= \begin{bmatrix} 1 & (1 - \tfrac{\rho \Delta_t}{2}) \Delta_t & 0 & 0 \\ 0 & (1 - \rho) & 0 & 0 \\ 0 & 0 & 1 & (1 - \tfrac{\rho \Delta_t}{2}) \\ 0 & 0 & 0 & (1 - \rho) \end{bmatrix} \alpha_{t} + \begin{bmatrix} \tfrac{\Delta^2_t}{2} & 0 \\ \Delta_t & 0 \\ 0 & \tfrac{\Delta^2_t}{2} \\ 0 & \Delta_t \end{bmatrix} \eta_{t},
28+
\end{align*}
29+
```
30+
31+
See more on [Vehicle tracking](@ref)
32+
"""
33+
mutable struct VehicleTracking <: StateSpaceModel
34+
system::LinearMultivariateTimeInvariant
35+
36+
function VehicleTracking(y::Matrix{Fl}, ρ::Fl, H::Matrix{Fl}, Q::Matrix{Fl}) where Fl
37+
p = 2
38+
Z = kron(Matrix{Fl}(I, p, p), [1.0 0.0])
39+
T = kron(Matrix{Fl}(I, p, p), [1 (1 - ρ / 2); 0 (1 - ρ)])
40+
R = kron(Matrix{Fl}(I, p, p), [0.5; 1])
41+
d = zeros(Fl, p)
42+
c = zeros(Fl, 4)
43+
H = H
44+
Q = Q
45+
46+
system = LinearMultivariateTimeInvariant{Fl}(y, Z, T, R, d, c, H, Q)
47+
48+
return new(system)
49+
end
50+
end
51+
52+
function default_filter(model::VehicleTracking)
53+
Fl = typeof_model_elements(model)
54+
steadystate_tol = Fl(1e-5)
55+
a1 = zeros(Fl, num_states(model))
56+
skip_llk_instants = length(a1)
57+
P1 = Fl(1e6) .* Matrix{Fl}(I, num_states(model), num_states(model))
58+
return MultivariateKalmanFilter(2, a1, P1, skip_llk_instants, steadystate_tol)
59+
end

test/models/vehicle_tracking.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@testset "Vehicle tracking" begin
2+
n = 100
3+
H = [1 0
4+
0 1.0]
5+
Q = [1 0
6+
0 1.0]
7+
rho = 0.1
8+
model = VehicleTracking(rand(n, 2), rho, H, Q)
9+
10+
# Not possible to fit
11+
@test !has_fit_methods(VehicleTracking)
12+
13+
# Simply test if it runs
14+
initial_state = [0.0, 0, 0, 0]
15+
sim = simulate(model.system, initial_state, n)
16+
17+
model = VehicleTracking(sim, 0.1, H, Q)
18+
kalman_filter(model)
19+
pos_pred = get_predictive_state(model)
20+
pos_filtered = get_filtered_state(model)
21+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ include("models/linear_regression.jl")
2727
include("models/exponential_smoothing.jl")
2828
include("models/naive_models.jl")
2929
include("models/dar.jl")
30+
include("models/vehicle_tracking.jl")
3031

3132
# Visualization
3233
include("visualization/forecast.jl")

0 commit comments

Comments
 (0)