1

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.

laury
  • 11
  • 7
  • Just a guess, this sounds like an issue about Unity's left-handed coordinate system vs your tracker providing the values in right-handed space => see e.g. [here](https://stackoverflow.com/questions/28673777/convert-quaternion-from-right-handed-to-left-handed-coordinate-system) and try `new Quaternion(quad.x, -quad.y, -quad.w, -quad.z);` and also [this](https://stackoverflow.com/questions/1274936/flipping-a-quaternion-from-right-to-left-handed-coordinates) and [this](https://stackoverflow.com/questions/1263072/changing-a-matrix-from-right-handed-to-left-handed-coordinate-system) similar posts – derHugo Feb 01 '23 at 12:00
  • Yes, I suspected that, too @derHugo -however, I couldn't find anything about switching the coordinate system in the original plugin. I tried your suggested quaternion, it resulted in even worse axes confusion: cube Y rotation leads to 3d object X rotation, cube Z rotation -> 3d object Y rotation and cube x rotation -> 3d object z rotation. So this mixes things up A LOT. :( – laury Feb 01 '23 at 12:31

2 Answers2

0

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. As suggested in the Unity Docs, I declared it as public static Quaternion fixedOffset = Quaternion.Euler(90, 90, 0) instead of just public and this seems to do the job! For some reason, the Inspector was messing with things. Don't know, why the original plugin didn't declare it as static. Hope this might help anyone struggling with the same GoCube-Unity implementation.

laury
  • 11
  • 7
-1

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)
anjelomerte
  • 286
  • 1
  • 9
  • 1
    Thank you for your suggestion! Unfortunately, this gives me exactly the same result as the suggested solution by @derHugo: cube Y rotation leads to 3d object X rotation, cube Z rotation -> 3d object Y rotation and cube x rotation -> 3d object z rotation However, I found my own solution! Will post it for anyone developing with the GoCube IMU. – laury Feb 01 '23 at 14:45
  • Ok glad to hear you solved your problem:) – anjelomerte Feb 01 '23 at 15:11