2

私は40ms(25Hz)ごとに携帯電話の加速度を記録するアプリを書いています。このフレームレートは平均して保持できますが、タイムフレーム間で5'000ms〜50'000msの遅延が発生することがあります。なぜこれが起こるのか疑問に思います。

ここに、遅延が非常に頻繁に発生することがわかるグラフがあります。

加速度計の測定間の時折の長い遅延

これが私がしていることです(これは悪いかもしれません):

  • アクティビティは、加速度計ロガークラス(シングルトン、純粋なJava、Androidクラス拡張なし)を指します。
  • 加速度計ロガーシングルトンは、バックグラウンドでログインし続けます。
  • 加速度計ロガーは、すべてのログをsqliteデータベースに直接保存します。
  • GPSデータもバックグラウンドで記録しています。
  • DAO(データアクセスオブジェクト)は、すべてのログをLinkedBlockingQueueに割り当て、それらを別のスレッドに保存します。

これが問題かもしれないと私が思うものです:

  • たぶん、私はさらにライフサイクルメソッドを実装するか、特定のandroidクラスを拡張して、加速度計ロガーが優先順位を取得するようにする必要があります(または優先順位をどこかに設定するだけです)。
  • event.timestampの代わりに使用する場合がありSystem.currentTimeMills()ます。(一部のセンサーはタイムゾーンが異なるため、これを行わないことをお勧めします。そのため、使用System.currentTimeMillis()しますが、必要に応じて切り替えます。)

これや、問題が発生する可能性のある提案についての経験はありますか?

これが私のコードです:

@SuppressLint("NewApi")
public class AccelerometerLogger implements SensorEventListener {

    private static AccelerometerLogger singleton = new AccelerometerLogger();

    private LoggerDao loggerDao;

    private SensorManager sensorManager;

    private Sensor accelerometer;

    private double acceleorometerRate = 25; // Hz

    int accelerometerDelayMicroseconds = (int) (Math.round(((1/this.acceleorometerRate)*1000000.0)));

    private AccelerometerLogger()
    {
        this.loggerDao = LoggerDao.getInstance();
    }

    public static AccelerometerLogger getInstance()
    {
        return singleton;
    }

    public void start(Context context)
    {
        this.sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        this.accelerometer = this.sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        int accelerometerMinDelay = this.accelerometer.getMinDelay();

        //Log.d("lggr-r", "desired delay: "+this.accelerometerDelayMicroseconds+" microseconds");
        //Log.d("lggr-r", "provided min delay: "+accelerometerMinDelay+" microseconds");

        if(accelerometerMinDelay < this.accelerometerDelayMicroseconds)
        {
            this.sensorManager.registerListener(this, this.accelerometer, this.accelerometerDelayMicroseconds);
            //Log.d("lggr-r", "listener registered for desired rate: "+this.acceleorometerRate+"Hz (delay of "+this.accelerometerDelayMicroseconds+" microseconds).");
        } 
        else if(accelerometerMinDelay==0)
        {           
            this.sensorManager.registerListener(this, this.accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
            // Log.d("lggr-r", "listener registered for streaming api. only changes will be notified (interrupt).");
        }
        else
        {
            int providedRate = (int) Math.round(1 / (accelerometerMinDelay / 1000000.0));
            this.sensorManager.registerListener(this, this.accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
            // Log.d("lggr-r", "can't read at the desired rate ("+this.acceleorometerRate+"Hz), app will read at "+providedRate+"Hz instead (delay of "+accelerometerMinDelay+" microseconds).");
        }
    }

    public void stop()
    {
        this.sensorManager.unregisterListener(this);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {
        // String name = sensor.getName();
        // Log.d("lggr", "the accurracy of "+name+" changed to "+accuracy+".");
    }

    @Override
    public void onSensorChanged(SensorEvent event)
    {
        // lazy load loggerDao (TODO: fix all of those)
        if(this.loggerDao == null)
        {
            this.loggerDao = LoggerDao.getInstance();
        }


        String values = "";
        for(float value : event.values) values += value+",";
        values = values.substring(0,values.length()-2);

        // long timestamp = System.currentTimeMillis();
        // Log.d("lggr", "acc = {time:"+timestamp+", data: ["+values+"]}");

        AccelerometerSample accelerometerSample = new AccelerometerSample();
        accelerometerSample.setTimestamp(System.currentTimeMillis());
        accelerometerSample.setValues(event.values);

        this.loggerDao.save(accelerometerSample);
    }

}

どうやら問題はサムスンギャラクシーSIIIミニでのみ発生します。私はSamsungGalaxySII(カスタムROM)でテストしましたが、遅延は常に約0.04秒(0.005〜0.12秒の範囲-はるかに優れています)でした。

これがSamsungGalaxySIII miniで発生する理由について何か提案はありますか?

アップデート:

を使用することを目的としたBenVoigtsの回答event.timestampにより、遅延が大幅に改善されました。それでも、私は時々いくつかのより長い遅延を経験しています。私がそれらをさらに改善する方法を知っていますか?

ここに画像の説明を入力してください

4

2 に答える 2

4

絶対に使用する必要がありますevent.timestampevent.timestamp現地時間を必要とする場合は、最初のイベント間の調整係数を計算しSystem.currentTimeMills()、同じ調整を後続のサンプルに適用します。

サンプルに添付されたハードウェア提供のタイムスタンプの要点は、スレッドのスケジューリング遅延によって混乱しないことです。

于 2013-03-29T15:05:33.590 に答える
0

Ben Voigtが言ったように、センサー測定の正確なタイムスタンプを取得するには、event.timestampを使用する必要があります。これが私が自分で使って私のために働いたコードサンプルです:

@Override
public void onSensorChanged(SensorEvent event) {
    if (sampleCounter == 0) {
        long miliTime = System.currentTimeMillis();

        long nanoTime = event.timestamp;

        timeDiff = miliTime - nanoTime / 1000000;
        log.info("Synchornizing sensor clock. Current time= " + miliTime
                + ", difference between clocks = " + timeDiff);
    }

    float x = event.values[0];
    float y = event.values[1];
    float z = event.values[2];
    long ts = event.timestamp / 1000000 + timeDiff;

    //Do your stuff

    sampleCounter++;
}
于 2014-03-31T11:32:08.687 に答える