Home > Net >  How do I flip two axes of a quaternion from IMU?
How do I flip two axes of a quaternion from IMU?

Time:02-02

I want to use a smart Rubik's Cube (GoCube) to control a 3D object in Unity, it has IMU and a Unity plugin is also available. Currently I'm trying to implement the basic logic to orient the 3D object the way the cube is oriented with IMU data, meaning the 3D object should follow the cube's rotations. For this, I tried to copy relevant elements from the original plugin.

Unfortunately, I cannot get the orientation quaternions to behave the right way: Rotating the cube on the X- and Z-axes results in a mirrored result, as I demonstrate in the GIF. What works is the rotation around the Y-axis.

Demo of quaternion rotations

Without the smart cube, there's obviously no working example, so I copied that part of the code I'm using to orient the 3D object:

public GameObject objectToBeSynchronised;
public Quaternion fixedOffset = Quaternion.Euler(90, 90, 0);

void Update()
{
    objectToBeSynchronised.transform.rotation = GetCurrentOrientation(); // live-rotate object
}

/// <summary>
/// Function to get current cube orientation as quaternion
/// </summary>
/// <returns>cube orientation as quaternion</returns>
public Quaternion GetCurrentOrientation()
{
    Quat q = GoCubeProvider.GetProvider().GetConnectedGoCube().orientation;
    Quaternion currentOrientation = new Quaternion();
    currentOrientation = ConvertQuatToQuaternion(q) * fixedOffset; // convert from type Particula.Quat to Quaternion and multiply fixed offset from Particula

    return currentOrientation;
}

/// <summary>
/// Function to convert quaternion from Particula.Quat to Quaternion type
/// </summary>
/// <param name="quat">quaternion type Particula.Quat from cube orientation</param>
/// <returns>converted Quaternion</returns>
Quaternion ConvertQuatToQuaternion(Quat quat)
{
    return new Quaternion(quat.x, quat.y, quat.z, quat.w);
}

The fixedOffset and ConvertQuatToQuaternion() are parts I imitated from the original plugin, the relevant file is CubeViewModel.cs. fixedOffset makes the 3D object stand upright and not lie on the side. Maybe I'm missing part of the original script to make it work - file CubeView.cs could also be interesting.

After reading answers such as here, here and here I played around with the ConvertQuatToQuaternion function - I tried switching the values to e.g. (w, x, y, z) or added minus (-x, y, -z, w) and a lot of other combinations. None made it right. Also tried Quaternion.Inverse on the converted quaternion - no success.

I don't have much knowledge about, let alone experience with quaternions and am a bit lost. I was expecting negating x and z to work, since those are the axes that are flipped. However, there seems to be more to this, maybe or probably I'm missing a step from the original plugin.

CodePudding user response:

Try converting the quaternion into Unity's left handed coordinate system. The correct conversion is as follows:

Original quaternion:

q = w   xi   yj   zk

Transformed into opposite coordinate system:

q = w - xi - yj - zk

Since Unity constructs quaternion in this manner:

Quaternion q = new Quaternion(x, y, z, w)

the transformed Quaternion can be constructed as follows:

Quaternion qTrans = new Quaternion(-q.x, -q.y, -q.z, q.w)

CodePudding user response:

For anyone planning on developing with the GoCube and their API: I found a solution! I changed nothing about my code sample except the fixedOffset. I now set it to Quaternion.Euler(225, 225, 0) instead of Quaternion.Euler(90, 90, 0) and this seems to do the job! Hope this might help anyone struggling with the same GoCube-Unity implementation.

  • Related