您的位置:首页 > 移动开发 > Android开发

Android CTS Verifier Sensor Test Cases (3)

2016-09-04 00:08 801 查看
2. Gyroscope Measurement Test

前面一章提到加速度传感器适合描述设备静止的状态,而陀螺仪传感器则适合描述设备运动的状态,由于陀螺仪的特性,它能非常精确的反映设备绕某一轴旋转的角速度。设备静止时,由于白噪声等原因,陀螺仪会产生零飘。

Gyroscope Measurement Test 只有存在物力陀螺仪传感器时才有意义。ECompass(Acc+Mag, 6dof),或 M4G(Acc+Mag, Mag for Gyro)方案下,本测试项应该skip. 即使是M4G方案也不应该进行该测试。

该测试的目的是检测校准后的Gyrocope(即,Calibrated Gyroscope)数据质量,和与校准前的Uncalibrated Gyrosocpe sensor 数据相比是否满足Android 对这两种sensor类型的需求。

testCalibratedAndUncalibrated

这项测试要求在测试开始后不停的旋转设备,直到测试结束。测试时收集在Fasted 模式下每一时刻的Gyroscope Sensor 和 Uncalibrated Gyroscope Sensor 数据,验证是否符合等式:

calibrated = uncalibrated - bias


同时CTS Verifier 定义了一个threshold允许Gyroscope 和Uncalibrated Gyroscope 数据的差值在bias之外的误差范围:

private static final float THRESHOLD_CALIBRATED_UNCALIBRATED_RAD_SEC = 0.01f;


我们直接来看测试执行的代码:

/* 不停的旋转设备,收集10秒钟的数据,然后验证收集到的数据 */
/**
* Executes the operation: it collects the data and run verifications on it.
*/
public void execute() throws Throwable {
/* 先打开 Calibrated Gyroscope, 后打开 Uncalibrated Gyroscope */
mCalibratedSensorManager.registerListener(mCalibratedTestListener);
mUncalibratedSensorManager.registerListener(mUncalibratedTestListener);
Thread.sleep(TimeUnit.SECONDS.toMillis(10));
mCalibratedSensorManager.unregisterListener();
mUncalibratedSensorManager.unregisterListener();
/* 验证搜集到的数据 */
verifyMeasurements(
mCalibratedTestListener.getCollectedEvents(),
mUncalibratedTestListener.getCollectedEvents(),
mThreshold);
}

/* Verification 的方法 */
private void verifyMeasurements(
List<TestSensorEvent> calibratedEvents,
List<TestSensorEvent> uncalibratedEvents,
float threshold) {
/* 获取Calibrated Gyroscope Sensor 的data rate. e.g. 200Hz = 5ms = 5000000ns */
long measuredSamplingPeriodNs = SensorCtsHelper.getSamplingPeriodNs(calibratedEvents);
/* Data rate 除以2得到用来做同步的时间值。下面会用来判断Uncalibrated Gyroscope data 是否跟之前收到的Calibrated Gyroscope data 属于同一时间产生的数据 */
long synchronizationPeriodNs = measuredSamplingPeriodNs / 2;
/* 有效事件的计数 */
int eventsValidated = 0;
// TODO: this makes the algorithm O(n^2) when we could have it O(n), but it has little
// impact on the overall test duration because the data collection is what takes the most
// time
for (TestSensorEvent calibratedEvent : calibratedEvents) {
/* 当前Calibrated Gyroscope 数据自带的时间戳 */
long calibratedTimestampNs = calibratedEvent.timestamp;
/* 加减前面的同步时间值得到期望的Uncalibrated Gyroscope 数据时间戳的范围 */
long lowerTimestampThresholdNs = calibratedTimestampNs - synchronizationPeriodNs;
long upperTimestampThresholdNs = calibratedTimestampNs + synchronizationPeriodNs;
for (TestSensorEvent uncalibratedEvent : uncalibratedEvents) {
long uncalibratedTimestampNs = uncalibratedEvent.timestamp;
/* Uncalibrated Gyroscope data自带的时间戳满足范围要求说明这两个数据来源于同一 gyroscope 物理原始数据 */
if (uncalibratedTimestampNs > lowerTimestampThresholdNs
&& uncalibratedTimestampNs < upperTimestampThresholdNs) {
/* 验证等式 calibrated = Uncalibrated - bias +- threshold */
// perform validation
verifyCalibratedUncalibratedPair(
calibratedEvent,
uncalibratedEvent,
threshold);
++eventsValidated;
}
}
}
String eventsValidatedMessage = String.format(
"Expected to find at least one Calibrated/Uncalibrated event pair for validation."
+ " Found=%d",
eventsValidated);
/* 根据时间戳范围限制,没找到符合要求的一对Calibrated Uncalbrated Gyro data, 则报错 */
Assert.assertTrue(eventsValidatedMessage, eventsValidated > 0);
}
private void verifyCalibratedUncalibratedPair(
TestSensorEvent calibratedEvent,
TestSensorEvent uncalibratedEvent,
float threshold) {
for (int i = 0; i < 3; ++i) {
float calibrated = calibratedEvent.values[i];
float uncalibrated = uncalibratedEvent.values[i];
float bias = uncalibratedEvent.values[i + 3];
String message = String.format(
"Calibrated (%s) and Uncalibrated (%s) sensor readings are expected to satisfy:"
+ " calibrated = uncalibrated - bias. Axis=%d, Calibrated=%s, "
+ "Uncalibrated=%s, Bias=%s, Threshold=%s",
calibratedEvent.sensor.getName(),
uncalibratedEvent.sensor.getName(),
i,
calibrated,
uncalibrated,
bias,
threshold);
/* 不符合等式要求,也报错 */
Assert.assertEquals(message, calibrated, uncalibrated - bias, threshold);
}
}
}


该项测试的失败类型有两种:

1)没找到符合要求的一对Calibrated Gyroscope data 和 Uncalibrated Gyroscope data. Calibrated 和 Uncalibrated 数据都是由算法输出的Virtual Sensor 类型。他们都来源于物理sensor的原始数据。但是代码中Calibrated Gyroscope 和 Uncalibrated Gyroscope是先后打开的,收到的数据也是顺序收到的。重点来了,这段代码到HAL层的执行效率,可能会导致同是第n个数据,但是Calibrated Gyro 和 Uncalibrated Gyro并不属于同一个物理原始数据。还有一点,Android自己并不提供HAL层的代码,而是厂商自己写,里面会集成厂商自己的算法库。这个算法库的执行效率也会影响到 Calibrated 和 Uncalibrated data 是否来源于同一个原始数据 .

解决方法有:

a. 同时从算法库中获取Calibrated 和 Uncalibrated data,上层有enable就上报,没enable就不报。这样两个data的时间戳就相等;

b. 厂商检查自己HAL/Algorithm 库的逻辑,确保Calibrated Gyroscope 和 Uncalibrated Gyroscope data 上报频率保持一致;

c. 如果是厂商自己的 HAL/Algorithm 代码执行效率的限制,上报数据时再赋上时间戳;

2)不符合等式,即calibrated 不
b664
等于 Uncalibrated - bias +- threshold. 原因两种,一是 Calibrated Gyroscope 未校准成功,algorithm 没有产生bias 或者产生了错误bias; 二是虽然时间戳满足要求,但是这一对(pair)Calibrated 和 Uncalibrated 数据不是来源于同一个物理原始数据。

解决方法:

a. 如果是第一种原因,先确认一下算法返回的Calibrated Gyroscope accuracy status是否为3;若小于3,则说明未校准。Gyroscope sensor 的校准方式非常简单,enable Gyroscope sensor 后,静止1~2秒钟即可校准。如果没有校准,检查你的Algorithm的实现是否有异常。

b. 如果是第二个原因,参考1)的解决方法,或告诉测试人员在测试时,非常缓慢的方式旋转设备,陀螺仪非常灵敏,而且量程非常大(2000dps)。如果Calibrated 和 Uncalibrated 不是来源于同一个物理原始数据,则完全可能不符合等式。(Android并没有具体定义测试设备旋转的速度,缓慢旋转则可以保证原始数据不会突然变化的非常大);

testDeviceStatic

设备静止放置,开始测试收集一组10秒钟的数据,计算Gyroscope 三个轴的旋转角度。因为设备是静止不动的,所以三轴的理想值应该是0度,但是由于误差的存在,Android CTS Verifier 定义了一个静止时的Threshold, 只要是在这个范围内,就认为测试通过。

/* 10 senconds, 50 degrees, 不知道 Android 出于什么目的这个threshold定义的足够大,以至于很容易就能满足。静止状态10秒钟能漂50度以上的sensor还能用吗? */

private static final float THRESHOLD_AXIS_UNDER_NO_ROTATION_DEG =

50.0f;

这项测试失败原因也只能是10秒钟的静止数据漂了50度以上。解决方法换算法库或换sensor。

testRotateClockwise

开始测试时,设备正面朝上放置,沿设备Z轴顺时针旋转360度(只能而且必须旋转1周,转多了/少了都不符合测试要求),然后放置(依然正面朝上,参考动画演示)。

/* 沿Z轴旋转,不考虑X/Y轴数据变化,理想值应该是设备旋转了 -360度, Android 定义了旋转时的threshold (误差允许范围) 为正负10度以内 */
private static final float THRESHOLD_AXIS_UNDER_ROTATION_DEG = 10.0f;

public String testRotateClockwise() throws Throwable {
return verifyMeasurements(R.string.snsr_gyro_rotate_device, Z_AXIS, -ROTATE_360_DEG);
}


失败的情况就一个,测量值在[350, 370]区间之外。

具体原因:

a. Gyroscope 未校准,有offset时,可以引起测量值过小或过大。解决方法就是先校准到3,再测试;

b. Gyroscope Noise 太大,即使校准成功了,也可能因为noise的原因导致测量值不符合要求。解决方法是提高Gyroscope 的filter,比如average 4 or 其他设置(具体filter请查看gyroscope相应datasheet); c. Gyroscope 硬件本身的sensitivity (灵敏度)误差,导致设备旋转了360度,而数据通过积分只能现实小于350度或大于370度的值。器件自身问题,没有好的解决方法;

剩下的几个测试项testRotateCounterClockwise(逆时针), testRotateRightSide(右侧旋转),testRotateLeftSide(左侧旋转),testRotateTopSide(顶部旋转),testRotateBottomSide(底部旋转)测试内容都与testRotateClockwise一样,看演示动画操作即可。

本章节代码连接:

GyroscopeIntegrationVerfication.java

GyroscopeMeasurementTestActivity
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android sensor cts gyroscope