1 function [estimates, covariances ] =
cdekf(f_func,jacobian_func,dt_between_measurements,rk4_steps, start_time, state_count, sensor_count, measurement_count,C,Q_root,R_root,P_0_root,x_0, measurements)
2 %Runs continuous-discrete Extended Kalman filter on data. The initial
3 %estimate and covariances are at the time step before all the
4 %measurements - be wary of the off-by-one error. If f_func is a
5 %linear
function the code is equivalent to continuous-discrete Kalman
7 %[estimates, covariances] =
cdekf(f_func,jacobian_func,dt_between_measurements,rk4_steps, start_time, state_count, sensor_count, measurement_count,C,Q_root,R_root,P_0_root,x_0, measurements)
9 % f_func: \dot{x} = f_func(x,t) where x is the state
10 % and lhs is the derivative of x at time t. The derivative is a
11 %
function of both the time and state.
13 % jacobian_func(x,t): jacobian of f_func with state x at time t
15 % rk4_steps: amount of steps taken in predict phase in rk4 scheme
17 % dt_between_measurements: time distance between incoming
20 % start_time: the time of first measurement
22 % state_count: dimension of the state
24 % sensor_count: dimension of observation matrix
26 % C: observation matrix of size
'sensor_count by state_count' 28 % R_root: The root of sensor error covariance matrix R where
29 % R = R_root*(R_root
'). R_root is of size 'sensor_count by
30 % sensor_count
'. R_root = chol(R)' is one way to derive it.
32 % Q_root: The root of process error covariance matrix Q where
33 % Q = Q_root*(Q_root
'). Q_root is of size 'state_count by
34 % state_count
'. Q_root = chol(Q)' is one way to derive it.
36 % P_0_root: The root of initial covariance matrix P_0 where
37 % P_0 = P_0_root*(P_root
'); P_0_root is of size 'state_count by
38 % state_count
'. P_0_root = chol(P_0)' is one way to derive it.
40 % x_0:Initial state estimate of size
'state_count by 1' 42 % measurements: ith column is ith measurement. Matrix of size
43 %
'sensor_count by measurement_count' 46 % estimates:
'state_count'X
'measurement_count+1' 47 % ith column is ith estimate. first column is x_0
49 % covariances: cell of size
'measurement_count+1' by 1
50 % where each entry is the P covariance matrix at that time.
51 % Time is computed based on dt_between_measurements
53 %make sure input is valid
54 assert(size(P_0_root,1)==state_count &&...
55 size(P_0_root,2)==state_count);
56 assert(size(C,1)==sensor_count && size(C,2)==state_count);
57 assert(size(Q_root,1)==state_count &&...
58 size(Q_root,2)==state_count);
59 assert(size(x_0,1)==state_count && size(x_0,2)==1);
60 assert(size(R_root,1)==sensor_count &&...
61 size(R_root,2)==sensor_count);
62 test = f_func(x_0,start_time);
63 assert(size(test,1)==state_count && size(test,2)==1);
64 test = jacobian_func(x_0,start_time);
65 assert(size(test,1)==state_count && size(test,2)==state_count);
66 assert(size(measurements,1)==sensor_count &&...
67 size(measurements,2)==measurement_count);
69 current_time = start_time;
70 h = dt_between_measurements/rk4_steps;
72 rk4_step = dt_between_measurements;
75 P_root_km1_p = P_0_root;
77 estimates = zeros(state_count,measurement_count+1);
78 covariances = cell(measurement_count + 1, 1);
81 covariances{1,1} = P_0_root*P_0_root
'; 83 for k=1:measurement_count 84 %loop through all measurements and follow through predict 86 [x_k_m,P_root_km] = cdekf_predict_phase(f_func,... 87 jacobian_func,h,dt_between_measurements,current_time,... 88 P_root_km1_p,x_km1_p,Q_root); 89 [x_k_p,P_root_kp] = cdekf_update_phase(R_root,... 90 P_root_km,C,x_k_m,measurements(:,k)); 93 P_root_km1_p = P_root_kp; 96 estimates(:,k+1) = x_k_p; 97 covariances{k+1,1} = P_root_kp*(P_root_kp');
99 current_time = current_time + dt_between_measurements;
function cdekf(in f_func, in jacobian_func, in dt_between_measurements, in rk4_steps, in start_time, in state_count, in sensor_count, in measurement_count, in C, in Q_root, in R_root, in P_0_root, in x_0, in measurements)