自定义 OpenVR 驱动程序,抖动 android 旋转
Custom OpenVR driver, with jittery android rotation
我正在开发一个简单的(我认为)OpenVR 驱动程序,它将合成器输出发送到我的 android phone 以使用 google 纸板显示。我已经掌握了基础知识,但是当我的驱动程序从我的 android 设备接收到旋转数据时,它非常嘈杂,而且我的 phone 仍然坐在我的桌子上,它会抖动负载。
浮点数按网络字节顺序发送。
接收旋转数据的代码如下:
float BytesToFloat(unsigned char* buffer, int start)
{
float f = (buffer[start] << 24) | (buffer[start + 1] << 16) | (buffer[start + 2] << 8) | buffer[start + 3];
return f;
}
void MobileDeviceReceiver::PoseThread(std::function<void(MobileVector*)> PoseUpdateCallback)
{
sockaddr_in client;
int inLen,clientStructLen = sizeof(client);
MobileVector currentPose;
DriverLog("started pose tracking thread %d\n",m_isActive);
bool errorLastCall = false;
char pchBuffer[65535];
while (m_isActive)
{
if ((inLen = recvfrom(m_socket, pchBuffer, 65535, 0, (sockaddr*)&client, &clientStructLen)) == SOCKET_ERROR)
{
if (errorLastCall == false)
{
DriverLog("Error receiving data: %d\n", WSAGetLastError());
}
errorLastCall = true;
}
else {
errorLastCall = false;
}
currentPose.x = floorf(BytesToFloat((unsigned char*)pchBuffer, 0)*10000)/10000;
currentPose.y = 0;//BytesToFloat((unsigned char*)pchBuffer, 4);
currentPose.z = 0;//BytesToFloat((unsigned char*)pchBuffer, 8);
PoseUpdateCallback(¤tPose);
}
}
以及从 phone 发送的代码:
class Task implements Runnable
{
public Queue<DatagramPacket> packets = new LinkedList<DatagramPacket>();
private boolean isActive = true;
@Override
public void run() {
try{
DatagramSocket socket = new DatagramSocket();
while(isActive)
{
if(packets.size() > 0)
{
socket.send(packets.remove());
}
}
}catch(Exception e)
{
e.printStackTrace();
}
}
public void Kill()
{
isActive = false;
}
}
ByteBuffer buffer = ByteBuffer.allocate(12);
protected float ALPHA = 0.05f;
private float[] lowPassFilter(float[] input,float[] output)
{
if(output == null) return input;
for ( int i=0; i<input.length; i++ ) {
output[i] = output[i] + ALPHA * (input[i] - output[i]);
}
return output;
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(sensorEvent.sensor == sRotation)
{
float x,y,z;
x = (float) Math.toRadians(sensorEvent.values[0]);
y = (float) Math.toRadians(sensorEvent.values[1]);
z = (float) Math.toRadians(sensorEvent.values[2]);
float[] values = lowPassFilter(new float[]{x,y,z},new float[3]);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putFloat(values[0]);
buffer.putFloat(values[1]);
buffer.putFloat(values[2]);
try {
DatagramPacket packet = new DatagramPacket(buffer.array(), 12, InetAddress.getByName(IP), 8888);
if(task != null) {
task.packets.add(packet);
}
}catch(Exception e)
{
e.printStackTrace();
}
buffer.clear();
}
}
提前致谢
为了将来参考,我做错了两件事:
- 我在网络字节顺序中发送浮点数,而不是在本地机器上将其重新排列为本机字节顺序。
- 位移位似乎不适用于浮点数,所以我改用 memset。
改变这两个东西后一切正常。
我正在开发一个简单的(我认为)OpenVR 驱动程序,它将合成器输出发送到我的 android phone 以使用 google 纸板显示。我已经掌握了基础知识,但是当我的驱动程序从我的 android 设备接收到旋转数据时,它非常嘈杂,而且我的 phone 仍然坐在我的桌子上,它会抖动负载。
浮点数按网络字节顺序发送。
接收旋转数据的代码如下:
float BytesToFloat(unsigned char* buffer, int start)
{
float f = (buffer[start] << 24) | (buffer[start + 1] << 16) | (buffer[start + 2] << 8) | buffer[start + 3];
return f;
}
void MobileDeviceReceiver::PoseThread(std::function<void(MobileVector*)> PoseUpdateCallback)
{
sockaddr_in client;
int inLen,clientStructLen = sizeof(client);
MobileVector currentPose;
DriverLog("started pose tracking thread %d\n",m_isActive);
bool errorLastCall = false;
char pchBuffer[65535];
while (m_isActive)
{
if ((inLen = recvfrom(m_socket, pchBuffer, 65535, 0, (sockaddr*)&client, &clientStructLen)) == SOCKET_ERROR)
{
if (errorLastCall == false)
{
DriverLog("Error receiving data: %d\n", WSAGetLastError());
}
errorLastCall = true;
}
else {
errorLastCall = false;
}
currentPose.x = floorf(BytesToFloat((unsigned char*)pchBuffer, 0)*10000)/10000;
currentPose.y = 0;//BytesToFloat((unsigned char*)pchBuffer, 4);
currentPose.z = 0;//BytesToFloat((unsigned char*)pchBuffer, 8);
PoseUpdateCallback(¤tPose);
}
}
以及从 phone 发送的代码:
class Task implements Runnable
{
public Queue<DatagramPacket> packets = new LinkedList<DatagramPacket>();
private boolean isActive = true;
@Override
public void run() {
try{
DatagramSocket socket = new DatagramSocket();
while(isActive)
{
if(packets.size() > 0)
{
socket.send(packets.remove());
}
}
}catch(Exception e)
{
e.printStackTrace();
}
}
public void Kill()
{
isActive = false;
}
}
ByteBuffer buffer = ByteBuffer.allocate(12);
protected float ALPHA = 0.05f;
private float[] lowPassFilter(float[] input,float[] output)
{
if(output == null) return input;
for ( int i=0; i<input.length; i++ ) {
output[i] = output[i] + ALPHA * (input[i] - output[i]);
}
return output;
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(sensorEvent.sensor == sRotation)
{
float x,y,z;
x = (float) Math.toRadians(sensorEvent.values[0]);
y = (float) Math.toRadians(sensorEvent.values[1]);
z = (float) Math.toRadians(sensorEvent.values[2]);
float[] values = lowPassFilter(new float[]{x,y,z},new float[3]);
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putFloat(values[0]);
buffer.putFloat(values[1]);
buffer.putFloat(values[2]);
try {
DatagramPacket packet = new DatagramPacket(buffer.array(), 12, InetAddress.getByName(IP), 8888);
if(task != null) {
task.packets.add(packet);
}
}catch(Exception e)
{
e.printStackTrace();
}
buffer.clear();
}
}
提前致谢
为了将来参考,我做错了两件事:
- 我在网络字节顺序中发送浮点数,而不是在本地机器上将其重新排列为本机字节顺序。
- 位移位似乎不适用于浮点数,所以我改用 memset。
改变这两个东西后一切正常。