|
| 1 | +################################################################################ |
| 2 | +# Simulation setup |
| 3 | +################################################################################ |
| 4 | + |
| 5 | +# The OTOS velocity measurement was calculated to have a standard deviation of |
| 6 | +# about 3 inches per second |
| 7 | +velStd = 3 * .0254; |
| 8 | + |
| 9 | +# The IMU acceleration measurement was calculated to have a standard deviation |
| 10 | +# of about 0.03 meters per second^2 |
| 11 | +accStd = 0.03; |
| 12 | + |
| 13 | +# The OTOS has 2.4ms loop period. With 1500 time steps, this simulates about 3.5 |
| 14 | +# seconds |
| 15 | +dt = 0.0024; |
| 16 | +numSteps = 1500; |
| 17 | +t = 0 : dt : dt*(numSteps-1); |
| 18 | + |
| 19 | +# Acceleration offset error |
| 20 | +accOffset = 0.5; |
| 21 | + |
| 22 | +# Generate measurement noise |
| 23 | +velNoise = randn([numSteps, 1]) * velStd; |
| 24 | +accNoise = randn([numSteps, 1]) * accStd + accOffset; |
| 25 | + |
| 26 | +# Pre-allocate arrays for position, velocity, and acceleration |
| 27 | +a = zeros([numSteps, 1]); |
| 28 | +v = zeros([numSteps, 1]); |
| 29 | +p = zeros([numSteps, 1]); |
| 30 | + |
| 31 | +# Simulate acceleration at start and end |
| 32 | +a(t < .3) = 5; |
| 33 | +a(t > 3) = -5; |
| 34 | + |
| 35 | +# Initialize Kalman filter state vector X: |
| 36 | +# [Position] |
| 37 | +# [Velocoty] |
| 38 | +# [Accleration] |
| 39 | +X = zeros([3,1]); |
| 40 | + |
| 41 | +# Initialize Kalman filter state transition model F (X_{k+1} = F * X_k): |
| 42 | +# [P_{k+1}] = P_k + V_k * dt = [1 dt 0] [P_k] |
| 43 | +# [V_{k+1}] = V_k + A_k * dt = [0 1 dt] * [V_k] |
| 44 | +# [A_{k+1}] = A_k = [0 0 1] [A_k] |
| 45 | +F = eye(3); |
| 46 | +F(1,2) = dt; |
| 47 | +F(2,3) = dt; |
| 48 | + |
| 49 | +# Initialize Kalman filter state estimate covariance matrix P: |
| 50 | +P = eye(3)*0; |
| 51 | + |
| 52 | +# Initialize Kalman filter observation models H (Z_k = H * X_k): |
| 53 | +# Z_{vk} = [0 1 0] * [P_k] |
| 54 | +# [V_k] |
| 55 | +# [A_k] |
| 56 | +# Z_{ak} = [0 0 1] * [P_k] |
| 57 | +# [V_k] |
| 58 | +# [A_k] |
| 59 | +Hv = [0 1 0]; |
| 60 | +Ha = [0 0 1]; |
| 61 | + |
| 62 | +# Initialize Kalman filter observation noise variance elements R: |
| 63 | +Rv = velStd^2; |
| 64 | +Ra = accStd^2; |
| 65 | + |
| 66 | +# Initialize Kalman filter process noise covariance matrix Q: |
| 67 | +Q = eye(3); |
| 68 | +Q(1,1) = 1e-8; |
| 69 | +Q(2,2) = 1e-6; |
| 70 | +Q(3,3) = 1e-4; |
| 71 | + |
| 72 | +################################################################################ |
| 73 | +# Simulation loop |
| 74 | +################################################################################ |
| 75 | + |
| 76 | +# Loop through all time steps |
| 77 | +for i = 1:numSteps |
| 78 | + |
| 79 | + # Physics time step, calculate next true velocity and position |
| 80 | + v(i+1) = v(i) + a(i) * dt; |
| 81 | + p(i+1) = p(i) + v(i) * dt; |
| 82 | + |
| 83 | + # Sensor measurement |
| 84 | + za = [a(i) + accNoise(i)]; |
| 85 | + zv = [v(i) + velNoise(i)]; |
| 86 | + |
| 87 | + # Simulate temporary loss of optical data |
| 88 | + if(i >= 500 && i < 700) |
| 89 | + zv = 0; |
| 90 | + end |
| 91 | + |
| 92 | + % Kalman filter prediction step |
| 93 | + X = F*X; |
| 94 | + P = F*P*F' + Q; |
| 95 | + |
| 96 | + # Kalman filter measurement update (accleration) |
| 97 | + y = za - Ha*X; |
| 98 | + S = Ha*P*Ha' + Ra; |
| 99 | + K = P*Ha'*inv(S); |
| 100 | + X = X + K*y; |
| 101 | + P = (eye(3) - K*Ha)*P; |
| 102 | + |
| 103 | + # Ignore velocity measurement if measurement is very different from estimate |
| 104 | + if(abs(zv - X(2)) < .5) |
| 105 | + # Kalman filter measurement update (velocity) |
| 106 | + y = zv - Hv*X; |
| 107 | + S = Hv*P*Hv' + Rv; |
| 108 | + K = P*Hv'*inv(S); |
| 109 | + X = X + K*y; |
| 110 | + P = (eye(3) - K*Hv)*P; |
| 111 | + else |
| 112 | + # Log velocity for plots to know where measurements are being ignored |
| 113 | + v(i) = 0; |
| 114 | + end |
| 115 | + |
| 116 | + # Log Kalman filter state and diagonal elements of covariance matrix |
| 117 | + ps(i) = X(1); |
| 118 | + pvs(i) = P(1,1); |
| 119 | + vs(i) = X(2); |
| 120 | + vvs(i) = P(2,2); |
| 121 | + as(i) = X(3); |
| 122 | + avs(i) = P(3,3); |
| 123 | +end |
| 124 | + |
| 125 | +# Remove last couple elements of these arrays to get sizes correct for plots |
| 126 | +v(end) = []; |
| 127 | +p(end) = []; |
| 128 | + |
| 129 | +################################################################################ |
| 130 | +# Output plots |
| 131 | +################################################################################ |
| 132 | + |
| 133 | +# Use Figure 1 and clear it |
| 134 | +figure 1 |
| 135 | +clf |
| 136 | + |
| 137 | +# Position subplot |
| 138 | +subplot(3,1,1) |
| 139 | +hold on |
| 140 | +grid on |
| 141 | + |
| 142 | +# True position |
| 143 | +plot(t, p, 'g') |
| 144 | + |
| 145 | +# Estimated position and standard deviation |
| 146 | +plot(t, ps, 'b') |
| 147 | +plot(t, ps - sqrt(pvs), 'r') |
| 148 | +plot(t, ps + sqrt(pvs), 'r') |
| 149 | + |
| 150 | +# Velocity subplot |
| 151 | +subplot(3,1,2) |
| 152 | +hold on |
| 153 | +grid on |
| 154 | + |
| 155 | +# True velocity and measured velocity |
| 156 | +plot(t, v, 'g') |
| 157 | +plot(t, v + velNoise, 'k') |
| 158 | + |
| 159 | +# Estimated velocity and standard deviation |
| 160 | +plot(t, vs, 'b') |
| 161 | +plot(t, vs - 2*sqrt(vvs), 'r') |
| 162 | +plot(t, vs + 2*sqrt(vvs), 'r') |
| 163 | + |
| 164 | +# Acceleration subplot |
| 165 | +subplot(3,1,3) |
| 166 | +hold on |
| 167 | +grid on |
| 168 | + |
| 169 | +# True acceleration and measured velocity |
| 170 | +plot(t, a, 'g') |
| 171 | +plot(t, a + accNoise, 'k') |
| 172 | + |
| 173 | +# Estimated acceleration and standard deviation |
| 174 | +plot(t, as, 'b') |
| 175 | +plot(t, as - 2*sqrt(avs), 'r') |
| 176 | +plot(t, as + 2*sqrt(avs), 'r') |
| 177 | + |
0 commit comments