• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GyroOperations(SensorManager sensorManager)45     public GyroOperations(SensorManager sensorManager) {
46         mSensorManager = sensorManager;
47     }
48 
startListening(GyroListener listener)49     public void startListening(GyroListener listener) {
50         mSensorManager.registerListener(mSensorEventListener, mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_FASTEST);
51         mListener = listener;
52     }
53 
stopListening()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 
GyroEvent2D(SensorEvent event)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 
delayGyroData(SensorEvent event)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 
integrateGyroForPosition(GyroEvent2D event)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