I am writing an application using phonegap to store an update lat/lon every 5 seconds to a mysql database. I would like to be able to allow my users to see the total distance traveled since starting the app.
I've taken a look at the Phonegap geolocation API and cannot see a way to calculate total distance traveled based upon lat / lon updates. Is there a way to accomplish this?
EDIT: # Drew thanks for the link. I have looked it over and the JS version of Haversine looks straight forward. the difficult part will be the way phonegap pulls and stores lat/lon. Currently my function to get and send the location to MySQL is
function geo_success(position) {
$("#status p").text("Tracking active");
$('#status').removeClass("stopped").addClass("active");
$('button').text("Stop tracking");
latlon.lat = position.coords.latitude;
latlon.lon = position.coords.longitude;
latlon.alt = position.coords.altitude;
if(!position.coords.speed) { latlon.speed = 0; }
else{ latlon.speed = position.coords.speed }
if(first) {
intervalId = setInterval(send, 5000);
}
first = false;
}
Is there a way you can think of to store the latest value for lat1 lon1 and use the previous for lat2 lon2 and cycle the newest incoming coordinates through those 2 sets of variables? That way i can take the returned variable d from the haversine and store it in the db (to be able to sum it up later). Many thanks.
You would have to create an algorithm yourself that take those coordinates every 5 seconds, do some algebra on them to determine the distance between the two, and add it to the total distance somewhere, then repeat for the next 5 seconds.
For the actual algorithm of calculating the distance, look at this answer.
Related
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)
Is there any way I can track a facebook's user's location in real time who is logged in my mobile app and has location services enabled and also has granted access to my app so as to make use of its location?
Assuming a user X, and 3 linear points in space: A,B,C.
X is traveling from A to C.
Is there an SDK that would enable me to check X's real time location ( latitude + longitude ) at any given time while X is moving from A to C so as to create a dotted map(by dropping a pin on the map) with the user's location at every 10ms?
Is this feasible given the fact that my device has a 4G internet connection?
I think you can use CLLocationManager to update user location after traveling a number of meters. I presume you are already having a CLLocationManager to update your location? you can save the dots in an array (starting with the location of A, ending with location of C). You can then draw a line using the dots. I believe Google Map API has a method for drawing line. There's an answer for that here:
Here is a link from SO
But for the sake of providing code, I will provide it for you in Swift 3.0 (the code in the link is in ObjC):
override func viewDidLoad() {
super.viewDidLoad()
//This is a dummy location, you'd add locations to it using the
// func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
let location:CLLocation = CLLocation(latitude: 200, longitude: 100)
let locationArray:Array<CLLocation> = [location]
let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: (locationArray.first?.coordinate.latitude)!, longitude: (locationArray.first?.coordinate.longitude)!, zoom: 2)
//You can obtain the Lat and Long for above from the list of arrays of locations you saved
//You can use the .first or .last on the array (I used first)
let mapview:GMSMapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
let path:GMSMutablePath = GMSMutablePath()
for nextLocation in locationArray {
if locationArray.index(of: nextLocation) != 0 {
//You dont want to use the first one as you've already done it
//so you start with 1
path.addLatitude(nextLocation.coordinate.latitude, longitude: nextLocation.coordinate.longitude)
}
}
let polyline:GMSPolyline = GMSPolyline(path: path)
polyline.strokeColor = UIColor.red
polyline.strokeWidth = 2
polyline.map = mapview
self.view = mapview
//I personally prefer view.addSubview(mapview)
}
I am trying to calculate the distance between two locations (Current location with the previous location).
So I tried the following:
Location previousLocation = new Location("");
previousLocation.setLatitude(sharedPreferences.getFloat("previousLatitude", 0f));
previousLocation.setLongitude(sharedPreferences.getFloat("previousLongitude", 0f));
float distance = location.distanceTo(previousLocation);
totalDistanceInMeters += distance;
editor.putFloat("totalDistanceInMeters", totalDistanceInMeters);
Log.e("Location Update","totalDistance"+totalDistanceInMeters);
if (totalDistanceInMeters > 1)
{
Toast.makeText(getApplicationContext(), "Total UpdateLocation"+totalDistanceInMeters/1609, Toast.LENGTH_SHORT).show();
Log.e("Alert","Update");
}
To test the above code. The first time result was perfect and when it triggered the second time. The phone was in the same location but I am getting distances like 141.0111 m. thrid time 304.0011 m. Am I doing something wrong here?
The results are not showing up correctly. According to doc online the results are in metres.
Is there an easy way to calculate the difference between the first location results with the second one and if it is more than 10m I would like to do some other calculation if not just keep quite.
Let me know.
why are you even using the following code
float distance = location.distanceTo(previousLocation);
totalDistanceInMeters += distance;
That adds up the previous distance to present distance and gives the added value everytime....
example
first time
distance between A and B is 100 m
second time
distance between A and B is 100 m+100 m=200 m
so try using distance directly in toast
float distance = location.distanceTo(previousLocation);
if (totalDistanceInMeters > 1)
{
Toast.makeText(getApplicationContext(), "Total UpdateLocation"+distance/1609,Toast.LENGTH_SHORT).show();
Log.e("Alert","Update");
}
I think accuracy needs to be set in order to get the exact distance. Also try to get hold of the previous and current locations manually so as to calculate the distance and verify.
I'm using google.maps.geometry.spherical.computeDistanceBetween() to compute the distance between relatively close points (10-30 meters). This works perfectly in Linux (Chrome and Firefox), but sometimes gives me crazy results in Android. One case that I got was with this:
var p1 = new google.maps.LatLng(-22.960584,-43.206687999999986);
var p2 = new google.maps.LatLng(-22.960584,-43.206939000000034);
alert(google.maps.geometry.spherical.computeDistanceBetween(p1,p2));
It should give 25 meters or so, yet once I got hundred of thousands of meters. Again, it is not always that I get crazy values, just "sometimes", probably related with lots of computations?
Is this a well known bug? If it is, I cannot use this method and would have to make my own.
Thanks,
L.
As far as I can tell, this is an Android bug. I think this could very well explain why in the MyTracks app I usually get randomly points in other continents and huge distances.
I computed the distance function with the method below, and now I always get the correct values. In particular, if this is what it looks, this is a very serious bug for Android app that uses this function.
In case anyone cares, this is the distance function between to LatLng p and q:
function dist(p,q) {
var c = Math.PI/180;
// Google (gives randomly wrong results in Android!)
//return google.maps.geometry.spherical.computeDistanceBetween(p,q);
// Chord
//return 9019995.5222 * Math.sqrt((1-Math.cos(c*(p.lat()-q.lat())))
// + (1-Math.cos(c*(p.lng()-q.lng()))) * Math.cos(c*p.lat()) * Math.cos(c*q.lat()));
// Taylor for chord
return 111318.845 * Math.sqrt(Math.pow(p.lat()-q.lat(),2)
+ Math.pow(p.lng()-q.lng(),2) * Math.cos(c*p.lat()) * Math.cos(c*q.lat()));
}
Notice that these are the computations for the chord, that is, the distance in R^3, not the geodesic distance in the sphere. Certainly more than enough for hiking/car travel computations using GPS. I ended up using the Taylor expansion since it is precise to 1/10 mm, and less tough with the CPU.
I'm making an application for tracking a user as they run, cycle or walk and display it to the screen.
I know that there is distanceBetween function built into android but is this accurate enough for a fittness application?
I was considering using Haversine formula or other such formula for calculating distances between points the only problem I see about these formulas is that it usually is straight line or as the crow flys distances.
Does anyone have an idea about this?
The Haversine formula is accurate for most distances, but it suffers from rounding errors when the points are (nearly) antipodal. The following formula is accurate for all distances.
> double delta = G1 - G2;
> double p1 = cos(L2) * sin(delta);
> double p2 = cos(L1) * sin(L2) - sin(L1) * cos(L2) * cos(delta);
> double p3 = sin(L1) * sin(L2) + cos(L1) * cos(L2) * cos(delta);
> distance = 60 * Math.atan2(Math.sqrt(p1*p1 + p2*p2), p3);
Here's an example and the implementation.
resource : Here
Tracking their route as they walk is going to involve a series of way points. If you sample at say 1 way point every 10 seconds then you can calculate the distance between the previous point and the new point using either a crow-flys technique like haversine or just make some webservice requests to an external service like google maps and their distance matrix which can give you the snapped-to-streets distance between 2 points using suggested best path.
http://code.google.com/apis/maps/documentation/distancematrix/
You just have to make sure that your sample rate isn't too high or you can go over the 2500 API calls/24-hour-period rate limiter (which is per IP I believe). But 2500 will give you 7 hours at 1 sample per 10 seconds, or you can try a lower rate like 1 per 35 seconds and risk having the route be guessed wrong, but guarantee that your device won't go over 2500 samples.
Personally, if location polling is free, I would just go with distanceBetween and poll every 1-2 seconds. That should be short enough that the accuracy of GPS becomes your biggest source of error.