Measure distance between two coordinates in an android app - android

I'am trying to measure the distance between two coordinates, i've implemented the haversine function, just like this:
package Services;
public class Route {
private double latitude1;
private double longitude1;
private double latitude2;
private double longitude2;
public Route(double latitude1, double longitude1, double latitude2, double longitude2) {
this.latitude1 = latitude1;
this.longitude1 = longitude1;
this.latitude2 = latitude2;
this.longitude2 = longitude2;
}
public double measureDistance() {
double earthRadius = 3958.75;
double dLat = Math.toRadians(latitude2-latitude1);
double dLng = Math.toRadians(longitude2-longitude1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(latitude1)) * Math.cos(Math.toRadians(latitude2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist;
}
}
The code works fine and ouputting something. But as I use the haversine formula, the code just measure the distance in skyline, not the roads if you know what I mean. Is there any possible way to measure distance like google maps does? Without using the google maps API, suddly google takes cash after 2500 API calls in a day or something..

Google Maps API pricing basically only affects web maps: http://code.google.com/apis/maps/faq.html#usage_apis
Google Maps for Android API is still free.
OTOH, there is no routing or navigation functionality in Google Maps for Android, so there is no way to calculate route distance with this API.
Also, you might find this handy: Geographical distance

You should try the Bing Maps Android SDK. They don't have an explicit usage quota.

Bing Maps does have a usage quota, however this does not apply for mobile apps. Bing Maps is definatelty worth looking into. You can use Bing Maps with Android in one of two ways. The first is to use the Bing Maps Android SDK: http://bingmapsandroidsdk.codeplex.com/
The second is to use Bing Maps V7 AJAX control with PhoneGap.

Related

Is it possible to track acceleration and speed using gps data?

Is it possible to track the speed and the acceleration through an android app using the GPS data it provides? I'm planning to create a react native app with these features. But I want to know whether it's possible to do it with the data we can get. Even in native android?
You can do it in pure JS.
For the speed part you have the core React Native Geolocation API where you can find the method watchPosition. On each position update, an object is returned with the current speed amongst other attributes (location, altitude...).
For the acceleration part you have the react-native-motion-manager library. You can listen to the accelerometer updates and get the acceleration.
Is it possible to track the speed and the acceleration through an
android app using the GPS data it provides?
Answer: yes
location.getSpeed() only returns what was set with
location.setSpeed(). This is a value that you can set for a location
object.
To calculate the speed using GPS, you'll have to do a little math:
Speed = distance / time
so how to do that
(currentGPSPoint - lastGPSPoint) / (time between GPS points)
Each location provided by all LocationProviders has the instant speed at the point where the location was taken, which is unstable and it can differ between devices. The average speed is more precise, you have to calculate distance and time. This is how I calculate distance between 2 locations:
static double distance (Location in1, Location in2) {
double R = 6371000;
double la1 = in1.getLatitude()* Math.PI/180;
double la2 = in2.getLatitude()* Math.PI/180;
double lo1 = in1.getLongitude()* Math.PI/180;
double lo2 = in2.getLongitude()* Math.PI/180;
double tmp1 = Math.sin((la1-la2)/2)*Math.sin((la1-la2)/2) + Math.cos(la1)*Math.cos(la2) * Math.sin((lo1-lo2)/2) * Math.sin((lo1-lo2)/2);
double tmp2 = Math.sqrt(tmp1);
double d = Math.abs(2 * R * Math.asin(tmp2) * 100000) / 100000;
return d;
}
You can use this function as well, but I'd rather use the other one, which stores the result in "results" :)
Location.distanceBetween(in1.getLatitude(),in1.getLongitude(),in2.getLatitude(),in2.getLongitude(),results);
So getting the speed in m/s (that's the 1000* for) is quite straightforward:
double avgSpeed = 1000 * distance(loc1,loc2) / (loc2.getTime()-loc1.getTime)

Calculating Speed for a navigation app without getSpeed() method

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!
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)
I agree with Pierre, also you are rounding the results. If the points are not far enough apart, you're rounding may just provide 0. I don't see how the rounding tolerance is defined.
I always calculate in meters - it makes things much easier. I'd suggest following the SI standard units in your code.
Your output also shows that the timeDelta is zero, so no distance was actually calculated.
Omg.....
Location
Check this method - it allows you to calculate distance between 2 geo points, just divide it by your time. It should be much more accurate than yours as it calculates distances with much better approximation (WGS83 instead of using sin, cos and rest of this stuff).
Good, general idea is to keep all your data in plain units like m, s, kg etc. and make changes only for showing data to user.
If the algorithm is correct?
The distance calculation looks like the haversine formula which is correct.
(There are much faster formulas for small distances (and you only use small distances), but haversine will work)
Should I calculate in Centimeters instead of meters?
Never use centimeter, stay with SI units, the unit of speed is meter/s. just use meter as floating point (double).
Ios, where I am developping a tracking App, seems to be more friendly related to the getSpeed() nethod from Location class.
But I (again?) warn you to use speeds at slow speed. If you get an invalid speed, then just stop calculation or mark it as invalid in your app.
If the GPS chip cannot deliver a valid speed, it has good reason to do so, and it's an interesting question whether you will do it better.
At low speed GPS tends to randomly jump around the true position, giving 5-30m jumps.
It's very likely that your self calculated speed shows much more speed that the device is (not) moving.
Try to fix your app, that it does not need speeds at low speeds.

Google Maps Lat/Long Accuracy, V2-Android

I am trying to write a simple application which uses Google Maps V2 API in android.
In a timer I am reading the lat long values from the googleMap mylocation function.
altitude = googleMap.getMyLocation().getAltitude();
latitude = googleMap.getMyLocation().getLatitude();
longitude = googleMap.getMyLocation().getLongitude();
I Plotted the lat,long using addPolyline() method.
The problem I am facing is while walking on road with this app in foreground, I was walking in straight line but the plot was going in nearby buildings. I have ensured that 2 lat,longs are at a distance of 10m.
I use the formula,
public double calcDistance(double lat1, double lng1, double lat2,
double lng2) {
int r = 6371; // average radius of the earth in km
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.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = r * c;
return d;
}
Questions
- How to get a straight line, how to get the accurancy or margin or error so that while walking on road I dont get into buildings
There are errors in maps and there are errors in GPS readings. Nearby big buildings will increase the errors in GPS readings due to blocked satellites and multipath from visible satellites. You might want to consider limiting your initial experiments to areas without buildings.
Concerning straight lines, if you are fortunate enough to have the map data, you could project the GPS readings to their closest points on the road.
If you are relying solely on you location returned from a LocationManager of google maps location and then plotting off that you will get points that are off sometimes due to a bad GPS lock, there really isnt anything you can do about that. You are more than welcome to not use the google maps location and use the Fused location API to try to get better results.
Google maps API does not provide nodes for roads so it is nearly impossible to tell how far away a point is from the road to try to straighten it out

How can I trigger the Several Functionality of Google Maps in my App

I am trying to create a maps app for a certain city that have some stored latitude and longitude for certain landmarks in the city. In the map,
you can only zoom in and zoom out within the boundaries of the city
While the app is open, when you reach a certain range of lat and long coordinates within a certain radius around the landmark, it will trigger and activity that will display details about the landmark and also a voice recording about the landmark
also, the map must also have the "directions" functionality in it, where it can show several possible ways for you to get to a certain location (like landmark) from your present location and also display the distance between two points
I've already tried a GPS program from androidhive that detects your lat and long coordinates. I'm also trying to understand how to acquire and use the google maps api. I would like to know the possible approaches in doing it since I'm still new to android.
Thanks in Advance!
you can zoom with specific mile or kmeter by this code:this is for two mile:
Display display = getWindowManager().getDefaultDisplay();
// double equatorLength = 3218; // in meters
double equatorLength = 40075004; // in meters
double widthInPixels = display.getWidth();
double metersPerPixel = equatorLength / 256;
int zoomLevel = 1;
// 2 mile=3218 mtr
while ((metersPerPixel * widthInPixels) > 3218) {
metersPerPixel /= 2;
++zoomLevel;
}
return zoomLevel;
hope this is helpfull for "you can only zoom in and zoom out within the boundaries of the city"

Android google route using 3 points (Source point, destination point and via point)

I am using google map to display route between two points . Now in my application i want to draw route in map using source point , destination point and via point.Please help me in this. Any help would be appreciated.
Thanks in Advance
Check this:
Answer : Draw path between two points using Google Maps Android API v2
But modify makeURL method to use
https://developers.google.com/maps/documentation/directions/#Waypoints
makeURL(double sourceLat, double sourceLng, double viaLat, double viaLng, double DestLat, double DestLng);
drawPath(result);

Categories

Resources