Skip to content

Added direct quaternion to euler transformation and solved issue #53#54

Open
evbernardes wants to merge 2 commits intomatthew-brett:mainfrom
evbernardes:main
Open

Added direct quaternion to euler transformation and solved issue #53#54
evbernardes wants to merge 2 commits intomatthew-brett:mainfrom
evbernardes:main

Conversation

@evbernardes
Copy link
Copy Markdown

Brief description

I recently published an article about a direct formula for the conversion between a quaternion variable to Euler angles in any sequence, which can be read here (Open Access).

Compared to either having 12 separate formulas (or 24, taking into account both intrinsic and extrinsic rotations) or using the well known quaternion-to-matrix-to-euler method, this has 3 main advantages:

  1. Numerically, it is up to 30 times faster than the previous quaternion-to-matrix-to-euler method (used both originally in SciPy and in transforms3d, for example).
  2. It is a lot simpler to implement, debug and maintain than both methods.
  3. It provides the simple formulas that can be used for theorerical work.

Because of points 1 and 2, it has already been merged into Scipy. Because point 3, it has also been merged into SymPy.

I truly believe it's the best possible way to do this conversion, so I'm trying to contribute it to as many open source projects I can!

Other comments

Apart from the execution time advantages, this also has other numerical advantages. The main one is that the only inverse trigonometric function used is arctan2 instead of arccos and asin, which is always preferred when both sin and cos are known (arccos, for example, can give much higher errors near 0).

It also fixes issue #53.

I left the other method (plus a correction as explained in #53) for testing purposes, but I'd argue that in the future this should be removed.

What is not implemented

I don't know exactly how to to use the axes checking functions already existing in transforms3d, so if someone helps me with that, we could also add that at the beginning!

@matthew-brett
Copy link
Copy Markdown
Owner

Thanks for this. Yes, in general, that sounds like a good idea. Could you say more about what you mean for the axes checking functions? Sorry to be slow - I haven't touched this code in a long time.

@evbernardes
Copy link
Copy Markdown
Author

Thanks for this. Yes, in general, that sounds like a good idea. Could you say more about what you mean for the axes checking functions? Sorry to be slow - I haven't touched this code in a long time.

Thanks for your reply! It's a very silly thing at the beginning: the test to check if the input axes string is correct or not.

For example, 'rxyz' gets accepted, but 'rxxz' or 'rxym' should throw errors.

@matthew-brett
Copy link
Copy Markdown
Owner

I think that would just be a case of checking axes in _AXES2TUPLE .

@evbernardes
Copy link
Copy Markdown
Author

evbernardes commented Dec 17, 2022

I think that would just be a case of checking axes in _AXES2TUPLE .

Alright, just changed it! It just tries to access it to have a KeyError, instead of checking axes in _AXES2TUPLE and throwing something else, for consistency with the other method.

Also, sorry if the code looks too much like the one from SciPy, it's because I wrote both!

if symmetric:
k = 6 - i - j # get third axis

# Step 0
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgive my ignorance, but is this the same as the parity check returned from _AXES2TUPLE?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is to get the third axis for symmetric sequences.
For example, for the sequence 'zyz', at first we have i, j, k == 3, 2, 3.
The third axis (the axis we don't have) is 1. Since i, j, k can only be 1, 2 or 3, we know that i + j + k_new == 6.
So: k_new = 6 - i - j gets this other axis.

@kopytjuk
Copy link
Copy Markdown

@evbernardes did you take a look into the ROS Stack ROS used in robotics? Its tf2 library heavily uses quarternions, maybe you can include your method there?

@evbernardes
Copy link
Copy Markdown
Author

@evbernardes did you take a look into the ROS Stack ROS used in robotics? Its tf2 library heavily uses quarternions, maybe you can include your method there?

Hey there! I didnt yet, but I am planing to! Are you familiar with where exactly it's implemented in the Ros stack?

@kopytjuk
Copy link
Copy Markdown

kopytjuk commented Dec 27, 2022

@evbernardes did you take a look into the ROS Stack ROS used in robotics? Its tf2 library heavily uses quarternions, maybe you can include your method there?

Hey there! I didnt yet, but I am planing to! Are you familiar with where exactly it's implemented in the Ros stack?

You transform a quarternion q to euler angles with (source):

tf::Matrix3x3 m(q);
double roll, pitch, yaw;
m.getRPY(roll, pitch, yaw);

The implementation is in Matrix3x3::getEulerYPR here: https://github.com/ros2/geometry2/blob/9139e0c266cfd579d55e2ef36b786fb334b15665/tf2/include/tf2/LinearMath/Matrix3x3.h#L286

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants