I'm working on a simple (I thought) OpenVR driver that sends the compositors output to my android phone to display with google cardboard. I've got the basics working but when my driver receives the rotation data from my android device it's very noisy and with my phone sat still on my desk it jitters loads.
the floats are being sent over in network byte order.
Here is the code receiving the rotation data:
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);
}
}
And the code sending it from the 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();
}
}
Thanks in advance
For future reference I was doing two things wrong:
After changing these two things it all worked perfectly.