Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to log data from Android Motion Sensors at a fixed rate

I'm learning the Basics of Android programming.

I have a simple android test application in which i log the accelerometer,magnetometer and the orientation data to an external file while also displaying it. I initiate the logging process on click of a Start button (registerListener for relevant sensors) by calling a method initLogger.

Which looks something similar to this...

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.... 

There is also a Stop button, which shall stop the logging process (and finally unregister by calling unregisterListener for each sensor)

The data retrieval process happens inside the onSensorChanged handler which shall retrieve the data from the relevant sensors, sets the value to the respective UI elements and finally log the data to an external .csv file.

onSensorChanged eventhandler looks something like this ...

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 ....

Although i receive the data from all the configured sensors, i do not have the control over the rate at which the data is received. i.e

I know SensorChanged event is fired as and when the Sensor data is changed. However i want this event to be fired at a fixed rate. For ex: every 40ms

Question:

  1. How to ensure the SensorChanged event is fired at constant rate ?
  2. Is the class TimerTask in Java of any help in this case ?

Experts out here in SO.Please help me :)

like image 924
this-Me Avatar asked Sep 03 '12 11:09

this-Me


People also ask

What is the use of SensorManager in Android?

SensorManager class provides methods : to get sensor instance, to access and list sensors, to register and unregister sensor listeners etc.

How can we work with the sensors in Android?

You can access sensors available on the device and acquire raw sensor data by using the Android sensor framework. The sensor framework provides several classes and interfaces that help you perform a wide variety of sensor-related tasks.


2 Answers

You can change the interval by changing the delay when registering for the sensor.

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

According to this, the Fastest delay is what you would need and if it doesn't changes fast enough for you is because there were no changes. There is no getSensorData method.

You can specify other data delays, such as SENSOR_DELAY_GAME (20,000 microsecond delay), SENSOR_DELAY_UI (60,000 microsecond delay), or SENSOR_DELAY_FASTEST (0 microsecond delay). As of Android 3.0 (API Level 11) you can also specify the delay as an absolute value (in microseconds).

The delay that you specify is only a suggested delay. The Android system and other applications can alter this delay. As a best practice, you should specify the largest delay that you can because the system typically uses a smaller delay than the one you specify (that is, you should choose the slowest sampling rate that still meets the needs of your application). Using a larger delay imposes a lower load on the processor and therefore uses less power.

like image 175
Marcio Covre Avatar answered Nov 08 '22 18:11

Marcio Covre


Since you know that if there was no SensorChanged Event fired, there was no change, you can just use your old value. As you asked for LOG data in specific intervals, i would not do any output in the onSensorChanged Method just clone the new data to your accelerometerdata variable. And than log the value of accelerometerdata every 40ms. This way you are logging the actual value every 40ms even if the data didnt change....

Note: According to Ridcullys Answer it also seem to be possible to get Sensor data "delivered" in specific time intervals. But since there is an delay on these "Deliveries" as always with sensor-data on Android, with my solution you will be more exactly on the 40ms interval. On the other hand it could happen that if the sensor data changes in the moment you log, it might happen that you delay the new data for one interval. And i guess (not sure about this point) - since its just about logging and not about sth like "get it as fast as possible in realtime", so this is not an requirement - the Timer-Solution causes less CPU-Load.

like image 43
nurgan Avatar answered Nov 08 '22 18:11

nurgan