c# - 使用 Vive (SteamVR) 从串行端口读取导致巨大延迟
问题描述
我正在使用最新的SteamVR 插件 (V 2.3.0)在 HTC Vive 中开发叉车模拟。我想在 sim中添加一个定制的方向盘,它根据它的旋转给出值。我已经使用 Vive 控制器和键盘实现了模拟控制。但是自从我添加串行连接读取代码的那一刻起,模拟就开始滞后了。15-20 fps 是我从串口读取得到的。
void Awake ()
{
InitializeCOMport();
StartCoroutine(ReadData());
}
void InitializeCOMport()
{
port = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
try
{
port.Open();
System.Threading.Thread.Sleep(1000);
port.Handshake = Handshake.None;
Debug.Log("Port open");
}
catch (Exception ex)
{
Debug.Log("Exception " + ex.Message);
}
}
IEnumerator ReadData()
{
yield return null;
do
{
yield return new WaitForSeconds(0.15f);
try
{
datareceived = port.ReadLine().Trim();
char[] charsToTrim = { 'd', 'a', 't', ' ', '=' };
datareceived = datareceived.Trim(charsToTrim);
//Debug.Log("Steering port: " + datareceived);
currSteeringValue = int.Parse(datareceived);
}
catch(System.Exception ex)
{
Debug.Log("Exception " + ex.Message);
}
} while (true);
}
我必须以这种方式读取串行端口数据,因为当我尝试使用 SerialPort.DataReceived
事件执行此操作时,会出现超时异常。使用上面的 Coroutine ReadData() 我可以获取 COMM 端口数据,但不能使用 DataRecieved 事件。这是使用事件读取缓冲区的代码-
port.DataReceived += new SerialDataReceivedEventHandler(Port_DataReceived);
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Debug.Log("received"); //This function is fired with
try
{
datareceived = port.ReadLine().Trim();
char[] charsToTrim = { 'd', 'a', 't', ' ', '=' };
datareceived = datareceived.Trim(charsToTrim);
Debug.Log("Steering port: " + datareceived);
currSteeringValue = int.Parse(datareceived);
}
catch (System.Exception ex)
{
Debug.Log("Exception " + ex.Message);
}
Debug.Log("received");
}
上面的 Port_DataReceived() 导致超时异常,并且控件永远不会到达Debug.Log("Steering port: " + datareceived);
这一点,因为它没有被记录。
这是因为我在 vive 上使用串行端口吗?有谁知道我该如何解决这个问题?
更新:实际上我也尝试过使用线程,但它也导致超时异常。这是线程函数的代码,这里的控件也没有到达 Debug.Log(steering) 行,并且存在超时异常。
serialThread = new System.Threading.Thread(RecordData);
serialThread.Start();
void RecordData()
{
while (true)
{
try
{
Debug.Log("Trying to read data");
datareceived = port.ReadLine().Trim();
//Debug.Log(datareceived);
char[] charsToTrim = { 'd', 'a', 't', ' ', '=' };
datareceived = datareceived.Trim(charsToTrim);
Debug.Log("Steering port: " + datareceived);
currSteeringValue = int.Parse(datareceived);
System.Threading.Thread.Sleep(10);
}
catch (System.Exception ex)
{
Debug.Log("Exception " + ex.Message);
}
}
}
解决方案
不幸的是,DataReceived 回调没有在 Mono 中实现,它根本不起作用,并且默认的池方法确实阻塞了线程。解决方案是启动另一个线程仅用于 com 端口处理。
推荐阅读
- jquery - 如何将 jQuery 与 amp-script 一起使用?
- spring-boot - 领导者选举与领导者闩锁
- r - 向 geom_density_ridges 添加手段
- php - 如何在 Typo3 的控制器中访问前端上传的文件?
- javascript - 如何创建 ref 来调用功能组合的函数?
- python - Python3转换字节串
- c# - 如何在 C# 中解析 JSON 并仅找到某些部分
- kubernetes - "" 无效: : 正文中的 spec.template.spec.volumes.userData 是一个被禁止的属性
- regex - 为什么“f”在 Bash 正则表达式中匹配 c*?
- android - 如何创建更轻量级的片段?