calculate actual distance travelled by mobile [closed]
------------------UPDATE----------------------
There is two major point in your question.
1) get the phone coordinates (which has been treated in the first part of this response)
2) Calculate the real distance between this two coordinates
IMHO, calculus could be done by a web service: calculation based onlyon the distance between two coordinates can lead to really wrong result.
Here is an exemple of such a web servicehttps://graphhopper.com/#directions-api
The demo app: https://graphhopper.com/api/1/examples/
It's based on traffic flow (as many of this tools)So you have to be careful with the order of the coordinatesbecause it can bring wrong result.
For exemple with two point in the right order:
This gives a good result
But if you give wrong order (with the same coordinates)
For the same coordinates, it can lead to an extremely different result.
So for coordinates ABCD (in chrnological order)you need to do:
A->B B->C C->D
Graphhopper seems able to do offline distance calculus
Here are the lib on iOS and Android
https://github.com/graphhopper/graphhopper-ios/
https://github.com/graphhopper/graphhopper/tree/master/android
---------------------------------------------------
You have to define how your app work. Foreground or background?
As said in other responses, you'll have to get the user position every X seconds. Then calculate the distance.
For iOS:
- You can use information on this website: http://mobileoop.com/
It talks about tracking user location on iOS when the app is in background.
- Here is the github: https://github.com/voyage11/Location
Then you have to convert the point thanks to
CLLocationDistance distance = [aCLLocationA distanceFromLocation:aCLLocationB];
You can also check this (from apple doc) https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html:
Make sure the location manager’s pausesLocationUpdatesAutomatically property is set to YES. When this property is set to YES, Core Location pauses location updates (and powers down the location hardware) whenever it makes sense to do so, such as when the user is unlikely to be moving anyway. (Core Location also pauses updates when it can’t obtain a location fix.)
Assign an appropriate value to the location manager’s activityType property. The value in this property helps the location manager determine when it is safe to pause location updates. For an app that provides turn-by-turn automobile navigation, setting the property to CLActivityTypeAutomotiveNavigation causes the location manager to pause events only when the user does not move a significant distance over a period of time.
CLActivityTypeAutomotiveNavigation insure you to get a position which is on a road.
For Android:
- You can use this project:https://github.com/quentin7b/android-location-tracker
That can easily helps you to get the user's position thru timeThanks to the TrackerSettings object
TrackerSettings settings = new TrackerSettings() .setUseGPS(true) .setUseNetwork(true) .setUsePassive(true) .setTimeBetweenUpdates(30 * 60 * 1000) .setMetersBetweenUpdates(100);
- To find the distance between two point on Android, you can check this:Get the distance between two geo points
Both OS
Based on a position picked up every X second you have to reduce time between picking location data to improve accuracy.
As you want to calculate distance on a road context, setup the Location manager in navigation mode, this mode gives you coordinates that are on road.
Finally
If you want to improve the accuracy of your distance calculus,you can use a google API:https://developers.google.com/maps/documentation/distance-matrix/intro
By setting the right mode parameter:
Optional parameters
mode (defaults to driving) — Specifies the mode of transport to use when calculating distance. Valid values and other request details are specified in the Travel Modes section of this document.
I'm working on something similar on Andoriod, but the principals are the same for iOS either:
- For each GPS sample, check its accuracy. If it's over some threshold (say 20 meters) - ignore it.
- Remember that even if the mobile device is static, different GPS samples will give you different locations, depending on the accuracy. A car standing still for a long time in a traffic light, will show that you've advanced few dozens of meters, so add a method that detects if the mobile is static or not. I've implemented this by reading the accelerometer - if the delta between two readings if bigger than some threshold - the device is moving. If it's too small - ignore the GPS.
- If you intend to use it in a car, you can read the GPS whenever it has a new reading (in Android use the
onLocationChanged
method). If you use it for running/walking, take into account that your speed is slow - two consecutive readings will be relativly close, but due to the GPS's accuracy, you can get quite a large distance betwwen them. It can be fixed by increasing the time between two consecutive readings, or by ignoring some of them (i.e. take into account only each 10th reading). - Use the Haversine formula to calculate the distance between two consecutive readings. In Android it can be done with the
Location.distanceTo()
method.
You'll have to test it against the odometer in your car and adjust the thresholds for the accelerometer.
4 years ago, I just made an app called Landsurvayor that calculates the actual distance of two geo-graphical points drawn on Google Map. I don't know that might help you or not but there is a formula called Haversine formula that calculates the actual distance between two geo-graphical points. You might give it a try and see whether it is useful for you or not. Below is the sample code of Haversine formula:
public double CalculationByDistance(double initialLat, double initialLong, double finalLat, double finalLong){int R = 6371; // kmdouble dLat = toRadians(finalLat-initialLat);double dLon = toRadians(finalLong-initialLong);lat1 = toRadians(lat1);lat2 = toRadians(lat2);double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c;}public double toRadians(deg) { return deg * (Math.PI/180)}
More about Haversine formula:https://en.wikipedia.org/wiki/Haversine_formula
There is another simple Android SDK built-in approach to calculate distance between two lat, lng:
Location locationA = new Location("point A"); locationA.setLatitude(latA); locationA.setLongitude(lngA);Location locationB = new Location("point B");locationB.setLatitude(latB); LocationB.setLongitude(lngB);distance = locationA.distanceTo(locationB) ;
I hope it might help you.