Calculating distance using Linear acceleration android [duplicate]

血红的双手。 提交于 2019-11-27 19:11:48

Accelerometers are very precise but bad at dead-reckoning. Gyroscopes are good at that but they "drift" over time. "Sensor-fusion" is the process of using accel/gyro data in tandem to correct one's deficiency using the other. AFAIR, "sensor-fusion" is NOT enabled on Galaxy Ace. LINEAR_ACCELERATION is nothing but ACCELEROMETER - gravity component. On devices without gyroscope, fusion is not possible by definition it requires accel+gyro.

The accelerometer data contains the gravity component of 9.8. This is filtered out by simply determining the difference between 2 consecutive samples of accelerometer data. This gives us the LINEAR_ACCELERATION data.

Check this out for actual internal code :
frameworks/base/services/sensorservice/LinearAccelerationSensor.cpp
The function LinearAccelerationSensor::process() is of interest in the above file.

Also rudimentary operations like filtering/averaging that the above link and video talk about, need to performed on the accel data obtained in your app. The processed values obtained in this manner will be better(though not as good as the ones that would have been obtaioned had sensor fusion been present on your device) than the raw values. These can then be used to calculate the velocity and position more accurately.

That said, 16 samples a second (@poll-rate=60ms) is relatively inaccurate in itself. You might want to try registering the sensorEventListner using SENSOR_DELAY_FASTEST to see the maximum number of samples that you can obtain on you device.

Also note that the accelerometers on phones are clamped to certain MAX sensitivity (usually -/+ 2/4/8 G range). While normal walking/running might operate under these ranges, a sudden impulse in acceleration (for example on a bike) will definitely be clamped to the MAX and you will lose sync in dead-reckoning. This can be checked by noting the number of samples that are very close to the -/+MAX. Lot of samples at -/+MAX imply that you would have most certainly lost sync with the actual position.

The first thing I would check is your time interval. I am not certain it is being converted properly. The timestamp is listed as:

public long timestamp The time in nanosecond at which the event happened

And so in the documentation we see the conversion is done by dividing by 1 billion instead of 1 thousand.

float dT = (event.timestamp - timestamp) / 1000000000.0f;
timestamp = event.timestamp;

That said I think that change will just shrink the values but to calculate real world distance you need to watch your units.

Next, when reading about these things people are always going on about how you need to know your initial position for each reading to make any sense with respect to real world linear measurements. I do not see you tracking your previous acceleration which will make each following measurement's integration based on instantaneous acceleration, or the change in acceleration, instead of full acceleration.

Try something like this:

final int X = 0;
double distance[];
double init_vel[];
double total_Accel[];

void dblIntegrate(SensorEvent event){
    double data[] = new double[3];
    for(int i = 0; i < event.lenght; i++){
        data[i] = (double)event[i];
        total_Accel[i] += data[i];
        vel[i] = init_vel[i] + (total_Accel[i] * dt);
        init_vel[i] = vel[i];

        ....rinse and repeate to get distance
        (not using the accel data of course)
    }
}

I realize you understand this but for anyone else is reading this => remember you can't have the counting vars total_Accel or init_vel re-instantiated each time you call dblIntegrate().

If you are doing it right you should see total_Accel go from zero to some max value then back to zero every time you move the device. This means you are adding equal parts positive and negative acceleration each time the device moves in any direction.

I believe this is the property of acceleration that is the hardest to understand properly because for the device to go from resting state to resting state your total_acceleration will go from zero to a max pos/neg value back to zero to the oppposite max value and then back to zero.

For example, if I move a phone resting on its back on a table with the bottom facing my chest to the right for one meter you will get something like this:

total_Accel = 0.0 (0 Meters)

total_Accel = 0.5

total_Accel = 1.0

total_Accel = 1.5 (approx .25 Meters)

total_Accel = 1.0

total_Accel = 0.5

total_Accel = 0.0 (if accel is perfectly distributed, .5 Meters)

total_Accel = -0.5

total_Accel = -1.0

total_Accel = -1.5 (approx .75 Meters)

total_Accel = -1.0

total_Accel = -0.5

total_Accel = 0.0 (1 Meter)

In the example you can start to see why simply doubly integrating the change in acceleration isn't going to give you the real change in velocity/displacement.

I hope so anyway because writing this took a lot longer than I had thought it would! :)

This is an answer to your question:

why I need to track my previous acceleration. onSensorChanged(MotionEvent event){} is called when there is a change in acceleration. It provides the new acceleration and not the change in acceleration.

The short answer is, integrating the reading w/o including the initial condition (your total previous acceleration) you will end up with a value that does not include all the information. Plus, the longer you go the further your value gets from the real value because you are losing more and more information.

I do not think you want an explanation of acceleration, velocity and displacement (and this is not the place for that) so maybe I can show it by expanding the example I included above.

A phone resting on its back on a table with the bottom facing my chest is moved to the right for an arbitrary distance and stops. If you look at your data you will get something like this. Of course the actual numbers will vary widely but their signs will be the same and the proportions will be kind of the same but will start smaller than they peak like you would expect (unless you fired it out of a gun at a wall or whatever).:

Time...........Accel Reading...........Total Accel........Total Velocity


00ms.............. 0.0......................0.0.......................0.000..

10ms.............. 0.5......................0.5.......................0.005 m/s..

20ms.............. 0.5......................1.0.......................0.015 m/s..

30ms............. 0.5......................1.5.......................0.030 m/s..

40ms............. -0.5......................1.0.......................0.040 m/s..

50ms............. -0.5......................0.5.......................0.045 m/s..

60ms............. -0.5......................0.0.......................0.045 m/s..

70ms............. -0.5.....................-0.5.......................0.040 m/s..

80ms............. -0.5.....................-1.0.......................0.030 m/s..

90ms............. -0.5.....................-1.5.......................0.015 m/s..

100ms............. 0.5.....................-1.0.......................0.005 m/s..

110ms............. 0.5.....................-0.5.......................0.000 m/s..

120ms............. 0.5......................0.0.......................0.000 m/s..

You can see that if you do not track total acceleration your total velocity would be the column marked Total Accel above. That would mean your phone would be moving in the positive direction of the x-axis the whole time but your velocity would be negative (moving backwards) the last half of the movement.

I hope this proves my case even if it does not explain the mechanics behind acceleration or accelerometers.

If you wanted to look-up how the accelerometer works they are MEMS type sensors and I think they use a suspended cantilever beam with a weighted end to measure the force of acceleration.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!