Calculating Speed for a navigation app without getSpeed() method
android, android-location, android-navigation, geolocation, gps
Solution
I develop MyTrails, an Android mapping and tracking app, and like you I struggled at first with the very crude location APIs Google has seen fit to include in Android.
hasSpeed() is false when the GPS chip doesn't have a good enough fix to compute speed based on dopler effect. Even when it does, I usually don't trust the speed if it's less than 5km/h or thereabouts.
The way I handle speed calculations is by using a crude low-pass filter: I record a trackpoint every second (and a minimum of 5m apart, based on `LocationManager.requestLocationUpdates()`, and to calculate the recent speed, I go back a few samples to get one that is a sufficient distance apart (but no more than 30s prior), and perform the averaging you're doing.
I'm using Location.distanceBetween() for the actual distance calculation. Beware that it fails on a very small (but unfortunate) number of devices, so the haversine method you have may be a better bet. You may want to check it though, what I have is
/**
* Gets distance in meters, coordinates in RADIAN
*/
private static double getDistance(double lat1, double lon1, double lat2, double lon2) {
double R = 6371000; // for haversine use R = 6372.8 km instead of 6371 km
double dLat = lat2 - lat1;
double dLon = lon2 - lon1;
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1) * Math.cos(lat2) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
//double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
// simplify haversine:
//return 2 * R * 1000 * Math.asin(Math.sqrt(a));
}
(note the 1000 factor)
Problem
I am developing an app which is more of a time-shift racing between your friends. I need to calculate speed of a moving vehicle, and I don't want to use `Location.getSpeed()` method. (Explained in detail in the bottom why I don't want to use it) I am trying to calculate speed with the help of Latitude and Longitude available to me, and this is where I need help. The help needed: I would want to know is: - If the algorithm is correct - Should I calculate in Centimeters instead of meters - And if there's any code/library already available which does it. I am using the following code: This gives me distance between two LatLng points: ``` long getDistanceBetweenPoints(double lat1, double lng1, double lat2, double lng2 ){ double dLat = Math.toRadians(lat2 - lat1); double dLon = Math.toRadians(lng2 - lng1); double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); double c = 2 * Math.asin(Math.sqrt(a)); long distanceInMeters = Math.round(6371000 * c); return distanceInMeters; } ``` And the following code is how it is being used: ``` if(lastLat == -1 && lastLng == -1){ lastLat = location.getLatitude(); lastLng = location.getLongitude(); lastTimeStamp = location.getTime(); return; } long distanceInMeters = getDistanceBetweenPointsAndSetTotal(lastLat, lastLng, location.getLatitude(), location.getLongitude()); long timeDelta = (location.getTime() - lastTimeStamp)/1000; long speed = 0; if(timeDelta > 0){ speed = (distanceInMeters/timeDelta); } Log.d("Calculations","Distance: "+distanceInMeters+", TimeDelta: "+timeDelta+" seconds"+",speed: "+speed+" Accuracy: "+location.getAccuracy()); lastLat = location.getLatitude(); lastLng = location.getLongitude(); lastTimeStamp = location.getTime(); ``` When I run it, I get following output from that LogCat: ``` Distance: 0, TimeDelta: 0 seconds,speed: 0 Accuracy: 5.0 ``` Detailed Reasons The target consumers are not supposed to have high quality devices with high-quality GPS chips, thus always getting a very accurate fix when the device is on the move is not possible. I thus don't want to depend on the `Location.getSpeed()` method, since I have observed it gives out speed values only when the accuracy is in the range of 5~8 metres. The normal accuracy ranges I am getting in general circumstances is 10-15 metres, and `getSpeed()` doesn't give any speed. Even `hasSpeed()` starts returning false. I have been tinkering my head around this thing for more than 3 days, any help in this would be deeply appreciated. Much Thanks in Advance!