I have a followup question from this post : Extracting Yaw from a Quaternion .
Alike the OP, I want to move away from Euler rotations and use Quaternions. My scenario is as follows:
I am wearing an Apple smartwatch on my left hand and performing the bicep curls exercise. I do a few reps in the first set, and stop. I then rotate my body 90 degrees to the right in my room, and do another set of a few repetitions. I do this 4 times, and store the quaternions to disk using the xArbitraryCorrectedZVertical frame. When I use Euler rotations to describe pitch, using below code, I see a sinusoidal shape. When I want to reproduce the same pattern using quaternions, I get close, except the signal drifts. Here is my code:
clc;
clear;
quaternions_table = readtable(strcat("quaternions"), 'Delimiter',',');
attitude = quaternion(quaternions_table.w, quaternions_table.x, quaternions_table.y, quaternions_table.z);
quats = zeros(length(attitude), 1);
eulers = zeros(length(attitude), 1);
for i = 1:length(attitude)
[w,x,y,z] = parts(attitude(i) * quaternion(0,0,0,1));
quats(i) = rad2deg(atan2(z,w));
[w,x,y,z] = parts(attitude(i));
eulers(i) = rad2deg(asin(2*(y * w - z * x)));
end
figure(1);
clf;
hold on;
plot(quats, '.r');
plot(eulers, '.b');
legend('Q', 'E');
hold off;
Here is a plot of the difference:
How can I fix my code so that the quaternion generated pattern is equivalent to the euler's pitch, regardless of my "body" rotation?
Some sample data: https://filebin.net/02k2323ccbct1n38/quaternions

DISCLAIMER 1: this is a first attempt at putting together an answer. What follows is by no means conclusive. Any feedback aimed at improving this answer is sincerely welcome.
DISCLAIMER 2: I don't have access to any toolboxes featuring functions related to quaternions, so I relied on what's available on Mathworks's File Exchange, to which I added a function that builds quaternions by extracting their components from a
table. Using the quaternion-related functions provided in Matlab's toolboxes, the OP should be able to replicate the calculations showcased hereinafter.DISCLAIMER 3: the selection of the point to which the rotations are applied matters. Picking a different
Pwill affect the resulting plot. In particular, with points far from P(1,0,0) the 3D map of the successive positions in space doesn't appear to be compatible with the physics of the OP moving the smart-watch in the way described in the question.With the sample data provided by the OP, I was able to apply the quaternions to the point with coordinates
P(1,0,0)i.e. a point on the global x-axis, using (pseudo-code):where
Qiis thei-thquaternion extracted from the sample data.Here's a plot showing the positions in space assumed by the point after being rotated:
Once the coordinates of the point are available, calculating the pitch could be done by computing the
acosof the dot product between the unit vector parallel toOP(Obeing the global origin) and the unit vector parallel to the z-axis (with components(0,0,1)), in pseudo-code:Here's a plot of the pitch shifted using the first value of the array, which is extremely close to what was obtained by the OP using Euler's angles:
Matlab code
Here's the code I used to generate the plots. As mentioned erlier, I relied on Przemyslaw Baranski's Quaternions. Please, note that my code is a very crude attempt at tackling the problem, with basically no optimization. Uncommenting the lines for the 3D plot slows down the process considerably:
And this is the definition of
qGetQuaternionFromComponents:In the event you have some of the toolboxes by MATLAB, you can do something like this:
References
Euclideanspace.com
Mathworks' FileExchange