//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.google.vrtoolkit.cardboard.sensors;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.opengl.Matrix;
import android.view.Display;
import android.view.WindowManager;
import com.google.vrtoolkit.cardboard.sensors.internal.GyroscopeBiasEstimator;
import com.google.vrtoolkit.cardboard.sensors.internal.Matrix3x3d;
import com.google.vrtoolkit.cardboard.sensors.internal.OrientationEKF;
import com.google.vrtoolkit.cardboard.sensors.internal.Vector3d;
import java.util.concurrent.TimeUnit;
public class HeadTracker implements SensorEventListener {
private static final float DEFAULT_NECK_HORIZONTAL_OFFSET = 0.08F;
private static final float DEFAULT_NECK_VERTICAL_OFFSET = 0.075F;
private static final float DEFAULT_NECK_MODEL_FACTOR = 1.0F;
private static final float PREDICTION_TIME_IN_SECONDS = 0.058F;
private final Display display;
private final float[] ekfToHeadTracker = new float[16];
private final float[] sensorToDisplay = new float[16];
private float displayRotation = -1.0F;
private final float[] neckModelTranslation = new float[16];
private final float[] tmpHeadView = new float[16];
private final float[] tmpHeadView2 = new float[16];
private float neckModelFactor = 1.0F;
private final Object neckModelFactorMutex = new Object();
private volatile boolean tracking;
private final OrientationEKF tracker;
private final Object gyroBiasEstimatorMutex = new Object();
private GyroscopeBiasEstimator gyroBiasEstimator;
private SensorEventProvider sensorEventProvider;
private Clock clock;
private long latestGyroEventClockTimeNs;
private volatile boolean firstGyroValue = true;
private float[] initialSystemGyroBias = new float[3];
private final Vector3d gyroBias = new Vector3d();
private final Vector3d latestGyro = new Vector3d();
private final Vector3d latestAcc = new Vector3d();
public static HeadTracker createFromContext(Context context) {
SensorManager sensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
return new HeadTracker(new DeviceSensorLooper(sensorManager), new SystemClock(), display);
}
public HeadTracker(SensorEventProvider sensorEventProvider, Clock clock, Display display) {
this.clock = clock;
this.sensorEventProvider = sensorEventProvider;
this.tracker = new OrientationEKF();
this.display = display;
this.setGyroBiasEstimationEnabled(true);
Matrix.setIdentityM(this.neckModelTranslation, 0);
}
public void onSensorChanged(SensorEvent event) {
Object var2;
if(event.sensor.getType() == 1) {
this.latestAcc.set((double)event.values[0], (double)event.values[1], (double)event.values[2]);
this.tracker.processAcc(this.latestAcc, event.timestamp);
var2 = this.gyroBiasEstimatorMutex;
synchronized(this.gyroBiasEstimatorMutex) {
if(this.gyroBiasEstimator != null) {
this.gyroBiasEstimator.processAccelerometer(this.latestAcc, event.timestamp);
}
}
} else if(event.sensor.getType() == 4 || event.sensor.getType() == 16) {
this.latestGyroEventClockTimeNs = this.clock.nanoTime();
if(event.sensor.getType() == 16) {
if(this.firstGyroValue && event.values.length == 6) {
this.initialSystemGyroBias[0] = event.values[3];
this.initialSystemGyroBias[1] = event.values[4];
this.initialSystemGyroBias[2] = event.values[5];
}
this.latestGyro.set((double)(event.values[0] - this.initialSystemGyroBias[0]), (double)(event.values[1] - this.initialSystemGyroBias[1]), (double)(event.values[2] - this.initialSystemGyroBias[2]));
} else {
this.latestGyro.set((double)event.values[0], (double)event.values[1], (double)event.values[2]);
}
this.firstGyroValue = false;
var2 = this.gyroBiasEstimatorMutex;
synchronized(this.gyroBiasEstimatorMutex) {
if(this.gyroBiasEstimator != null) {
this.gyroBiasEstimator.processGyroscope(this.latestGyro, event.timestamp);
this.gyroBiasEstimator.getGyroBias(this.gyroBias);
Vector3d.sub(this.latestGyro, this.gyroBias, this.latestGyro);
}
}
this.tracker.processGyro(this.latestGyro, event.timestamp);
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void startTracking() {
if(!this.tracking) {
this.tracker.reset();
Object var1 = this.gyroBiasEstimatorMutex;
synchronized(this.gyroBiasEstimatorMutex) {
if(this.gyroBiasEstimator != null) {
this.gyroBiasEstimator.reset();
}
}
this.firstGyroValue = true;
this.sensorEventProvider.registerListener(this);
this.sensorEventProvider.start();
this.tracking = true;
}
}
public void resetTracker() {
this.tracker.reset();
}
public void stopTracking() {
if(this.tracking) {
this.sensorEventProvider.unregisterListener(this);
this.sensorEventProvider.stop();
this.tracking = false;
}
}
public void setNeckModelEnabled(boolean enabled) {
if(enabled) {
this.setNeckModelFactor(1.0F);
} else {
this.setNeckModelFactor(0.0F);
}
}
public float getNeckModelFactor() {
Object var1 = this.neckModelFactorMutex;
synchronized(this.neckModelFactorMutex) {
return this.neckModelFactor;
}
}
public void setNeckModelFactor(float factor) {
Object var2 = this.neckModelFactorMutex;
synchronized(this.neckModelFactorMutex) {
if(factor >= 0.0F && factor <= 1.0F) {
this.neckModelFactor = factor;
} else {
throw new IllegalArgumentException("factor should be within [0.0, 1.0]");
}
}
}
public void setGyroBiasEstimationEnabled(boolean enabled) {
Object var2 = this.gyroBiasEstimatorMutex;
synchronized(this.gyroBiasEstimatorMutex) {
if(!enabled) {
this.gyroBiasEstimator = null;
} else if(this.gyroBiasEstimator == null) {
this.gyroBiasEstimator = new GyroscopeBiasEstimator();
}
}
}
public boolean getGyroBiasEstimationEnabled() {
Object var1 = this.gyroBiasEstimatorMutex;
synchronized(this.gyroBiasEstimatorMutex) {
return this.gyroBiasEstimator != null;
}
}
public void getLastHeadView(float[] headView, int offset) {
if(offset + 16 > headView.length) {
throw new IllegalArgumentException("Not enough space to write the result");
} else {
float rotation = 0.0F;
switch(this.display.getRotation()) {
case 0:
rotation = 0.0F;
break;
case 1:
rotation = 90.0F;
break;
case 2:
rotation = 180.0F;
break;
case 3:
rotation = 270.0F;
}
if(rotation != this.displayRotation) {
this.displayRotation = rotation;
Matrix.setRotateEulerM(this.sensorToDisplay, 0, 0.0F, 0.0F, -rotation);
Matrix.setRotateEulerM(this.ekfToHeadTracker, 0, -90.0F, 0.0F, rotation);
}
OrientationEKF var4 = this.tracker;
synchronized(this.tracker) {
if(!this.tracker.isReady()) {
return;
}
double secondsSinceLastGyroEvent = (double)TimeUnit.NANOSECONDS.toSeconds(this.clock.nanoTime() - this.latestGyroEventClockTimeNs);
double secondsToPredictForward = secondsSinceLastGyroEvent + 0.057999998331069946D;
double[] mat = this.tracker.getPredictedGLMatrix(secondsToPredictForward);
int i = 0;
while(true) {
if(i >= headView.length) {
break;
}
this.tmpHeadView[i] = (float)mat[i];
++i;
}
}
Matrix.multiplyMM(this.tmpHeadView2, 0, this.sensorToDisplay, 0, this.tmpHeadView, 0);
Matrix.multiplyMM(headView, offset, this.tmpHeadView2, 0, this.ekfToHeadTracker, 0);
Matrix.setIdentityM(this.neckModelTranslation, 0);
Matrix.translateM(this.neckModelTranslation, 0, 0.0F, -this.neckModelFactor * 0.075F, this.neckModelFactor * 0.08F);
Matrix.multiplyMM(this.tmpHeadView, 0, this.neckModelTranslation, 0, headView, offset);
Matrix.translateM(headView, offset, this.tmpHeadView, 0, 0.0F, this.neckModelFactor * 0.075F, 0.0F);
}
}
Matrix3x3d getCurrentPoseForTest() {
return new Matrix3x3d(this.tracker.getRotationMatrix());
}
void setGyroBiasEstimator(GyroscopeBiasEstimator estimator) {
Object var2 = this.gyroBiasEstimatorMutex;
synchronized(this.gyroBiasEstimatorMutex) {
this.gyroBiasEstimator = estimator;
}
}
}