Unity Quaternion to rhs euler X-Y'-Z''

Hi,

i’m currently struggeling with a certain kinematic problem. This problem occupies me now for almost two days. but I just can’t wrap my head around the math.

The Problem:
I need to apply a transform of an object within Unity to another program (“V-rep”). The interface of this program only allows me to set three euler angles (X-Y’-Z’’ notation) of an object (no quaternion, rotation matrix or angle axis).

More detailed:
In unity, I have a sphere (position and orientation are important) which defines the desired end-frame of a robot arm.
In V-rep, I have another sphere, defining the target position and orientation for some inverse kinematic algorithms.

A manipulation of the sphere in Unity (e.g. rotating it) shall be aplied to the sphere in V-rep.
The difference between the coordinate system is only that Y and Z axis are swapped:
Right: Unity(1,0,0) and V-rep (1,0,0)
Up: Unity(0,1,0) and V-rep (0,0,1)
Forward: Unity(0,0,1) and V-rep(0,1,0)

I tried already several code snippets and pseudo code.
Usually by creating a transformation matrix with the unity quaternion components (w,x,y,z), (modifing this matrix) and afterwards calculating the three euler angles (a,b,c) for the euler angle notation: Rx(a)*Ry’(b)*Rz’'(c)
Mostly are the second and third rotations not correct.
I am, due design limitations, not able to use a workaround on the V-rep side. I really have to use this interface method.

Does anyone have some insightfull hints or maybe even some working code for this problem?
Many thanks in advance, even if only for reading till here! :wink:

Get the eulerAngles through the eulerAngles property of the quat:

And swap the y and z values.

@lordofduct
thanks for your reply. but those euler angles are given for a constant reference frame. Anyway, I wasn’t able to get your idea to work.

However, a clever college supported me. We found a solution:

  • Build a rotation matrix from the quaternion. Details

  • Swap row two with row three

  • Swap column two with column three

  • Calculate euler angles from this matrix.

float w = transform.rotation.w;
float x = transform.rotation.x;
float y = transform.rotation.y;
float z = transform.rotation.z;
double rmx1, rmx2, rmy, rmz1, rmz2;
float[] euler = { 0, 0, 0 };

rmx1 = 2 * y * z + 2 * x * w;
rmx2 = 1 - 2 * x * x - 2 * z * z;
rmy = 2 * x * y - 2 * z * w;
rmz1 = 2 * x * z + 2 * y * w;
rmz2 = 1 - 2 * y * y - 2 * z * z;

euler[0] = (float)Math.Atan2(-rmx1, rmx2);
euler[1] = (float)Math.Asin(rmy) ;
euler[2] = (float)Math.Atan2(-rmz1, rmz2); ;

Verbose code with plenty overhead

  float[] euler = { 0, 0, 0 };

  float w = transform.rotation.w;
  float x = transform.rotation.x;
  float y = transform.rotation.y;
  float z = transform.rotation.z;
 
  double[,] rm = new double[4, 4];  //only 1...3 are used. 0 is for temporary buffer
  rm[1, 1] = 1 - 2 * y * y - 2 * z * z;
  rm[2, 1] = 2 * x * y + 2 * z * w;
  rm[3, 1] = 2 * x * z - 2 * y * w;

  rm[1, 2] = 2 * x * y - 2 * z * w;
  rm[2, 2] = 1 - 2 * x * x - 2 * z * z;
  rm[3, 2] = 2 * y * z + 2 * x * w;

  rm[1, 3] = 2 * x * z + 2 * y * w;
  rm[2, 3] = 2 * y * z - 2 * x * w;
  rm[3, 3] = 1 - 2 * x * x - 2 * y * y;

  //swap the last two rows
  //copy second row to temporary buffer
  rm[0, 1] = rm[2, 1];
  rm[0, 2] = rm[2, 2];
  rm[0, 3] = rm[2, 3];

  //copy third row in second row
  rm[2, 1] = rm[3, 1];
  rm[2, 2] = rm[3, 2];
  rm[2, 3] = rm[3, 3];

  //write-back the third row from temporary buffer
  rm[3, 1] = rm[0, 1];
  rm[3, 2] = rm[0, 2];
  rm[3, 3] = rm[0, 3];

  //swap the last two columns
  //copy the second column to temporary buffer
  rm[1, 0] = rm[1, 2];
  rm[2, 0] = rm[2, 2];
  rm[3, 0] = rm[3, 2];

  //copy the third column in the second
  rm[1, 2] = rm[1, 3];
  rm[2, 2] = rm[2, 3];
  rm[3, 2] = rm[3, 3];

  //write-back the third column from temporary buffer
  rm[1, 3] = rm[1, 0];
  rm[2, 3] = rm[2, 0];
  rm[3, 3] = rm[3, 0];
 
  double rx = Math.Atan2(-rm[2, 3], rm[3, 3] );
  double ry = Math.Asin(rm[1,3]); 
  double rz = Math.Atan2(-rm[1, 2], rm[1, 1]);
 
  euler[0] = (float)(rx /Math.PI * 180.0);
  euler[1] = (float)(ry / Math.PI * 180.0);
  euler[2] = (float)(rz / Math.PI * 180.0);
  Debug.Log("euler X: " + (euler[0]).ToString() + " Y: " + (euler[1]) + " Z: " + (euler[2]));

  euler[0] = (float)rx;
  euler[1] = (float)ry;
  euler[2] = (float)rz;