Home » Android » accelerometer – Calculating distance using Linear acceleration android

# accelerometer – Calculating distance using Linear acceleration android

Questions:

Possible Duplicate:

I am using the following code to calculate the distance. `tnew` and `anew` are `arraylists` containing timestamps and accelerations respectively.

`````` double distance=0;
double init_vel=0;
long time_prev=tnew.next();
while(anew.hasNext())
{
float temp_acc=anew.next();
long temp_time=tnew.next();

interval=(temp_time-time_prev)/1000f;   //milliseconds to seconds
double fin_vel=init_vel+(temp_acc*interval);
distance+=(init_vel*interval)+0.5f*temp_acc*interval*interval;

init_vel=fin_vel;
time_prev=temp_time;
}
``````

Is there any logical mistake in the code? Because I am getting values much smaller than the actual length.

Output of `LogCat` :

``````--------- beginning of /dev/log/system
--------- beginning of /dev/log/main
V/PhonetapeActivity( 8842): Sensor Listener Registered
V/PhonetapeActivity( 8842): Sensor Unregistered
V/PhonetapeActivity( 8842): No. of Iterations : 49
V/PhonetapeActivity( 8842): Value of acceleration : 3.5762787E-7
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665585965
V/PhonetapeActivity( 8842): Value of acceleration : -0.15275347
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586017
V/PhonetapeActivity( 8842): Value of acceleration : 0.15585232
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586077
V/PhonetapeActivity( 8842): Value of acceleration : 1.075269
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586138
V/PhonetapeActivity( 8842): Value of acceleration : 3.6529458
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586199
V/PhonetapeActivity( 8842): Value of acceleration : 9.645137
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586257
V/PhonetapeActivity( 8842): Value of acceleration : 17.022213
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586316
V/PhonetapeActivity( 8842): Value of acceleration : 9.721476
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586376
V/PhonetapeActivity( 8842): Value of acceleration : -18.729362
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586437
V/PhonetapeActivity( 8842): Value of acceleration : -22.868385
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586497
V/PhonetapeActivity( 8842): Value of acceleration : -16.777517
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586557
V/PhonetapeActivity( 8842): Value of acceleration : -7.0492268
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586617
V/PhonetapeActivity( 8842): Value of acceleration : -3.860828
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586677
V/PhonetapeActivity( 8842): Value of acceleration : 1.7244682
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586737
V/PhonetapeActivity( 8842): Value of acceleration : 5.0734243
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586797
V/PhonetapeActivity( 8842): Value of acceleration : 6.4193974
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586857
V/PhonetapeActivity( 8842): Value of acceleration : 2.739545
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586917
V/PhonetapeActivity( 8842): Value of acceleration : 5.559997
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665586977
V/PhonetapeActivity( 8842): Value of acceleration : 4.2290807
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587037
V/PhonetapeActivity( 8842): Value of acceleration : 5.0012918
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587097
V/PhonetapeActivity( 8842): Value of acceleration : 5.9317436
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587157
V/PhonetapeActivity( 8842): Value of acceleration : 5.20226
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587217
V/PhonetapeActivity( 8842): Value of acceleration : 7.1381693
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587276
V/PhonetapeActivity( 8842): Value of acceleration : 7.6460614
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587337
V/PhonetapeActivity( 8842): Value of acceleration : 5.566694
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587396
V/PhonetapeActivity( 8842): Value of acceleration : 3.355657
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587457
V/PhonetapeActivity( 8842): Value of acceleration : 1.8876343
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587517
V/PhonetapeActivity( 8842): Value of acceleration : -0.8815446
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587577
V/PhonetapeActivity( 8842): Value of acceleration : -0.9595623
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587646
V/PhonetapeActivity( 8842): Value of acceleration : -4.233544
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587697
V/PhonetapeActivity( 8842): Value of acceleration : -1.9580669
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587765
V/PhonetapeActivity( 8842): Value of acceleration : -1.4569702
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587822
V/PhonetapeActivity( 8842): Value of acceleration : -0.6058636
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587876
V/PhonetapeActivity( 8842): Value of acceleration : -0.21207428
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587937
V/PhonetapeActivity( 8842): Value of acceleration : 0.5068469
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665587997
V/PhonetapeActivity( 8842): Value of acceleration : 5.614555
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588057
V/PhonetapeActivity( 8842): Value of acceleration : -4.5297813
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588122
V/PhonetapeActivity( 8842): Value of acceleration : -0.29250193
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588178
V/PhonetapeActivity( 8842): Value of acceleration : -2.4922757
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588237
V/PhonetapeActivity( 8842): Value of acceleration : -1.7652755
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588297
V/PhonetapeActivity( 8842): Value of acceleration : -2.3279366
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588357
V/PhonetapeActivity( 8842): Value of acceleration : -1.8127642
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588419
V/PhonetapeActivity( 8842): Value of acceleration : -1.956768
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588477
V/PhonetapeActivity( 8842): Value of acceleration : -0.8337221
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588537
V/PhonetapeActivity( 8842): Value of acceleration : -0.24841261
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588601
V/PhonetapeActivity( 8842): Value of acceleration : 0.23997736
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588657
V/PhonetapeActivity( 8842): Value of acceleration : 0.14441395
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588723
V/PhonetapeActivity( 8842): Value of acceleration : 0.23150349
V/PhonetapeActivity( 8842): Value of timestamp(milli) : 1350665588777
V/PhonetapeActivity( 8842):  1st while loop ended
V/PhonetapeActivity( 8842): 2nd while loop ended
V/PhonetapeActivity( 8842): Avg value : 0.4006781578063965
V/PhonetapeActivity( 8842): Max Value : 17.022213
V/PhonetapeActivity( 8842): Min Value : -22.868385
V/PhonetapeActivity( 8842): Standard Deviation : -0.0031174493
V/PhonetapeActivity( 8842): 3rd while loop started
V/PhonetapeActivity( 8842): startpos=3 endpos=8
V/PhonetapeActivity( 8842): acceleration=0.1558523178100586 interval=0.061000000685453415
V/PhonetapeActivity( 8842): distance=5.799264876044276E-4
V/PhonetapeActivity( 8842): next init velocity=0.009506991493243078
V/PhonetapeActivity( 8842): acceleration=1.0752689838409424 interval=0.061000000685453415
V/PhonetapeActivity( 8842): distance=0.005160928954000712
V/PhonetapeActivity( 8842): next init velocity=0.07509840024458736
V/PhonetapeActivity( 8842): acceleration=3.6529457569122314 interval=0.057999998331069946
V/PhonetapeActivity( 8842): distance=0.021805144861910285
V/PhonetapeActivity( 8842): next init velocity=0.2869692480489858
V/PhonetapeActivity( 8842): acceleration=9.645136833190918 interval=0.05900000035762787
V/PhonetapeActivity( 8842): distance=0.07231105232279186
V/PhonetapeActivity( 8842): next init velocity=0.8560323246566197
V/PhonetapeActivity( 8842): acceleration=17.022212982177734 interval=0.05999999865889549
V/PhonetapeActivity( 8842): distance=0.18495295465057213
V/PhonetapeActivity( 8842): next init velocity=1.8773650807587172
V/PhonetapeActivity( 8842): 3rd while loop ended
V/PhonetapeActivity( 8842): final distance=0.18495295465057213
V/PhonetapeActivity( 8842): values of acceleration, timestamp, distance, start_time and calibrating reset
``````

If you observe the logcat, first it iterates through 49 values of acceleration and their respective time stamps in milliseconds. Then there is a avg, sum, max, min etc.
Then if you see there is a `startpos=3` and `endpos=8`. This is the iteration number range, I am using to calculate the distance .i.e I am using the values of acceleration and timestamp only from iteration 3 to 8.
This is because, I detect the start of distance calculation from a rise in acceleration to a sudden change in the opposite direction. You can see that the values from 3-8 fit into the logic. From 3 there is a considerable rise in acceleration and after 8 there is a sudden decrease.

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! 🙂

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).:

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.