I have the coordinates of a player and another object. Both are with geographical coordinates (Latitude and longitude). I have also the direction in what the player is facing (compass). How can I calculate the angle to the other object from the player direction? e.g. I want to know if the object is to the right/left of the player and how many degrees.
Thanks a lot!
With a few it depends, the answer is in essence, you want to know about how to do geographic navigation. One of the reasons it depends is that the distances involve as well as the accuracy needed may influence the answer.
For short distances (<10km) you may be able to ignore the curvature of the Earth, and treat it like a two dimensional Cartesian map (latitude / longitude as X-Y). Then you question becomes basic trigonometry.
For larger distances, or improved accuracy, you can either approximate using an spheroid model of the Earth (assume the Earth is a perfect sphere, which it is not) and calculate the Great Circle bearing and distance.
Or you can model the Earth as an ellipsoid, and calculate its geographic navigation.
Two web pages that may help: Details for computing distance using lat/long coordinates and Calculate distance, bearing and more between Latitude/Longitude points.
Note: atan2 and Haversine formula are often useful implementation details.
Small added note: bearing is a synonym for heading or direction in this context.
You need this spherical trig formula: http://williams.best.vwh.net/avform.htm#Crs Once you have the course (angle relative to true north), you can subtract off the compass heading of the direction the player is facing to get the relative heading.
(I don't know if Android automatically compensates for magnetic variation or not, but if not you'll have to account for it too to get the angle right in all areas)
There are tools in the API to do this for you: Location.bearingTo(Location) and GeomagneticSensor will give you the direction from your position to the target - which you can then adjust based off the devices current heading.
If you've already got a MapView running & are lazy, set up a MyLocationOverlay, enableCompass and skip the GeomagneticSensor and let the MapView do it for you.
Related
Can anyone tell me if “getBearing” uses the phone compass (magnetic north) or simply calculates the bearing storing one coordinate where the user has passed and calculate the bearing using the actual coordinate (true north)?
I see from the reference that “bearingTo” uses the coordinates to calculate the phone actual bearing (using true north), but with the “getBearing” I can’t understand how it works and if it uses the compass/magnetic field sensor (magnetic north) or simply de GPS coordinates(true north).
http://developer.android.com/reference/android/location/Location.html
Thanks
bearingTo gives the initial bearing in a great circle course towards user point. This not the direct bearing to user point but shortest over earth. Google great circle and rhumb lines. For most apps it does not matter as its being updated regularly but if compared to magnetic or doing calculations it throws everything.( It did me I use rhumb bearings)
getBearing gives a "direction of horizontal travel" from the last two location (gps) points.
In my application I need to calculate the distance between two gps devices.
When using a GPS coordinates (longitude, latitude, altitude) there is a problem:
The height is determined with greater absolute error. You can verify this by calculating the error
phi and tetta (latitude and longitude) on the basis of formulas
x = r*sin(tetta)*cos(phi)
y = r*sin(tetta)*cos(phi)
z = r*cos(tetta)
However, it is obvious that the GPS receiver is at the beginning accepts data in a Cartesian coordinate system (x, y, z), and then translates them
the system of coordinates r, tetta, phi (altitude, latitude, longitude).
How can I get the original coordinates x,y,z? Are there existing methods in the API? Once again, I don't need conversion formulas
from a spherical coordinate system in a rectangular, I need the accuracy of the original data obtained from a GPS receiver. Is it possible?
You are right the GPS receiver internally uses the ECEF Coordinate system, which is cartesian.
But you cannot get that coordinates on a smartphone. See the above link for conversion from WGS84 coordinates you get in the smartphone to ECEF.
But be warned ECEF this is a 3d cartesian, so the direct line between two points will cut through the earth, that is usefull only for flight applications.
For vehicles (cars, ships) normally you should forget the height of an GPS, just calculate the ground distance (2d- cartesian).
Another solution: first do a (lat,lon) to 2-d cartesian conversion with units meter, then add the height as 3d dimension, this then modells a small part of the earth as flat.
It always depends for whoich purpose you need the calculation.
Why is it obvious that the GPS starts with Cartesian coordinates?
In any case, I'm not seeing a way to get the accuracy of a particular element of the location from the API. It is true that altitude tends to be most error prone (and depends on chipset and is above the reference geoid rather than anything physical). You could get some indication of accuracy by recording data for altitude and modelling the variation.
I am currently playing a bit with Android and GPS tracking and so forth.
I found out, that I have to call the OSM API with the corner points of the bounding I want to get POIs for example. I would like to achieve, that I get my current cooredinates from the handset (which allready works) and then get some pois from OSM for the bounding box where my current position is the center.
I could imagine a function like that:
public Map getBoundingBox(Double long, Double lat, int meters);
BUT I do not have any idea how to calculate this bounding box.
Could someone give me some hints please?
cheers, christian
I assume that long and lat are given in seconds.
First, you need to calculate width of the rectangle in seconds. One second is 30.9 meters on the equator, for other latitudes, multiply by cos(lat), so to convert it to seconds you do the following:
double widthSeconds = meters / (30.9 * cos(lat));
Second, knowing the center of the box, it's easy to calculate the coordinates of corners:
EDIT: the example above works for Europe and Asia. For other locations, directions of coordinate axes may be different.
I am looking for good solution to calculate distance between two points.
I want to sort by distance my Geo points.
I have:
Cursor c = database.rawQuery("SELECT name,latitude,longitude,((longitude-21.15)*(longitude-21.15) +(latitude-54.05)*(latitude-54.05)) AS len FROM Object ORDER BY len;", null);
But this is wrong solution...
Distance is wrong...
Please help me.
The problem you have here is that you're combining:
GPS coordinates (WGS84) that are used to represent a point on a sphere.
Pythagoras theorem, requires a 2D rectangular coordinate system, to determine distance.
This will simply not work if you're after accuracy!
Here are some options that I've used.
Option 1 - Use great circle distance
This formula is used to calculate the distance in meters between two GPS co-ordinates
Android provides a function distanceBetween as part of the android.location.Location class to assist with this.
The downside is you have to pull out all your points from SQLite in order to calculate the distance.
I have also seen some hybrids such as:
treating WGS84 (GPS) as rectangular
specifying a zones in your db to limit the size of data you pull out when calculating distance.
and then using the distanceBetween function to further filter the results.
Option 2 - Use a rectangular coordinate system
If your distances are small then you can solve this problem is by storing the database points in UTM which is rectangular.
Using a formula almost identical, but using easting and northings, the SQLite db can be used to provide the x closest points to a UTM point. Once these points are identified the square-root function can be performed on the x results to get the distance in meters.
Huh?
There are some caveats about using UTM also. It might help you looking at Calculating Distance Between Two Sets of Coordinates
So your solution ultimately depends on your application and is a compromise between speed and accuracy.
You are calculating the square of the distance. Since SQLite doesn't have a square-root function, you will need to calculate this in your Java code.
If all you need is to sort by distance, then your current code is fine.
You can use static method distanceBetween of android.location.Location class. Then based on calculated distance you can produce some sorted collection of object like SortedMap.
Assume that my current point is lat = 50.000 and long = 50.000 and I want to show some bus stations on these location but my limit should depends on zoom level.
So far, for that aim I find a way: If a can take left-up corner and right-down corners lat's long's ; I will find stations between these locations.
Do you know how can I take these points or any different idea about this situation?
Thanks in advance..
Well you can easily get the top left and bottom right lat/lon coordinates using
GeoPoint tlGpt; // Top left
GeoPoint brGpt; // Bottom right
tlGpt = mapView.getProjection().fromPixels(0, 0);
brGpt = mapView.getProjection().fromPixels(mapView.getWidth(), mapView.getHeight());
At any zoom level where you could actually see the bus stations on the map, then the top left longitude could be considered the same as the bottom left longitude, similarly bottom left long would be approx = bottom right long. Thus you could consider the bounding box as a rectangle, rather than an isosceles trapezium (trapezoid in US English)
If you just want a rough measure to pick up a reasonable sample of objects, then lat/long "distance" is good enough. Just make sure you divide the latitude range by the cosine of the latitude, to get the longitude range (i.e., ∆long = ∆lat/cos(lat)). This is to compensate for the contraction of longitude lines as you approach the poles. You use ∆lat as the basis because latitude lines have the same distance between them everywhere on the globe.
For a more accurate measure, there are some complicated functions that allow you to compute great circle distances from lat/long pairs, but it is conceptually much easier to convert lat/long pairs into 3-D coordinates, and use a simple pythagorean distance to approximate the great circle distance. You could use 2*r*acos(d/(2*r)) (if my whiteboard geometry serves me well), where r is the nominal radius of the earth, to get the exact great circle. But if all you want is to get objects within a range, you can invert the formula to get the pythagorean-distance equivalent of the great-circle limit. This can also be used to derive a 3-D bounding box to speed up the search. If your database supports R-trees, then you're laughing! SQLite supports R*Trees, but they are disabled in the default build, so I don't know if they're available on Android (it seems that it isn't).