How can I find the velocity using accelerometers only?

前端 未结 8 1234
情书的邮戳
情书的邮戳 2020-12-08 12:01

Using only the phone\'s (Android) built in accelerometer, how would I go about finding its velocity?

I have been tinkering with the maths of this but whatever funct

相关标签:
8条回答
  • 2020-12-08 12:26

    Gravity is going to destroy all of your measurements. The phone, at standstill, is experiencing a high constant upward (yes, UP) acceleration. An accelerometer can't distinguish between acceleration and gravity (technically, they are the same), so it would get to extremely high velocities after a few seconds. If you never tilt your accelerometer even slightly, then you can simply subtract the constant gravitional pull from the z-axis (or whichever axis is pointing up/down), but thats quite unlikely.

    Basically, you have to use a complicated system of a gyroscope/magnetometor and an accelerometer to calculate the exact direction of gravity and then subtract the acceleration.

    0 讨论(0)
  • 2020-12-08 12:33

    If the phone is at standstil, you have ZERO acceleration, so your speed is 0. Probably you should find location data from GPS and get the associated time samples and compute velocity distance over time.

    0 讨论(0)
  • 2020-12-08 12:35

    Integrating acceleration to get velocity is an unstable problem and your error will diverge after a couple of seconds or so. Phone accelerometers are also not very accurate, which doesn't help, and some of them don't allow you to distinguish between tilt and translation easily, in which case you're really in trouble.

    0 讨论(0)
  • 2020-12-08 12:36

    There is nothing else to do but agree with the reasonable arguments put forward in all the great answers above, however if you are the pragmatic type like me, I need to come up with a solution that works somehow.

    I suffered a similar problem to yours and I decided to make my own solution after not finding any on-line. I only needed a simple "tilt" input for controlling a game so this solution will probably NOT work for more complex needs, however I decided to share it in case others where looking for something similar.

    NOTE: I have pasted my entire code here, and it is free to use for any purpose.

    Basically what I do in my code is to look for accelerometer sensor. If not found, tilt feedback will be disabled. If accelerometer sensor is present, I look for magnetic field sensor, and if it is present, I get my tilt angle the recommended way by combining accelerometer and magnetic field data.

    public TiltSensor(Context c) {
        man = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);
        mag_sensor = man.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        acc_sensor = man.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        has_mag = man.registerListener(this, mag_sensor, delay);
        has_acc = man.registerListener(this, acc_sensor, delay);
        if (has_acc) {
            tiltAvailble = true;
            if (has_mag) {
                Log.d("TiltCalc", "Using accelerometer + compass.");
            }
            else {
                Log.d("TiltCalc", "Using only accelerometer.");
            }
        }
        else {
            tiltAvailble = false;
            Log.d("TiltCalc", "No acceptable hardware found, tilt not available.");
            //No use in having listeners registered
            pause();
        }
    }
    

    If however only the accelerometer sensor was present, I fall back to accumulating the acceleration, that is continuously damped (multiplied by 0.99) to remove any drift. For my simple tilt needs this works great.

    @Override
    public void onSensorChanged(SensorEvent e) {
        final float[] vals = e.values;
        final int type = e.sensor.getType();
        switch (type) {
            case (Sensor.TYPE_ACCELEROMETER): {
                needsRecalc = true;
                if (!has_mag) {
                    System.arraycopy(accelerometer, 0, old_acc, 0, 3);
                }
                System.arraycopy(vals, 0, accelerometer, 0, 3);
                if (!has_mag) {
                    for (int i = 0; i < 3; i++) {
                        //Accumulate changes
                        final float sensitivity = 0.08f;
                        dampened_acc[i] += (accelerometer[i] - old_acc[i]) * sensitivity;
                        //Even out drift over time
                        dampened_acc[i] *= 0.99;
                    }
                }
            }
                break;
            case (Sensor.TYPE_MAGNETIC_FIELD): {
                needsRecalc = true;
                System.arraycopy(vals, 0, magnetic_field, 0, 3);
            }
                break;
        }
    }
    

    In conclusion I will just repeat that this is probably not "correct" in any way, it simply works as a simple input to a game. To use this code I simply do something like the following (yes magic constants are bad mkay):

    Ship ship = mShipLayer.getShip();
    mTiltSensor.getTilt(vals);
    float deltaY = -vals[1] * 2;//1 is the index of the axis we are after
    float offset = ((deltaY - (deltaY / 1.5f)));
    if (null != ship) {
        ship.setOffset(offset);
    }
    

    Enjoi!

    0 讨论(0)
  • 2020-12-08 12:37

    v = Integral(a) ?

    Generally though, I'd think the inaccuracies in the accelerometers would make this quite tough

    0 讨论(0)
  • 2020-12-08 12:40

    That will really depend on what the acceleration is and for how long. A mild, long acceleration could be measurable, but any sudden increase in acceleration, followed by a constant velocity, will make your measurements quite difficult and prone to error.

    Assuming constant acceleration, the formula is extremely simple: a = (V1-V0)/t . So, knowing the time and the acceleration, and assuming V0 = 0, then V1 = a*t

    In a more real world, you probably won't have a constant acceleration, so you should calculate Delta V for each measurement, and adding all those changes in velocity to get the final velocity. Always consider that you won't have a continuous acceleration data, so this is the most feasible way (i.e, real data vs integral math theory).

    In any way, even in the best scenario, you will end up with a very high error margin, so I do not recommend this approach for any app that truly depends on real velocities.

    0 讨论(0)
提交回复
热议问题