What does bearingTo(Location dest) exactly calculate? Can anyone please explain this??
Thanks in advance.
protected void onCreate(Bundle savedInstanceState) {
DestinationLoc.setLatitude(39.543394);
DestinationLoc.setLongitude(-119.816010);
LocationManager lm =(LocationManager)getSystemService(LOCATION_SERVICE);
String provider = lm.getBestProvider(new Criteria(), true);
loc=lm.getLastKnownLocation(provider)
}
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
Startloc.setLatitude(loc.getLatitude());
Startloc.setLongitude(loc.getLongitude());
if ( Startloc == null ) return;
float azimuth = event.values[0];
float baseAzimuth = azimuth;
mInitialPosition.setText("Initial LatLong: " + Startloc.getLatitude() + " " + Startloc.getLongitude());
GeomagneticField geoField = new GeomagneticField( Double
.valueOf( Startloc.getLatitude() ).floatValue(), Double
.valueOf( Startloc.getLongitude() ).floatValue(),
Double.valueOf( Startloc.getAltitude() ).floatValue(),
System.currentTimeMillis() );
azimuth += geoField.getDeclination(); // converts magnetic north into true north
//Correct the azimuth
azimuth = azimuth % 360;
//This is where we choose to point it
float direction = azimuth + Startloc.bearingTo( DestinationLoc );
float direction2 = Startloc.bearingTo(DestinationLoc);
}
The direction2 value is shown as negative.
Source : Android Developers
Bearing is basically another ATTRIBUTE that is associated with Location object in Android. So, Location has lat, long and it can bearing, altitude, velocity. According to the method description getBearing() it means the horizontal direction of the device.
Source : Wikipedia
In land navigation, a bearing is ordinarily calculated in a clockwise direction starting from a reference direction of 0° and increasing to 359.9 degrees.[4] Measured in this way, a bearing is referred to as an azimuth by the US Army but not by armies in other English speaking nations, which use the term bearing.[5] If the reference direction is north (either true north, magnetic north, or grid north), the bearing is termed an absolute bearing. In a contemporary land navigation context, true, magnetic, and grid bearings are always measured in this way, with true north, magnetic north, or grid north being 0° in a 360-degree system.[4]
Read the documentation please. It describes exactly that that method returns.
Returns the approximate initial bearing in degrees East of true North
when traveling along the shortest path between this location and the
given location. The shortest path is defined using the WGS84
ellipsoid. Locations that are (nearly) antipodal may produce
meaningless results.
Parameters
dest the destination location
Returns
the initial bearing in degrees
I want to display an arrow at my location on a google map view that displays my direction relative to a destination location (instead of north).
a) I have calculated north using the sensor values from the magnetometer and accelerometer. I know this is correct because it lines up with the compass used on the Google Map view.
b) I have calculated the initial bearing from my location to the destination location by using myLocation.bearingTo(destLocation);
I'm missing the last step; from these two values (a & b) what formula do I use to get the direction in which the phone is pointing relative to the destination location?
Appreciate any help for an addled mind!
Ok I figured this out. For anyone else trying to do this you need:
a) heading: your heading from the hardware compass. This is in degrees east of magnetic north
b) bearing: the bearing from your location to the destination location. This is in degrees east of true north.
myLocation.bearingTo(destLocation);
c) declination: the difference between true north and magnetic north
The heading that is returned from the magnetometer + accelermometer is in degrees east of true (magnetic) north (-180 to +180) so you need to get the difference between north and magnetic north for your location. This difference is variable depending where you are on earth. You can obtain by using GeomagneticField class.
GeomagneticField geoField;
private final LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
geoField = new GeomagneticField(
Double.valueOf(location.getLatitude()).floatValue(),
Double.valueOf(location.getLongitude()).floatValue(),
Double.valueOf(location.getAltitude()).floatValue(),
System.currentTimeMillis()
);
...
}
}
Armed with these you calculate the angle of the arrow to draw on your map to show where you are facing in relation to your destination object rather than true north.
First adjust your heading with the declination:
heading += geoField.getDeclination();
Second, you need to offset the direction in which the phone is facing (heading) from the target destination rather than true north. This is the part that I got stuck on. The heading value returned from the compass gives you a value that describes where magnetic north is (in degrees east of true north) in relation to where the phone is pointing. So e.g. if the value is -10 you know that magnetic north is 10 degrees to your left. The bearing gives you the angle of your destination in degrees east of true north. So after you've compensated for the declination you can use the formula below to get the desired result:
heading = myBearing - (myBearing + heading);
You'll then want to convert from degrees east of true north (-180 to +180) into normal degrees (0 to 360):
Math.round(-heading / 360 + 180)
#Damian - The idea is very good and I agree with answer, but when I used your code I had wrong values, so I wrote this on my own (somebody told the same in your comments). Counting heading with the declination is good, I think, but later I used something like that:
heading = (bearing - heading) * -1;
instead of Damian's code:
heading = myBearing - (myBearing + heading);
and changing -180 to 180 for 0 to 360:
private float normalizeDegree(float value){
if(value >= 0.0f && value <= 180.0f){
return value;
}else{
return 180 + (180 + value);
}
and then when you want to rotate your arrow you can use code like this:
private void rotateArrow(float angle){
Matrix matrix = new Matrix();
arrowView.setScaleType(ScaleType.MATRIX);
matrix.postRotate(angle, 100f, 100f);
arrowView.setImageMatrix(matrix);
}
where arrowView is ImageView with arrow picture and 100f parameters in postRotate is pivX and pivY).
I hope I will help somebody.
In this an arrow on compass shows the direction from your location to Kaaba(destination Location)
you can simple use bearingTo in this way.bearing to will give you the direct angle from your location to destination location
Location userLoc=new Location("service Provider");
//get longitudeM Latitude and altitude of current location with gps class and set in userLoc
userLoc.setLongitude(longitude);
userLoc.setLatitude(latitude);
userLoc.setAltitude(altitude);
Location destinationLoc = new Location("service Provider");
destinationLoc.setLatitude(21.422487); //kaaba latitude setting
destinationLoc.setLongitude(39.826206); //kaaba longitude setting
float bearTo=userLoc.bearingTo(destinationLoc);
bearingTo will give you a range from -180 to 180, which will confuse things a bit. We will need to convert this value into a range from 0 to 360 to get the correct rotation.
This is a table of what we really want, comparing to what bearingTo gives us
+-----------+--------------+
| bearingTo | Real bearing |
+-----------+--------------+
| 0 | 0 |
+-----------+--------------+
| 90 | 90 |
+-----------+--------------+
| 180 | 180 |
+-----------+--------------+
| -90 | 270 |
+-----------+--------------+
| -135 | 225 |
+-----------+--------------+
| -180 | 180 |
+-----------+--------------+
so we have to add this code after bearTo
// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.
if (bearTo < 0) {
bearTo = bearTo + 360;
//bearTo = -100 + 360 = 260;
}
you need to implements the SensorEventListener and its functions(onSensorChanged,onAcurracyChabge) and write all the code inside onSensorChanged
Complete code is here for Direction of Qibla compass
public class QiblaDirectionCompass extends Service implements SensorEventListener{
public static ImageView image,arrow;
// record the compass picture angle turned
private float currentDegree = 0f;
private float currentDegreeNeedle = 0f;
Context context;
Location userLoc=new Location("service Provider");
// device sensor manager
private static SensorManager mSensorManager ;
private Sensor sensor;
public static TextView tvHeading;
public QiblaDirectionCompass(Context context, ImageView compass, ImageView needle,TextView heading, double longi,double lati,double alti ) {
image = compass;
arrow = needle;
// TextView that will tell the user what degree is he heading
tvHeading = heading;
userLoc.setLongitude(longi);
userLoc.setLatitude(lati);
userLoc.setAltitude(alti);
mSensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if(sensor!=null) {
// for the system's orientation sensor registered listeners
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);//SensorManager.SENSOR_DELAY_Fastest
}else{
Toast.makeText(context,"Not Supported", Toast.LENGTH_SHORT).show();
}
// initialize your android device sensor capabilities
this.context =context;
#Override
public void onCreate() {
// TODO Auto-generated method stub
Toast.makeText(context, "Started", Toast.LENGTH_SHORT).show();
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); //SensorManager.SENSOR_DELAY_Fastest
super.onCreate();
}
#Override
public void onDestroy() {
mSensorManager.unregisterListener(this);
Toast.makeText(context, "Destroy", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
Location destinationLoc = new Location("service Provider");
destinationLoc.setLatitude(21.422487); //kaaba latitude setting
destinationLoc.setLongitude(39.826206); //kaaba longitude setting
float bearTo=userLoc.bearingTo(destinationLoc);
//bearTo = The angle from true north to the destination location from the point we're your currently standing.(asal image k N se destination taak angle )
//head = The angle that you've rotated your phone from true north. (jaise image lagi hai wo true north per hai ab phone jitne rotate yani jitna image ka n change hai us ka angle hai ye)
GeomagneticField geoField = new GeomagneticField( Double.valueOf( userLoc.getLatitude() ).floatValue(), Double
.valueOf( userLoc.getLongitude() ).floatValue(),
Double.valueOf( userLoc.getAltitude() ).floatValue(),
System.currentTimeMillis() );
head -= geoField.getDeclination(); // converts magnetic north into true north
if (bearTo < 0) {
bearTo = bearTo + 360;
//bearTo = -100 + 360 = 260;
}
//This is where we choose to point it
float direction = bearTo - head;
// If the direction is smaller than 0, add 360 to get the rotation clockwise.
if (direction < 0) {
direction = direction + 360;
}
tvHeading.setText("Heading: " + Float.toString(degree) + " degrees" );
RotateAnimation raQibla = new RotateAnimation(currentDegreeNeedle, direction, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
raQibla.setDuration(210);
raQibla.setFillAfter(true);
arrow.startAnimation(raQibla);
currentDegreeNeedle = direction;
// create a rotation animation (reverse turn degree degrees)
RotateAnimation ra = new RotateAnimation(currentDegree, -degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// how long the animation will take place
ra.setDuration(210);
// set the animation after the end of the reservation status
ra.setFillAfter(true);
// Start the animation
image.startAnimation(ra);
currentDegree = -degree;
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
xml code is here
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/flag_pakistan">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/heading"
android:textColor="#color/colorAccent"
android:layout_centerHorizontal="true"
android:layout_marginBottom="100dp"
android:layout_marginTop="20dp"
android:text="Heading: 0.0" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/heading"
android:scaleType="centerInside"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">
<ImageView
android:id="#+id/imageCompass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/images_compass"/>
<ImageView
android:id="#+id/needle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:scaleType="centerInside"
android:src="#drawable/arrow2"/>
</RelativeLayout>
</RelativeLayout>
I know this is a little old but for the sake of folks like myself from google who didn't find a complete answer here. Here are some extracts from my app which put the arrows inside a custom listview....
Location loc; //Will hold lastknown location
Location wptLoc = new Location(""); // Waypoint location
float dist = -1;
float bearing = 0;
float heading = 0;
float arrow_rotation = 0;
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(loc == null) { //No recent GPS fix
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(true);
criteria.setCostAllowed(true);
criteria.setSpeedRequired(false);
loc = lm.getLastKnownLocation(lm.getBestProvider(criteria, true));
}
if(loc != null) {
wptLoc.setLongitude(cursor.getFloat(2)); //Cursor is from SimpleCursorAdapter
wptLoc.setLatitude(cursor.getFloat(3));
dist = loc.distanceTo(wptLoc);
bearing = loc.bearingTo(wptLoc); // -180 to 180
heading = loc.getBearing(); // 0 to 360
// *** Code to calculate where the arrow should point ***
arrow_rotation = (360+((bearing + 360) % 360)-heading) % 360;
}
I willing to bet it could be simplified but it works!
LastKnownLocation was used since this code was from new SimpleCursorAdapter.ViewBinder()
onLocationChanged contains a call to notifyDataSetChanged();
code also from new SimpleCursorAdapter.ViewBinder() to set image rotation and listrow colours (only applied in a single columnIndex mind you)...
LinearLayout ll = ((LinearLayout)view.getParent());
ll.setBackgroundColor(bc);
int childcount = ll.getChildCount();
for (int i=0; i < childcount; i++){
View v = ll.getChildAt(i);
if(v instanceof TextView) ((TextView)v).setTextColor(fc);
if(v instanceof ImageView) {
ImageView img = (ImageView)v;
img.setImageResource(R.drawable.ic_arrow);
Matrix matrix = new Matrix();
img.setScaleType(ScaleType.MATRIX);
matrix.postRotate(arrow_rotation, img.getWidth()/2, img.getHeight()/2);
img.setImageMatrix(matrix);
}
In case you're wondering I did away with the magnetic sensor dramas, wasn't worth the hassle in my case.
I hope somebody finds this as useful as I usually do when google brings me to stackoverflow!
I'm no expert in map-reading / navigation and so on but surely 'directions' are absolute and not relative or in reality, they are relative to N or S which themselves are fixed/absolute.
Example: Suppose an imaginary line drawn between you and your destination corresponds with 'absolute' SE (a bearing of 135 degrees relative to magnetic N). Now suppose your phone is pointing NW - if you draw an imaginary line from an imaginary object on the horizon to your destination, it will pass through your location and have an angle of 180 degrees. Now 180 degrees in the sense of a compass actually refers to S but the destination is not 'due S' of the imaginary object your phone is pointing at and, moreover, if you travelled to that imaginary point, your destination would still be SE of where you moved to.
In reality, the 180 degree line actually tells you the destination is 'behind you' relative to the way the phone (and presumably you) are pointing.
Having said that, however, if calculating the angle of a line from the imaginary point to your destination (passing through your location) in order to draw a pointer towards your destination is what you want...simply subtract the (absolute) bearing of the destination from the absolute bearing of the imaginary object and ignore a negation (if present). e.g., NW - SE is 315 - 135 = 180 so draw the pointer to point at the bottom of the screen indicating 'behind you'.
EDIT: I got the Maths slightly wrong...subtract the smaller of the bearings from the larger then subtract the result from 360 to get the angle in which to draw the pointer on the screen.
If you are on the same timezone
Convert GPS to UTM
http://www.ibm.com/developerworks/java/library/j-coordconvert/
http://stackoverflow.com/questions/176137/java-convert-lat-lon-to-utm
UTM coordinates get you a simples X Y 2D
Calculate the angle between both UTM locations
http://forums.groundspeak.com/GC/index.php?showtopic=146917
This gives the direction as if you were looking north
So whatever you rotate related do North just subtract this angle
If both point have a UTM 45º degree angle and you are 5º east of north, your arrow will point to 40º of north
Here is how I have done it:
Canvas g = new Canvas( compass );
Paint p = new Paint( Paint.ANTI_ALIAS_FLAG );
float rotation = display.getOrientation() * 90;
g.translate( -box.left, -box.top );
g.rotate( -bearing - rotation, box.exactCenterX(), box.exactCenterY() );
drawCompass( g, p );
drawNeedle( g, p );
This is the best way to detect Bearing from Location Object on Google Map:->
float targetBearing=90;
Location endingLocation=new Location("ending point");
Location
startingLocation=new Location("starting point");
startingLocation.setLatitude(mGoogleMap.getCameraPosition().target.latitude);
startingLocation.setLongitude(mGoogleMap.getCameraPosition().target.longitude);
endingLocation.setLatitude(mLatLng.latitude);
endingLocation.setLongitude(mLatLng.longitude);
targetBearing =
startingLocation.bearingTo(endingLocation);
The formula will give the bearing using the coordinates of the start point to the end point see
The following code will give you the bearing (angle between 0-360)
private double bearing(Location startPoint, Location endPoint) {
double longitude1 = startPoint.getLongitude();
double latitude1 = Math.toRadians(startPoint.getLatitude());
double longitude2 = endPoint.getLongitude();
double latitude2 = Math.toRadians(endPoint.getLatitude());
double longDiff = Math.toRadians(longitude2 - longitude1);
double y = Math.sin(longDiff) * Math.cos(latitude2);
double x = Math.cos(latitude1) * Math.sin(latitude2) - Math.sin(latitude1) * Math.cos(latitude2) * Math.cos(longDiff);
return Math.toDegrees(Math.atan2(y, x));
}
This works for me hope it will work others as well
I am in the process of figuring it out now but it seems as though the math depends on where you and your target are on the earth relative to true and magnetic North. For example:
float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) > myLocation.getBearing()){
thetaMeThem = myLocation.bearingTo(targetLocation) - azimuth + declination;}
See Sensor.TYPE_ORIENTATION for azimuth.
See getDeclination() for declination
This assumes declination is negative (west of true north) and theirBearing > yourBearing.
If declination is positive and yourBearing > theirBearing another option:
float thetaMeThem = 0.0;
if (myLocation.bearingTo(targetLocation) < myLocation.getBearing()){
thetaMeThem = azimuth - (myLocation.bearingTo(targetLocation) - declination);}
I haven't tested this fully but playing with the angles on paper got me here.
Terminology : The difference between TRUE north and Magnetic North is known as "variation" not declination. The difference between what your compass reads and the magnetic heading is known as "deviation" and varies with heading. A compass swing identifies device errors and allows corrections to be applied if the device has correction built in. A magnetic compass will have a deviation card which describes the device error on any heading.
Declination : A term used in Astro navigation : Declination is like latitude. It reports how far a star is from the celestial equator. To find the declination of a star follow an hour circle "straight down" from the star to the celestial equator. The angle from the star to the celestial equator along the hour circle is the star's declination.
I'm trying to make a compass that points to a custom location in a Unity program. However it's completely off, it points in generally the wrong direction and I can't quite seem to figure out what is wrong with my logic.
I'm using the curved geometry bearing equation from here: http://www.yourhomenow.com/house/haversine.html
Get current location.
Calculate bearing from current location to target location.
Rotate screen compass relative to true north.
// Calculate bearing between current location and target location
// Get current GPS location
float lat1 = Input.location.lastData.latitude;
float lon1 = Input.location.lastData.longitude;
float lat2 = TargetLatitude;
float dLon = TargetLongitude - lon1;
// Calculate bearing
var y = Mathf.Sin(dLon) * Mathf.Cos(lat2);
var x = Mathf.Cos(lat1) * Mathf.Sin(lat2) -
Mathf.Sin(lat1) * Mathf.Cos(lat2) * Mathf.Cos(dLon);
var brng = ((Mathf.Atan2(y, x)*(180.0f/Mathf.PI)) + 360.0f) % 360.0f;
Dump.text = brng.ToString();
// Rotate the to target location relative to north. Z axis pointing out of screen.
transform.eulerAngles = new Vector3(0, 0, Mathf.MoveTowardsAngle(transform.localEulerAngles.z, Input.compass.trueHeading + brng, COMPASS_MAXDELTA));
If I remove the bearing offset in that code, it points north enough for a digital compass.
Make sure that all of your angles are in radians rather than degrees.
Using Mathf.Deg2Rad in cases such as Mathf.Sin(dLon * Mathf.Deg2Rad) should yield the correct result. The Haversine formula only works for angles in radians.
I am developing augmented reality android application based on real time location.
It is a simple concept: my application should show some places around me. I have
researched this intensively and yet I am still running into issues. I have my GPS coordinates
and the target place's GPS coordinates.
My question is: How can I retrieve what my phone's camera is looking at (for example a building)?
What is the logical way to solve something like this?
Augmented Reality will transfer real coordinates system to camera coordinates system. In AR Location-based, the real coordinate is Geographic coordinate system. We will convert the GPS coordinate (Latitude, Longitude, Altitude) to Navigation coordinate (East, North, Up), then transfer Navigation coordinate to Camera coordinate and display it on camera view.
I just create the demo for you:
https://github.com/dat-ng/ar-location-based-android
First check the availability of sensors in the device. If the device supports TYPE_ROTATION_VECTOR then register a sensor listener for the same or else check for TYPE_MAGNETIC_FIELD and TYPE_ACCELEROMETER.
SensorManager mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
rSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
if (rSensor == null) {
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
aSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
Then in onSensorChanged function you should calculate the azimuth.
if (rSensor == null) {
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
magnetic = event.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER:
accelerometer = event.values.clone();
break;
}
if (magnetic != null && accelerometer != null) {
Rot = new float[9];
I = new float[9];
SensorManager.getRotationMatrix(Rot, I, accelerometer, magnetic);
float[] outR = new float[9];
SensorManager.remapCoordinateSystem(Rot, SensorManager.AXIS_X,
SensorManager.AXIS_Z, outR);
SensorManager.getOrientation(outR, values);
azimuth = values[0];
magnetic = null;
accelerometer = null;
}
} else {
SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
SensorManager.getOrientation(mRotationMatrix, mValues);
azimuth = Math.toDegrees(mValues[0]));
}
}
You can use this azimuth to plot the location in cameraview
double angle = bearing(myLatitude, myLongitude, dLatitude, dLongitude) - azimuth;
double xAxis, yAxis;
if(angle < 0)
angle = (angle+360)%360;
xAxis = Math.sin(Math.toRadians(angle)) * dist;
yAxis = Math.sqrt(Math.pow(dist, 2) - Math.pow(xAxis, 2));
if (angle > 90 && angle < 270)
yAxis *= -1;
double xAxisPosition = angle * (screenWidth / 90d);
xAxis = xAxisPosition - spotImageWidth/2;
float x, y;
if (angle <= 45)
x = (float) ((screenWidth / 2) + xAxis);
else if (angle >= 315)
x = (float) ((screenWidth / 2) - ((screenWidth*4) - xAxis));
else
x = (float) (float)(screenWidth*9);
y = (float)(((screenHeight - 300) - (i * 100)));
protected static double bearing(double lat1, double lon1, double lat2, double lon2) {
double longDiff = Math.toRadians(lon2 - lon1);
double la1 = Math.toRadians(lat1);
double la2 = Math.toRadians(lat2);
double y = Math.sin(longDiff) * Math.cos(la2);
double x = Math.cos(la1) * Math.sin(la2) - Math.sin(la1) * Math.cos(la2) * Math.cos(longDiff);
double result = Math.toDegrees(Math.atan2(y, x));
return (result+360.0d)%360.0d;
}
x, y will give the coordinates of the destination location.
The first step you need is to use sensor to get the direction of the back camera. You can read more about sensor at http://developer.android.com/reference/android/hardware/SensorManager.html
After you are done coding with sensors come back and ask the next question.
Try the DroidAR SDK https://github.com/bitstars/droidar . This is a AR SDK for Android. Most of your problems should be solved with it. There are also video manuals. You can also look into the code if you need just some stuff for your project.
There're two directions in this issue, device and targets.
The Azimuth of device location is shown below:
This information can be collected by sensors. However, if the orientation of the device is not fixed, you should do SensorManager.remapCoordinateSystem
The azimuth to targets is shown below:
It's probably the best figure I can find on the internet.
Once you have device location and the target location can be computed by:
azi = Math.abs(Math.toDegrees(Math.atan((tlon-lon)/(tlat-lat))));
where tlat and tlon indicates target gps locations, lat and lon are device location.
the value of this equation lies in -90 to +90, which is not what azimuth really is. So, there're 3 additional code should be added.
if((tlon-lon)>0&&(tlat-lat)<0){
azi = 180 - azi;
}
if((tlon-lon)<0&&(tlat-lat)<0){
azi = 180 + azi;
}
if((tlon-lon)<0&&(tlat-lat)>0){
azi = 360 - azi;
}
After these are all done, it's just easy to detect if targets are in your sight.
Hope these helped.
I want to make a function that calculate the angle between the user and one point of interest (POI) with reference to the true north.
I already have the longitude and latitude of my position and the POI position and now i need the angle between them.
Here is what i have:
private float calcAzimuth1(float lat0, float long0, float lat1, float long1)
{
//user's latitude and longitude
float userLat = (float) ((lat0 * ((float)Math.PI))/180);
float userLong = (float) ((long0 * ((float)Math.PI))/180);
//POI's latitude and longitude
float latT1 = (float) ((lat1 * ((float)Math.PI))/180);
float longT1 = (float) ((long1 * ((float)Math.PI))/180);
//angle between them
float angle=??}
Check bearingTo function of Location class
http://developer.android.com/reference/android/location/Location.html#bearingTo(android.location.Location)
You can create two Location objects from your Lat/Longs and then get the bearing between them.
The other thing you might need is to calculate the device orientation and then combine them together. That requires listening to Sensors and calculating the North from the information received. check the answer here:
Compass readings on SGS III