JuliaGNSS / KalmanFilters.jl

Various Kalman Filters: KF, UKF, AUKF and their Square root variant
Other
41 stars 6 forks source link

error in unscented kalman filtering with nonlinear observations scheme #5

Closed fmeulen closed 2 years ago

fmeulen commented 2 years ago

I am trying to use the UKF for filtering a swinging pendulum model.

using KalmanFilters

δ = 0.01
# Process model
F(s) = [s[1] + δ*s[2], s[2] - 9.8*sin(s[1]) * δ] 
# Process noise covariance
Q = [δ^3/3 δ^2/2; δ^2/2 δ]
# Measurement model
H(s) = sin(s[1])
# Measurement noise covariance
R = 0.02

# Initial state and covariances
s_init = [0.0, 0.0]
P_init = [5.0 0.0 ; 0.0 5.0]

# Take first measurement
obs = 0.5
mu = measurement_update(s_init, P_init, obs, H, R)

I get the error

ERROR: LoadError: ArgumentError: indexed assignment with a single value to possibly many locations is not supported; perhaps use broadcasting `.=` instead?
Stacktrace:
 [1] setindex_shape_check(::Float64, ::Int64, ::Int64)
   @ Base ./indices.jl:261
 [2] _unsafe_setindex!(::IndexLinear, ::Matrix{Float64}, ::Float64, ::Base.Slice{Base.OneTo{Int64}}, ::Int64)
   @ Base ./multidimensional.jl:903
 [3] _setindex!
   @ ./multidimensional.jl:894 [inlined]
 [4] setindex!
   @ ./abstractarray.jl:1315 [inlined]
 [5] transform(F::typeof(H), χ::KalmanFilters.SigmaPoints{Float64, Vector{Float64}, LinearAlgebra.LowerTriangular{Float64, Matrix{Float64}}, WanMerweWeightingParameters})
   @ KalmanFilters ~/.julia/packages/KalmanFilters/YuCmI/src/sigmapoints.jl:184
 [6] measurement_update(x::Vector{Float64}, P::Matrix{Float64}, y::Float64, h::Function, R::Float64; weight_params::WanMerweWeightingParameters, consider::Nothing)
   @ KalmanFilters ~/.julia/packages/KalmanFilters/YuCmI/src/ukf.jl:87
 [7] measurement_update(x::Vector{Float64}, P::Matrix{Float64}, y::Float64, h::Function, R::Float64)
   @ KalmanFilters ~/.julia/packages/KalmanFilters/YuCmI/src/ukf.jl:86

Unsure whether this is a bug, or input parameters are not provided in the right format. I could not find many examples or documentation.

zsoerenm commented 2 years ago

The problem here is that the measurement can be represented by a scalar. KalmanFilters.jl can not handle scalars in all cases yet. So a workaround is to represent the scalar observation in a vector with a single entry:

δ = 0.01
# Process model
F(s) = [s[1] + δ*s[2], s[2] - 9.8*sin(s[1]) * δ] 
# Process noise covariance
Q = [δ^3/3 δ^2/2; δ^2/2 δ]
# Measurement model
H(s) = [sin(s[1])]
# Measurement noise covariance
R = Matrix([0.02]')

# Initial state and covariances
s_init = [0.0, 0.0]
P_init = [5.0 0.0 ; 0.0 5.0]

# Take first measurement
obs = [0.5]
mu = measurement_update(s_init, P_init, obs, H, R)

Does that work for you?

fmeulen commented 2 years ago

Yes, that solves it. Thanks.

Perhaps it is worthwhile to point this out in the example, as the scalar syntax seems to work for the "ordinary" kalman filter.