CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Airspeed/models/ADS_cal_EKF.m
Views: 1799
1
% Implementation of a simple 3-state EKF that can identify the scale
2
% factor that needs to be applied to a true airspeed measurement
3
% Paul Riseborough 27 June 2013
4
5
% Inputs:
6
% Measured true airsped (m/s)
7
8
clear all;
9
10
% Define wind speed used for truth model
11
vwn_truth = 4.0;
12
vwe_truth = 3.0;
13
vwd_truth = -0.5; % convection can produce values of up to 1.5 m/s, however
14
% average will zero over longer periods at lower altitudes
15
% Slope lift will be persistent
16
17
% Define airspeed scale factor used for truth model
18
K_truth = 1.2;
19
20
% Use a 1 second time step
21
DT = 1.0;
22
23
% Define the initial state error covariance matrix
24
% Assume initial wind uncertainty of 10 m/s and scale factor uncertainty of
25
% 0.2
26
P = diag([10^2 10^2 0.001^2]);
27
28
% Define state error growth matrix assuming wind changes at a rate of 0.1
29
% m/s/s and scale factor drifts at a rate of 0.001 per second
30
Q = diag([0.1^2 0.1^2 0.001^2])*DT^2;
31
32
% Define the initial state matrix assuming zero wind and a scale factor of
33
% 1.0
34
x = [0;0;1.0];
35
36
for i = 1:1000
37
38
%% Calculate truth values
39
% calculate ground velocity by simulating a wind relative
40
% circular path of 60m radius and 16 m/s airspeed
41
time = i*DT;
42
radius = 60;
43
TAS_truth = 16;
44
vwnrel_truth = TAS_truth*cos(TAS_truth*time/radius);
45
vwerel_truth = TAS_truth*sin(TAS_truth*time/radius);
46
vwdrel_truth = 0.0;
47
vgn_truth = vwnrel_truth + vwn_truth;
48
vge_truth = vwerel_truth + vwe_truth;
49
vgd_truth = vwdrel_truth + vwd_truth;
50
51
% calculate measured ground velocity and airspeed, adding some noise and
52
% adding a scale factor to the airspeed measurement.
53
vgn_mea = vgn_truth + 0.1*rand;
54
vge_mea = vge_truth + 0.1*rand;
55
vgd_mea = vgd_truth + 0.1*rand;
56
TAS_mea = K_truth * TAS_truth + 0.5*rand;
57
58
%% Perform filter processing
59
% This benefits from a matrix library that can handle up to 3x3
60
% matrices
61
62
% Perform the covariance prediction
63
% Q is a diagonal matrix so only need to add three terms in
64
% C code implementation
65
P = P + Q;
66
67
% Perform the predicted measurement using the current state estimates
68
% No state prediction required because states are assumed to be time
69
% invariant plus process noise
70
% Ignore vertical wind component
71
TAS_pred = x(3) * sqrt((vgn_mea - x(1))^2 + (vge_mea - x(2))^2 + vgd_mea^2);
72
73
% Calculate the observation Jacobian H_TAS
74
SH1 = (vge_mea - x(2))^2 + (vgn_mea - x(1))^2;
75
SH2 = 1/sqrt(SH1);
76
H_TAS = zeros(1,3);
77
H_TAS(1,1) = -(x(3)*SH2*(2*vgn_mea - 2*x(1)))/2;
78
H_TAS(1,2) = -(x(3)*SH2*(2*vge_mea - 2*x(2)))/2;
79
H_TAS(1,3) = 1/SH2;
80
81
% Calculate the fusion innovaton covariance assuming a TAS measurement
82
% noise of 1.0 m/s
83
S = H_TAS*P*H_TAS' + 1.0; % [1 x 3] * [3 x 3] * [3 x 1] + [1 x 1]
84
85
% Calculate the Kalman gain
86
KG = P*H_TAS'/S; % [3 x 3] * [3 x 1] / [1 x 1]
87
88
% Update the states
89
x = x + KG*(TAS_mea - TAS_pred); % [3 x 1] + [3 x 1] * [1 x 1]
90
91
% Update the covariance matrix
92
P = P - KG*H_TAS*P; % [3 x 3] *
93
94
% force symmetry on the covariance matrix - necessary due to rounding
95
% errors
96
% Implementation will also need a further check to prevent diagonal
97
% terms becoming negative due to rounding errors
98
% This step can be made more efficient by excluding diagonal terms
99
% (would reduce processing by 1/3)
100
P = 0.5*(P + P'); % [1 x 1] * ( [3 x 3] + [3 x 3])
101
102
%% Store results
103
output(i,:) = [time,x(1),x(2),x(3),vwn_truth,vwe_truth,K_truth];
104
105
end
106
107
%% Plot output
108
figure;
109
subplot(3,1,1);plot(output(:,1),[output(:,2),output(:,5)]);
110
ylabel('Wind Vel North (m/s)');
111
xlabel('time (sec)');
112
grid on;
113
subplot(3,1,2);plot(output(:,1),[output(:,3),output(:,6)]);
114
ylabel('Wind Vel East (m/s)');
115
xlabel('time (sec)');
116
grid on;
117
subplot(3,1,3);plot(output(:,1),[output(:,4),output(:,7)]);
118
ylim([0 1.5]);
119
ylabel('Airspeed scale factor correction');
120
xlabel('time (sec)');
121
grid on;
122
123
124