2017-02-13 8 views
12

मेरे आवश्यकता में सही ढंग से बढ़ रहा है, कंपास मोड में Google maps apps की तरह में असर है (आप जब current location button twice लिए क्लिक डेमो देख सकते हैं):की गणना सही एंड्रॉयड

  • इस compass मोड में, मैप्स हमेशा इतना है कि एक कोण तक घुमाया bluedot arrow हमेशा शीर्ष स्क्रीन पर इंगित करें।

लेकिन मुझे नहीं पता कि azimuth, pitch, roll मानों से सही गणना कैसे करें।

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(); 
    } 

आईओएस में, CLHeading बिल्कुल सच heading लौट सकते हैं। क्या android में कक्षा में एक ही सुविधा है या मैं इसकी गणना कैसे कर सकता हूं? आपकी समस्या असर-उदाहरण

bearing-example

इसके अलावा उत्तर नीचे के लिए लिंक नीचे

+0

क्या इससे मदद मिलती है? http://stackoverflow.com/q/7355679/7292819 – Gary99

+0

@ गैरी 99, कोई आदमी नहीं। – 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

कई संदर्भित साइटों के बाद, अब मैं आपके साथ सहमत हो सकता हूं, 'अजीमुथ' और 'स्थान' की गिरावट ऐसी चीजें हैं जिन्हें हमें शीर्षक की गणना करने की आवश्यकता है । – NamNH

3

एक शीर्षक गणना करने के लिए, आप केवल दिगंश की जरूरत है। this answer में

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

अधिक जानकारी के, जो भी effect of device orientation मानता है: आप से पता चला है के रूप में, यह values[0] तब SensorManager.getOrientation

करने के लिए कॉल से लौटे, रेडियन को अंश में से कनवर्ट करते हैं, और यह सकारात्मक है सुनिश्चित है।

संबंधित मुद्दे