2012-11-08 8 views
13

Sto provando a programmare una bussola con Android utilizzando l'accellerometro e il sensore di campo magnetico, ora mi chiedo come ottenere l'angolo corretto per la mia bussola.Compass in Android

Ho letto i valori dell'accelerometro e del sensore di campo magnetico rispettivamente in "accele" e "magne". Per ottenere l'angolo, eseguo il seguente:

float R[] = new float[9]; 
float I[] = new float[9]; 
boolean success = SensorManager.getRotationMatrix(R, I, accele, magne); 
     if(success) { 
      float orientation[] = new float[3]; 
      SensorManager.getOrientation(R, orientation); 
      azimuth = orientation[0]; // contains azimuth, pitch, roll 
          .... 

Più tardi, io uso una matrice di rotazione di mettere il mio ago:

rotation.setRotate(azimuth, compass.getWidth()/2, compass.getHeight()/2); 
canvas.drawBitmap(needle, rotation, null); 

Ora, la documentazione di getOrientation dice, che l'orientamento [0] dovrebbe essere la rotazione attorno all'asse z. La documentazione per TYPE_ORIENTATION afferma che "Azimut, angolo tra la direzione nord magnetica e l'asse y, attorno all'asse z (da 0 a 359) 0 = Nord, 90 = Est, 180 = Sud, 270 = Ovest".

Il mio azimut tuttavia non è compreso tra 0 e 359, ma piuttosto tra -2 e 2. Che cos'è esattamente l'azimuth di getOrientation e come posso convertirlo in un angolo?

risposta

20

utilizzare la seguente per convertire dalla data di azimut in radianti (-PI , + PI) in gradi (0, 360) nomi

float azimuthInRadians = orientation[0]; 
float azimuthInDegress = (float)Math.toDegrees(azimuthInRadians); 
if (azimuthInDegress < 0.0f) { 
    azimuthInDegress += 360.0f; 
} 

variabile per convenienza ;-)

+0

grazie :) Qual è esattamente l'ultima istruzione if? – user1809923

+0

Math.toDegrees() vi darà un angolo compreso tra -180 e 180 da un angolo di radiazione PI-PI e + PI. Questo ha appena messo tutto sulla direzione positiva. – rgrocha

+0

Questa è la risposta giusta. –

2

ho trovato questo nella ApiDemos del google:

/* 
* Copyright (C) 2007 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 

package com.example.android.apis.graphics; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.*; 
import android.hardware.SensorListener; 
import android.hardware.SensorManager; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.os.SystemClock; 
import android.util.Config; 
import android.util.Log; 
import android.view.View; 

public class Compass extends GraphicsActivity { 

    private static final String TAG = "Compass"; 

    private SensorManager mSensorManager; 
    private SampleView mView; 
    private float[] mValues; 

    private final SensorListener mListener = new SensorListener() { 

     public void onSensorChanged(int sensor, float[] values) { 
      if (Config.LOGD) Log.d(TAG, "sensorChanged (" + values[0] + ", " + values[1] + ", " + values[2] + ")"); 
      mValues = values; 
      if (mView != null) { 
       mView.invalidate(); 
      } 
     } 

     public void onAccuracyChanged(int sensor, int accuracy) { 
      // TODO Auto-generated method stub 

     } 
    }; 

    @Override 
    protected void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 
     mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); 
     mView = new SampleView(this); 
     setContentView(mView); 
    } 

    @Override 
    protected void onResume() 
    { 
     if (Config.LOGD) Log.d(TAG, "onResume"); 
     super.onResume(); 
     mSensorManager.registerListener(mListener, 
       SensorManager.SENSOR_ORIENTATION, 
       SensorManager.SENSOR_DELAY_GAME); 
    } 

    @Override 
    protected void onStop() 
    { 
     if (Config.LOGD) Log.d(TAG, "onStop"); 
     mSensorManager.unregisterListener(mListener); 
     super.onStop(); 
    } 

    private class SampleView extends View { 
     private Paint mPaint = new Paint(); 
     private Path mPath = new Path(); 
     private boolean mAnimate; 
     private long mNextTime; 

     public SampleView(Context context) { 
      super(context); 

      // Construct a wedge-shaped path 
      mPath.moveTo(0, -50); 
      mPath.lineTo(-20, 60); 
      mPath.lineTo(0, 50); 
      mPath.lineTo(20, 60); 
      mPath.close(); 
     } 

     @Override protected void onDraw(Canvas canvas) { 
      Paint paint = mPaint; 

      canvas.drawColor(Color.WHITE); 

      paint.setAntiAlias(true); 
      paint.setColor(Color.BLACK); 
      paint.setStyle(Paint.Style.FILL); 

      int w = canvas.getWidth(); 
      int h = canvas.getHeight(); 
      int cx = w/2; 
      int cy = h/2; 

      canvas.translate(cx, cy); 
      if (mValues != null) {    
       canvas.rotate(-mValues[0]); 
      } 
      canvas.drawPath(mPath, mPaint); 
     } 

     @Override 
     protected void onAttachedToWindow() { 
      mAnimate = true; 
      super.onAttachedToWindow(); 
     } 

     @Override 
     protected void onDetachedFromWindow() { 
      mAnimate = false; 
      super.onDetachedFromWindow(); 
     } 
    } 
} 

Come si può vedere si vuole ricevere i gradi da 0 a 360

+0

sarebbe fantastico, se hai spiegato :) – user1809923

+0

Ok, modifico la mia risposta. –

+0

ciao, questo è un approccio interessante, tuttavia penso che questo potrebbe non essere molto accurato, dal momento che ho appena stimato il -2 a 2. – user1809923

7

È possibile ottenere uno snippet di codice da https://github.com/iutinvg/compass

Non utilizza oggetti deprecati, applica filtri passa-basso.

+0

quali sono i criteri per decidere 'final float alpha = 0.97f;' Hai usato 0.97 come costante di filtro, google ha usato 0.8. – DeltaCap

+1

Influirà sulla velocità della rotazione della freccia. Quindi la scelta è basata sul senso visivo: movimento più fluido. – iutinvg