如何在一个固定的速度登录Android电子运动传感器数据(How to log data from

2019-06-27 18:10发布

我正在学习的Android编程的基础知识。

我在我的加速计,磁力计和方位数据记录到外部文件,同时还显示它简单的Android测试应用程序。 我通过调用一个方法initLogger发起一个启动按钮(registerListener的相关传感器)的点击记录过程。

这类似于这样的东西?

public void initLogger(View view)
{
    boolean bFlag = false;

    Button btnStart = (Button)findViewById(R.id.btnStartLog);
    Button btnStop = (Button)findViewById(R.id.btnStopLog);

    btnStart.setEnabled(bFlag);
    btnStop.setEnabled(!bFlag);

    bEnableLogging = true;
    //Start reading the sensor values
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);

   //so on.... 

还有一个停止按钮,其中应停止记录进程(和最后通过调用unregisterListener每个传感器注销)

数据检索过程发生在onSensorChanged处理机其中应检索来自相关传感器的数据内,将值设置为相应的UI元素和最后的数据记录到外部.csv文件。

onSensorChanged事件处理程序看起来是这样的...

public void onSensorChanged(SensorEvent event) {


    // TODO Auto-generated method stub
    // accelerometer
    TextView tAX = (TextView) findViewById(R.id.txtViewAxValue);
    TextView tAY = (TextView) findViewById(R.id.txtViewAyValue);
    TextView tAZ = (TextView) findViewById(R.id.txtViewAzValue);

    // magnetic field
    TextView tMX = (TextView) findViewById(R.id.txtViewMx);
    TextView tMY = (TextView) findViewById(R.id.txtViewMy);
    TextView tMZ = (TextView) findViewById(R.id.txtViewMz);

    if (bEnableLogging) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

            accelerometerdata = event.values.clone();

            tAX.setText(Double.toString(accelerometerdata[0]));
            tAY.setText(Double.toString(accelerometerdata[1]));
            tAZ.setText(Double.toString(accelerometerdata[2]));


        }

        if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {

            magneticmatrixdata = event.values.clone();

            tMX.setText(Double.toString(magneticmatrixdata[0]));
            tMY.setText(Double.toString(magneticmatrixdata[1]));
            tMZ.setText(Double.toString(magneticmatrixdata[2]));

        }

               // so on ....

虽然我接收来自所有配置的传感器的数据,我没有超过在其上接收所述数据的速率控制。 即

我知道SensorChanged事件被触发为当传感器数据被改变。 不过,我想在一个固定的速度来触发此事件。 对于例如:每40ms

题:

  1. 如何保证SensorChanged事件以恒定速率解雇?
  2. 是Java类的TimerTask在这种情况下,任何帮助吗?

专家在这里在SO.Please帮我:)

Answer 1:

既然你知道,如果没有SensorChanged触发的事件,也没有改变,你可以用你的旧值。 至于你问在特定的时间间隔的日志数据,我不会做的onSensorChanged方法的任何输出只是复制新的数据到你accelerometerdata变量。 而不是登录accelerometerdata每40ms的价值。 这样,你正在登录的实际价值,甚至每40ms,如果数据没有改变....

注:根据Ridcullys答案也似乎是可能获得传感器数据在特定的时间间隔“交付”。 但由于没有对这些“交付”一如既往与Android设备上的传感器数据的延迟,我的解决方案,你会更准确地在40毫秒的时间间隔。 在另一方面,它可能发生,如果在当下的传感器数据更改登录,它可能发生,你耽误了新的数据对一个区间。 我猜(这点不知道) - 因为它的只是记录和不是像某事“得到它尽可能快地实时”,所以这不是一个要求 - 定时器的解决方案,使更少的CPU负载。



Answer 2:

可以通过改变用于传感器注册时的延迟改变的时间间隔。

int SENSOR_DELAY_FASTEST    get sensor data as fast as possible 
int SENSOR_DELAY_GAME       rate suitable for games 
int SENSOR_DELAY_NORMAL     rate (default) suitable for screen orientation changes
int SENSOR_DELAY_UI         rate suitable for the user interface

根据这个 ,最快的延迟,你需要什么,如果不改变速度不够快,你是因为没有改变。 没有getSensorData方法。

您可以指定其他数据的延迟,如SENSOR_DELAY_GAME(20,000微秒延迟),SENSOR_DELAY_UI(60,000微秒延迟),或SENSOR_DELAY_FASTEST(0微秒的延迟)。 由于Android 3.0(API等级11),你还可以指定延迟的绝对值(微秒)。

您指定的延迟仅仅是一个建议的延迟。 Android系统和其他应用程序可以改变这种延迟。 作为最佳做法,应指定,你可以因为系统通常使用超过您指定的一个较小的延迟(即,您应该选择仍满足您的应用需求最慢的采样率)最大的延迟。 使用较大的延迟施加所述处理器上的负载较低,因此使用较少的功率。



Answer 3:

当您注册使用监听器SensorManager使用registerListener ,而不是固定的常数, SENSOR_DELAY_...你可以通过在如JavaDoc中所述微秒的时间间隔

速率传感器事件在被传递的速率。 这只是一个提示系统。 事件可以接收比指定的速率更快或更慢。 通常的事件接收更快。 该值必须是SENSOR_DELAY_NORMAL,SENSOR_DELAY_UI,SENSOR_DELAY_GAME,或SENSOR_DELAY_FASTEST或,在微秒事件之间的期望延迟中的一个。

所以,仅仅通过40000以符合您的要求范例,也为说,这只是一个提示,所以我不会依赖于区间得到确切值到微秒。



Answer 4:

我一直在试图找出我怎么能有传感器很长的延迟,到目前为止,我已经成功了。 对延迟时间可以用微秒来指定developer.android会谈的文档,下面是一个大数目我想:

// Initialize in onCreate
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE)
mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

// Register the listener, and play around with delay
mSensorManager.registerListener(this, mLight, 200000000);

但是请注意下面的logcat转储 - 在onSensorChanged() - 被调用多达4次,第二...我想弄清楚越来越大延迟,但没有成功为止!

6月1日至14日:58:07.088:d / IOE传感器(20933):onSensorChanged调用,事件是:android.hardware.SensorEvent@42849f70 6月1日至14日:58:07.268:d / IOE传感器(20933):onSensorChanged称为中,事件是:android.hardware.SensorEvent@42849f70 01-14 06:58:07.448:d / IOE传感器(20933):onSensorChanged调用,事件是:android.hardware.SensorEvent@42849f70 01-14 6点58分: 07.628:d / IOE传感器(20933):onSensorChanged调用,事件是:android.hardware.SensorEvent@42849f70六月一日至14日:58:07.808:d / IOE传感器(20933):onSensorChanged调用,事件是:机器人。 hardware.SensorEvent@42849f70 6月1日至14日:58:07.989:d / IOE传感器(20933):onSensorChanged调用,事件是:android.hardware.SensorEvent@42849f70 6月1日至14日:58:08.169:d / IOE传感器( 20933):onSensorChanged叫,事件是:android.hardware.SensorEvent@42849f70



Answer 5:

看来,在这onSensorChanged被称为率已经是4个建议值之一。

你能为“慢读”做的是使用SENSOR_DELAY_UI和(在onSensorChanged)衡量,因为你读的sensordata最后一次经过的时间:

long lastUpdate = System.currentTimeMillis();

// In onSensorChanged:
long curTime = System.currentTimeMillis();

        if ((curTime - lastUpdate) > 500){ // only reads data twice per second
            lastUpdate = curTime;
            // do stuff
        }

唯一的缺点我在这里看到的是,if语句将与假的结果多次被调用。



文章来源: How to log data from Android Motion Sensors at a fixed rate