Useful Tool for Calculating Rotations

Not direcly ROS-related per se but I suspect some of you will find this useful…

I made a prototype of this tool a while back to simplify some repetitive calculations I was doing at work every so often when calibrating the pose of our sensors in a kinematic chain.

I finally got around to cleaning it up and adding quite a bit more functionality, so here it is!

https://articulatedrobotics.xyz/tools/rotation-calculator

The three main use cases are:

  • Converting rotations between different representations (and visualising them)
  • Calculating the result of a bunch of rotations applied consecutively
  • Solving for the unknown rotation in a chain

Play around and please let me know if you find any bugs!

10 Likes

Wow, great! So far I’ve been using quaternions.xyz . One thing I’m missing in both: The ROS RPY representation. I know it corresponds to some Euler angles, but I never know which!

Great idea! I’ll see about adding that - I know I get confused every time I check haha.

I’ve updated the page with a note at the bottom explaining how to correctly read it for the ROS RPY representation (I hope I’ve got that correct).

That reminds me of something that I’ve noticed before in REP-103 which is this quote:

  1. fixed axis roll, pitch, yaw about X, Y, Z axes respectively:
  • No ambiguity on order
  • Used for angular velocities
  1. euler angles yaw, pitch, and roll about Z, Y, X axes respectively
  • Euler angles are generally discouraged due to having 24 ‘valid’ conventions with different domains using different conventions by default.

It says Euler angles are discouraged for having 24 valid conventions, but surely the fixed axis RPY is just one of those 24 valid conventions? And it says that one (XYZs) has no ambiguity on order, but it doesn’t have any less order ambiguity as, say, YZXr.

Fair enough it may be seen as the most intuitive, but I don’t see it as any less ambiguous (unless you are saying that the order “roll-pitch-yaw” is a given, in which case XYZs and XYZr seem on a level standing to me.

Or have I missed something? @tfoote your name seems to crop up on a lot of this stuff, you might have some insight?

Edit: I meant to add that I do see the potential for ambiguity with “true” Euler angles, where the first and last axis are repeated.

1 Like

Oh wow, this is super helpful. BOOKMARKED! :bookmark:

I wish we could could embed something like this in docs.ros.org.

1 Like

Another resource I have used is 3D Rotation Converter

Thanks, if there’s a way you can embed it then go ahead but also if you want the source code let me know.

Yes I’ve used this one in the past and it was my inspiration! In fact it’s probably a little easier if you just want a single conversion but I wanted to be able to do the multiplications/solves as well, and also the option for true Euler angles.

Unfortunately no it’s not just one of the valid conventions. Although the notation and information is similar, fixed axis and Euler angles have the significant difference that one has world fixed axes, versus the latter with body fixed axes, this means that Euler vs Fixed result in different rotations when doing compound changes.

It’s quite interesting to me that there’s now the nomenclature around intrinsic and extrinsic axes. As far as I can tell that nomenclature is new since this was written. (Search before 2010 vs now) I went down a bit of a rabbit hole. It’s pretty interesting to see the history of the wikipedia article on it Euler Angles and it’s evolution. In addition the differentiation of matched first and last axes being true Euler angles wasn’t called out in the past either.

So depending on your categorization, in more modern language there’s 24 possible intrinsic and 24 possible extrinsic permutations. But in practice few people use the alternative fixed axis/extrinsic representations outside of XYZ.

We have specifically designed the standard ROS interfaces to make sure to call out the ordering in the function name because of the order ambiguity. Historically a lot of places just pass (yaw, pitch, roll) or store those values as a triplet without defining the axis convention clearly.

Updates of the documentation for clarity and newer verbiage would be appreciated.

1 Like

Edited after I realised I misread something

Thanks Tully, that’s so interesting the way the language has shifted!
And I absolutely agree on the value of putting the order in the function names and trying to be explicit about it wherever possible, it’s such an easy source of confusion.

There’s one thing I’m still confused about in your comment though and would like to get it straight for myself and others who come across this topic:

Ok this seems like the source of my confusion, as I thought there were 24 total - 6 permutations of Tait-Bryan, 6 Proper Euler, and each of those 12 can be fixed or rotating axis. Where do the other 12 come from? And I take it you’re saying that the standard ROS rotation is not the same as XYZs (one of my 24), in which case, how does it differ?

Or are you defining “world axes” as the global world rather than just the parent rotation? It’s been a little while since I was deep in this in a ROS context, but that feels to me like it just wouldn’t work.

And yes, the Euler (by which I assume you mean rotating) vs Fixed will result in different rotations to each other, I’m still struggling to grasp what makes one superior to another? (Presumably something to do with my misunderstanding above)


I personally find intrinsic angles far easier to “think” in, when I’m holding/imagining an axis marker I can focus on spinning each axis one at a time and let the global frame just hang, otherwise trying to do the second and third rotations about an invisible axis becomes tricky

I’m not sure at this point what the 24 enumerated possibilities were when that was written that long ago. But I would agree with your notation of the 12 different representations “Proper Euler” and “Tate-Bryan” in your listing. I think that the other permutations might have come from presentation orders as well. Some APIs call out getEuler(Z, Y, X) or getEuler(X, Y, Z), or more commonly more ambiguously defining the interface getEuler(yaw, pitch, roll) or getEuler(roll, pitch, yaw) in the development API despite it being always meaning ZYX(intrinsic) but presenting them in the API not in order of computation left to right, instead preferring alphabetical order. (I missed the definitions of what your s and r postscripts mean so being explicit) But it’s another dimension of unclear permutations possible. Where most instances of extrinsic APIs, typically call out the axes order in the function, and also explicitly call the axes in the argument names. There’s nothing mathematically inherently worse about the intrinsic vs extrinsic notation, only confusing usage.

Yes sorry I mixed notation a bit there (r and s being rotating vs static reference). I’ll use E and I here.

I think you’ve got me on board.

XYZ, being alphabetical, is probably going to be the least ambiguous order when the function and argument names are unclear (especially compared to something like ZYZ) . It’s just a matter then of whether it is extrinsic or intrinsic. XYZE (using the fixed axes) is arguably slightly less confusing to a newcomer, and its counterpart ZYXI is probably more standard/intuitive for most people (yaw first, then pitch, then roll), so a win all around.

(My personal preference for XYZI is probably an anomaly due to mostly using it in code for processing lidar scans, where someone replacing the lidar with it’s bottom-mounted bolts is most likely to result in a slight shift in Z rotation as the last step in the chain)

I’ll think about where I could do that most usefully. I reckon a page on docs.ros.org would be good, and I wonder if even the inline documention for the tf2 functions void setEulerYPR(eulerZ, eulerY, eulerX) and void setRPY(roll, pitch, yaw) could do with some clarification given that “Euler” does not necessarily imply “Intrinsic”.

Thanks for taking the time to talk through this!

1 Like