code:7_state_ekf_with_bias
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
code:7_state_ekf_with_bias [2010/01/10 00:12] – created laurenceb | code:7_state_ekf_with_bias [2010/01/10 00:23] (current) – laurenceb | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | <code matlab> | ||
- | function quat_IMU_bias(beta, | ||
+ | ===== Bias tracking in Octave ===== | ||
+ | This has been tested with three axes of accel and gyro, adding a magnetometer will give a dramatic improvement as absolute yaw determination will be possible. Interestingly this filter is still able to filter out yaw gyro bias errors if the IMU is tilted - i.e. any roll or pitch. | ||
+ | |||
+ | In the first plot you can see an artiffically introduced large yaw bias being corrected reasonably well after the first few manovers. Angles are in radians. | ||
+ | |||
+ | {{code: | ||
+ | |||
+ | This second test uses raw test data with a sparkfun 6DOF IMU - i.e. actual biases. The intialisation of the filter was just guesstimated, | ||
+ | |||
+ | {{code: | ||
+ | |||
+ | |||
+ | ===== GNU Octave code ===== | ||
+ | |||
+ | <code matlab> | ||
+ | function quat_IMU_bias(beta, | ||
%constants--------------------------------------- | %constants--------------------------------------- | ||
- | |||
%beta=3e-6; - gyroscope noise | %beta=3e-6; - gyroscope noise | ||
- | |||
%alpha=1e-4; | %alpha=1e-4; | ||
- | |||
%q=4e-2 - quaternion process noise | %q=4e-2 - quaternion process noise | ||
%b=1e-10 - gyro bias process noise | %b=1e-10 - gyro bias process noise | ||
% ^ these are sensible values | % ^ these are sensible values | ||
- | |||
# | # | ||
- | |||
gyro_gain=[1/ | gyro_gain=[1/ | ||
- | |||
delta_time=0.02857; | delta_time=0.02857; | ||
- | |||
%read in the data - each data type is in a seperate row | %read in the data - each data type is in a seperate row | ||
- | |||
fp=fopen(' | fp=fopen(' | ||
- | |||
data=fscanf(fp,' | data=fscanf(fp,' | ||
- | |||
fclose(fp); | fclose(fp); | ||
- | |||
j=size(data); | j=size(data); | ||
- | |||
j=j(1,2); | j=j(1,2); | ||
- | |||
x_nav=[0; | x_nav=[0; | ||
- | |||
v_nav=[0; | v_nav=[0; | ||
biases=[0; | biases=[0; | ||
- | |||
%setup Kalman filter | %setup Kalman filter | ||
- | |||
x=[1; | x=[1; | ||
- | |||
P=[pi^2, | P=[pi^2, | ||
q/=35; | q/=35; | ||
- | |||
Q=[q, | Q=[q, | ||
- | |||
%main loop--------------------------------------- | %main loop--------------------------------------- | ||
- | |||
for n=1:j; | for n=1:j; | ||
- | |||
%takes vectors g and a as inputs for gyros and accels, g needs to be | %takes vectors g and a as inputs for gyros and accels, g needs to be | ||
- | |||
%premultiplied by delta time per run. | %premultiplied by delta time per run. | ||
- | |||
g=gyro_gain*data(2: | g=gyro_gain*data(2: | ||
- | |||
%get the accel vecor | %get the accel vecor | ||
- | |||
a=data(5: | a=data(5: | ||
- | |||
%a=-a for some of the sensors on the dataset; | %a=-a for some of the sensors on the dataset; | ||
- | |||
a(2)=-a(2); | a(2)=-a(2); | ||
- | |||
a(1)=-a(1); | a(1)=-a(1); | ||
- | |||
%normalise acceleration vector | %normalise acceleration vector | ||
- | |||
a=a/ | a=a/ | ||
- | |||
%accel sensor measurement jacobian | %accel sensor measurement jacobian | ||
- | |||
H=[2*x(3), | H=[2*x(3), | ||
- | |||
%misalignment error jacobian | %misalignment error jacobian | ||
- | |||
F=[1, | F=[1, | ||
- | |||
%input error jacobian | %input error jacobian | ||
- | |||
E=0.5*[-x(2), | E=0.5*[-x(2), | ||
- | |||
%propogate the state vector note the inclusion of 2*I | %propogate the state vector note the inclusion of 2*I | ||
- | |||
x=0.5*[2, | x=0.5*[2, | ||
- | |||
%normalise the quaternion | %normalise the quaternion | ||
- | |||
x(1: | x(1: | ||
- | |||
%propogate the covarience, can also use P+=, and subtract identity from F | %propogate the covarience, can also use P+=, and subtract identity from F | ||
- | |||
P=F*P*F' | P=F*P*F' | ||
- | |||
%find the residual | %find the residual | ||
- | |||
y=a-[2*(x(2)*x(4)+x(1)*x(3)); | y=a-[2*(x(2)*x(4)+x(1)*x(3)); | ||
fflush(stdout); | fflush(stdout); | ||
- | |||
%alpha is accel noise | %alpha is accel noise | ||
- | |||
S=H*P*H' | S=H*P*H' | ||
- | |||
%find gain | %find gain | ||
- | |||
K=P*H' | K=P*H' | ||
- | |||
%state update | %state update | ||
- | |||
x=x+(K*y); | x=x+(K*y); | ||
- | |||
%covariance update | %covariance update | ||
- | |||
P=P-K*H*P; | P=P-K*H*P; | ||
- | |||
%normalise quaternion | %normalise quaternion | ||
- | |||
x(1: | x(1: | ||
%work out the roll pitch and yaw (these are NOT EULER ANGLES) | %work out the roll pitch and yaw (these are NOT EULER ANGLES) | ||
Line 129: | Line 89: | ||
p_x=-p_x; | p_x=-p_x; | ||
endif | endif | ||
- | |||
yaw(n)=asin(norm(cross(trans_x, | yaw(n)=asin(norm(cross(trans_x, | ||
- | |||
if trans_x(2)< | if trans_x(2)< | ||
yaw(n)=-yaw(n); | yaw(n)=-yaw(n); | ||
endif | endif | ||
if trans_x(1)< | if trans_x(1)< | ||
- | |||
yaw(n)=pi-yaw(n); | yaw(n)=pi-yaw(n); | ||
if(yaw(n)> | if(yaw(n)> | ||
yaw(n)-=2*pi; | yaw(n)-=2*pi; | ||
endif | endif | ||
- | |||
endif | endif | ||
- | |||
if z_z< | if z_z< | ||
- | |||
yaw(n)=-yaw(n); | yaw(n)=-yaw(n); | ||
- | |||
endif | endif | ||
biases=[biases, | biases=[biases, | ||
- | |||
endfor | endfor | ||
- | |||
plot(data(1, | plot(data(1, | ||
- | |||
h = legend(' | h = legend(' | ||
- | |||
set(h,' | set(h,' | ||
- | |||
# | # | ||
endfunction | endfunction | ||
</ | </ |
code/7_state_ekf_with_bias.1263082325.txt.gz · Last modified: 2010/01/10 00:12 by laurenceb