Description
Describe the bug
In Unity, to convert a vector from unity space RUF (Right, Up, Front) to ENU (East, North, Up), the following transformation is applied:
public Vector3 ConvertFromRUF(Vector3 v) => new Vector3(v.x, v.z, v.y);
This assumes that in Unity a positive x is East, a positive z is North and a positive y is up.
However, to convert a rotation from Unity space RUF (Right, Up, Forward) to ENU (East, North, Up), the following transformation is applied:
public Quaternion ConvertFromRUF(Quaternion q) => new Quaternion(q.x, q.z, q.y, -q.w);
This however assumes when in Unity, an identity rotation (When the forward vector is positive z (0, 0, 1)) would also be an identity rotation in ENU.
This means that in Unity, when facing z forward or North, the orientation in ENU is also the identity.
However in ENU, when the rotation is identity, forward should be facing East, see:
"In case of land vehicles like cars, tanks etc., which use the ENU-system (East-North-Up) as external reference (World frame), the vehicle's (body's) positive y- or pitch axis always points to its left"
Image from Wikipedia shows the zero point on the yaw to be East, rotating counter-clockwise
The problem seems to be that:
Unity geographic coordinates have +x = East
, +y = Up
and +z = North
, but when converting geographic rotations offsets are not taken into account 0 = North
when it should be 0 = East
(In ENU terms).
We found this discrepancy to be an issue when using Unity to simulate IMU data (converted to ENU before publishing) which would then be fed into the ROS robot_localization package. When doing this, we found that we would be pitching when the object was rolling in Unity and vise versa. The robot_localization link provided indicates that ENU should be used for all IMU data. Switching the conversion to FLU and re-framing our environment such that -x = North
, +y = Up
and +z = East
corrected this discrepancy.
To correctly convert a rotation from Unity space to ENU, either:
- Unity should be
-x = North
,+y = Up
and+z = East
and ENU transformations should be equivalent to FLU transformations. (Note: This would probably break NED rotational transformations)
OR - Unity should apply a yaw offset of 90 degrees when converting from Unity orientations to ENU orientations and vice versa.
Is there something else about the Unity implementation that I am missing?
Some related links