# Transform roll, pitch, yaw from one coordinate system to another

I'm trying to figure out how to transform a pose given with Euler angles roll (righthanded around X axis), pitch (righthanded around Y axis), and yaw (lefthanded around Z axis) from the Unreal Engine into a pose in a purely right-handed North, West, Up coordinate frame.

I know the full rotation matrix is $$R = R_z R_y R_x$$, as Euler angles are applied in that order.

But, irritatingly, the Y axis switches direction, and the whole coordinate system is rotated.

How can I elegantly determine pose in my target reference frame? I'm open to quaternions.

There's actually a really neat identity for this particular problem.

Yaw, pitch, and roll are applied in that order to recover a body frame from the world frame. If I have $$yaw = \psi$$, $$pitch = \theta$$ and $$roll = \phi$$ in the UE4 reference frame, then I can get to my NWU coordinate frame in two stages.

First let's transform to a frame I'm calling $$C$$.

Here the coordinate axes all still span the same dimensions, so we can find $$R_{Cb} = R_z(-\psi)R_y(-\theta)R_x(\phi)$$, the same ZYX ordering as before; we just have to negate the pitch and yaw angles because we've flipped the direction of $$+Y$$, which reverses the direction of rotation, and we choose to reverse the rotation around $$Z$$ to make $$C$$ entirely right-handed.

Note that the body frame also gets these changes, but its orientation of course doesn't change.

Now we can find $$R_{NWUC} = R_z(-\frac{\pi}{2})$$, because the $$R_y$$ and $$R_x$$ terms are $$I$$.

This time the body frame won't change at all, because it's already similar to the world frame.

In general we have to find

$$R_{NWUb} = R_{NWUC}R_{Cb} = R_z(-\frac{\pi}{2})R_z(-\psi)R_y(-\theta)R_x(\phi) = R_z(-\frac{\pi}{2}-\psi)R_y(-\theta)R_x(\phi)$$

This is because to find the cumulative rotation matrix you right multiply and follow some canceling rules.

And in the end, since you don't have to change the ZYX order of application, you're left with a rotation matrix with Euler angles you can easily pick out: $$yaw = -\frac{\pi}{2} - \psi$$, $$pitch = -\theta$$, and $$roll = \phi$$.

To verify this (particularly the right-multiplying, which defies my intuition), I wrote a little script to visualize the example of a south-easterly-facing camera pitched downward at 20 degrees. This would have a $$psi = +45^{\circ}$$, $$\theta = -20^{\circ}$$, and $$\phi = 0^{\circ}$$ in UE4 coordinates:

D2R = numpy.pi/180
R2D = 180/numpy.pi

R_z = R_(-135*D2R, 'z') # implementation of the three 3D rotation matrices
R_y = R_(20*D2R, 'y')

RR = R_z.dot(R_y)
print(RR)

angles = recover_angles(RR) # https://www.gregslabaugh.net/publications/euler.pdf
for a in angles: print(a*R2D)

fig = pyplot.figure()
ax = fig.gca(projection='3d')
ax.plot([0,5],[0,0],[0,0],c='k')
ax.plot([0,0],[0,5],[0,0],c='k')
ax.plot([0,0],[0,0],[0,5],c='k')

ax.plot([0,RR[0,0]],[0,RR[1,0]],[0,RR[2,0]],c='r') # recall columns of R are
ax.plot([0,RR[0,1]],[0,RR[1,1]],[0,RR[2,1]],c='g') # unit coordinate vectors
ax.plot([0,RR[0,2]],[0,RR[1,2]],[0,RR[2,2]],c='b') # of frame b in world frame

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
pyplot.show()


which returns:

That's the rotation matrix and recovered Euler angles (listed roll, pitch, yaw order) from an implementation of this function.

And here are the NWU axes in black with the body axes in color. This visualization is based on the fact that the columns of the rotation matrix are unit-length vectors pointing in the directions of the body frame's coordinate axes.

The relationship between the two frames as you’ve drawn them is simple: rotate by an angle of $$\pi/2$$ radians counterclockwise around the z axis, then reflect through the plane perpendicular to y.

There isn’t going to be any elegance about it with Euler angles. Someone has already done the repulsive conversion from unreal to 3x3 matrix or to quaternions for you, so find that. Just pick one and stick with it.

By “handed” it sounds like you mean the choice of sign when expressing a rotation around an axis. If that bothering you then obviously you can swap direction by swapping signs. But like I said, if it’s coming out of unreal someone probably already has written a conversion to a normal right handed coordinate system. (That’s what I think of as handedness: an orientation assigned to a coordinate system, not a type of rotation.)

Performing the rotation and reflection is trivial using matrices or quaternions. Rotations by quaternions are of course famous. Reflections might be lesser known but they are pretty simple to describe: take the unit normal $$n$$ to your plane expressed a s a quaternion: then $$x\mapsto nxn$$ is the reflection.

• "The relationship between the two frames as you’ve drawn them is simple: rotate by an angle of 𝜋/2 radians counterclockwise around the z axis, then reflect through the plane perpendicular to y." Right, it's simple for locations. For rotations it's doing my head in. Can you elaborate? Nov 24, 2020 at 5:11