1+ import numpy as np
2+ from pyrecest .distributions import GaussianDistribution
3+ from .unscented_kalman_filter import UnscentedKalmanFilter
4+ from .abstract_hyperspherical_filter import AbstractHyperSphericalFilter
5+
6+
7+ class HypersphericalUKF (AbstractHyperSphericalFilter ):
8+ def __init__ (self ):
9+ # Constructor
10+ self .state = GaussianDistribution (1 , 1 )
11+ self .ukf = UnscentedKalmanFilter (dim_x = 1 , dim_z = 1 , dt = 1 )
12+
13+ @property
14+ def filter_state (self ):
15+ return self ._filter_state
16+
17+ @filter_state .setter
18+ def filter_state (self , new_state ):
19+ # Sets the current system state
20+ #
21+ # Parameters:
22+ # new_state (GaussianDistribution)
23+ # new state (1D Gaussian)
24+ if not isinstance (new_state , GaussianDistribution ):
25+ new_state = new_state .toGaussian ()
26+ self ._filter_state = new_state
27+
28+ def predictNonlinear (self , f , gaussSys ):
29+ # Predicts assuming a nonlinear system model, i.e.,
30+ # x(k+1) = f(x(k)) + w(k)
31+ # where w(k) is additive noise given by gaussSys.
32+ #
33+ # Parameters:
34+ # f (function handle)
35+ # function from R^(d-1) to R^(d-1)
36+ # gaussSys (GaussianDistribution)
37+ # distribution of additive noise (warning: mean is
38+ # ignored)
39+ assert callable (f )
40+ if not isinstance (gaussSys , GaussianDistribution ):
41+ gaussSys = gaussSys .toGaussian ()
42+
43+ def g (x ):
44+ x = x / np .linalg .norm (x )
45+ y = f (x )
46+ y = y / np .linalg .norm (y )
47+ return y
48+
49+ self .ukf .x = self .state .mu
50+ self .ukf .P = self .state .C
51+ self .ukf .predict (fx = g , Q = gaussSys .C )
52+ self .state .mu , self .state .C = self .ukf .x , self .ukf .P
53+
54+ # normalize mean
55+ if np .linalg .norm (self .state .mu ) != 0 :
56+ self .state .mu = self .state .mu / np .linalg .norm (self .state .mu )
57+ else :
58+ raise ValueError ('mu was 0' )
59+
60+ def getEstimateMean (self ):
61+ return self .state .mu
0 commit comments