Android: calculate vehicle moving distance using mobile device - java

Using GPS points I am calculating by holding previous and current points with
location1.distanceTo(location2) by adding each time to a variable on some time diff to get traveled distance. Is it good approach to get vehicle movement distance? Is any better approach to get accurate travel distance during moving vehicle?

Use the following code. I hope it will help.
public double CalculationByDistance(LatLng StartP, LatLng EndP) {
int Radius = 6371;// radius of earth in Km
double lat1 = StartP.latitude;
double lat2 = EndP.latitude;
double lon1 = StartP.longitude;
double lon2 = EndP.longitude;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
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));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
int kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
int meterInDec = Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value", "" + valueResult + " KM " + kmInDec
+ " Meter " + meterInDec);
return Radius * c;
}
float[] results = new float[1];
Location.distanceBetween(oldPosition.latitude, oldPosition.longitude,
newPosition.latitude, newPosition.longitude, results);

Related

How to advance X distance (meters) between two points of latitude and longitude?

I'm simulating a polyline with different stops in Java, I have the distance in meters between these two points, the problem is, that I have to go from point A to point B at a speed of 1 to 3 meters per second, and I will need to take the current coordinates I am every 15 min more or less, how can I do that?
The way between the points are straight lines, and all of this is simulated, not happening in a map or something, I just need to print this info every X time, any help?
Example:
I have the coordinates:
LAT: 51.504870000000004 LNG: -0.21533000000000002
and I have to go at that speed to:
LAT: 51.50475 LNG: -0.21571
So, I have to simulate that I go from A to B at 3 meters second, and I need to know my position (lat/lng) while I'm moving between this two points
There's another question that is more or less the same, the difference is that I can't do this with android, is a Java application.
So you know latA, lngA, latB, lngB. From your question, I assume that you know the speed, it's constant, v = 3 m/s. You can get the start time LocalDateTime tA = LocalDateTime.now(); You want to know your coordinates at some moment of time tX.
In order to do this, I would introduce coefLat and coefLng coefficients for transforming coordinates into meters and back. They use mean radius of Earth and translate degrees into radians:
double coefLat = 180 / Math.PI / 6371000;
double coefLng = coefLat / Math.cos(Math.PI * (latA + latB) / 360);
Then calculate distances by Lat and Lng axis and full distance in meters:
double distLat = (latB - latA) / coefLat;
double distLng = (lngB - lngA) / coefLng;
double dist = Math.sqrt(distLat * distLat + distLng * distLng);
double fullTime = dist / v; // Full time needed to pass from A to B in seconds
After some time of moving, find duration and get current coordinates:
LocalDateTime tX = LocalDateTime.now(); // get current time
long dT = Duration.between(tA, tX).getSeconds(); // in seconds
double ratio = dT / fullTime;
double latX = latA + coefLat * ratio * distLat;
double lngX = lngA + coefLng * ratio * distLng;
Please also see this answer
The full code:
public class GetCurrentCoords {
public static void main(String[] args) {
LocalDateTime tA = LocalDateTime.now();
double latA = 51.504870000000004;
double lngA = -0.21533000000000002;
double latB = 51.50475;
double lngB = -0.21571;
double coefLat = 180 / Math.PI / 6371000;
double coefLng = coefLat / Math.cos(Math.PI * (latA + latB) / 360);
double distLat = (latB - latA) / coefLat; // meters
double distLng = (lngB - lngA) / coefLng; // meters
double dist = Math.sqrt(distLat * distLat + distLng * distLng);
System.out.println("distLat = " + distLat + "m; distLng = " + distLng + "m; full dist from A to B = " + dist + "m");
double v = 3;
double fullTime = dist / v; // seconds
System.out.println("full time from A to B = " + fullTime + "s");
// let's move for 4 seconds
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException ex) {
Logger.getLogger(GetCurrentCoords.class.getName()).log(Level.SEVERE, null, ex);
}
LocalDateTime tX = LocalDateTime.now();
long dT = Duration.between(tA, tX).getSeconds();
double ratio = dT / fullTime;
double latX = latA + coefLat * ratio * distLat;
double lngX = lngA + coefLng * ratio * distLng;
System.out.println("Moving " + dT + " seconds; latX = " + latX + "; lngX = " + lngX);
}
}
I dont get the question clearly but if you want to do something after a given distance you can use this approach
LatLng startPoint=new LatLng(51.504870000000004,-0.21533000000000002);
LatLng endPoin=new LatLng(51.50475,-0.21571);
Location loc1 = new Location("");
loc1.setLatitude(startPoint.latitude);
loc1.setLongitude(startPoint.longitude);
Location loc2 = new Location("");
loc2.setLatitude(endPoint.latitude);
loc2.setLongitude(endPoint.longitude);
float distance = loc1.distanceTo(loc2);
//instead of if you can use for loop
if (distance <= 100) {
//do something, like get the coordinates
} else {
//do something
}

java interpolate between two gps points with a speed

I'm trying to come up with function that could fill in gps coordinates between two points every second. There are few posts about this here, but I couldn't find something complete. The closest answer I found was:
Interpolate between 2 GPS locations based on walking speed
I modified one of the answer using the bearing. However, it still doesn't seem to work. Especially I think the distance calculation is wrong. Could someone look at the code below and change?
Thank you!
import java.util.ArrayList;
public class Test {
double radius = 6371;
public Test() {
Location start = new Location(lat, lon);
Location end = new Location(lat, lon);
double speed = 1.39;
double distance = CalculateDistanceBetweenLocations(start, end);
double duration = distance / speed;
System.out.println(distance + ", " + speed + ", " + duration);
ArrayList<Location> locations = new ArrayList<Location>();
for (double i = 0; i < duration; i += 1.0) {
double bearing = CalculateBearing(start, end);
double distanceInKm = speed / 1000;
Location intermediaryLocation = CalculateDestinationLocation(start, bearing, distanceInKm);
locations.add(intermediaryLocation);
System.out.println(intermediaryLocation.latitude + ", " + intermediaryLocation.longitude);
start = intermediaryLocation;
}
}
double DegToRad(double deg) {
return (deg * Math.PI / 180);
}
double RadToDeg(double rad) {
return (rad * 180 / Math.PI);
}
double CalculateBearing(Location startPoint, Location endPoint) {
double lat1 = DegToRad(startPoint.latitude);
double lat2 = DegToRad(endPoint.latitude);
double deltaLon = DegToRad(endPoint.longitude - startPoint.longitude);
double y = Math.sin(deltaLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(deltaLon);
double bearing = Math.atan2(y, x);
return (RadToDeg(bearing) + 360) % 360;
}
Location CalculateDestinationLocation(Location point, double bearing, double distance) {
distance = distance / radius;
bearing = DegToRad(bearing);
double lat1 = DegToRad(point.latitude);
double lon1 = DegToRad(point.longitude);
double lat2 = Math
.asin(Math.sin(lat1) * Math.cos(distance) + Math.cos(lat1) * Math.sin(distance) * Math.cos(bearing));
double lon2 = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(distance) * Math.cos(lat1),
Math.cos(distance) - Math.sin(lat1) * Math.sin(lat2));
lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
return new Location(RadToDeg(lat2), RadToDeg(lon2));
}
double CalculateDistanceBetweenLocations(Location startPoint, Location endPoint) {
double lat1 = DegToRad(startPoint.latitude);
double lon1 = DegToRad(startPoint.longitude);
double lat2 = DegToRad(endPoint.latitude);
double lon2 = DegToRad(endPoint.longitude);
double deltaLat = lat2 - lat1;
double deltaLon = lon2 - lon1;
double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)
+ Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - 1));
return (radius * c);
}
public static void main(String[] args) {
new Test();
}
class Location {
public double latitude, longitude;
public Location(double lat, double lon) {
latitude = lat;
longitude = lon;
}
}
}
You have a typing error in line
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - 1));
It should be
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
Your method CalculateDistanceBetweenLocations contains an this line:
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - 1));
which is equivalent to
double c = 2 * Math.atan2(Math.sqrt(a), 0.0);
which means that the result of Math.atan2 is always pi, independent of the value of a as long as a is positive.
Therefore CalculateDistanceBetweenLocations always returns 20015.086796020572 independent of the input coordinates.

Not able to get perfect distance between two places

i have used Haversine for calculating distance between two location.
public static class Haversine {
static int Radius = 6371;
public static double haversine(double lat1, double lon1, double lat2,
double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
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));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
int kmInDec = Integer.valueOf(newFormat.format(km));
double meter = valueResult % 1000;
int meterInDec = Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value", "" + valueResult + " KM " + kmInDec
+ " Meter " + meterInDec);
return Radius * c;
/*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.asin(Math.sqrt(a));
return R * 2 * Math.asin(Math.sqrt(a));*/
}
}
From the above code i am not able to get exact distance between 2 location.
When i run the above mehtod then it shows 4.32 km from my two places but when i checked on the google map then it shows the 5.3 km .
i have also used Location.distanceBetween method still it shows the 4.32 km .
How can i get exact distance between location?
You can see this link.
Haversine and Location.distanceBetween method are both the origin to the point at which a line.
So, you can use http://maps.googleapis.com/maps/api/directions/json?origin=Toronto&destination=Montreal&sensor=false to get the real distance.
From Google official repository link
SphericalUtil
MathUtil
Usage
double distance = SphericalUtil.computeDistanceBetween(new LatLng(9.000,10.00), new LatLng(9.000,11.00));
The above method will returns the distance between two LatLngs, in meters. Or try this
private String getDistance(LatLng my_latlong,LatLng frnd_latlong){
Location l1=new Location("One");
l1.setLatitude(my_latlong.latitude);
l1.setLongitude(my_latlong.longitude);
Location l2=new Location("Two");
l2.setLatitude(frnd_latlong.latitude);
l2.setLongitude(frnd_latlong.longitude);
float distance=l1.distanceTo(l2);
String dist=distance+" M";
if(distance>1000.0f)
{
distance=distance/1000.0f;
dist=distance+" KM";
}
return dist;
}
or you can give a look at link

Find min and max latitude and longitude in java from given latitude , longitude and radius values

I can find the distance from latitude and longitude (i.e; minLatitude,minLongitude,maxLatitude and maxLongitude respectively) but I need sample java code to find minLatitude, minLongitude, maxLatitude and maxLongitude from input latitude , longitude and radius values.
Here is the code for finding distance from lat1 , long1, lat2 and lang2 values.
public static double distance(double lat1, double lon1, double lat2, double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.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.asin(Math.sqrt(a));
return R * c;
}
try something like:
/** returns minLatitude, maxLatitude, minLongitude, maxLongitude */
public double[] calculateMinMaxValues(double latitude , double longitude, double radius){
double[] res = new double[4];
res[0] /*minLatitude*/ = latitude - (radius*2)/60.0;
res[1] /*maxLatitude*/ = latitude + (radius*2)/60.0;
res[2] /*minLongitude*/ = (longitude*2)/60.0 *(Math.cos(res[0]));
res[3] /*maxLongitude*/ = (longitude*2)/60.0 *(Math.cos(res[1]));
return res;
}

How can I measure distance and create a bounding box based on two latitude+longitude points in Java?

I am wanting to find the distance between two different points. This I know can be accomplished with the great circle distance.
http://www.meridianworlddata.com/Distance-calculation.asp
Once done, with a point and distance I would like to find the point that distance north, and that distance east in order to create a box around the point.
Here is a Java implementation of Haversine formula. I use this in a project to calculate distance in miles between lat/longs.
public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; // miles (or 6371.0 kilometers)
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist;
}
Or you could use SimpleLatLng. Apache 2.0 licensed and used in one production system that I know of: mine.
Short story:
I was searching for a simple geo library and couldn't find one to fit my needs. And who wants to write and test and debug these little geo tools over and over again in every application? There's got to be a better way!
So SimpleLatLng was born as a way to store latitude-longitude data, do distance calculations, and create shaped boundaries.
I know I'm two years too late to help the original poster, but my aim is to help the people like me who find this question in a search. I would love to have some people use it and contribute to the testing and vision of this little lightweight utility.
We've had some success using OpenMap to plot a lot of positional data. There's a LatLonPoint class that has some basic functionality, including distance.
For a more accurate distance (0.5mm) you can also use the Vincenty approximation:
/**
* Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula
* for ellipsoids
*
* #param lat1
* first point latitude in decimal degrees
* #param lon1
* first point longitude in decimal degrees
* #param lat2
* second point latitude in decimal degrees
* #param lon2
* second point longitude in decimal degrees
* #returns distance in meters between points with 5.10<sup>-4</sup> precision
* #see Originally posted here
*/
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) {
double a = 6378137, b = 6356752.314245, f = 1 / 298.257223563; // WGS-84 ellipsoid params
double L = Math.toRadians(lon2 - lon1);
double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
double lambda = L, lambdaP, iterLimit = 100;
do {
sinLambda = Math.sin(lambda);
cosLambda = Math.cos(lambda);
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)
+ (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
if (sinSigma == 0)
return 0; // co-incident points
cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1 - sinAlpha * sinAlpha;
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
if (Double.isNaN(cos2SigmaM))
cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (ยง6)
double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
lambdaP = lambda;
lambda = L + (1 - C) * f * sinAlpha
* (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
} while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
if (iterLimit == 0)
return Double.NaN; // formula failed to converge
double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
double deltaSigma = B
* sinSigma
* (cos2SigmaM + B
/ 4
* (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM
* (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
double dist = b * A * (sigma - deltaSigma);
return dist;
}
This code was freely adapted from http://www.movable-type.co.uk/scripts/latlong-vincenty.html
Corrected Haversine Distance formula....
public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2)
{
// mHager 08-12-2012
// http://en.wikipedia.org/wiki/Haversine_formula
// Implementation
// convert to radians
lat1 = Math.toRadians(lat1);
lng1 = Math.toRadians(lng1);
lat2 = Math.toRadians(lat2);
lng2 = Math.toRadians(lng2);
double dlon = lng2 - lng1;
double dlat = lat2 - lat1;
double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return EARTH_RADIUS * c;
}
http://www.movable-type.co.uk/scripts/latlong.html
public static Double distanceBetweenTwoLocationsInKm(Double latitudeOne, Double longitudeOne, Double latitudeTwo, Double longitudeTwo) {
if (latitudeOne == null || latitudeTwo == null || longitudeOne == null || longitudeTwo == null) {
return null;
}
Double earthRadius = 6371.0;
Double diffBetweenLatitudeRadians = Math.toRadians(latitudeTwo - latitudeOne);
Double diffBetweenLongitudeRadians = Math.toRadians(longitudeTwo - longitudeOne);
Double latitudeOneInRadians = Math.toRadians(latitudeOne);
Double latitudeTwoInRadians = Math.toRadians(latitudeTwo);
Double a = Math.sin(diffBetweenLatitudeRadians / 2) * Math.sin(diffBetweenLatitudeRadians / 2) + Math.cos(latitudeOneInRadians) * Math.cos(latitudeTwoInRadians) * Math.sin(diffBetweenLongitudeRadians / 2)
* Math.sin(diffBetweenLongitudeRadians / 2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (earthRadius * c);
}
You can use the Java Geodesy Library for GPS, it uses the Vincenty's formulae which takes account of the earths surface curvature.
Implementation goes like this:
import org.gavaghan.geodesy.*;
...
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0);
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0);
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();
The resulting distance is in meters.
This method would help you find the distance between to geographic location in km.
private double getDist(double lat1, double lon1, double lat2, double lon2)
{
int R = 6373; // radius of the earth in kilometres
double lat1rad = Math.toRadians(lat1);
double lat2rad = Math.toRadians(lat2);
double deltaLat = Math.toRadians(lat2-lat1);
double deltaLon = Math.toRadians(lon2-lon1);
double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
Math.cos(lat1rad) * Math.cos(lat2rad) *
Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
return d;
}
Kotlin version of Haversine formula. Returned result in meters. Tested on https://www.vcalc.com/wiki/vCalc/Haversine+-+Distance
const val EARTH_RADIUS_IN_METERS = 6371007.177356707
fun distance(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Double {
val latDiff = Math.toRadians(abs(lat2 - lat1))
val lngDiff = Math.toRadians(abs(lng2 - lng1))
val a = sin(latDiff / 2) * sin(latDiff / 2) +
cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
sin(lngDiff / 2) * sin(lngDiff / 2)
val c = 2 * atan2(sqrt(a), sqrt(1 - a))
return EARTH_RADIUS_IN_METERS * c
}
I know that there are many answers, but in doing some research on this topic, I found that most answers here use the Haversine formula, but the Vincenty formula is actually more accurate. There was one post that adapted the calculation from a Javascript version, but it's very unwieldy. I found a version that is superior because:
It also has an open license.
It uses OOP principles.
It has greater flexibility to choose the ellipsoid you want to use.
It has more methods to allow for different calculations in the future.
It is well documented.
VincentyDistanceCalculator
I typically use MATLAB with the Mapping Toolbox, and then use the code in my Java using MATLAB Builder JA. It makes my life a lot simpler. Given most schools have it for free student access, you can try it out (or get the trial version to get over your work).
For Android, there is a simple approach.
public static float getDistanceInMeter(LatLng start, LatLng end) {
float[] results = new float[1];
Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
return results[0];
}
;
https://developer.android.com/reference/android/location/Location#distanceBetween(lat1,lng1,lat2,lng2,output[])

Categories

Resources