How can I find the velocity using accelerometers o

2020-02-03 05:13发布

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 function I come up with tends to lead to exponential growth of the velocity. I am working from the assumption that on startup of the App, the phone is at a standstill. This should definitely make finding the velocity (at least roughly) possible.

I have a decent background in physics and math too, so I shouldn't have any difficulty with any concepts here.

How should I do it?

8条回答
▲ chillily
2楼-- · 2020-02-03 05:23

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.

查看更多
贼婆χ
3楼-- · 2020-02-03 05:28

First, you have to remove the acceleration due to gravity from the accelerometer data. Then it's just a matter of integrating the acceleration to get the velocity. Don't forget that acceleration and velocity are properly vectors, not scalars, and that you will also have to track rotation of the phone in space to properly determine the orientation of the acceleration vector with respect to the calculated velocity vector.

查看更多
▲ chillily
4楼-- · 2020-02-03 05:30

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.

查看更多
你好瞎i
5楼-- · 2020-02-03 05:31

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!

查看更多
再贱就再见
6楼-- · 2020-02-03 05:33

The accelerometers in a phone are pretty much useless for such a task. You need highly accurate accelerometers with very low drift - something which is way beyond what you will find in a phone. At best you might get useful results for a few seconds, or if very lucky for a minute or two after which the results become meaningless.

Also, you need to have a three axis gyroscope which you would use to integrate the velocity in the right direction. Some phones have gyros, but they are even poorer than the accelerometers as far as drift and accuracy are concerned.

One possibly useful application though would be to use the accelerometers in conjunction with gyros or the magnetic compass to fill in for missing data from the GPS. Each time the GPS gives a good fix one would reset the initial conditions of position, speed and orientation and the accelerometers would provide the data until the next valid GPS fix.

查看更多
聊天终结者
7楼-- · 2020-02-03 05:34

v = Integral(a) ?

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

查看更多
登录 后发表回答