Problem with quaternion rotation maths

Are you sure that's the way you want to chain your transformations?I suspect that you wantQ_{R->C} = Q_{R->B}Q_{B->C}Q_{R'->C'} = Q_{R'->B'}Q_{B'->C'}which would correspond to the following sequence of quaternion multiplications:camera_relative_to_reference_quat = quatmultiply(reference_relative_to_balloon_quat, camera_relative_to_balloon_quat)target_relative_to_reference_quat = quatmultiply(initial_balloon_relative_to_reference_quat, target_relative_to_reference_quat)In summary, the conversation discusses the use of quaternions to represent
  • #1
bras0463
3
0
Hi,
I am trying to work out the maths to keep a camera connected to a balloon pointing in a fixed direction. The camera can roll, pitch and yaw relative to the balloon which itself can roll, pitch and yaw relative to an inertial frame. Sensors provide the camera roll, pitch and yaw relative to the balloon and the balloon roll, pitch and yaw relative to the reference frame.

Here is the MATLAB code I'm using to try and find the desired camera roll, pitch and yaw angles of rotation:

Code:
clear all;
clc;

% Setup target
initial_camera_relative_to_balloon_yaw      = 0;
initial_camera_relative_to_balloon_pitch    = 0;
initial_camera_relative_to_balloon_roll     = 0;

initial_balloon_relative_to_reference_yaw        = -90;
initial_balloon_relative_to_reference_pitch      = 0;
initial_balloon_relative_to_reference_roll       = 0;

initial_camera_relative_to_balloon_quat     = angle2quat(deg2rad(initial_camera_relative_to_balloon_yaw), deg2rad(initial_camera_relative_to_balloon_pitch), deg2rad(initial_camera_relative_to_balloon_roll));
initial_balloon_relative_to_reference_quat  = angle2quat(deg2rad(initial_balloon_relative_to_reference_yaw), deg2rad(initial_balloon_relative_to_reference_pitch), deg2rad(initial_balloon_relative_to_reference_roll));
target_relative_to_reference_quat           = quatmultiply(initial_camera_relative_to_balloon_quat, initial_balloon_relative_to_reference_quat)
    
% Normal running
balloon_relative_to_reference_yaw    = -90;
balloon_relative_to_reference_pitch  = 45;
balloon_relative_to_reference_roll   = 0;

balloon_relative_to_reference_quat   = angle2quat(deg2rad(balloon_relative_to_reference_yaw), deg2rad(balloon_relative_to_reference_pitch), deg2rad(balloon_relative_to_reference_roll));
reference_relative_to_balloon_quat   = quatinv(balloon_relative_to_reference_quat);
camera_relative_to_balloon_quat      = quatmultiply(target_relative_to_reference_quat, reference_relative_to_balloon_quat);

[c_yaw, c_pitch, c_roll] = quat2angle(camera_relative_to_balloon_quat);
camera_yaw      = rad2deg(c_yaw);
camera_pitch    = rad2deg(c_pitch);
camera_roll     = rad2deg(c_roll);
% If the maths was right this should be [0 -45 0] not [0 0 -45]
[camera_yaw, camera_pitch, camera_roll]

There is clearly a problem with the maths but I can't see what it is. Does this quaternion maths look correct?
 
Physics news on Phys.org
  • #2
bras0463 said:
Hi,
I am trying to work out the maths to keep a camera connected to a balloon pointing in a fixed direction. The camera can roll, pitch and yaw relative to the balloon which itself can roll, pitch and yaw relative to an inertial frame. Sensors provide the camera roll, pitch and yaw relative to the balloon and the balloon roll, pitch and yaw relative to the reference frame.

Here is the MATLAB code I'm using to try and find the desired camera roll, pitch and yaw angles of rotation:

Code:
clear all;
clc;

% Setup target
initial_camera_relative_to_balloon_yaw      = 0;
initial_camera_relative_to_balloon_pitch    = 0;
initial_camera_relative_to_balloon_roll     = 0;

initial_balloon_relative_to_reference_yaw        = -90;
initial_balloon_relative_to_reference_pitch      = 0;
initial_balloon_relative_to_reference_roll       = 0;

initial_camera_relative_to_balloon_quat     = angle2quat(deg2rad(initial_camera_relative_to_balloon_yaw), deg2rad(initial_camera_relative_to_balloon_pitch), deg2rad(initial_camera_relative_to_balloon_roll));
initial_balloon_relative_to_reference_quat  = angle2quat(deg2rad(initial_balloon_relative_to_reference_yaw), deg2rad(initial_balloon_relative_to_reference_pitch), deg2rad(initial_balloon_relative_to_reference_roll));
target_relative_to_reference_quat           = quatmultiply(initial_camera_relative_to_balloon_quat, initial_balloon_relative_to_reference_quat)
    
% Normal running
balloon_relative_to_reference_yaw    = -90;
balloon_relative_to_reference_pitch  = 45;
balloon_relative_to_reference_roll   = 0;

balloon_relative_to_reference_quat   = angle2quat(deg2rad(balloon_relative_to_reference_yaw), deg2rad(balloon_relative_to_reference_pitch), deg2rad(balloon_relative_to_reference_roll));
reference_relative_to_balloon_quat   = quatinv(balloon_relative_to_reference_quat);
camera_relative_to_balloon_quat      = quatmultiply(target_relative_to_reference_quat, reference_relative_to_balloon_quat);

[c_yaw, c_pitch, c_roll] = quat2angle(camera_relative_to_balloon_quat);
camera_yaw      = rad2deg(c_yaw);
camera_pitch    = rad2deg(c_pitch);
camera_roll     = rad2deg(c_roll);
% If the maths was right this should be [0 -45 0] not [0 0 -45]
[camera_yaw, camera_pitch, camera_roll]

There is clearly a problem with the maths but I can't see what it is. Does this quaternion maths look correct?

Hey bras0463 and welcome to the forums.

It's been a while since I did this kind of thing so take my advice with a grain of salt.

My understanding is that if you want to transform something quaternions you have to use the identity x = p q p^-1. Then you take x and convert it to a matrix or euler angles (which you are doing in your code).

I noticed that your code does the right format, but your p^-1 does not correspond to the inverse of p, but rather a different set of parameters.

If you want to compose rotations, then you should do that the standard way, but when I did this kind of thing, I remember doing x = p q p^-1 to get my rotation information which was then converted to a linear map (matrix) to use for transforming points.
 
  • #3
Hi thanks for the response.

I think if you want to rotate a vector then the formula you have is correct i.e.

Code:
vector_result_in_quat_form = quaternion X vector_in_quat_form X quaternion^-1

where 'X' is quaternion multiplication.

I think what I'm trying to do is different. I'm trying to combine two rotation quaternions to create a combined rotation quaternion and that is performed by a straight quaternion multiplication.

Code:
combined_b_and_a_quat = quat_a X quat_b

The reason I have the inverse there is that I want to perform the opposite rotation to the one I have the quaternion for.

There's a good chance that I'm wrong about this though, after all my code doesn't do what I expect! :)
 
  • #4
bras0463 said:
Code:
target_relative_to_reference_quat =
  quatmultiply(initial_camera_relative_to_balloon_quat,
               initial_balloon_relative_to_reference_quat)

...
    
camera_relative_to_balloon_quat =
  quatmultiply(target_relative_to_reference_quat,
               reference_relative_to_balloon_quat);

The problem is that there are four ways to use quaternions to represent rotations and transformations. You appear to be assuming a representation that is different from Matlab's. The four choices are (left versus right) × (rotation versus transformation).
  • Left versus right: Which of qvq-1 or q-1vq are you using to rotate/transform a vector?
  • Rotation versus transformation: Does your quaternion represent the physical rotation of some device, or does it represent the transformation of coordinates from one frame to another?

How a sequence of quaternions chain depends on your choice for a representation scheme. For example, left transformation quaternions chain from right to left, but left rotation quaternions chain from left to right.

I'll denote [itex]Q_{A\to B}[/itex] as the quaternion that rotates/transforms from orientation A to orientation B. Now look at the two quaternion multiplications in your code. Denoting R as reference, B as balloon, C as camera, T as target, the first quaternion multiplication is
Code:
target_relative_to_reference_quat =
  quatmultiply(initial_camera_relative_to_balloon_quat,
               initial_balloon_relative_to_reference_quat)
[tex]Q_{R\to T} = Q_{B->C}Q_{R->B}[/tex]
You are chaining from right to left here.

The second multiplication is
Code:
camera_relative_to_balloon_quat =
  quatmultiply(target_relative_to_reference_quat,
               reference_relative_to_balloon_quat)
[tex]Q_{B'->C'} = Q_{R\to T}Q_{B'->R}[/tex]
Once again you are chaining from right to left.If the Matlab's representation scheme is such that quaternions chain from left to right, those computations should have been done as

Code:
target_relative_to_reference_quat =
  quatmultiply(initial_balloon_relative_to_reference_quat,
               initial_camera_relative_to_balloon_quat)

...
    
camera_relative_to_balloon_quat =
  quatmultiply(reference_relative_to_balloon_quat,
               target_relative_to_reference_quat);
 
  • #5
Thanks DH! You were absolutely right, making that change fixed it straight away.
 
  • #6
From http://www.mathworks.com/matlabcentral/fileexchange/1176-quaternion-toolbox, Matlab uses left rotation quaternions / right transformation quaternions, which chain left to right.

They mistakenly use the terms left-handed and right-handed quaternions on that web page. There's no handedness involved here, at least not in the sense of left-handed versus right-handed coordinates. The left/right distinction is with respect to qvq* versus q*vq: Does the unconjugated quaternion go to the left or the right of the vector to be transformed/rotated?
 

1. What are quaternions and how are they used in rotation maths?

Quaternions are a mathematical concept used to represent rotations in three-dimensional space. They consist of four components: a scalar (real number) and three imaginary components (i, j, k) that represent the rotation axis. In rotation maths, quaternions are used for their efficiency and accuracy in representing 3D rotations.

2. What is the problem with quaternion rotation maths?

One of the main problems with quaternion rotation maths is the issue of gimbal lock. This occurs when two of the rotation axes align, resulting in a loss of one degree of freedom and a potential loss of accuracy in the rotation representation.

3. How can gimbal lock be avoided in quaternion rotation maths?

To avoid gimbal lock, techniques such as quaternion interpolation (slerp) and converting to and from Euler angles can be used. Additionally, using quaternions with a four-component vector rather than a three-component vector can also help prevent gimbal lock.

4. Are there any other limitations or challenges associated with quaternion rotation maths?

Another limitation of quaternion rotation maths is that it can be more complex and difficult to understand compared to other methods of rotation representation, such as Euler angles. Additionally, quaternions may not always be the most efficient or accurate choice for certain types of rotations, such as rotations around a fixed axis.

5. How can I learn more about quaternion rotation maths?

There are many online resources and tutorials available for learning about quaternion rotation maths, including videos, articles, and interactive demonstrations. Additionally, studying linear algebra and geometry can provide a deeper understanding of the principles behind quaternion rotation maths.

Back
Top