Stormworks: Build and Rescue

Stormworks: Build and Rescue

Not enough ratings
How to use the euler x, euler y and euler z outputs of Physics and Astronomy Sensors (the nitty gritty)
By Kernle Frizzle
If you don't have any experience in 3D coordinate transforms and rotations, then chances are the euler angle outputs make no sense. Hopefully this guide will help you understand what they mean and how to use them.
   
Award
Favorite
Favorited
Unfavorite
What the hell is an Euler Angle?
Euler angles, named after the Swiss Leonhard Euler, are a way to describe an orientation in space using three Davenport chained rotations around fixed coordinate axes.

English translation:
It's like roll, compass heading and elevation. You have three separate angle measures, and each describes a different aspect of the orientation.

The theory is that any orientation in 3D space can be described by a sequence of three consecutive rotations, each with reference to one of the three coordinate axes, x, y, and z. Any point in one coordinate system can then be transformed to its relative position in the rotated coordinate system and vice versa by applying those three rotations to the point's coordinates.

For now this is just the theory. I'll do my best to lay out ways to visualize and make sense of it yourself, but if it doesn't click, don't worry. You can just skip it and trust the math at the end.

Visualization:
I ripped this gif from the wikipedia for Euler angles.[en.wikipedia.org] It shows how the final orientation is reached by the three individual rotations:
.gif]In this case, imagining that the down-left axis is x, the vertical axis is y, and the down-right axis is z, the order of the rotations is y-x'-y''. The 's just represent the fact that each consecutive rotation is done after the first, and in mathematics usually the coordinates of anything once a transformation is done are described as the original names of the coordinates plus one ' for each time a transformation is applied.

One thing that is important to note:
The order of the rotations shown in the gif is actually backwards from what you must do mathematically. Rotations are most easily be performed if they are with respect to one of the fixed (blue) axes.
This gif is actually misleading due to that fact.

This idea is probably easiest to visualize if we talk about roll, elevation and azimuth, which I'm guessing you're familiar with. If the idea of rotating around the three fixed axes is confusing, then follow the steps below, otherwise skip to the next heading.

I want you to sit up straight in your chair and look straight ahead.

Your head is now the fixed coordinate system, you are not allowed to move your head in any way.

Imagine a point directly in front of you, height level, one meter away.

You are allowed to rotate the position of the point around your head, but only in three directions:
  • Around your x-axis (pointing directly out of the right side of your head, rotating around this axis would move the point up or down in your vision),

  • Around your y-axis (pointing directly out of the top of your head, rotating around this axis would move the point left or right in your vision), and

  • Around your z-axis (pointing directly out of the front of your head, if the point is in your vision's centerline then it will look like it doesn't move, as it has no wings to indicate its roll position, but if the point is slightly off, it will rotate around your centerline clockwise or counterclockwise).
Imagine you want to describe the orientation of an aircraft, at zero azimuth to keep it simple. The aircraft is pointed slightly up and rolled slightly to the right.

If you want to move the point in front of your head into the same position as the aircraft, you could do it in two ways:
  • First rotate the dot around the x axis (upward) and then around the z axis (clockwise)

  • First rotate the dot around the z axis (clockwise) and then around the x axis (upward)
Now imagine performing these rotations on the dot in front of you. Using the first way, the dot would rotate upward (good), but then rotating around your z axis, the dot will swing out to the right as it rolls (not good, as the orientation of the dot should be at 0 azimuth). Remember, these rotations are being done around the axes relative to your head, not the dot.

Using the second way, first you would rotate the dot around the z axis, giving it the correct roll value (good), and then you would rotate the dot around the x axis, moving it up and giving it the correct elevation (also good).

This should show you how the order that you apply the rotations is just as important as the size of the rotations themselves. The idea can be extrapolated for azimuth as well, but I'll leave that visualization to you.

But wait, the gif example only rotates around the x and y axes, why doesn't it use all three?

At some point, people decided that Euler's angles were a bit too abstract to be used for more practical applications like aeronautics. Two dudes, Peter Guthrie Tait and George H. Bryan came up with Tait-Bryan angles (creative), which are synonymous with your classic and familiar heading, elevation, bank, or yaw, pitch, roll and such. They use all three axes instead of just two.

Over time, these Tait-Bryan angles have also been called Euler angles, and in that situation, Euler's original angles are called classic Euler angles.

Finally getting to the game itself, the three "euler" angles outputted by the physics and astronomy sensors are actually Tait-Bryan angles in disguise.
The only mystery left is: In what order are these angles applied?
What angles, and in what frame of reference, and in what order, are outputted by the sensors?
The only info we have to go off of is the names of each output: "euler x," euler y" and "euler z."

It's a pretty safe assumption that the "euler x" angle is the value of the rotation around the x axis, and likewise for the rest. As it turns out, this is indeed the case.

These rotations are with respect to the world itself.

Important to remember: As with the sensor's x, y and z position outputs, y is the vertical axis and x and z are analogous to the in-game map's x and y.

Stop beating around the bush, what order are these angles performed in?
I don't know about you, but my first instinct would be z-x'-y'', as this would be identical to what you would expect as roll, elevation and azimuth. First you would perform the roll, then the elevation and lastly the azimuth.

If you tried the steps earlier to visualize these rotations, you should be able to see that this would indeed make the most sense. That is, only if x, y and z are truly trying to describe elevation, azimuth and roll.

This, sadly, is not the case.

After some experimenting, I found the true order.
It's x-y'-z''.

I guess it should be obvious, being in alphabetical order, but the game has no indication of this order other than I guess it being implied by the order the outputs are in, being channels 4, 5 and 6 respectively.

Now we get to the math.
How do I use these angles in any meaningful way?
As described earlier, the order in which these rotations are performed is x-y'-z''. If you rotated a coordinate system around these axes in this order, the resulting coordinate system would be in the same orientation as the physics or astronomy sensor in-game.

One of the most common instances where you need this kind of coordinate shift is with radars.

The radar component will output enough data to allow you to calculate the x, y and z position of a target with reference to the radar component itself, that data being relative distance, azimuth and elevation. The tricky part comes when you need to describe that target's position relative to the map instead of the radar.

If you slap a physics sensor right next to the radar, you can use the euler x, y and z outputs to "decode" these relative positions into their world/map/true positions.

Because of what those "euler" angles represent, that being the angles something has to rotate by in order to result in the final position of the sensor (if their starting position is facing dead ahead (north) with reference to the world/map), if you apply those rotations to the relative coordinates of the target from the radar, you can in essence rotate that entire coordinate system and result in coordinates relative to the map instead of the radar.

Even though the x-y'-z'' order may be harder to visualize, the actual math to perform these rotations is exactly the same as it would be for any other order.

Important notes:
  • For some reason, "euler x" returns negative when rotating upward and returns positive when rotating downward. This is opposite of what you would expect if you're used to elevation.

  • "euler y" is signed the same way you would expect for a compass. Technically, this makes it also signed opposite of what the in-game compass returns. Odd.

  • For some other reason, "euler z" returns negative when rotating clockwise and returns positive when rotating counterclockwise. This is opposite of what you would expect if you're used to roll.

  • If you experiment with the angles yourself you may notice that sometimes they seem to randomly flip from positive to negative or gain an extra pi in their measurement. This is normal. Think of how an artificial horizon or compass quickly flips around when you face straight up in a full loop-de-loop. It is a form of gimbal lock.

Your best friend:
function rotmat2d(x,y,r) return x*math.cos(r)-y*math.sin(r), x*math.sin(r)+y*math.cos(r) end
You will find this subprogram in my massive list of useful subprograms, if you've seen my other lua guide.

This function will take in what are essentially the components of a vector on the x,y plane, as well as an angle measure "r" to rotate that vector by. The function will output x',y', which just means the x and y coordinates after they've been rotated.

Here is a visual example:
You may notice that this is in 2D rather than 3D.

However, because our Euler angles are locked to their respective axis, you can fully ignore that axis when calculating the rotation.
Skip the context, just show me what to copy and paste into my Lua.
This code will take the coordinates of a target relative to a physics or astronomy sensor and transform them into coordinates relative to the map:
function rotmat2d(x,y,r) return x*math.cos(r)-y*math.sin(r), x*math.sin(r)+y*math.cos(r) end function onTick() ex = input.getNumber(4) ey = input.getNumber(5) ez = input.getNumber(6) targetx, targety, targetz = 24, 5, 72 --These are just random coordinates for a target relative to the physics sensor, likely coming from a radar or some other kind of sonar or laser sensor. targety, targetz = rotmat2d(targety, targetz, ex) targetz, targetx = rotmat2d(targetz, targetx, ey) targetx, targety = rotmat2d(targetx, targety, ez) --This series of rotations will rotate the coordinates of the target according to the Euler angles from the sensor output.setNumber(1, targetx) output.setNumber(2, targety) output.setNumber(3, targetz) end
Strangely, if you've ever dealt with the cross product of 3D vectors before, the order of x, y and z may look familiar. For the cross product the order to remember is 23-32,31-13,12-21, and equating that number to x, y or z results in yz-zy,zx-xz,xy-yx, which is almost exactly what you see in the code, yz,zx,xy. Just a weird observation, it isn't important for this, at least I don't think.

This code will do the opposite of the previous code. It will take world coordinates of a target and transform them into relative coordinates to a physics or astronomy sensor:
function rotmat2d(x,y,r) return x*math.cos(r)-y*math.sin(r), x*math.sin(r)+y*math.cos(r) end function onTick() ex = input.getNumber(4) ey = input.getNumber(5) ez = input.getNumber(6) targetx, targety, targetz = 18, 2, 92.1042957 --These are just random coordinates for a target relative to the map targetx, targety = rotmat2d(targetx, targety, -ez) targetz, targetx = rotmat2d(targetz, targetx, -ey) targety, targetz = rotmat2d(targety, targetz, -ex) --This series of rotations will rotate the coordinates of the target according to the Euler angles from the sensor output.setNumber(1, targetx) output.setNumber(2, targety) output.setNumber(3, targetz) end
You can see that in this code, the signs of the rotations are reversed. It is important to remember that the order of the rotations has to also be reversed.
(bonus) How to extract other orientation data
If you had just the Euler angles from one of the sensors, you can use them to calculate the corresponding pitch, roll and yaw.

The method consists of applying rotations to vectors representing axes representing the local x, y and z axes of the sensor, then based on the real world directions of those axes, calculating the different angles.

This code will do just that:
function rotmat2d(x,y,r) return x*math.cos(r)-y*math.sin(r), x*math.sin(r)+y*math.cos(r) end function norm(x) return x-pi*2*math.floor(x/pi/2) end function onTick() ex=input.getNumber(4) ey=input.getNumber(5) ez=input.getNumber(6) i1={x=1,y=0,z=0} j1={x=0,y=1,z=0} k1={x=0,y=0,z=1} i1.y,i1.z=rotmat2d(i1.y,i1.z,ex) i1.z,i1.x=rotmat2d(i1.z,i1.x,ey) i1.x,i1.y=rotmat2d(i1.x,i1.y,ez) j1.y,j1.z=rotmat2d(j1.y,j1.z,ex) j1.z,j1.x=rotmat2d(j1.z,j1.x,ey) j1.x,j1.y=rotmat2d(j1.x,j1.y,ez) k1.y,k1.z=rotmat2d(k1.y,k1.z,ex) k1.z,k1.x=rotmat2d(k1.z,k1.x,ey) k1.x,k1.y=rotmat2d(k1.x,k1.y,ez) a=math.atan(k1.x,k1.z) tjz,tjx=rotmat2d(j1.z,j1.x,-a) tkz,tkx=rotmat2d(k1.z,k1.x,-a) e=math.atan(k1.y,tkz) tjz,tjy=rotmat2d(tjz,j1.y,-e) tkz,tky=rotmat2d(tkz,k1.y,-e) r=math.atan(tjx,tjy) output.setNumber(1,a) output.setNumber(2,e) output.setNumber(3,r) end
Technically only the j and k normal vectors are needed for this calculation, but I included all three because why not. Maybe you'll need i for something yourself.

Copy and paste this into a lua hooked up directly to a physics or astronomy sensor, and it will give you your a (azimuth, compass), e (elevation, pitch) and r (roll), all in radians of course.

If you need all the data of a physics sensor, but are stuck with an astronomy sensor, use this microcontroller to derive the missing data.
If you have any questions or if anything needs clarification,
Please ask in the comments below and I will do my best to answer or explain.

I commend you for making it to this point

Originally posted by Thomas Joseph Grasso:
I did not get my SpaghettiOs, I got spaghetti. I want the press to know this.


1 Comments
Nitty_Gritty1 20 Aug @ 10:48am 
Wow, this is the most complete guide on this that I have seen. Great job! It really has helped me get to the real me of Euler angles, thanks! This will help me out a ton with the "Nitty Gritty" of automated navigation and orienting systems. :-)