Home | History | Annotate | Download | only in devcamera
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.devcamera;
     17 
     18 import android.hardware.Sensor;
     19 import android.hardware.SensorEvent;
     20 import android.hardware.SensorEventListener;
     21 import android.hardware.SensorManager;
     22 import android.util.Log;
     23 
     24 import java.util.ArrayDeque;
     25 
     26 /**
     27  * Put all the Gyro stuff here.
     28  */
     29 public class GyroOperations {
     30     private static final String TAG = "DevCamera_GYRO";
     31 
     32     private SensorManager mSensorManager;
     33     private GyroListener mListener;
     34 
     35     private SensorEventListener mSensorEventListener = new SensorEventListener() {
     36         @Override
     37         public void onSensorChanged(SensorEvent event) {
     38             delayGyroData(event);
     39         }
     40         @Override
     41         public void onAccuracyChanged(Sensor sensor, int accuracy) {
     42         }
     43     };
     44 
     45     public GyroOperations(SensorManager sensorManager) {
     46         mSensorManager = sensorManager;
     47     }
     48 
     49     public void startListening(GyroListener listener) {
     50         mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_FASTEST);
     51         mListener = listener;
     52     }
     53 
     54     public void stopListening() {
     55         mSensorManager.unregisterListener(mSensorEventListener);
     56     }
     57 
     58     // We need to make a copy of SensorEvent so we can put it in our delay-line.
     59     class GyroEvent2D {
     60         public long timestamp;
     61         public final float[] values = new float[2];
     62 
     63         public GyroEvent2D(SensorEvent event) {
     64             this.timestamp = event.timestamp;
     65             this.values[0] = event.values[0];
     66             this.values[1] = event.values[1];
     67         }
     68     }
     69 
     70     private long mGyroLastTimestamp = 0;
     71     private float[] mGyroAngle = new float[]{0f, 0f}; // radians, X and Y axes.
     72     // Gyro arrives at 230 Hz on N6: 23 samples in 100 ms.  Viewfinder latency is 70 ms.  Delay about 15 samples.
     73     private ArrayDeque<GyroEvent2D> mSensorDelayLine = new ArrayDeque<>();
     74     private static final int DELAY_SIZE = 10;
     75 
     76     void delayGyroData(SensorEvent event) {
     77         mSensorDelayLine.addLast(new GyroEvent2D(event));
     78         if (mSensorDelayLine.size() < DELAY_SIZE) {
     79             return;
     80         }
     81         GyroEvent2D delayedEvent = mSensorDelayLine.removeFirst();
     82         integrateGyroForPosition(delayedEvent);
     83     }
     84 
     85     void integrateGyroForPosition(GyroEvent2D event) {
     86         if (mGyroLastTimestamp == 0) {
     87             mGyroLastTimestamp = event.timestamp;
     88             return;
     89         }
     90         long dt = (event.timestamp - mGyroLastTimestamp) / 1000; // microseconds between samples
     91         if (dt > 10000) { // below 100 Hz
     92             Log.v(TAG, " ===============> GYRO STALL <==============");
     93         }
     94         mGyroAngle[0] += event.values[0] * 0.000001f * dt;
     95         mGyroAngle[1] += event.values[1] * 0.000001f * dt;
     96         mGyroLastTimestamp = event.timestamp;
     97 
     98         // TODO: Add UI
     99         //updateOrientationUI(mGyroAngle, dt);
    100         //Log.v(TAG, String.format("Gyro: theta_x = %.2f  theta_y = %.2f   dt = %d", mGyroAngle[0]*180f/3.14f, mGyroAngle[1]*180f/3.14f, dt));
    101 
    102         mListener.updateGyroAngles(mGyroAngle);
    103     }
    104 
    105 }
    106