我最近一直在尝试同步传感器更新,尤其是尽可能及时地从 TYPE_ROTATION_VECTOR 和 TYPE_ACCELEROMETER 获取值。
这是一个完整的程序,用于展示是什么让我很难做到这一点:
public class FusionTest extends Activity implements SensorEventListener {
private SensorManager sensorManager = null;
private Sensor rotSensor = null;
private Sensor accSensor = null;
private int rots = 0;
private int accs = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
rotSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
accSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, rotSensor, 500 * 1000);
sensorManager.registerListener(this, accSensor, 500 * 1000);
}
@Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
accs++;
System.out.println("accs: "+accs+", rots: "+rots);
}else if(event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR){
rots++;
System.out.println("accs: "+accs+", rots: "+rots);
}
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) { }
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this, rotSensor);
sensorManager.unregisterListener(this, accSensor);
}
}
该程序的目的是查看传感器多久提供一次更新及其延迟集。如果我让这个程序运行 50 秒,这是输出的最后一行:
05-21 19:37:01.431: D/FusionTest(26378): accs: 758, rots: 100
似乎我得到了延迟 500 毫秒的旋转矢量更新,但延迟了大约 66 毫秒的加速度更新。这是来自 registerListener 的文档:
rateUs --> 速率传感器事件的发送时间。这只是对系统的提示。事件的接收速度可能比指定的速率快或慢。通常会更快地接收到事件。该值必须是 SENSOR_DELAY_NORMAL、SENSOR_DELAY_UI、SENSOR_DELAY_GAME 或 SENSOR_DELAY_FASTEST 之一,或者是所需的事件之间的延迟(以微秒为单位)。以微秒为单位指定延迟仅适用于 Android 2.3(API 级别 9)以后。对于早期版本,您必须使用 SENSOR_DELAY_* 常量之一。
我的目标是 Android 4.4.2,所以我应该能够以微秒为单位指定延迟。我了解,如果我指定系统以 500 毫秒延迟交付更新,这将只是对系统的提示。但是在旋转矢量和加速度计的实现中延迟时间的解释不同,这一事实使得数据同步变得困难。当我得到时间 t 的加速度更新时,我也想得到时间 t 的旋转向量,反之亦然。有没有办法做到这一点?
编辑:目前我能做的最接近的是选择提供更新最慢的传感器,然后在另一个传感器的值之间进行插值,以在我从第一个传感器获得值时近似较慢传感器的值。这仍然不是我想要的,但至少比仅收集非同步数据有所改进。