1

I wonder how to caluclate the vertical movement of a mobile device regardless of its orientation in space. That is, up and down movement in the real world. Below are three examples to demonstrate my purpose:

Example 1: A mobile phone lies flat on a table and is moved towards the ceiling for 100ms.

Example 2: A mobile phone is in landscape mode and is then moved towards the ceiling for 100ms.

Example 3: A mobile phone is in landscape mode but is tilted 45° on the horizontal axis (earth's surface) and is moved towards the floor for 100ms.

The algorithm I am looking for should output for all examples above and in general for every possible phone orientation that at least the device was moved upwards respectively downwards during the time period in the real world coordinate system.

I am not asking how this works on a particular system or OS. I only want to be given instructions how something like this would be accomplished in general.

What I do have right now is the code example below (which is from this topic on stackoverflow) but a) I don't really understand how it works and b) it doesn't work so well at all. Especially upwards movement detection is quite bad. The alpha value seems to be chosen quite arbitrarily (as many threshholds in answers to related questions do) which leaves me a little confused what it actually means.

As an alternative, I though about reading values out of the gyroscope and the accelerometer. With gyroscope data I could calculate a rotation matrix. By multiplying the matrix with the accelerometer data (a 1D vector of the device's x, y and z acceleration in its own coordinate system) I should be able to obtain real world movement, shouldn't I?

I am developing for Android so I am able to make use of accelerometer, gyroskop, magnetometer etc.

Thanks!

class AccelerometerReader(context: Context): SensorEventListener {

    private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
    private val gravity = FloatArray(3)
    private val linearAcc = FloatArray(3)

    fun registerListener(){
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL)
    }

    fun unregisterListener(){
        sensorManager.unregisterListener(this)
    }

    override fun onSensorChanged(event: SensorEvent?) {

        // alpha is calculated as t / (t + dT)
        // with t, the low-pass filter's time-constant
        // and dT, the event delivery rate
        val alpha = 0.8f

        gravity[0] = alpha * gravity[0] + (1 - alpha) * event!!.values[0]
        gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]
        gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]

        linearAcc[0] = event.values[0] - gravity[0]
        linearAcc[1] = event.values[1] - gravity[1]
        linearAcc[2] = event.values[2] - gravity[2]

        val scalarProduct: Float = gravity[0] * linearAcc[0] + gravity[1] * linearAcc[1] + gravity[2] * linearAcc[2]
        val gravityVectorLength = sqrt(gravity[0] * gravity[0] + gravity[1] * gravity[1] + gravity[2] * gravity[2])
        val linearAccVectorLength = sqrt(linearAcc[0] * linearAcc[0] + linearAcc[1] * linearAcc[1] + linearAcc[2] * linearAcc[2])

        val cosVectorAngle = scalarProduct / (gravityVectorLength * linearAccVectorLength)
        if (linearAccVectorLength > 2) { //increase to detect only bigger accelerations, decrease to make detection more sensitive but noisy
            if (cosVectorAngle > 0.5) {
                println("Down")
            } else if (cosVectorAngle < -0.5) {
                println("Up")
            }
        }
    }
}
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
rosmax
  • 11
  • 3
  • I'm assuming you want vertical acceleration, and not speed? Because you can't measure speed, there's no sensor for it on any device. – Nicolas Jun 22 '20 at 20:37
  • In the end I'd like my device to realize that it was moved upwards / downwards. I don't really care about the distance or how fast it was moved. I know that I have to make use of the accelerometer but I'm stuck on what to do with it. – rosmax Jun 23 '20 at 11:18
  • Calculating distance moved with the accelerometer is possible, although very inaccurate: https://arduino.stackexchange.com/questions/25529/detecting-distance-moved-by-accelerometer/25547. You'll have to do double numerical integration of the Y acceleration with respect to time. – Nicolas Jun 23 '20 at 14:46
  • 1
    Please read carefully. I am *not* interested in the distance. I only want to know whether my device was moved upwards or not at all during the given time period. – rosmax Jun 23 '20 at 18:08

0 Answers0