Kalman C
Kalman C
Kalman C
c
This file contains the code for a kalman filter, an
extended kalman filter, and an iterated extended kalman filter.
For ready extensibility, the apply_measurement() and apply_system()
functions are located in a separate file: kalman_cam.c is an example.
It uses the matmath functions provided in an accompanying file
to perform matrix and quaternion manipulation.
J. Watlington, 11/15/95
Modified:
11/30/95 wad The extended kalman filter section seems to be
working now.
*/
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<math.h>
"kalman.h"
#define ITERATION_THRESHOLD
#define ITERATION_DIVERGENCE
2.0
20
m_elem
m_elem
m_elem
m_elem
**cov_pre;
**cov_post;
**sys_noise_cov;
**mea_noise_cov;
/*
/*
/*
/*
int
int
int
global_step = 0;
measurement_size;
state_size;
*/
*/
*/
*/
m_elem
m_elem
m_elem
m_elem
m_elem
*z_estimate;
**temp_state_state;
**temp_meas_state;
**temp_meas_meas;
**temp_meas_2;
/*
/*
/*
/*
/*
a measurement_size x 1 vector */
a state_size x state_size matrix */
a measurement_size x state_size matrix */
a measurement_size squared matrix */
another one ! */
/* kalman_get_state
This function returns a pointer to the current estimate (a posteriori)
of the system state.
*/
m_elem *kalman_get_state( void )
{
return( state_post );
}
/******************************************************************
Non-linear Kalman Filtering
extended_kalman_init()
This function initializes the extended kalman filter.
*/
void extended_kalman_init( m_elem **GQGt, m_elem **R, m_elem **P, m_elem *x,
int num_state, int num_measurement )
{
#ifdef PRINT_DEBUG
printf( "ekf: Initializing filter\n" );
#endif
alloc_globals( num_state, num_measurement );
sys_transfer = matrix( 1, num_state, 1, num_state );
mea_transfer = matrix( 1, num_measurement, 1, num_state );
/* Init the global variables using the arguments. */
vec_copy(
vec_copy(
mat_copy(
mat_copy(
x,
x,
P,
P,
state_post, state_size );
state_pre, state_size );
cov_post, state_size, state_size );
cov_pre, state_size, state_size );
sys_noise_cov = GQGt;
mea_noise_cov = R;
}
/* extended_kalman_step()
This function takes a set of measurements, and performs a single
recursion of the extended kalman filter.
*/
void extended_kalman_step( m_elem *z_in )
{
#ifdef PRINT_DEBUG
printf( "ekf: step %d\n", global_step );
#endif
/***************** Gain Loop *****************
First, linearize locally, then do normal gain loop
*/
=
=
=
=
vector(
vector(
matrix(
matrix(
1,
1,
1,
1,
num_state );
num_state );
num_state, 1, num_state );
num_measurement, 1, num_state );
x,
x,
P,
P,
state_post, state_size );
state_pre, state_size );
cov_post, state_size, state_size );
cov_pre, state_size, state_size );
sys_noise_cov = GQGt;
mea_noise_cov = R;
}
/* iter_ext_kalman_step()
This function takes a set of measurements, and iterates over a single
recursion of the extended kalman filter.
*/
void iter_ext_kalman_step( m_elem *z_in )
{
int
iteration = 1;
m_elem est_change;
m_elem *prev_state;
m_elem *new_state;
m_elem *temp;
generate_system_transfer( state_pre, sys_transfer );
estimate_prob( cov_post, sys_transfer, sys_noise_cov, cov_pre );
apply_system( state_post, state_pre );
/* Now iterate, updating the probability and the system model
until no change is noticed between iteration steps
*/
prev_state = iter_state0;
new_state = iter_state1;
*/
#ifdef DIV_DEBUG
print_matrix( "P", P_pre, state_size, state_size );
#endif
mat_mult( H, P_pre, temp_meas_state,
measurement_size, state_size, state_size );
mat_mult_transpose( H, temp_meas_state, temp_meas_meas,
measurement_size, state_size, measurement_size );
mat_add( temp_meas_meas, R, temp_meas_meas,
measurement_size, measurement_size );
take_inverse( temp_meas_meas, temp_meas_2, measurement_size );
#ifdef DIV_DEBUG
print_matrix( "1 / (HPH + R)", temp_meas_2,
measurement_size, measurement_size );
#endif
mat_transpose_mult( temp_meas_state, temp_meas_2, K,
state_size, measurement_size, measurement_size );
/*
print_matrix( "Kalman Gain", K, state_size, measurement_size );
*/
mat_mult( K, temp_meas_state, temp_state_state,
state_size, measurement_size, state_size );
#ifdef PRINT_DEBUG
printf( "ekf: updating prob 3\n" );
#endif
mat_add( temp_state_state, P_pre, P_post, state_size, state_size );
}
static void take_inverse( m_elem **in, m_elem **out, int n )
{
#ifdef PRINT_DEBUG
printf( "ekf: calculating inverse\n" );
#endif
/* Nothing fancy for now, just a Gauss-Jordan technique,
with good pivoting (thanks to NR).
*/
gaussj( in, n, out, 0 ); /* out is SCRATCH */
mat_copy( in, out, n, n );
}
static m_elem calc_state_change( m_elem *a, m_elem *b )
{
int
m;
m_elem acc = 0.0;
for( m = 1; m <= state_size; m++ )
{
acc += fabs( a[m] - b[m] );
}
return( acc );
}