# Convert quaternion into values to rotate a cube (eulers?)

Hi,

I’m testing some stuff with a inertial measuring unit (IMU) to capture motion and send it to unity3d.
Now the sensor sends over the rotation information as a quaternion.

At least thats what they call it. Its actually 4 floats

Can I somehow convert this to for example euler angles to apply them on the transform of a cube and visualize the capture?

I don’t seem to find what to do with my 4 float values to get usefull data for rotating.

Kind regards,

Bart

Quaternion.eulerAngles…

Hi, thanks,

I have created a quaternion variable rot and assigned the following variables to it.

X: 3.447687e-24
Y: 2.267136e-26
Z: 1.11063e+22
W: 4.661048e+14

Somehow the quaternion object seems to accept these values, since they appear in the inspector,

But if I now try to do

myGameObject.rotation=rot;

then I get following message

Quaternion To Matrix conversion failed because input Quaternion is invalid {0.000000, 0.000000, 0.000000, 0.000000} l=0.000000

and the rotation is not set on the gameobject. Any idea what I could do wrong ?
The quaternion values come directly from the IMU device.

Kind regards,

Bart

Taken from RobotDuck. You can find his complete explanation here:Quick Tip : How to choose which way to turn? | robotduck

Dear Juanelo, thank you for the reply but I don’t get how your info should solve my problem (or I’m to dumb to understand, thats also possible).

As far as I can guess, it looks like the quaternion data should be normalized somehow before unity will accept it. Any idea how I could to that ?

Or is the stuff you described above a trick to get the quaternion in a normalized state?

Kind regards,

Bart

Basic code…

``````Quaternion x=Quaternion.Euler(0,30,0);
Debug.Log(x);
Debug.Log(x.eulerAngles.y);
``````

Woops,

Reading your post, I am not sure you can have quaternion values above 1.

Maybe I should do it another way, since I don’t think I expressed myself 100% clearly,

This is my code (abbreviated)

``````public Quaternion rot=Quaternion.identity;

rot.x=getImuX();
rot.y=getImuY();
rot.z=getImuZ();
rot.w=getImuW();

//Important place here

myGameObjectTransform.rotation=rot;
``````

So in this code it gets 4 float values from my IMU unit.
On the line marked “Important place here”, the x,y,z,w properties of the Quaternion contain

x: 3.447687e-24
y: 2.267136e-26
z: 1.11063e+22
w: 4.661048e+14

And I get that error, because I think these values are not normalised ?

If I change my code to

``````public Quaternion rot=Quaternion.identity;

rot.x=0;
rot.y=0;
rot.z=0;
rot.w=0;

//Important place here

myGameObjectTransform.rotation=rot;
``````

then this executes without the message that conversion fails, but having all values at 0 is pretty useless of course.

So I was wondering if I have to do something else to have these values (which may indeed have some rounding error because it was transferred as floats from the electronics hardware) accepted by the quaternion as valid values?

Hi Educa,
The linked article explains how to avoid dealing directly with Quaternions by converting them to Euler Angles or Vectors instead. In theory, using vectors, you should be able to apply the rotations that you’d like more simply. If you convert two Quaternion rotations to vectors, you can subtract them from one another to get the delta angle, and use that to drive your rotations. Although, it seems that you’re trying to import rotation data directly, rather than figure out interpolations between different angles, right? Maybe my post was somewhat off subject. In that case sorry for the misunderstanding.

Anyhow, I hope the article comes in handy.
Best regards,
-Juan

First, try clamping the values between -1 and 1. This probably is not going to solve your problem. You need to get ahold of the documentation for the device and figure out exactly what those numbers mean. Quaternions are generally -1 to 1 numbers so 4.661048e+14 is really 466104800000000

As noted above, the first step is probably to determine exactly what the input data represents. (Your ‘z’ and ‘w’ values are very large, which suggests that the input data does not represent a quaternion.)

Well they do represent a quaternion, but…

I get these quaternions as a string with hex values in

Like

AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD

This represents 4 32-bits float values and I am actually looking for a wat to convert these to 4 floats.

I don’t find however how I can convert for example 654AF10C to its corresponding float value. 654AF10C is in a stringvariable.

I tried making my own conversion but it looks like there something goes wrong.

Anyone have an idea if its possible with some function call to convert a string containing a hex representation to its corresponding float?

Kind regards,

Bart

What format are the values supposed to be in? Is it a fixed-point format of some sort? Or is it supposed to be the bit pattern for an IEEE 754 representation?

(Also, maybe you could post your conversion function.)

1 float comes to me as a string of 8 characters.

Each character can be converted to 4 bits and concatenated to create 1 bit list of 32 bits

Then I extract sign, exponent and the 3rd part from these bits, but I think I don’t do conversion ok there since I only check (I think) for normilised values.

Is there any possibility to do this with PROVEN functions?

The 32 bits I get present a IEEE 754 format 32bits float.

Cannot post my code now since I’m not at that correct pc for the moment.

This is the code I use to convert
It can still be optimised, but first it has to work.

``````private string HexToBin(string hexVal)
{
if (hexVal=="0") return ("0000");
else if (hexVal=="1") return ("0001");
else if (hexVal=="2") return ("0010");
else if (hexVal=="3") return ("0011");
else if (hexVal=="4") return ("0100");
else if (hexVal=="5") return ("0101");
else if (hexVal=="6") return ("0110");
else if (hexVal=="7") return ("0111");
else if (hexVal=="8") return ("1000");
else if (hexVal=="9") return ("1001");
else if (hexVal=="A") return ("1010");
else if (hexVal=="B") return ("1011");
else if (hexVal=="C") return ("1100");
else if (hexVal=="D") return ("1101");
else if (hexVal=="E") return ("1110");
else if (hexVal=="F") return ("1111");
else return ("0000");
}

private float HexToFloat(string hexWaarde)
{
byte[] bins= new byte[32];
string binair=HexToBin(hexWaarde.Substring(0,1))+HexToBin(hexWaarde.Substring(1,1))+HexToBin(hexWaarde.Substring(2,1))+HexToBin(hexWaarde.Substring(3,1))+HexToBin(hexWaarde.Substring(4,1))+HexToBin(hexWaarde.Substring(5,1))+HexToBin(hexWaarde.Substring(6,1))+HexToBin(hexWaarde.Substring(7,1));

bins[31]=Convert.ToByte(binair.Substring(0,1));
bins[30]=Convert.ToByte(binair.Substring(1,1));
bins[29]=Convert.ToByte(binair.Substring(2,1));
bins[28]=Convert.ToByte(binair.Substring(3,1));
bins[27]=Convert.ToByte(binair.Substring(4,1));
bins[26]=Convert.ToByte(binair.Substring(5,1));
bins[25]=Convert.ToByte(binair.Substring(6,1));
bins[24]=Convert.ToByte(binair.Substring(7,1));
bins[23]=Convert.ToByte(binair.Substring(8,1));
bins[22]=Convert.ToByte(binair.Substring(9,1));
bins[21]=Convert.ToByte(binair.Substring(10,1));
bins[20]=Convert.ToByte(binair.Substring(11,1));
bins[19]=Convert.ToByte(binair.Substring(12,1));
bins[18]=Convert.ToByte(binair.Substring(13,1));
bins[17]=Convert.ToByte(binair.Substring(14,1));
bins[16]=Convert.ToByte(binair.Substring(15,1));
bins[15]=Convert.ToByte(binair.Substring(16,1));
bins[14]=Convert.ToByte(binair.Substring(17,1));
bins[13]=Convert.ToByte(binair.Substring(18,1));
bins[12]=Convert.ToByte(binair.Substring(19,1));
bins[11]=Convert.ToByte(binair.Substring(20,1));
bins[10]=Convert.ToByte(binair.Substring(21,1));
bins[09]=Convert.ToByte(binair.Substring(22,1));
bins[08]=Convert.ToByte(binair.Substring(23,1));
bins[07]=Convert.ToByte(binair.Substring(24,1));
bins[06]=Convert.ToByte(binair.Substring(25,1));
bins[05]=Convert.ToByte(binair.Substring(26,1));
bins[04]=Convert.ToByte(binair.Substring(27,1));
bins[03]=Convert.ToByte(binair.Substring(28,1));
bins[02]=Convert.ToByte(binair.Substring(29,1));
bins[01]=Convert.ToByte(binair.Substring(30,1));
bins[00]=Convert.ToByte(binair.Substring(31,1));

int exponent=(bins[30]*128+	bins[29]*64+bins[28]*32+bins[27]*16+bins[26]*8+bins[25]*4+bins[24]*2+bins[23])-127;

float significand=(float)(1+bins[22]*Math.Pow(2,-1)+bins[21]*Math.Pow(2,-2)+bins[20]*Math.Pow(2,-3)+bins[19]*Math.Pow(2,-4)+bins[18]*Math.Pow(2,-5)+bins[17]*Math.Pow(2,-6)+bins[16]*Math.Pow(2,-7)+bins[15]*Math.Pow(2,-8)+bins[14]*Math.Pow(2,-9)+bins[13]*Math.Pow(2,-10)+bins[12]*Math.Pow(2,-11)+bins[11]*Math.Pow(2,-12)+bins[10]*Math.Pow(2,-13)+bins[09]*Math.Pow(2,-14)+bins[08]*Math.Pow(2,-15)+bins[07]*Math.Pow(2,-16)+bins[06]*Math.Pow(2,-17)+bins[05]*Math.Pow(2,-18)+bins[04]*Math.Pow(2,-19)+bins[03]*Math.Pow(2,-20)+bins[02]*Math.Pow(2,-21)+bins[01]*Math.Pow(2,-22)+bins[00]*Math.Pow(2,-24));

if (bins[31]==1) return (float) (-1*significand * Math.Pow(2,exponent));
else return (float) (-1*significand * Math.Pow(2,exponent));
}
``````

Normally you would use the BitConverter class to do such conversions (BitConverter Class (System) | Microsoft Learn). However, your input seems to use a very obscure float representation. I would expect a float to be represented with 4 bytes (4 characters of 8 bit). Using 8 characters and then only 4 bytes per char seems like a rather odd way to waste space. Are you sure you are interpreting the float data correctly?

Tom, each 2 characters in the hexadecimal string is 1 byte

Like if the Hexadecimal string would be “AABBCCDD” then AA means binary 10101010 or decimal 170

So these 8 characters do realy five me 4 bytes values

Could you explain where to go to when I have 4 bytes ?

Ah, i get it now. You were talking character as in a character from a hexadecimal representation, not the classical character as a 1 byte char :P.

You could convert your hex-strings to arrays of 4 byte (each pair of hex characters being one byte. Then use BitConverter.ToSingle (BitConverter.ToSingle Method (System) | Microsoft Learn) to convert the array to a float. This should work as long as your program that generates the hexadecimal strings uses the same bit-representation for floats as used in Mono.