• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 
17 package com.android.cts.verifier.sensors;
18 
19 import com.android.cts.verifier.R;
20 import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
21 import com.android.cts.verifier.sensors.renderers.GLRotationGuideRenderer;
22 
23 import android.hardware.Sensor;
24 import android.hardware.SensorManager;
25 import android.hardware.cts.helpers.SensorCalibratedUncalibratedVerifier;
26 import android.hardware.cts.helpers.TestSensorEnvironment;
27 import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
28 import android.hardware.cts.helpers.sensorverification.GyroscopeIntegrationVerification;
29 
30 import java.util.concurrent.TimeUnit;
31 
32 /**
33  * Semi-automated test that focuses on characteristics associated with Gyroscope measurements.
34  */
35 public class GyroscopeMeasurementTestActivity extends SensorCtsVerifierTestActivity {
36     private static final float THRESHOLD_CALIBRATED_UNCALIBRATED_RAD_SEC = 0.01f;
37     private static final float THRESHOLD_AXIS_UNDER_ROTATION_DEG = 10.0f;
38     private static final float THRESHOLD_AXIS_UNDER_NO_ROTATION_DEG = 50.0f;
39 
40     private static final int ROTATE_360_DEG = 360;
41     private static final int ROTATION_COLLECTION_SEC = 10;
42 
43     private static final int X_AXIS = 0;
44     private static final int Y_AXIS = 1;
45     private static final int Z_AXIS = 2;
46 
47     private final GLRotationGuideRenderer mRenderer = new GLRotationGuideRenderer();
48 
GyroscopeMeasurementTestActivity()49     public GyroscopeMeasurementTestActivity() {
50         super(GyroscopeMeasurementTestActivity.class, true);
51     }
52 
53     @Override
activitySetUp()54     protected void activitySetUp() throws InterruptedException {
55         getTestLogger().logInstructions(R.string.snsr_gyro_device_placement);
56         waitForUserToContinue();
57         initializeGlSurfaceView(mRenderer);
58     }
59 
60     @Override
activityCleanUp()61     protected void activityCleanUp() {
62         closeGlSurfaceView();
63     }
64 
65     @SuppressWarnings("unused")
testDeviceStatic()66     public String testDeviceStatic() throws Throwable {
67         return verifyMeasurements(
68                 R.string.snsr_gyro_device_static,
69                 -1 /* rotationAxis */,
70                 0 /* expectationDeg */);
71     }
72 
73     @SuppressWarnings("unused")
testRotateClockwise()74     public String testRotateClockwise() throws Throwable {
75         return verifyMeasurements(R.string.snsr_gyro_rotate_device, Z_AXIS, -ROTATE_360_DEG);
76     }
77 
78     @SuppressWarnings("unused")
testRotateCounterClockwise()79     public String testRotateCounterClockwise() throws Throwable {
80         return verifyMeasurements(R.string.snsr_gyro_rotate_device, Z_AXIS, ROTATE_360_DEG);
81     }
82 
83     @SuppressWarnings("unused")
testRotateRightSide()84     public String testRotateRightSide() throws Throwable {
85         return verifyMeasurements(R.string.snsr_gyro_rotate_device, Y_AXIS, ROTATE_360_DEG);
86     }
87 
88     @SuppressWarnings("unused")
testRotateLeftSide()89     public String testRotateLeftSide() throws Throwable {
90         return verifyMeasurements(R.string.snsr_gyro_rotate_device, Y_AXIS, -ROTATE_360_DEG);
91     }
92 
93     @SuppressWarnings("unused")
testRotateTopSide()94     public String testRotateTopSide() throws Throwable {
95         return verifyMeasurements(R.string.snsr_gyro_rotate_device, X_AXIS, -ROTATE_360_DEG);
96     }
97 
98     @SuppressWarnings("unused")
testRotateBottomSide()99     public String testRotateBottomSide() throws Throwable {
100         return verifyMeasurements(R.string.snsr_gyro_rotate_device, X_AXIS, ROTATE_360_DEG);
101     }
102 
103     /**
104      * Verifies that the relationship between readings from calibrated and their corresponding
105      * uncalibrated sensors comply to the following equation:
106      *      calibrated = uncalibrated - bias
107      */
108     @SuppressWarnings("unused")
testCalibratedAndUncalibrated()109     public String testCalibratedAndUncalibrated() throws Throwable {
110         setRendererRotation(Z_AXIS, false);
111 
112         setFirstExecutionInstruction(R.string.snsr_keep_device_rotating_clockwise);
113 
114         getTestLogger().logWaitForSound();
115 
116         TestSensorEnvironment calibratedEnvironment = new TestSensorEnvironment(
117                 getApplicationContext(),
118                 Sensor.TYPE_GYROSCOPE,
119                 SensorManager.SENSOR_DELAY_FASTEST);
120         TestSensorEnvironment uncalibratedEnvironment = new TestSensorEnvironment(
121                 getApplicationContext(),
122                 Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
123                 SensorManager.SENSOR_DELAY_FASTEST);
124         SensorCalibratedUncalibratedVerifier verifier = new SensorCalibratedUncalibratedVerifier(
125                 calibratedEnvironment,
126                 uncalibratedEnvironment,
127                 THRESHOLD_CALIBRATED_UNCALIBRATED_RAD_SEC);
128 
129         try {
130             verifier.execute();
131         } finally {
132             playSound();
133         }
134         return null;
135     }
136 
137     /**
138      * This test verifies that the Gyroscope measures the appropriate angular position.
139      *
140      * The test takes a set of samples from the sensor under test and calculates the angular
141      * position for each axis that the sensor data collects. It then compares it against the test
142      * expectations that are represented by signed values. It verifies that the readings have the
143      * right magnitude.
144      */
verifyMeasurements(int instructionsResId, int rotationAxis, int expectationDeg)145     private String verifyMeasurements(int instructionsResId, int rotationAxis, int expectationDeg)
146             throws Throwable {
147         setRendererRotation(rotationAxis, expectationDeg >= 0);
148 
149         setFirstExecutionInstruction(instructionsResId);
150 
151         getTestLogger().logWaitForSound();
152 
153         TestSensorEnvironment environment = new TestSensorEnvironment(
154                 getApplicationContext(),
155                 Sensor.TYPE_GYROSCOPE,
156                 SensorManager.SENSOR_DELAY_FASTEST);
157         TestSensorOperation sensorOperation = TestSensorOperation
158                 .createOperation(environment, ROTATION_COLLECTION_SEC, TimeUnit.SECONDS);
159 
160         int gyroscopeAxes = environment.getSensorAxesCount();
161         int[] expectationsDeg = getExpectationsDeg(gyroscopeAxes, rotationAxis, expectationDeg);
162         float[] thresholdsDeg = getThresholdsDeg(gyroscopeAxes, rotationAxis);
163         GyroscopeIntegrationVerification integrationVerification =
164                 new GyroscopeIntegrationVerification(expectationsDeg, thresholdsDeg);
165         sensorOperation.addVerification(integrationVerification);
166 
167         try {
168             sensorOperation.execute(getCurrentTestNode());
169         } finally {
170             playSound();
171         }
172         return null;
173     }
174 
getExpectationsDeg(int axes, int rotationAxis, int expectationDeg)175     private int[] getExpectationsDeg(int axes, int rotationAxis, int expectationDeg) {
176         int[] expectationsDeg = new int[axes];
177         for (int i = 0; i < axes; ++i) {
178             // tests assume that rotation is expected on one axis at a time
179             expectationsDeg[i] = (i == rotationAxis) ? expectationDeg : 0;
180         }
181         return expectationsDeg;
182     }
183 
getThresholdsDeg(int axes, int rotationAxis)184     private float[] getThresholdsDeg(int axes, int rotationAxis) {
185         float[] thresholdsDeg = new float[axes];
186         for (int i = 0; i < axes; ++i) {
187             // tests set a high threshold on the axes where rotation is not expected, to account
188             // for movement from the operator
189             // the rotation axis has a lower threshold to ensure the gyroscope's accuracy
190             thresholdsDeg[i] = (i == rotationAxis)
191                     ? THRESHOLD_AXIS_UNDER_ROTATION_DEG
192                     : THRESHOLD_AXIS_UNDER_NO_ROTATION_DEG;
193         }
194         return thresholdsDeg;
195     }
196 
setRendererRotation(int rotationAxis, boolean positiveRotation)197     private void setRendererRotation(int rotationAxis, boolean positiveRotation) {
198         int axis1 = 0;
199         int axis2 = 0;
200         int axis3 = 0;
201         switch (rotationAxis) {
202             case X_AXIS:
203                 axis1 = positiveRotation ? 1 : -1;
204                 break;
205             case Y_AXIS:
206                 axis2 = positiveRotation ? 1 : -1;
207                 break;
208             case Z_AXIS:
209                 axis3 = positiveRotation ? 1 : -1;
210                 break;
211         }
212         mRenderer.setRotation(axis1, axis2, axis3);
213     }
214 }
215