I am trying to implement a fitness app that can keep track of the running speed and running distance in Android.
It looks like I can either use GPS or Accelerometer to calculate these information.
Since a runner may put his phone in hand, on the shoulder or in his pocket, my first intuition is to use GPS to get locations and calculate running speed and running distance. But recently someone telled me that I can also use Accelerometer also does that.
My question is: In Android, which approach is better to calculate running speed and running distance, GPS or Accelerometer?
I suspect that pedometers are based on accelerometers because accelerometers are cheaper than GPS to use. in fact I think a lot of pedometers don't even try to measure distance. just acceleration jolts which equal steps. and then if they give you a distance measurement, it's by multiplying detected steps by a guessed or average step size.
GPS (if you are in an area where it works!) will do a very good measurement of distance. Even with a very cheap GPS receiver. All being basically OK, you should expect start and end positions to within 10m, and so for a 1km travel, you have 20m of uncertianty, which is 2% total distance uncertianty. This uncertianty goes down linearly with distance travelled (ie a 2km run will have 1% uncertianty, 4 km run will have 0.5% uncertianty, etc) the issues here will be with your realtime displays (GPS position jumps from satellite switching giving massive speed values, or immediate loss of signal giving a loss of all immediately displayable data)
I think that with a good accelerometer, starting from stopped you can continually integrate the signal to get speed, and continually integrate that result to get distance... I am just unsure what kind of accelerometer quality you get in any given phone? you may need to filter for noise or even garbage data.. And you also need to consider what accuracy it has. 20% accuracy in your sensor would make for a very bad distance tracker. So you might have to work with step counting and step size guesstimates.
perhaps a combination of both could work?
I'd be tempted to use the accelerometer data (either integrating or step counting depending on what will always work) to track speed and distance in short timeframe, then with much longer timeframe, generalised GPS data could be used to correct or scale that data from the accelerometer. Especially if you filtered/blocked GPS data based on uncertianty measurement at any given time.
Adding to what Julian said ... Normally GPS doesn't work under the roofs therefore for indoor gyms it will not work. Theoretically GPS signals are not bothered by clouds but when I was working on my GPS application, I had experience of unavailability of GPS signals in really bad weather (this might not be your case as no one will go on jogging in thunder storm :D)
Agreeing with Julian, you should use both GPS and accelerometer to build a reliable app for every condition.
The best results are obtained by using both of them, through sensor fusion. See:
Android accelerometer accuracy (Inertial navigation)
You will have accuracy problems if you just use either the GPS or a pedometer algorithm.
All pedometers I know are based on accelerometers. I guess, GPS is not precise enough for this stuff. It may say "no motion" while you did some steps, it's also dependent on the area you are trying to use it.
Related
I'm developing iOS/Android app that tracks mileage user has driven in his car.
Even though the task seems pretty trivial, there are 2 problems:
1) Mileage is not accurate comparing to car's odometer. (OD-10mi, App-8.5mi)
2) When user stays still outside the car, mileage keeps accumulating (it can add up like 4mi within 30 minutes.)
Is there any "easy" fix for that without adding complicated filtering, etc?
There are two small but significant things you can do:
For each GPS sample, check its accuracy. If it's over some threshold (say 20 meters) - ignore it.
Add a method that detects if the mobile is static or not. You can do it by reading the device's accelerometer - if the delta between two readings is bigger than some threshold - the car is moving. If it's too small - ignore the GPS. You'll have to try some values until you find the right threshold/
For question 1, vehicle odometer, in the US, are only required to be within 5mph of the actual speed at 50mph. My experience shows most vehicles are more erroneous than the law requires. That 10% difference could easily become the 1.5 miles you saw.
Vehicles odometers are allowed to over estimate in europe by 7%.
My car has about 3% over estimate.
There are simple solutions, that work for cars, that have been posted here on Stackoverflow multiple times, including by myself.
There is no simple solution for pedestrians.
Answer to question 2: problem certainly comes from the accurary of the GPS location.
Android Location object comes with an estimated accuracy for the given coordinates.
Suppose you stay in absolute position (0,0) without moving. The android device GPS could produce the following Locations stream:
(1,1) with an accuracy of 2m
(-2,3) with an accuracy of 5m
(0,0) with an accuracy of 1m
etc...
If you just keep adding the distances between the successive Locations, the sum will indefinitely increase, although you don't move.
One solution could be that you take into account new Locations from the stream only if their accuracy is small enough compared to the distance to the last location.
I understand that there are three approaches for it
GPS Based: Add up short distances travelled (calculated using Location.distanceTo) in small time intervals (5-10 secs), but this method is prone to GPS errors and would not work indoors or in short running area (like a small park)
Double Integration of acceleration: I can do double integral of accelerometer data to calculate distance but errors due to noise in accelerometer readings may add up.
Step counting: I can detect steps by measuring spikes in accelerometer data OR using Google Fit API and then multiply the total number of steps with the average stride length. But the problem here is figuring out average stride length.
I am inclined towards using #3 as it works indoors and is not much error prone OR battery draining. But How do I get average stride length for each step, especially when runner's stride varies in length when sprinting and jogging.
Does anyone know of any combination of these methods to get the best results? OR any other totally different but efficient method?
Well it's engineering - there is no simple answer ;)
All these methods you've mentioned has their pros and cons.
GPS tracking won't sumarize errors of each measurement - it's great but on the other hand each location will be given with noticeable error. What is more you'll have problems with using your app in buildings etc.
Double integration of acceleration works great on small distances by the time error grow to big number. It is also difficult to create program which will calculate it in appropriate way. There is a lot of important issues like e.g time of sampling or rotation and translation matrix calculation that makes these application very problematic on android.
In my app I used following algorytm:
Calculate location from GPS (from Network provider or GPS provider - best precision wins)
Start using accelerometer-based algorytm.
Stop using accelerometer-based algorytm when:
GPS and accelerometer measurements are very different
Accelerometer-based algorythm finds that calculated quaternions are different from what magnetometer says.
The velocity or acceleration from measurments is bigger than given value.
Go to point 1
Hope it helps
I am working on app in which I have to calculate the total distance from start point to end point. I use the Location Manager of the Android SDK, use location listener and use both provider(GPS and network provider) and in every 20 seconds I have track the location and put the tracked location into the array list. After a time period calculate the total distance by
total distance = dist at point[0,1]+ dist at point[1,2] + ... +dist at point[n-1,n]
where 0,1,2,...,n is the index of array list location value.
After several test, Not got the accurate result. Approximately 60-70% of actual odometer value. Please guide if have some other alternative to be used.
Please guide me how I got more accurate result.
GPS and network location both have a degree of uncertainty associated with them, so neither will generally give you an exact distance when compared to something like an odometer. If you're outdoors and not in urban canyons, GPS will generally give you a better distance estimate than network location.
Underestimates of distance (what you're seeing) is probably due to your sampling rate (every 20 secs) or lost GPS signals. I'd try increasing your sampling rate to once every 4 seconds or so, and make sure your GPS unit isn't losing a fix. GPS sensitivity can vary widely across devices, so try to test with a few different Android devices. You can also check out an Android app I developed to help measure GPS accuracy on Android devices:
http://www.gpsbenchmark.com/
Overestimates of distance are generally caused by GPS noise, or the position bouncing around due to small (and sometimes large) GPS position error. Kalman filters are a good way to reduce the impact of some of this noise. You can also try to filter the path and reduce some of the detail via line simplification. An implementation of the Douglas-Peucker algorithm to do this is available under Apache 2.0 in the MyTracks project:
http://code.google.com/p/mytracks/source/browse/MyTracks/src/com/google/android/apps/mytracks/util/LocationUtils.java#78
What is the best way to detect user device moving? For now I'm using network/GPS location determining best coordinates on small interval. But it would be great to improve accuracy user movement information up to meters. Geolocation strongly depends on network connection quality or weather.. Is there a way to find very accurate info about device moving? May be accelerometer can help?
Accelerometers tend to be a poor way to measure distance moved, as the slightest error in the measurement of acceleration or orientation rapidly integrates to a substantial position error. That's even more true with low-accuracy components used in a consumer device - inertial navigation systems used in aircraft/spacecraft are not cheap, and even those might not be accurate enough for your needs.
If you want positioning accuracy, especially over any duration of time, you need to measure in relation to the outside world, as GPS does. There are various beacon systems available using things like ultrasonics, or even adding pretend satellites to the GPS system which you could look into, but it's not going to be simple.
let's say i want to build a smartphone app that tells a user when/where to get off a subway station. i can think of two ways of doing this:
1) using GPS and map of the subway routes, track the location of the user and notifies him when the destination is reached
2) have him press start when he gets on a train as the train starts (which may not be realistic because the user could simply forget to do this), use the known travel time from starting station to end station, and simply notifies him when the time is up.
can someone tell me if there are any other good approaches? thanks.
You may have to go with 'dead reckoning'. Basically, dead reckoning is a navigation technique that uses a confirmed starting location plus accurate velocity and time to calculate a new location. Keep in mind that velocity is itself a combination of heading and speed and that the heading must be a true heading. In an airplane, compass heading would have to be combined with wind speed and direction to get a true heading. I don't think you have to account for drift on a subway, but you will have to account for varying device orientation as the user moves around or uses the device itself. Also, just because heading is normally a compass bearing doesn't mean that it has to be. You may be able to get the job done using only the accelerometers and a timer.
Proper use of dead-reckoning also requires frequent 'resets' to known locations as you reach them so that errors can't add up too badly. For this application, I would argue that curve- and stop-detection can be used as resets. You may get false positives for 'service' stops that are too close to real stops, but those may be rare enough to ignore. In fact, if it wasn't the exit stop, it might not matter because you might still be accurate enough for the next-stop warning and if was the exit stop, it won't matter because the ride is over.
To summarize: you need to be sure that you have a good initial starting point; you need to compensate for device reorientation to get true heading; you need to know your average speed between heading changes and the time-on-heading to calculate distance-on-heading. You can improve overall accuracy by resetting at known landmarks.
Edit: I don't know if this gets you any closer to the answer, but Chris Stratton raised an interesting point about summing the accelerometer vectors. Is it possible to track the orientation of the device accurately enough to have a reliable orientation-independent gravity vector? Can you keep that out of your vector sum? Can that provide a useful acceleration along a useful orientation-independent vector? If so, then tracking the duration of the acceleration will get you an average speed for that duration and a final speed for the end of acceleration. Absent acceleration, the speed will remain constant. Putting that all together might pile inaccuracy on top of inaccuracy to the point of uselessness.
If the subway line has cellular service (some that were going to had it turned off on security concerns) you might be able to do something with network location.
You could use the accelerometer to try to detect and count station stops - but trains stop in between stations from time to time due to delays ahead. Also battery life would be reduced. EDIT: realized you won't be able to tell acceleration from deceleration as you have no idea of orientation (unless you find the compass sensor workable in that environment) - you could only see that the vector sum of the three accelerometers was greater than gravity for a period of seconds.
You could try to use the microphone to detect the sounds of train motors and brakes (some are extremely characteristic) but that has the same problem with battery life and unscheduled stops between stations. Not to mention scheduled stations bypassed for repair work.
Perhaps you should give the user a scrollable list of stations marking the journey and let them keep track.
Both of those sound like poor solutions. You almost certainly won't get a GPS trace in a subway. And the 2nd way sounds like it will be inaccurate enough to make the app useless.
Read carefully Falmarri's answer. He's completely right, although he didn't give you an answer. Let me try then...
If the routes have no many curves, it will be easier: you just have to hardcode the latitude and longitude of each station, and then, calculating the position of the user will be straightforward (just a little of math and that's it). If the routes have curves, then you have more work to do but it's basically the same.
You will probably want to use a way to know the distance between the current location and the station location. You could use some of the existing algorithms, for instance the Haversine formula.