# Question regarding quaternion conventions; particularly with respect to point vs frame rotations

19 views (last 30 days)
Morten Nissov on 22 Apr 2021
Edited: James Tursa on 29 Apr 2021
I've been using the quaternion class from the sensor fusion toolbox and I just want to be sure that I haven't made a misunderstanding with the conventions.
At first glance, I guessed that this is following the Hamilton convention for quaternions: in that the scalar part comes first, and so on. But I am slightly in doubt when it comes to the "point" vs "frame" rotation terminology. I am assuming point corresponds to passive and frame corresponds to active due to the results of this
q = quaternion([0.42718, 0.24083, 0.59322, 0.63844]);
v = [1,0,0];
vQuat = quaternion([0,v]);
q * vQuat * conj(q)
rotatepoint(q, v)
conj(q) * vQuat * q
rotateframe(q, v)
the result of which is
ans =
quaternion
0 - 0.51903i + 0.83119j - 0.19931k
ans =
-0.5190 0.8312 -0.1993
ans =
quaternion
0 - 0.51903i - 0.25973j + 0.81433k
ans =
-0.5190 -0.2597 0.8143
which suggests that rotatepoint corresonds to where quaternion multiplication.
"Realistic" Example for body to local frame rotation
If we a consider a "real-life" example instead, say the quaternion q represents the orientation of a body frame in a local frame (like e.g. if I want to construct the rotation matrix from body -> local then my guess is that would be rotmat(quat, 'point'). My implementation of this "real-life" example is here
drawArrow = @(p,varargin) quiver( 0,0,p(1),p(2),0,varargin{:} );
% original point
p1 = [1; 0; 0];
% axis-angle rotation, 45 degrees around positive x axis
a = [0, 0, 1];
q = quaternion([cos(theta/2), sin(theta/2)*a]);
% i think rotation corresponds to
p2 = rotatepoint(q, p1'); % body to local frame
p3 = rotateframe(q, p1'); % local frame to body
figure(1)
clf
hold on
drawArrow(p1);
drawArrow(p2);
drawArrow(p3);
grid on
xlabel('x')
ylabel('y')
xlim([-0.5,2])
ylim([-1,1])
legend({'orignal','b->l','l->b'})
where the resulting plot is attached. My understanding here is that blue is the original vector in body frame, red is the same vector in the local frame when the rotation from body to local is given by the specific axis-angle rotation.

Yiping Liu on 23 Apr 2021
Your understanding seems to be correct.
If the quaternion q reprsents a 3D rotation that rotates frame Local into frame Body, then the rotation matrix acquired through R = q.rotmat('frame') represents the same 3D rotation, but keep in mind that the same R can also be interpreted as "the rotation that re-expresses a point in body frame into local frame".
To express a point that is originally given in local frame into the body frame, you need R', which is equivalent to q.rotmat('point')
>> q.rotmat('frame') * q.rotmat('point')
ans =
1.0000 0 0
0 1.0000 0
0 0 1.0000
Morten Nissov on 26 Apr 2021
And I suppose the same is true for the quaternion which represents the orientation of the body frame with respect to the local?
Like for example, a body which sits at with some heading (yaw) ψ corresponds to the quaternion by the axis-angle to quaternion conversion. The rotation from {b} to {l} is then
which in this case would be given by rotmat(q, 'point').
I think I get it.

James Tursa on 26 Apr 2021
Edited: James Tursa on 26 Apr 2021
James Tursa on 29 Apr 2021
I am not seeing the confusion here. If you look at your explicit rotation matrix
0.7071 -0.7071 0
0.7071 0.7071 0
0 0 1.0000
this sure looks like an active rotation of 45 degrees to me. E.g., take a vector along the x-axis [1;0;0] and multiply it by that matrix and you will get the first column. This is what you would expect by actively rotating a [1;0;0] vector by 45 degrees within the same coordinate frame. It should end up halfway between the x-axis and the y-axis, and that is what we got. And take a y-axis vector [0;1;0] and do the same multiplication and you get the 2nd column, which is a vector halfway between the y-axis and the negative x-axis. Again, this is what I would expect from an active rotation of 45 degrees within the same coordinate frame.
As for the quaternion to direction cosine matrix conversion formula, this does look like a Scalar-Vector order Left Chain Active Hamilton convention.

Brian Fanous on 28 Apr 2021
The quaternion class does follow the Hamilton convention – the scalar part is first.
Point rotations are active rotations and correspond to q * v * conj(q).
Frame rotations are passive rotations and corresponds to conj(q) * v * q
##### 2 CommentsShowHide 1 older comment
Brian Fanous on 28 Apr 2021
We might be using the same definition of orientation, but just to be sure, our orientation definition is :
“Orientation is defined as the frame rotation that takes the parent frame to the child frame.”
The equation you’ve written with the rotation matrix takes the body (child) frame to the parent (navigation) frame. Your rotation matrix is what we’d call a point rotation matrix. Really it’s the transpose of what we call orientation in the toolboxes. But that’s why it works in your equation – you are going body to nav so using the transpose is correct.
The quaternion you’ve built is the same one you’d get if you did this:
quaternion([45 0 0], 'eulerd', 'ZYX', 'point')
which is to say, “make a quaternion q such that q * v * conj(q) will rotate a point 45 degrees around the Z axis.”
That’s why you get the same answer as the matrix you’ve defined above which rotates a point around the Z axis. The transpose of that matrix rotates the frame of reference.

R2020b

### Community Treasure Hunt

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

Start Hunting!

Translated by