Problem with calculating relative orientation using quaternions

20 views (last 30 days)
AM on 19 Jan 2021
Edited: Brian Fanous on 20 Jan 2021
I am using an IMU which provides absolute orientation of the sensors frame S relative to an earth-fixed frame N in form of a unit quaternion (i.e. rotation from frame N to frame S). The first field of the provided quaternion is the scalar part, which I believe agrees with MATLAB notation. In my experiments, I first obtain an initial orientation (when the sensor is relatively static) , and I would like to obtain the relative orientation of the sensor in the form of ZYX Euler angles (more precisely).
Here is the procedure that I have tried:
First, I invert the initial orientation,
=
then, I use the result the obtain the relative quaternion as follows,
=
(I have also tried , but that does not give the correct result either).
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,
Curiously, if I manually set the Z and Y rotations of to zero (and then convert the result back to quaternion form), the angle trajectories match exactly (except for the offset of Z and Y).
What am I doing wrong?
This is the MATLAB code that I'm using. Note that initQ is and `relQ` is .
% 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;

Brian Fanous on 20 Jan 2021
Edited: Brian Fanous on 20 Jan 2021
As I understand it you have two quaternions and and a third rotation that you are looking for which denotes the difference in orientation between these two, call it p. These should be related by:
Where the * is quaternion multiplication. Remember that quaternion multiplication is not commutative.
To solve for p you simply need to left multiply by the conjugate
You can do that by swapping your arguments in quatmultiply in your code or using quaternion/ldivide
qstart = meanrot(quaternion(initData))
relQ = qstart.\mocapData;

Brian Fanous on 20 Jan 2021
Edited: Brian Fanous on 20 Jan 2021
AM,
Can you explain your setup a little more? What are you trying to achieve and why are you multiplying the two quaternions? From your description it sounds like and are both quaternions representing the rotation that takes the global frame to the sensor frame, but just at different time instances. Can you describe a little be more? Are you trying to find the change in orientation from the initial orientation?
AM on 20 Jan 2021
Yes, I am trying to to find the change in orientation from the initial orientation. The IMU is placed on a person's foot.

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!