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:
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.