Hello everyone. I’m having a problem with quaternions in my code. I’m using a YEI 3 Space Embedded for head tracking. I’ve found a code here on UnityAnswers for using this device and adapted for what I need.
Problem is: the axes are wrong. For example, when it should rotate around X it rotates around Z and I don’t know how to correct this. Everything I’ve tried until now has failed.
Can anyone help me?
My code is:
using UnityEngine;
using System;
using System.Collections;
using System.IO.Ports;
using System.Management;
public class YEIHeadTracking : MonoBehaviour{
public static SerialPort sp = new SerialPort("COM3");
// Command packet for getting the filtered tared orientation as a quaternion
// {header byte, command byte, [data bytes], checksum byte}
// checksum = (command byte + data bytes) % 256
public static byte[] send_bytes = {0xf7, 0x00, 0x00};
public static byte[] button_bytes = {0xf7, 0xfa, 0xfa};
public static byte[] tare_bytes = {0xf7, 0x60, 0x60};
public int counter = 0;
// Use this for initialization
void Start(){
sp.BaudRate = 115200;
sp.Parity = Parity.None;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
sp.WriteTimeout = 100;
sp.ReadTimeout = 100;
sp.Open();
sp.Write(send_bytes,0,3);
}
// Helper function for taking the bytes read from the 3-Space Sensor and converting them into a float
float bytesToFloat(byte[] raw_bytes, int offset){
byte[] big_bytes = new byte[4];
big_bytes[0] = raw_bytes[offset+3];
big_bytes[1] = raw_bytes[offset+2];
big_bytes[2] = raw_bytes[offset+1];
big_bytes[3] = raw_bytes[offset+0];
return BitConverter.ToSingle(big_bytes,0);
}
// Update is called once per frame
void Update(){
counter++;
// A quaternion consists of 4 floats which is 16 bytes
byte[] read_bytes = new byte[16];
// Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
// through to make sure the bytes are read and Mono also seems not to always read the amount asked
// so we must also read one byte at a time
int read_counter = 100;
int byte_idx = 0;
while (read_counter > 0){
try{
byte_idx += sp.Read(read_bytes, byte_idx, 1);
}
catch{
// Failed to read from serial port
}
if (byte_idx == 16){
break;
}
if (read_counter <= 0){
throw new System.Exception("Failed to read quaternion from port too many times." +
" This could mean the port is not open or the Mono serial read is not responding.");
}
--read_counter;
}
// Convert bytes to floats
float x = bytesToFloat(read_bytes,0);
float y = bytesToFloat(read_bytes,4);
float z = bytesToFloat(read_bytes,8);
float w = bytesToFloat(read_bytes,12);
//Quaternion rotateX = Quaternion.AngleAxis(-x, Vector3.left);
//Quaternion rotateY = Quaternion.AngleAxis(-y, Vector3.up);
//Quaternion rotateZ = Quaternion.AngleAxis(z, Vector3.forward);
// Create a quaternion
Quaternion quat = new Quaternion(x,y,z,w);
// Perform rotation
Camera.main.transform.rotation = quat;
//Camera.main.transform.rotation = rotateY * rotateX * rotateZ;
sp.Write(send_bytes,0,3);
}
}