Detect tilting and shaking of Android device via accelerometer and magnetic field sensors

3.1k views Asked by At

At the moment I am totally stuck with an university exercise. I've been trying hard the past few days and also did a lot of research but either I am trying to do something impossible or I am suffering from a terrible error in reasoning.

What is my goal? - I want to implement an Android App (android:minSdkVersion="8") which makes it possible to send feedback messages (positive or negative) via OSC. The feedback sending should not only be possible via clicking some buttons (that one was quite easy ;-) but also via shaking and tilting the device.

Shaking means rotating the smartphone from right to left or the other way round - just like shaking your head. Tilting means rotating the device up and down - like nodding your head.

As my device is not the freshest on the market I can only use the accelerometer and magnetic field sensors (i do not have a gyroscope or other stuff).

My idea based on googling a lot was to listen to the accelerometer and magnetic field events and use the rotation matrix to calculate the deltas between the angles. A certain delta on the x axis would be interpreted as tilting (nodding) and a certain delta on y would be shaking. As I did not come to a good result so far, I am asking myself if this is the right approach?!

Currently my SensorEventListener looks like this:

/**
 * TYPE_ACCELEROMETER
 * <ul>
 * <li>SensorEvent.values[0] Acceleration force along the x axis (including
 * gravity) in m/s2</li>
 * <li>SensorEvent.values[1] Acceleration force along the y axis (including
 * gravity) in m/s2</li>
 * <li>SensorEvent.values[2] Acceleration force along the z axis (including
 * gravity) in m/s2</li>
 * </ul>
 * 
 * TYPE_MAGNETIC_FIELD
 * <ul>
 * <li>SensorEvent.values[0] Geomagnetic field strength along the x axis in
 * µT</li>
 * <li>SensorEvent.values[1] Geomagnetic field strength along the y axis in
 * µT</li>
 * <li>SensorEvent.values[2] Geomagnetic field strength along the z axis in
 * µT</li>
 * </ul>
 */
@Override
public void onSensorChanged(SensorEvent event) {
    now = event.timestamp;

    // Handle the events for which we registered
    switch (event.sensor.getType()) {
    case Sensor.TYPE_ACCELEROMETER:
        System.arraycopy(event.values, 0, valuesAccelerometer, 0, 3);

        // no magnetic field data
        if (isArrayZeroFilled(valuesMagneticField)) {
            return;
        }

        // if rotation matrix cannot be retrieved
        if (!SensorManager.getRotationMatrix(null, rotationMatrix,
                valuesAccelerometer, valuesMagneticField))
            return;

        SensorManager.getOrientation(rotationMatrix, valuesOrientation);

        // valuesOrientation
        // values[0]: azimuth, rotation around the Z axis.
        // values[1]: pitch, rotation around the X axis.
        // values[2]: roll, rotation around the Y axis.

        zRotation = valuesOrientation[0];
        xRotation = valuesOrientation[1];
        yRotation = valuesOrientation[2];

        float xRotationDelta = Math.abs(xRotation - lastXRotation);
        System.out.println("x rotation delta " + xRotationDelta);

        float yRotationDelta = Math.abs(yRotation - lastYRotation);
        System.out.println("y rotation delta " + yRotationDelta);

        float zRotationDelta = Math.abs(zRotation - lastZRotation);
        System.out.println("z rotation delta " + zRotationDelta);

        break;

    case Sensor.TYPE_MAGNETIC_FIELD:
        System.arraycopy(event.values, 0, valuesMagneticField, 0, 3);
        break;
    }
}

Strangely, the y and z deltas are always 0.0, regardless of how I move or shake my phone.

I hope someone can give me a hint on what's wrong in my code or in my thinking.

Thanks in advance!

1

There are 1 answers

0
gregm On

This code will help you do detect shaking: 1