2

Samsung Galaxy Nexus (Android 4.0) からできるだけ速くセンサー値を読み取ろうとしています。このために、さまざまなセンサーとサンプリング レートを使用していくつかの実験を行い、非常に奇妙な動作を見つけました。Acc-Sensor のみを使用した場合、サンプリング レートは約 50Hz です。しかし、ジャイロ センサー (または磁場センサー) も使用すると、Acc センサーのサンプル レートが増加し、どちらも 90 ~ 100 Hz のサンプル レートになります。センサー遅延の変更 (たとえば、SENSOR_DELAY_FASTEST から SENSOR_DELAY_UI へ) はサンプリング レートに影響を与えず、磁場センサーも追加すると、3 つのセンサーすべてのサンプリング レートが高くなります (90-100Hz)。もう 1 つの奇妙な点は、3 つのセンサーからの値が常に同じタイムスタンプで到着することです (1 つまたは 2 ミリ秒の違いがある場合があります。他の 2 つのタイムスタンプはまったく同じです)。Android-NDKでも同じことをテストしましたが、サンプリングレートの変更(ASensorEventQueue_setEventRate()を使用)が効果がないことを含め、まったく同じ動作があります。

私の友人は、HTC Desire HD で同じことを試しました (Android 2.3 で、ジャイロを持っていないため、加速度センサーと磁気センサーのみ)。 acc-sensor の速度は、磁気センサーの使用とは無関係でした (これは、通常の動作として期待されることです)。

他のセンサーを追加で使用すると、acc-sensor が高速になるのはなぜですか? 誰かが同様の動作を理解しましたか? これはバグですか?それとも私のコードのバグですか?

Android-SDK でのテストに使用したコードは次のとおりです (各センサーで 1000 回の測定を行うのにかかる時間を計算します)。

package de.tum.sdktest;

import java.util.ArrayList;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class TestSDKActivity extends Activity implements SensorEventListener {

private SensorManager mSensorManager;
private Sensor mAccSensor;
private Sensor mGyroSensor;
private Sensor mMagSensor;

private int accCounter = 0;
private long lastAccTime = 0;

private int gyroCounter = 0;
private long lastGyroTime = 0;

private int magCounter = 0;
private long lastMagTime = 0;

private int measuresPerInterval = 1000;

private ArrayList<Float> accValues;
private ArrayList<Float> gyroValues;
private ArrayList<Float> magValues;


private static final String TAG = "TestSDKActivity";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    accValues = new ArrayList<Float>();
    gyroValues = new ArrayList<Float>();
    magValues = new ArrayList<Float>();

    mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    mAccSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
    mMagSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

    TextView  tv = new TextView(this);
    tv.setText("Hello World!!!");
    setContentView(tv);
}

protected void onResume() {
    super.onResume();
    mSensorManager.registerListener(this, mAccSensor, SensorManager.SENSOR_DELAY_UI);
    mSensorManager.registerListener(this, mGyroSensor, SensorManager.SENSOR_DELAY_UI);
    mSensorManager.registerListener(this, mMagSensor, SensorManager.SENSOR_DELAY_UI);
}


public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub

}


public synchronized void onSensorChanged(SensorEvent event) {



    if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    {
        if(accCounter == 0 || accCounter == measuresPerInterval)
        {
            String s = String.valueOf("acc: "+(event.timestamp-lastAccTime)/1000000000.0);
            lastAccTime = event.timestamp;
            Log.i(TAG, s);
            accCounter = 0;
            accValues.clear();
        }
        accValues.add(event.values[0]);

        accCounter++;
    }
    else if(event.sensor.getType() == Sensor.TYPE_GYROSCOPE)
    {
        if(gyroCounter == 0 || gyroCounter == measuresPerInterval)
        {
            String s = String.valueOf("gyro: "+(event.timestamp-lastGyroTime)/1000000000.0);
            lastGyroTime = event.timestamp;
            Log.i(TAG, s);
            gyroCounter = 0;
        }
        gyroValues.add(event.values[0]);

        gyroCounter++;
    }
    else if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
    {
        if(magCounter == 0 || magCounter == measuresPerInterval)
        {
            String s = String.valueOf("mag: "+(event.timestamp-lastMagTime)/1000000000.0);
            lastMagTime = event.timestamp;
            Log.i(TAG, s);
            magCounter = 0;
        }
        magValues.add(event.values[0]);

        magCounter++;
    }

}

}

4

2 に答える 2

2

これは Invensense の「スマート センサー」の結果であり、アプリケーション レベル コードのバグによるものではありません。これは、このデバイスの奥深くにあるプラットフォーム ソフトウェアの実装のバグです。

この電話の Invensense MPU3050 チップには、MEMsジャイロスコープに加えてモーション プロセッシング ユニットがあります。加速度計と磁力計を制御し、データを結合し、センサー フュージョンを実行し、データを Android に送り返します。Android では、アプリがデータを認識します。

MPU3050 データシートから:

組み込みのデジタル モーション プロセッサ (DMP) は MPU-30X0 内にあり、モーション処理アルゴリズムの計算をホスト プロセッサからオフロードします。DMP は、加速度計、ジャイロスコープ、および磁力計などの追加センサーからデータを取得し、データを処理します。[..中略...]DMP の目的は、タイミング要件と処理能力の両方をホスト プロセッサからオフロードすることです。

于 2012-08-17T17:43:02.363 に答える
1

これは奇妙です。私も同じ問題を経験しました。そこで、開発者向けにこの問題を確認するためのアプリを作成しましたhere

于 2013-01-21T08:43:12.667 に答える