I am using an IMU which provides absolute orientation of the sensors frame $S$ relative to an earth-fixed frame $N$ in quaternion form, $^S_Nq$. In my experiments, I first obtain an initial orientation (when the sensor is relatively static) $^I_Nq$, and I would like to obtain the relative orientation of the sensor in the form of ZYX Euler angles (more precisely $ZY^{'}X^{''}$).
Here is the procedure that I have tried:
First, I invert the initial orientation,
$^N_Iq$ = $^I_Nq^{-1}$
then, I use the result the obtain the relative quaternion as follows,
$^S_Iq$ = $^S_Nq$ $\otimes$ $^N_Iq$
Finally, to visualize the results, I convert the relative orientation to Euler angles. I also have reference trajectories calculated in a motion capture software which uses the same data. However, my result looks completely different (and wrong) as seen below,
Calculated vs. reference relative orientation
Curiously, if I manually set the $Z$ and $Y$ rotations of $^I_Nq$ to zero (and then convert the result back to quaternion form), the angle trajectories match exactly (except for the offset of $Z$ and $Y$).
Result with setting the first two rotations of initial orientation set to zero
What am I doing wrong?
By the way, this is the MATLAB code that I'm using. Note that initQ
is $^I_Nq$ and relQ
is $^S_Iq$.
% Average quaternion using meanrot to obtain initial orientation.
[q(1), q(2), q(3), q(4)] = parts(meanrot(quaternion(initData));
initQ = q;
% The second method, if I manually set the first two rotations to zero.
% initEul = quat2eul(q,'ZYX');
% initEul(2) = 0;
% initEul(1) = 0;
% initQ = eul2quat(initEul,'ZYX');
relQ = quatmultiply(mocapData,quatinv(initQ));
eulerAngles = quat2eul(quaternion(relQ),'ZYX')*180/pi;