Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
Midori edited this pageJan 29, 2024 ·30 revisions

True Heading

magneticHeading and trueHeading are two different types of orientations used to indicate direction.

magnetic heading: This is an orientation based on the geomagnetic field. That is, it is the azimuth angle with respect to north as indicated by the earth's magnetic field. This value is affected by the geomagnetic field and therefore depends on geographic location and variations in the geomagnetic field.

true heading: This is the azimuth relative to the geographic north pole (true north). Since true north is based on the earth's axis of rotation, it is not affected by the geomagnetic field. However, to accurately determine true north, the deviation between the device's current position and the geomagnetic field must be taken into account.

Calculation formula: true heading = magnetic heading + magnetic declination

Magnetic declination shifts with location and time. For example, the magnetic declination in Tokyo, Japan around 2024 is about -7.3 degrees, which means there is a difference of 7.3 degrees between magnetic heading and true heading.

CompassX uses true heading to obtain a more accurate value from north.

Why does Android require location permission?

While iOS has long had a standard API that provides true heading, Android has only recently implemented it since API 33, mostly because it requires getting the declination from the current location and calculating it manually.

Calibration

How to calibrate compass

Hold the smartphone and draw the number "8" Repeat a couple of times. You can see more details ongoogle maps.

It is impossible to get perfect values with the physical compass sensor on the phone. However, calibration can improve accuracy.
In situations where high accuracy is required, it is recommended that users be prompted to calibrate each time.

Checking the accuracy of CompassX

Prepare an actual iOS device.

  1. Go to Settings -> Privacy & Security -> Location Service -> System Service -> Calibrate Compass = On
  2. Go to Settings -> Compass app -> Use true north = On

After calibrating the device sufficiently, compare the CompassXheading with the iOS default compass app.

Android will be compared to the iOS device prepared here.Unfortunately, Google does not provide a standard compass app, we do not recommend using third-party apps from the Google Play Store for measuring accuracy. You don't know if they really provide true heading.In Android, the sensors on each device are different, so there are individual differences.

How does it work

True heading

- iOS: Use CoreLocation library's CLLocationManager. Obtain usingCLHeading.trueHeading.

publicfunc locationManager(_ manager:CLLocationManager, didUpdateHeading newHeading:CLHeading){eventSink?(newHeading.trueHeading)}

- Android: UseSensor.TYPE_HEADING from the android.hardware.Sensor library.

publicvoidonAttachedToEngine(FlutterPlugin.FlutterPluginBindingflutterPluginBinding) {context =flutterPluginBinding.getApplicationContext();sensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);headingSensor =sensorManager.getDefaultSensor(Sensor.TYPE_HEADING);}

However, Sensor.TYPE_HEADING was added from API 33 and is still rare in Android devices. Therefore, in most cases, it is necessary to calculate usingSensor.TYPE_ROTATION_VECTOR adjusted with declination.

Calculate the true heading based on the true north by adding the magnetic declination to the azimuth based on the geomagnetic north.

Calculation formula: trueHeading = azimuth (magnetic heading) + declination (magnetic declination)

Azimuth (Magnetic heading): This is the angle based on geomagnetic north representing the direction to a target from a specific point.

Declination (Magnetic declination): Magnetic declination is the angular difference between magnetic north (geomagnetic north) and geographic north (true north) at a location. This value varies by geographic location and changes over time.

Add sensor

publicvoidonAttachedToEngine(FlutterPlugin.FlutterPluginBindingflutterPluginBinding) {///rotationVectorSensor =sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);///}

Calculate azimuth with ROTATION_VECTOR sensor

publicvoidonSensorChanged(SensorEventevent) {if (event.sensor.getType() ==Sensor.TYPE_ROTATION_VECTOR) {float[]rotationMatrix =newfloat[9];SensorManager.getRotationMatrixFromVector(rotationMatrix,event.values);float[]orientationAngles =newfloat[3];SensorManager.getOrientation(rotationMatrix,orientationAngles);floatazimuth = (float)Math.toDegrees(orientationAngles[0]);floattrueHeading =calculateTrueHeading(azimuth);///    } }

Obtain location and calculate trueHeading from azimuth and declination

publicCompassXPlugin() {locationListener =newLocationListener() {@OverridepublicvoidonLocationChanged(Locationlocation) {currentLocation =location;        }///    };}privatefloatcalculateTrueHeading(floatazimuth) {floatdeclination =currentLocation !=null                    ?newGeomagneticField((float)currentLocation.getLatitude(),                            (float)currentLocation.getLongitude(),                            (float)currentLocation.getAltitude(),System.currentTimeMillis()).getDeclination()                    :0f;floattrueHeading = (azimuth +declination +360) %360;returntrueHeading;}

Accuracy

Due to the use of physical sensors, results can be unstable. Calibration may be necessary in situations where accuracy is crucial. On Android, the type of sensors varies by device, leading to significant differences.

- iOS: Obtain usingCLHeading.headingAccuracy.

Estimated error. Larger values indicate greater deviation. Negative values are returned when estimation is not possible. (degrees)

publicfunc locationManager(_ manager:CLLocationManager, didUpdateHeading newHeading:CLHeading){eventSink?(newHeading.headingAccuracy)}

- Android: Acquired through SensorEventListener.

Accuracy can be obtained withSensorManager.SENSOR_STATUS_ACCURACY

publicvoidonAccuracyChanged(Sensorsensor,intaccuracy) {if (sensor !=rotationVectorSensor &&sensor !=headingSensor)return;shouldCalibrate =accuracy !=SensorManager.SENSOR_STATUS_ACCURACY_HIGH;}

ForRotation Vector Sensor,event.values[4] can provide the estimated error. However, many devices lack the necessary sensors for estimation, in which case -1 is returned. (radians)

publicvoidonSensorChanged(SensorEventevent) {if (event.sensor.getType() ==Sensor.TYPE_ROTATION_VECTOR) {///floataccuracyRadian =event.values[4];floataccuracy =accuracyRadian != -1 ? (float)Math.toDegrees(accuracyRadian) : -1;///    }}

ForHeading Sensor,event.values[1] can provide the estimated error. (degrees)

}elseif (event.sensor.getType() ==Sensor.TYPE_HEADING) {floatheading =event.values[0];floataccuracy =event.values[1];///}

References


[8]ページ先頭

©2009-2025 Movatter.jp