0

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?

ryoga86
  • 3
  • 2
  • " heading != bearing. " And can you please so kind to post the difference value? Is that some degrees, tenth of degrees ot totally different (10 or more?)? – AlexWien Aug 15 '15 at 17:01

1 Answers1

1

Heading is the direction where you look, e.g a tank in which direction it would shoot, while bearing is the direction this vehicle moves. So that should answer why bearing is not heading. They have different names, and meanings, they are different caluclated, they could not be expected to deliver the same value.

More details

You can move North (bearing = North) , but look at NE. (heading)

  • Gps delivers bearing (or course (over ground)), the direction the vehicle moves (altough some Api wrongly call it heading)

  • Compass (=magnetometer) delivers the direction in which you hold the device = (heading)

When you calculate the bearing between the two locations defined as coordinates in lat,lon , as you do in targetLocation (location.bearingTo(targetLocation)). then this is bearing! It is not heading!

And neither the compass not the accelrometer will deliver a decent heading value. Some android device are very wrong in their magnetomter ( I saw +-20 degrees compared to +/- 2 degrees of my iPhone., Always use a traditional high quality compass as reference) The ios devices shows the heading well within +/- 2 degress when well calibrated, (you have to calibrate each time before looking at the decice value, not only when you are asked by the operating system to calibrate).
GPS when moving > 10 km(h delives goot bearing results, but not heading.

Magnetometer can be off by some degree even when calibrated. And usually the declination is smaller than the error. Declination is nearly nothing in europe, 3 degress very north (europe), only a few places have a high declination >6-7°(north alaska)

Update to your further explantion in your graphic:

You have placed two points with a distance of only 15m, while GPS will not be much more acurate than 3-6m. So imagine 6m offset of start or destination: such a triangle where a = 6m, b = 15, has an angle of atan2(6 / 15.0) = 21°. So you have an offset of 21° only by inacuracy of location. However still think at the differnce of heading by compass and bearing by line of sight between two locations.

AlexWien
  • 28,470
  • 6
  • 53
  • 83
  • Thx for your answer. i already know the difference between heading and bearing. Better topic would be why is my headingValue such diffrent from bearingValue while looking on targetLocation? – ryoga86 Aug 15 '15 at 18:15
  • I told you that 1) the offset of GPS alone will cuase at least 20° in you case. Use higher distance, Look at a target in 1km distance, kets say the biggest tower or top of mountain you can see. 2) the magentometer does not work well, Buy a compass from recta, silva or suunto. And look what it tells when you look at the target, Or you use another well working application, and look what they show as heading. – AlexWien Aug 15 '15 at 18:24
  • Further just mark the places where you realy have been standing, and measure the azimuth with googl earth. And always us high distances for such measures. – AlexWien Aug 15 '15 at 18:26
  • But the application is focused for pedestrian user which starts at a certain point and gets nagivated by angleValue = bearingValue - currentHeadingValue. for example i have to use it on a footballfield where sight to satellites is even much better. At this place the measures have deviation of around 3 meters. Do you think its a bad idea to use android GPS bearing method on such short distances? First idea was solving this with simple vector calculations, but since i figured out that google serves those functions, i decided for those ones.. – ryoga86 Aug 15 '15 at 20:04
  • The bearing function works precise. But the locations coordinates are not. Test your code for long disatcnes, When that wokrs than you know its not an error in your code. When it does not work for short distances, you can easily find out why. mark th eplace where you are standing on the map. Compare it with the place that the gps delivers. Find out where is the problem: the inacurate magento meter ? (Buy a compass!!!) and compare. And calculate bearing with correct location, and incorrect from gps. Then you should know where are the inacuaries and where are the limits. – AlexWien Aug 16 '15 at 00:03
  • (Many experts that I know tell, that pedestrian navigation is an extremly difficult task, due the fact that gps bearing is very inacurate at low speeds) – AlexWien Aug 16 '15 at 00:05
  • Why should be bearing very inaccurate at low speeds? Its just a calculation which depens on currentPosition. i cant imagine to – ryoga86 Aug 16 '15 at 12:23
  • No! course by GPS is NOT!!! (only) caluclated by positional change, the physical doppler effect is used. which is much more acurate. However at low speeds this does not work well. Even if the course would be created only by positional change, this clearly means that at low sped this is more inacuarte. Just take a paper and draw it. draw two points 2m appart (this is speed 2m/s (as by pedestrian used) now offset each position by 2m, one 2m left, the other 2m right, The coure totally change. now do the same with 11m, offset again with 2m, and you see the course is nearer to the real course. – AlexWien Aug 16 '15 at 13:36
  • 1
    You need a better feeling how gps behaves. Just record all points and draw them on a map. Then you see how positions will jump at low speeds.Look first at the data, then develop your algorithm, not the opposite: having an algorithm in mind without looking at the data. – AlexWien Aug 16 '15 at 13:38