2

I'm trying to read out sensor values as fast as possible from a Samsung Galaxy Nexus (with Android 4.0). For this I did a few experiments using different sensors and sampling rates and figured out a very weird behaviour. When I use only the Acc-Sensor the sampling-rate is about 50Hz. But when I also use the Gyro-Sensor (or magnetic-field-sensor) the sample-rate of the Acc-Sensor increases and both have a sample-rate of between 90 and 100 Hz. A change of the sensor-delay (e.g. from SENSOR_DELAY_FASTEST to SENSOR_DELAY_UI) has no effect on the sampling rate and when I add also the magnetic-field-sensor all three sensors have a high sampling-rate (90-100Hz). Another strange thing is that the values from the three sensors arrive always with the same timestamp (sometimes one has 1 or 2 ms difference, but the other two have exactly the same timestamp). I also tested the same with Android-NDK and there is exactly the same behaviour including that a change of the sampling-rate (using ASensorEventQueue_setEventRate()) has no effect.

A friend of mine tried the same things on a HTC Desire HD (with Android 2.3 and only acc- and magnetic-sensor, since he has no gyro) and there the sampling-rate of the sensors was different from each other and the sampling-rate of the acc-sensor was independent on the use of the magnetic sensor (that's what I would expect as normal behaviour).

Why becomes the acc-sensor faster if other sensors are used additionally? Did someone figure out a similar behaviour? Is this a bug? Or maybe a bug with my code?

Here is the code I used for testing with Android-SDK (I calculate the time it takes for doing 1000 measures on each of the sensors):

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

What you are seeing is a result of the "smart sensor" from Invensense, and is definitely not from a bug in your application level code. It's a bug in the implementation of platform software much lower down in the bowels of this device.

The Invensense MPU3050 chip on this phone has a Motion Processing Unit in addition to its MEMs gyroscope. It controls the accelerometer and magnetometer, coalesces the data, runs the sensor fusion, and sends the data back up to Android, where your app sees it.

From the MPU3050 datasheet:

The embedded Digital Motion Processor (DMP) is located within the MPU-30X0 and offloads computation of motion processing algorithms from the host processor. The DMP acquires data from accelerometers, gyroscopes, and additional sensors such as magnetometers, and processes the data. [..snip...]The purpose of the DMP is to offload both timing requirements and processing power from the host processor

于 2012-08-17T17:43:02.363 回答
1

This is weird. I experienced the same problem too. So I created an App for developer to check this problem here.

于 2013-01-21T08:43:12.667 回答