-
Notifications
You must be signed in to change notification settings - Fork 165
/
kalman_filter.c
148 lines (136 loc) · 4.67 KB
/
kalman_filter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* FileName : kalman_filter.c
* Author : xiahouzuoxin @163.com
* Version : v1.0
* Date : 2014/9/24 20:36:51
* Brief :
*
* Copyright (C) MICL,USTB
*/
#include "kalman_filter.h"
/*
* @brief
* Init fields of structure @kalman1_state.
* I make some defaults in this init function:
* A = 1;
* H = 1;
* and @q,@r are valued after prior tests.
*
* NOTES: Please change A,H,q,r according to your application.
*
* @inputs
* state - Klaman filter structure
* init_x - initial x state value
* init_p - initial estimated error convariance
* @outputs
* @retval
*/
void kalman1_init(kalman1_state *state, float init_x, float init_p)
{
state->x = init_x;
state->p = init_p;
state->A = 1;
state->H = 1;
state->q = 2e2;//10e-6; /* predict noise convariance */
state->r = 5e2;//10e-5; /* measure error convariance */
}
/*
* @brief
* 1 Dimension Kalman filter
* @inputs
* state - Klaman filter structure
* z_measure - Measure value
* @outputs
* @retval
* Estimated result
*/
float kalman1_filter(kalman1_state *state, float z_measure)
{
/* Predict */
state->x = state->A * state->x;
state->p = state->A * state->A * state->p + state->q; /* p(n|n-1)=A^2*p(n-1|n-1)+q */
/* Measurement */
state->gain = state->p * state->H / (state->p * state->H * state->H + state->r);
state->x = state->x + state->gain * (z_measure - state->H * state->x);
state->p = (1 - state->gain * state->H) * state->p;
return state->x;
}
/*
* @brief
* Init fields of structure @kalman1_state.
* I make some defaults in this init function:
* A = {{1, 0.1}, {0, 1}};
* H = {1,0};
* and @q,@r are valued after prior tests.
*
* NOTES: Please change A,H,q,r according to your application.
*
* @inputs
* @outputs
* @retval
*/
void kalman2_init(kalman2_state *state, float *init_x, float (*init_p)[2])
{
state->x[0] = init_x[0];
state->x[1] = init_x[1];
state->p[0][0] = init_p[0][0];
state->p[0][1] = init_p[0][1];
state->p[1][0] = init_p[1][0];
state->p[1][1] = init_p[1][1];
//state->A = {{1, 0.1}, {0, 1}};
state->A[0][0] = 1;
state->A[0][1] = 0.1;
state->A[1][0] = 0;
state->A[1][1] = 1;
//state->H = {1,0};
state->H[0] = 1;
state->H[1] = 0;
//state->q = {{10e-6,0}, {0,10e-6}}; /* measure noise convariance */
state->q[0] = 10e-7;
state->q[1] = 10e-7;
state->r = 10e-7; /* estimated error convariance */
}
/*
* @brief
* 2 Dimension kalman filter
* @inputs
* state - Klaman filter structure
* z_measure - Measure value
* @outputs
* state->x[0] - Updated state value, Such as angle,velocity
* state->x[1] - Updated state value, Such as diffrence angle, acceleration
* state->p - Updated estimated error convatiance matrix
* @retval
* Return value is equals to state->x[0], so maybe angle or velocity.
*/
float kalman2_filter(kalman2_state *state, float z_measure)
{
float temp0 = 0.0f;
float temp1 = 0.0f;
float temp = 0.0f;
/* Step1: Predict */
state->x[0] = state->A[0][0] * state->x[0] + state->A[0][1] * state->x[1];
state->x[1] = state->A[1][0] * state->x[0] + state->A[1][1] * state->x[1];
/* p(n|n-1)=A^2*p(n-1|n-1)+q */
state->p[0][0] = state->A[0][0] * state->p[0][0] + state->A[0][1] * state->p[1][0] + state->q[0];
state->p[0][1] = state->A[0][0] * state->p[0][1] + state->A[1][1] * state->p[1][1];
state->p[1][0] = state->A[1][0] * state->p[0][0] + state->A[0][1] * state->p[1][0];
state->p[1][1] = state->A[1][0] * state->p[0][1] + state->A[1][1] * state->p[1][1] + state->q[1];
/* Step2: Measurement */
/* gain = p * H^T * [r + H * p * H^T]^(-1), H^T means transpose. */
temp0 = state->p[0][0] * state->H[0] + state->p[0][1] * state->H[1];
temp1 = state->p[1][0] * state->H[0] + state->p[1][1] * state->H[1];
temp = state->r + state->H[0] * temp0 + state->H[1] * temp1;
state->gain[0] = temp0 / temp;
state->gain[1] = temp1 / temp;
/* x(n|n) = x(n|n-1) + gain(n) * [z_measure - H(n)*x(n|n-1)]*/
temp = state->H[0] * state->x[0] + state->H[1] * state->x[1];
state->x[0] = state->x[0] + state->gain[0] * (z_measure - temp);
state->x[1] = state->x[1] + state->gain[1] * (z_measure - temp);
/* Update @p: p(n|n) = [I - gain * H] * p(n|n-1) */
state->p[0][0] = (1 - state->gain[0] * state->H[0]) * state->p[0][0];
state->p[0][1] = (1 - state->gain[0] * state->H[1]) * state->p[0][1];
state->p[1][0] = (1 - state->gain[1] * state->H[0]) * state->p[1][0];
state->p[1][1] = (1 - state->gain[1] * state->H[1]) * state->p[1][1];
return state->x[0];
}