In my Android application I have to use my current heading (using accelerometer and magnetometer) and current bearing to targetLocation
(location.bearingTo(targetLocation)
).
I already know that using accelerometer and magnetometer to figure out current heading starts at 0° on magnetic North and current Bearing starts on geographical North. So i figured out, that i have to add to headingValue
, depending on my current location, a value called declination.
For example, I pick up a certain GPS point from google-maps, adding this point as locationpoint in the application. Starting application, moving before measuring the device like a infinity-sign in the air and holding the device in front of me focused in target direction. So i notice that heading != bearing. Can anyone explain to me the error? Assume that i tried different distances between 50 and 3 meters and that my device is calibrated correctly. Below are important methods of source code:
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = event.values.clone();
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values.clone();
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
double tempAzimuth = Math.toDegrees(orientation[0]); // orientation contains: azimut, pitch and roll
if(tempAzimuth < 0){
currentHeading = tempAzimuth + 360;
} else {
currentHeading = tempAzimuth;
}
TVheadingMag.setText(""+String.format( "%.2f",currentHeading)+"°");
}
}
}
@Override
public void onLocationChanged(Location location) {
//Declination http://stackoverflow.com/questions/4308262/calculate-compass-bearing-heading-to-location-in-android
geoField = new GeomagneticField(
Double.valueOf(location.getLatitude()).floatValue(),
Double.valueOf(location.getLongitude()).floatValue(),
Double.valueOf(location.getAltitude()).floatValue(),
System.currentTimeMillis());
if(location.bearingTo(this.target)<0){
currentBearing = location.bearingTo(this.target)+360;
} else {
currentBearing = location.bearingTo(this.target);
}
headingWithDeclination = currentHeading;
headingWithDeclination += geoField.getDeclination();
currentDistance = location.distanceTo(this.target);
TVheading.setText(""+String.format( "%.2f", headingWithDeclination)+"°");
TVheadingMag.setText(""+String.format( "%.2f",currentHeading)+"°");
TVbearing.setText(""+String.format( "%.2f",currentBearing)+"°");
TVgps.setText(""+ String.format( "%.6f",location.getLatitude()) + " " + String.format( "%.6f",location.getLongitude()));
}
UPDATE
Picture: https://pl.vc/1r6ap
The orange marked position is targetLocation. Both position are heading to targetLocation. Can you agree that these results are quiet correctly displayed?
During creation of this pic, i've noticed that both white marks are not equal to positions i was standing at. It seems like bad gps data is the reason because of the problem, isnt it?