MATLAB: Relative rotation between two IMU’s

calibrationframes alignementquaternionsrelative movement imu's

I'm trying to obtain the relative rotation between two IMU's.
In order to verify the quality of the orientation delivered by the IMU (quaternions), I attached both IMUs to a rigid body (bar) but placed in a different orientation.
I recording of 1 min data for a rotation of the system (2 IMUs attached to the bar) in slow motion.
Both IMUs should give the same orientations after aligning their frames or in other words the relative rotation between both should be constant.
So, to align the frames, i first take q_start of both (imu1 and 2) in the first 5s when the system was at rest on the table:
q_start1 = mean(Q1(t0->5s));
q_start2 = mean(Q2(t0->5s));
Now in order to express their frames in world frame:
Q1_w = Q1 * Inverse(q_start1);
Q2_w = Q2 * Inverse(q_start2);
And to obtain the relative rotation between them:
Q_relative_w= Inverse(Q1_w) * Q2_w;
But Q_relative was not constant but if I switch the 3rd and – 2nd component of Q2_w that’s mean:
Q2_w = [w,x,y,z] -> Q2_w_new = [w,-y,x,z]
Then i apply: Q_ relative_w_new = Inverse(Q1_w) * Q2_w_new;
I obtain a relative constant Q_ relative_w_new.
My Question:
Where is my error in the calculation or if this calibration makes sense at all?
If not how can I otherwise align the frames?

Best Answer

Assuming the coordinate frames are as follows:
ECI, the world frame
BODY1, the IMU1 body frame
BODY2, the IMU2 body frame
Examining your quaternion arithmetic:
q_start1 = mean(Q1(t0->5s)); % ECI->BODY1_t0
q_start2 = mean(Q2(t0->5s)); % ECI->BODY2_t0
% (NOTE: The above should be normalized)
Now in order to express their frames in world frame:
Q1_w = Q1 * Inverse(q_start1); % ECI->BODY1_t * inverse(ECI->BODY1_t0) = ECI->BODY1_t * BODY1_t0->ECI
Q2_w = Q2 * Inverse(q_start2); % ECI->BODY2_t * inverse(ECI->BODY2_t0) = ECI->BODY2_t * BODY2_t0->ECI
And to obtain the relative rotation between them:
Q_relative_w= Inverse(Q1_w) * Q2_w; % inverse(ECI->BODY1_t * BODY1_t0->ECI) * (ECI->BODY2_t * BODY2_t0->ECI)
Expanding that last one:
(ECI->BODY1_t0 * BODY1_t->ECI) * (ECI->BODY2_t * BODY2_t0->ECI) =
ECI->BODY1_t0 * (BODY1_t->ECI * ECI->BODY2_t) * BODY2_t0->ECI =
ECI->BODY1_t0 * (BODY1_t->BODY2_t) * BODY2_t0->ECI
So, you have what I think you are after, BODY1_t->BODY2_t, wrapped inside of other ECI to BODY stuff. I think what you should be after is just the BODY1_t->BODY2_t stuff. E.g.,
q_t0 = inverse(q_start1) * q_start2; % inverse(ECI->BODY1_t0) * ECI->BODY2_t0 = BODY1_t0->BODY2_t0
Then calculate this downstream:
q_t = inverse(Q1) * Q2; % inverse(ECI->BODY1_t) * ECI->BODY2_t = BODY1_t->BODY2_t
And see if all of the q_t calculations seems to be fairly constant.
For a discussion of MATLAB quaternion conventions (you need to know this in order to do the quaternion arithmetic correctly), see these links: