2017-02-13 2 views
12

に正しく見出し:このcompassモード、ように常に角度で回転地図で計算が真の私の要件は(<code>current location button twice</code>にクリックしたときに、デモを見ることができます)コンパスモードで<code>Google maps apps</code>などに軸受けされてアンドロイド

  • bluedot arrowは常にトップ画面をポイントします。

しかし、私は値からbearingを正しく計算する方法がわかりません。

public void onSensorChanged(SensorEvent sensorEvent) { 
     switch (sensorEvent.sensor.getType()) { 
      case Sensor.TYPE_ACCELEROMETER: 
       System.arraycopy(sensorEvent.values, 0, mAccelerometers, 0, 3); 
       break; 
      case Sensor.TYPE_MAGNETIC_FIELD: 
       System.arraycopy(sensorEvent.values, 0, mMagnetometers, 0, 3); 
       break; 
      default: 
       break; 
     } 
     float[] rotationMatrix = new float[9]; 
     boolean success = 
        SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometers, mMagnetometers); 
     if (success) { 
      SensorManager.getOrientation(rotationMatrix, mOrientation); 
      float azimuth = Math.toDegrees(mOrientation[0]); 
      float pitch = Math.toDegrees(mOrientation[1]); 
      float roll = Math.toDegrees(mOrientation[2]); 
     } 
     // cal to updateBearing(); 
    } 

は、iOSでは、CLHeadingは、まさに真のheading返すことができます。 androidにクラスがありますか?それをどのように計算できますか?あなたの問題ベアリング-例も回答以下

bearing-example

ためのリンク以下

+0

これは役に立ちますか? http://stackoverflow.com/q/7355679/7292819 – Gary99

+0

@ Gary99、no man。 – NamNH

+0

あなたは[これ](http://stackoverflow.com/a/4316717/5993410)をチェックしました –

答えて

3

チェックは、あなたの問題にsimilorです。

How do I get the correct bearing?

package ymc.ch.bearingexample; 
import android.content.Context; 
import android.hardware.GeomagneticField; 
import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.hardware.SensorEventListener; 
import android.hardware.SensorManager; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.util.Log; 

/** 
* Utility class that provides bearing values to true north. 
*/ 
public class BearingToNorthProvider implements SensorEventListener, LocationListener 
{ 
    public static final String TAG = "BearingToNorthProvider"; 

    /** 
    * Interface definition for a callback to be invoked when the bearing changes. 
    */ 
    public static interface ChangeEventListener { 
     /** 
     * Callback method to be invoked when the bearing changes. 
     * @param bearing the new bearing value 
     */ 
     void onBearingChanged(double bearing); 
    } 

    private final SensorManager mSensorManager; 
    private final LocationManager mLocationManager; 
    private final Sensor mSensorAccelerometer; 
    private final Sensor mSensorMagneticField; 

    // some arrays holding intermediate values read from the sensors, used to calculate our azimuth 
    // value 

    private float[] mValuesAccelerometer; 
    private float[] mValuesMagneticField; 
    private float[] mMatrixR; 
    private float[] mMatrixI; 
    private float[] mMatrixValues; 

    /** 
    * minimum change of bearing (degrees) to notify the change listener 
    */ 
    private final double mMinDiffForEvent; 

    /** 
    * minimum delay (millis) between notifications for the change listener 
    */ 
    private final double mThrottleTime; 

    /** 
    * the change event listener 
    */ 
    private ChangeEventListener mChangeEventListener; 

    /** 
    * angle to magnetic north 
    */ 
    private AverageAngle mAzimuthRadians; 

    /** 
    * smoothed angle to magnetic north 
    */ 
    private double mAzimuth = Double.NaN; 

    /** 
    * angle to true north 
    */ 
    private double mBearing = Double.NaN; 

    /** 
    * last notified angle to true north 
    */ 
    private double mLastBearing = Double.NaN; 

    /** 
    * Current GPS/WiFi location 
    */ 
    private Location mLocation; 

    /** 
    * when we last dispatched the change event 
    */ 
    private long mLastChangeDispatchedAt = -1; 

    /** 
    * Default constructor. 
    * 
    * @param context Application Context 
    */ 
    public BearingToNorthProvider(Context context) { 
     this(context, 10, 0.5, 50); 
    } 

    /** 
    * @param context Application Context 
    * @param smoothing the number of measurements used to calculate a mean for the azimuth. Set 
    *      this to 1 for the smallest delay. Setting it to 5-10 to prevents the 
    *      needle from going crazy 
    * @param minDiffForEvent minimum change of bearing (degrees) to notify the change listener 
    * @param throttleTime minimum delay (millis) between notifications for the change listener 
    */ 
    public BearingToNorthProvider(Context context, int smoothing, double minDiffForEvent, int throttleTime) 
    { 
     mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 
     mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
     mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); 
     mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); 

     mValuesAccelerometer = new float[3]; 
     mValuesMagneticField = new float[3]; 

     mMatrixR = new float[9]; 
     mMatrixI = new float[9]; 
     mMatrixValues = new float[3]; 

     mMinDiffForEvent = minDiffForEvent; 
     mThrottleTime = throttleTime; 

     mAzimuthRadians = new AverageAngle(smoothing); 
    } 

    //============================================================================================== 
    // Public API 
    //============================================================================================== 

    /** 
    * Call this method to start bearing updates. 
    */ 
    public void start() 
    { 
     mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI); 
     mSensorManager.registerListener(this, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI); 

     for (final String provider : mLocationManager.getProviders(true)) { 
      if (LocationManager.GPS_PROVIDER.equals(provider) 
        || LocationManager.PASSIVE_PROVIDER.equals(provider) 
        || LocationManager.NETWORK_PROVIDER.equals(provider)) { 
       if (mLocation == null) { 
        mLocation = mLocationManager.getLastKnownLocation(provider); 
       } 
       mLocationManager.requestLocationUpdates(provider, 0, 100.0f, this); 
      } 
     } 
    } 

    /** 
    * call this method to stop bearing updates. 
    */ 
    public void stop() 
    { 
     mSensorManager.unregisterListener(this, mSensorAccelerometer); 
     mSensorManager.unregisterListener(this, mSensorMagneticField); 
     mLocationManager.removeUpdates(this); 
    } 

    /** 
    * @return current bearing 
    */ 
    public double getBearing() 
    { 
     return mBearing; 
    } 

    /** 
    * Returns the bearing event listener to which bearing events must be sent. 
    * @return the bearing event listener 
    */ 
    public ChangeEventListener getChangeEventListener() 
    { 
     return mChangeEventListener; 
    } 

    /** 
    * Specifies the bearing event listener to which bearing events must be sent. 
    * @param changeEventListener the bearing event listener 
    */ 
    public void setChangeEventListener(ChangeEventListener changeEventListener) 
    { 
     this.mChangeEventListener = changeEventListener; 
    } 

    //============================================================================================== 
    // SensorEventListener implementation 
    //============================================================================================== 

    @Override 
    public void onSensorChanged(SensorEvent event) 
    { 
     switch (event.sensor.getType()) { 
      case Sensor.TYPE_ACCELEROMETER: 
       System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3); 
       break; 
      case Sensor.TYPE_MAGNETIC_FIELD: 
       System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3); 
       break; 
     } 

     boolean success = SensorManager.getRotationMatrix(mMatrixR, mMatrixI, 
       mValuesAccelerometer, 
       mValuesMagneticField); 

     // calculate a new smoothed azimuth value and store to mAzimuth 
     if (success) { 
      SensorManager.getOrientation(mMatrixR, mMatrixValues); 
      mAzimuthRadians.putValue(mMatrixValues[0]); 
      mAzimuth = Math.toDegrees(mAzimuthRadians.getAverage()); 
     } 

     // update mBearing 
     updateBearing(); 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int i) { } 

    //============================================================================================== 
    // LocationListener implementation 
    //============================================================================================== 

    @Override 
    public void onLocationChanged(Location location) 
    { 
     // set the new location 
     this.mLocation = location; 

     // update mBearing 
     updateBearing(); 
    } 

    @Override 
    public void onStatusChanged(String s, int i, Bundle bundle) { } 

    @Override 
    public void onProviderEnabled(String s) { } 

    @Override 
    public void onProviderDisabled(String s) { } 

    //============================================================================================== 
    // Private Utilities 
    //============================================================================================== 

    private void updateBearing() 
    { 
     if (!Double.isNaN(this.mAzimuth)) { 
      if(this.mLocation == null) { 
       Log.w(TAG, "Location is NULL bearing is not true north!"); 
       mBearing = mAzimuth; 
      } else { 
       mBearing = getBearingForLocation(this.mLocation); 
      } 

      // Throttle dispatching based on mThrottleTime and minDiffForEvent 
      if(System.currentTimeMillis() - mLastChangeDispatchedAt > mThrottleTime && 
       (Double.isNaN(mLastBearing) || Math.abs(mLastBearing - mBearing) >= mMinDiffForEvent)) { 
       mLastBearing = mBearing; 
       if(mChangeEventListener != null) { 
        mChangeEventListener.onBearingChanged(mBearing); 
       } 
       mLastChangeDispatchedAt = System.currentTimeMillis(); 
      } 
     } 
    } 

    private double getBearingForLocation(Location location) 
    { 
     return mAzimuth + getGeomagneticField(location).getDeclination(); 
    } 

    private GeomagneticField getGeomagneticField(Location location) 
    { 
     GeomagneticField geomagneticField = new GeomagneticField(
       (float)location.getLatitude(), 
       (float)location.getLongitude(), 
       (float)location.getAltitude(), 
       System.currentTimeMillis()); 
     return geomagneticField; 
    } 
} 
+0

ありがとう!私はこのサンプルを読んだ。いいですが、それが正しい答えであることを確認することはできません。なぜ、「方位」が「方位」を計算するために使用する唯一の値であるのか、「ピッチ」および「ロール」値はどうですか?また、どこかで、私は 'remapCoordinateSystem'メソッドについて混乱しました。 – NamNH

3

方位と位置が見出しを計算するのに必要なパラメータのみです。

角度の計算や変換のための規則は、この順序でそれらを使用することです:
1)方位
2)ピッチ
3)ロール

+1

申し訳ありませんが、私の担当者が50歳未満であるため、回答として私のコメントを投稿しなければなりませんでした。 –

+0

多くの参照サイトの後で、私はあなたに同意することができます、 'azimuth'と' location'の偏差は、 。 – NamNH

3

見出しを計算するには、あなただけの方位を必要としています。

float current_measured_bearing = (float) (results[0] * 180/Math.PI); 
if (current_measured_bearing < 0) current_measured_bearing += 360; 

詳細をthis answerに、またeffect of device orientationを考慮している:あなたが示したように、それはvalues[0]をラジアンから度に変換して、それはポジティブだことを確認、その後

SensorManager.getOrientationに呼び出しから返さあります。

関連する問題

 関連する問題