android - 银河 Nexus : Sensor Sampling Rate becomes faster when sampling more Sensors

标签 android performance android-sensors

我正在尝试从 Samsung Galaxy Nexus(使用 Android 4.0)尽快读取传感器值。为此,我使用不同的传感器和采样率做了一些实验,并发现了一个非常奇怪的行为。当我只使用 Acc-Sensor 时,采样率约为 50Hz。但是,当我还使用陀螺仪传感器(或磁场传感器)时,加速传感器的采样率会增加,并且两者的采样率都在 90 到 100 Hz 之间。传感器延迟的变化(例如从 SENSOR_DELAY_FASTEST 到 SENSOR_DELAY_UI)对采样率没有影响,当我添加磁场传感器时,所有三个传感器都具有高采样率(90-100Hz)。 另一个奇怪的事情是,来自三个传感器的值始终具有相同的时间戳(有时一个传感器有 1 或 2 毫秒的差异,但其他两个具有完全相同的时间戳)。 我还使用 Android-NDK 进行了相同的测试,并且存在完全相同的行为,包括采样率的更改(使用 ASensorEventQueue_setEventRate())没有效果。

我的一个 friend 在 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++;
    }

}

}

最佳答案

您所看到的是 Invensense 的“智能传感器”的结果,绝对不是应用程序级代码中的错误。这是该设备内部的平台软件实现中的一个错误。

Invensense MPU3050 chip on this phone除了 MEM 陀螺仪之外,还有一个运动处理单元。它控制加速度计和磁力计,合并数据,运行 sensor fusion ,和sends the data back up to Android ,您的应用程序在哪里看到它。

来自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

关于android - 银河 Nexus : Sensor Sampling Rate becomes faster when sampling more Sensors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10607137/

相关文章:

java - Android API 中的上下文参数和标识符

javascript - 事件事件上的 HTML 元素

sql-server - 是否 CTE

android - 检测从 Android 获取的汽车转弯角度

android - 尽管删除了 SMS 或 CALL LOG 权限,但应用更新在 Play Store 上一次又一次被拒绝

android - 带文字的 Lollipop 开关看起来不太好

android - 在 BottomAppBar 中隐藏 fab/显示菜单项时,Material Components 版本 1.1.0 会闪烁

c++ - 为什么 snprintf 比 ostringstream 快,还是这样?

android - 每秒获取传感器值

android - 我可以在后台使用 Android Wear 分析传感器数据吗?