After reading through the paper and the library, I found something I did not understand. Maybe someone can help me.
How is it possible that the paper states that:
bx = sqrtf(hx*hx+hy*hy);
But the library says that
_2bx = sqrtf(hx*hx+hy*hy);
After reading through the paper and the library, I found something I did not understand. Maybe someone can help me.
How is it possible that the paper states that:
bx = sqrtf(hx*hx+hy*hy);
But the library says that
_2bx = sqrtf(hx*hx+hy*hy);
Just a guess - I’m on my smartphone so can’t look it up in details:
You should check the formulas but my assumption would be that h[sub]x[/sub]
and h[sub]y[/sub]
and h[sub]z[/sub]
as calculated in the library are not the same as in the original paper but twice as much (probably using 2mx 2my and 2mz in the paper’s formulas and just mx,my and mz in code or something like that).
So if this is a correct assumption then
orig_hx = 1/2 * hx
orig_hy = 1/2 * hy
So when in the paper they are doing
orig_bx = sqrt(orig_hx2+ orig_hy2)
It’s translates to
orig_bx = sqrt(0.52.hx2+ 0.52.hy2) = sqrt(0.52) * sqrt(hx2+ hy2)
Which is orig_bx = 0.5 * sqrt(hx2+ hy2)
Hence this would explain the
_2bx = sqrt(hx2+ hy2)
If that’s true then for coherence they would have been better calling the library hx and hy variables _2hx and _2hy.
Of course it would mean then that the earth’s magnetic field vector components are off but It does not matter when discussing just the direction of the vector if all the components are multiplied by a constant (the vector is longer or shorter but the direction is the same).
If I remember well the equations involve a factor 2 or 4 but not just bx or by so may be there is an advantage in reducing the number of computations doing it this way.
Just some food for thoughts on what to double check, I might be totally wrong
Sorry for the late reply. I just saw your answer now.
So I had a similar assumption, but if this is correct, then the paper is wrong. The variable mx, my, mz are taken directly from raw readings of the IMU.
Therefore, equation 29 or 31 from the paper must be wrong.
I checked all the steps. The only one that did not make sense to me was this one. I have simulated the Madgwick filter from the beginning to the end symbolically using MATLAB to ensure that I understood the steps taken on the library.
I have also declared:
m = [0, mx, my, mz]
and using the quaternion multiplication of:
h = q (x) m (x) q*
I become the correct h:
h = [0, hx, hy, hz]
Also the gradient decent algorithm corrective step are correct.
(Maybe I misunderstood what you said)
I’m still on the run and just on my iPhone
Did you check if check if hx, hy and hz as calculated in the library are the same as in the original paper? (If they used 2mx 2my and 2mz in the paper's formulas and just mx,my and mz in code then the formula would indeed calculate 2.bx ).
Yeah, nothing on the paper regarding 2*m. I made a small summary that you will find in the attachments (AHRSlibrary.pdf). I will also upload a symbolic MATLAB script that you can use for visual aid and the paper from Madgwick.
I somehow cannot believe that the library is wrong. It was checked by so many people. Unfortunately, I am not at home the couple of weeks, so I cannot test if it would make a difference if I change the library.
MATLAB script:
% Estimation of IMU and MARG orientation using a gradient descent algorithm
% Sebastian O.H. Madgwick, Andrew J.L. Harrison, Ravi Vaidyanathan
% June 29 - July 1, 2011
clear;
clc;
syms q1 q2 q3 q4 gx gy gz ax ay az mx my mz bx bz by hx hy hz
%% Symbolic Parameters
Beta = 0.1; %Eq.(33)
% SR = 500;
q = [q1 q2 q3 q4]; %Eq.(9)
cong_q = [q1 -q2 -q3 -q4]; % Conjugate of q
% q1 = q(1);
% q2 = q(2);
% q3 = q(3);
% q4 = q(4);
gyro = [0 gx gy gz]; %Eq.(1)
wg = [0 0 0 1]; %Eq.(10)
a = [0 ax ay az]; %Eq.(11)
b = [0 bx 0 bz]; %Eq.(14)
m = [0 mx my mz]; %Eq.(15)
h = [0 hx hy hz]; %Eq.(31)
%% Symbolic Calculations
% Gyroscope
qdotg =0.5*quatmul(q,gyro); %Eq.(2)
% Accelerometer
fg1 = quatmul(cong_q,wg); %Eq.(6),(12)
fg = quatmul(fg1,q) - transpose(a); %Eq.(6),(12)
fg = quatsimp(fg,q1,q2,q3,q4); %Eq.(6),(12)
fg(1) = []; %Eq.(6),(12)
Jg = jacobian(fg, [q1, q2, q3, q4]); %Eq.(13)
Jg_t_fg = transpose(Jg)*fg; %Eq.(21)
% Magnetometer
h1 = quatmul(q,m); %Eq.(31)
h = quatmul(h1, cong_q); %Eq.(31)
h = quatsimp(h,q1,q2,q3,q4); %Eq.(31)
h(1) = []; %Eq.(31)
hx = h(1); hy = h(2); hz = h(3); %Eq.(31)
b = [0 sqrt(hx^2+hy^2) 0 hz]; %Eq. (32)
bx = b(2); bz = b(4); %Eq. (32)
fb1 = quatmul(cong_q,b); %Eq.(6),(16)
fb = quatmul(fb1,q) - transpose(m); %Eq.(6),(16)
fb = quatsimp(fb,q1,q2,q3,q4); %Eq.(6),(16)
fb(1) = []; %Eq.(6),(16)
Jb = jacobian(fb, [q1, q2, q3, q4]); %Eq.(17)
Jb_t_fb = transpose(Jb)*fb; %Eq.(21)
% Error function
ftot = Jg_t_fg + Jb_t_fb; %Eq.(21)
fnorm = ftot * (1/sqrt(ftot(1)^2+ftot(2)^2+ftot(3)^2+ftot(4)^2)); %Eq.(30)
% Update
qdot = qdotg - Beta*fnorm; %Eq.(30)
% qnew = qdot./SR;
% q = qdot./SR;
% roll = atan2(q1*q2+q3*q4,0.5-q2^2-q3^2);
% pitch = asin(-2.0*(q2*q4-q1*q3));
% yaw = atan2(q2*q3+q1*q4, 0.5-q3^2-q4^2);
%% Functions for Quaternions (not important to understand the process)
function quatprod = quatmul(r, k)
% r * k
quatprod1 = r(1)*k(1) - r(2)*k(2) - r(3)*k(3) - r(4)*k(4);
quatprod2 = r(1)*k(2) + r(2)*k(1) + r(3)*k(4) - r(4)*k(3);
quatprod3 = r(1)*k(3) - r(2)*k(4) + r(3)*k(1) + r(4)*k(2);
quatprod4 = r(1)*k(4) + r(2)*k(3) - r(3)*k(2) + r(4)*k(1);
quatprod = [quatprod1;quatprod2;quatprod3;quatprod4];
end
function [simp] = quatsimp(q,q1,q2,q3,q4)
j = 1 - q1^2 - q2^2 - q3^2 - q4^2;
q = simplify(q);
q = expand(q);
if q(1) == 0
c1 = 0;
else
c1 = symvar(q(1));
c1(c1 == q1) = [];
c1(c1 == q2) = [];
c1(c1 == q3) = [];
c1(c1 == q4) = [];
end
if q(2) == 0
c2 = 0;
else
c2 = symvar(q(2));
c2(c2 == q1) = [];
c2(c2 == q2) = [];
c2(c2 == q3) = [];
c2(c2 == q4) = [];
end
if q(3) == 0
c3 = 0;
else
c3 = symvar(q(3));
c3(c3 == q1) = [];
c3(c3 == q2) = [];
c3(c3 == q3) = [];
c3(c3 == q4) = [];
end
if q(4) == 0
c4 = 0;
else
c4 = symvar(q(4));
c4(c4 == q1) = [];
c4(c4 == q2) = [];
c4(c4 == q3) = [];
c4(c4 == q4) = [];
end
for i = 1:length(c1)
if q(1) == 0
f1 = 0;
else
f = coeffs(q(1), c1(i));
f(1) = [];
f1(i) = f;
end
end
for i = 1:length(c2)
if q(2) == 0
f2 = 0;
else
f = coeffs(q(2), c2(i));
f(1) = [];
f2(i) = f;
end
end
for i = 1:length(c3)
if q(3) == 0
f3 = 0;
else
f = coeffs(q(3), c3(i));
f(1) = [];
f3(i) = f;
end
end
for i = 1:length(c4)
if q(4) == 0
f4 = 0;
else
f = coeffs(q(4), c4(i));
f(1) = [];
f4(i) = f;
end
end
d1 = f1.*c1;
d2 = f2.*c2;
d3 = f3.*c3;
d4 = f4.*c4;
g1 = -simplify(sum(d1)-q(1));
g2 = -simplify(sum(d2)-q(2));
g3 = -simplify(sum(d3)-q(3));
g4 = -simplify(sum(d4)-q(4));
if f1 == 0
f1 = 0;
else
for i = 1:length(f1)
if (has(f1(i), q1^2) && has(f1(i), q2^2) && has(f1(i), q3^2) && has(f1(i), q4^2))
f1(i) = f1(i) + j;
else
f1(i) = f1(i);
end
end
end
for i = 1:length(f2)
if (has(f2(i), q1^2) && has(f2(i), q2^2) && has(f2(i), q3^2) && has(f2(i), q4^2))
f2(i) = f2(i) + j;
else
f2(i) = f2(i);
end
end
for i = 1:length(f3)
if (has(f3(i), q1^2) && has(f3(i), q2^2) && has(f3(i), q3^2) && has(f3(i), q4^2))
f3(i) = f3(i) + j;
else
f3(i) = f3(i);
end
end
for i = 1:length(f4)
if (has(f4(i), q1^2) && has(f4(i), q2^2) && has(f4(i), q3^2) && has(f4(i), q4^2))
f4(i) = f4(i) + j;
else
f4(i) = f4(i);
end
end
d1 = f1.*c1;
d2 = f2.*c2;
d3 = f3.*c3;
d4 = f4.*c4;
h1 = expand(simplify(sum(d1)+g1));
h2 = expand(simplify(sum(d2)+g2));
h3 = expand(simplify(sum(d3)+g3));
h4 = expand(simplify(sum(d4)+g4));
h = [h1;h2;h3;h4];
for i = 1:length(h)
if (has(h(i), q1^2) && has(h(i), q2^2) && has(h(i), q3^2) && has(h(i), q4^2))
h(i) = h(i) + j;
else
h(i) = h(i);
end
simp = h;
end
end
AHRSlibrary.pdf (195 KB)
madgwick_internal_report.pdf (1.47 MB)
Did you figure this one out? I would still love to know.
The point you make is that in the paper bx is defined as the square root of (hx2 + hy2) and in the library they have the same square root but call that two times bx.
I had just a high level quick look and they have different definition of hx,y,z
In the paper, this looks like this and they use two_mx
In the library, they just use mx
The expressions are different. Have you checked if they actually match or if they would actually have a factor 2 difference?
it would make sense if you can calculate directly 2bx since the matrix does not use just bx, but requires 2bx and 4bx. So it would save one multiplication.
(also if hz was twice as big and the square root twice as big as well, then the direction of the earth’s magnetic field would still be correct. The vector would just be twice as long but if you are only interested in the direction....)
I tried posting the answer but there is a limit of 9000 characters. I had to create a new PDF.
What I did is compare ∇f with h. Anyway, here it is.
Madgwick.pdf (189 KB)
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.