I am sending x,y,z orientation data from a BNO055 IMU to Unity through a Serial Port. I can receive the data fine with a FixedUpdate(), however it was lagging so I decided to try a coroutine. It runs for 1 iteration and the returns:
Error!
UnityEngine.Debug:LogError(Object)
Could someone shed some light as to why this may happen? In the Serial Monitor of my Arduino, the data is being sent fine.
using System.Collections;
using System.IO.Ports;
using UnityEngine;
using System;
public class bno055_orientation : MonoBehaviour
{
float gyroX;
float gyroY;
float gyroZ;
float gyro_norm = 1.0f / 360.0f;
public float speed;
private Rigidbody rb;
public GameObject target;
Vector3 rotation;
public SerialPort stream;
public int baudrate = 115200;
public string port = "COM6";
int readTimeout = 50;
void Start()
{
Open();
StartCoroutine(AsynchronousReadFromArduino
((string s) => Debug.Log(s),// Callback
() => Debug.LogError("Error!"), // Error callback
10f // Timeout (seconds)
)
);
}
public void Open()
{
stream = new SerialPort(port, baudrate);
stream.ReadTimeout = readTimeout;
stream.Open();
}
//Action is a delegate that points to a method which in turn accepts one or more arguments but returns no value. Implements an event.
public IEnumerator AsynchronousReadFromArduino(Action<string> callback, Action fail = null, float timeout = float.PositiveInfinity)
{
DateTime initialTime = DateTime.Now;
DateTime nowTime;
TimeSpan diff = default(TimeSpan);
string dataString = null;
string[] vec3 = null;
do
{
//Single read attempt
try
{
dataString = stream.ReadLine();
vec3 = dataString.Split(',');
}
catch (TimeoutException)
{
dataString = null;
}
if ((dataString != null) & (vec3.Length == 3))
{
Debug.Log(vec3.ToString());
bool gyroXbool = float.TryParse(vec3[0], out gyroY);
bool gyroYbool = float.TryParse(vec3[1], out gyroZ);
bool gyroZbool = float.TryParse(vec3[2], out gyroX);
gyroX = (gyroX < 180) ? gyroX + 180 : gyroX;
gyroY = (gyroY < 180) ? gyroY + 180 : gyroY;
gyroX = (gyroZ < 180) ? gyroZ + 180 : gyroZ;
Debug.LogFormat("Gyro Offset: {0}, {1}, {2}", gyroX.ToString(), gyroY.ToString(), gyroZ.ToString());
if (gyroXbool && gyroYbool && gyroZbool)
{
target.transform.rotation = Quaternion.Euler(gyroX, gyroY, gyroZ);
};
callback(dataString);
yield return null; //It will run first on call fo the StartCoroutine until a yield is hit.
//Then it will return from the coroutine and place it onto a stack based on the yield.
//If null, then it will run again next frame. Some coroutine may WaitForEndOfFrame if they need to perform action at that specific moment.
}
else
yield return new WaitForSeconds(10f);
nowTime = DateTime.Now;
diff = nowTime - initialTime;
} while (diff.Milliseconds < timeout);
if (fail != null)
fail();
yield return null;
}
public void Close()
{
stream.Close();
}
}