In case anyone comes across this, here is how I solved it (for my needs at least).
This solution requires the target object have an parent GameObject (child position offset 0,0,0). Both must be specified as parameters to the script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
public class playerController : MonoBehaviour {
public string COMPort = "COM3";
public int baudRate = 115200;
//rotate input - X by 90, Y by 90
private Quaternion offset = new Quaternion();
public Vector3 offsetEuler = new Vector3(90, 90, 0);
public Transform target;
public Transform targetParent;
public bool calibrate = true;
private Quaternion calibrationAngle = new Quaternion();
public bool reverse = false;
SerialPort stream;
void Start () {
stream = new SerialPort(COMPort, baudRate); //Set the port and the baud rate
stream.Open();
// Set the offset
offset = Quaternion.Euler(offsetEuler);
}
private void Update()
{
Quaternion rawInput;
string value = stream.ReadLine(); //Read the information
string[] vec3 = value.Split(','); //Arduino returns a Quaternion, note however the order is different to Unity
if (vec3[0] != "" && vec3[1] != "" && vec3[2] != "" && vec3[3] != "") //Check if all values are recieved
{
rawInput = new Quaternion(float.Parse(vec3[1]), float.Parse(vec3[2]), float.Parse(vec3[3]), float.Parse(vec3[0]));
if (calibrate)
{
// resets the child oritentation so that it remains consistent with world
// needs to be sampled prior to setting parent and set afterwards.
// this could be probably be done cleaner in the Start function
calibrationAngle = target.transform.rotation ;
calibrate = false;
targetParent.transform.rotation = offset * rawInput;
target.transform.rotation = calibrationAngle;
}
targetParent.transform.rotation = offset * rawInput;
}
}
}