Java 自定义OpenVR驱动程序,带有抖动的android旋转

Java 自定义OpenVR驱动程序,带有抖动的android旋转,java,android,c++,openvr,Java,Android,C++,Openvr,我正在开发一个简单(我认为)的OpenVR驱动程序,它将合成器输出发送到我的android手机,并用谷歌硬纸板显示。我已经有了基本的工作,但当我的驱动程序从我的android设备接收到旋转数据时,它非常嘈杂,而且我的手机静止在桌子上,它会抖动 浮点数按网络字节顺序发送 以下是接收旋转数据的代码: float BytesToFloat(unsigned char* buffer, int start) { float f = (buffer[start] << 24) | (b

我正在开发一个简单(我认为)的OpenVR驱动程序,它将合成器输出发送到我的android手机,并用谷歌硬纸板显示。我已经有了基本的工作,但当我的驱动程序从我的android设备接收到旋转数据时,它非常嘈杂,而且我的手机静止在桌子上,它会抖动

浮点数按网络字节顺序发送

以下是接收旋转数据的代码:

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(&currentPose);
    }


}
float-BytesToFloat(无符号字符*缓冲区,int-start)
{

float f=(buffer[start]作为将来的参考,我做错了两件事:

  • 我以网络字节顺序发送浮点,而不是在本地机器上将其重新排列为本机字节顺序
  • 位移位似乎对浮点不起作用,所以我改用了memset
  • 在改变了这两件事之后,一切都很完美

    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();
            }
        }