2012-11-08 151 views
13

我正在嘗試使用accelorometer和磁場傳感器爲Android編程指南針,現在我想知道如何爲我的指南針獲得正確的角度。指南針在Android中

我讀的加速度計和磁場傳感器的值分別爲「加速」和「磁化」。要獲取的角度,我執行以下操作:

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 
          .... 

後來,我用一個旋轉矩陣把我的針:

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

現在,getOrientation的文件說,該方向[0]應該是圍繞z軸的旋轉。 TYPE_ORIENTATION的文件指出 「方位角,磁北方向與y軸之間的角度,圍繞z軸(0至359),0 =北,90 =東,180 =南,270 =西」。

但是我的方位角不在0到359之間,而是在-2到2之間。getOrientation的方位角是什麼,我怎樣才能將它轉換成角度?

回答

20

使用之間的度以下從給定的方位轉換弧度(-PI ,+ PI)爲度(0,360)用於方便

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

變量名;-)

+0

謝謝:)最後一條if語句到底是什麼? – user1809923

+0

Math.toDegrees()將從-PI和+ PI弧度角給出-180到180之間的角度。這只是把一切放在積極的方向上。 – rgrocha

+0

這是正確的答案。 –

2

我發現這在谷歌的ApiDemos:

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

正如你可以看到你得到0至360

+0

這將是偉大的,如果你解釋:) – user1809923

+0

好吧,我會編輯我的答案。 –

+0

嗨,這是一個有趣的方法,但我認爲這可能不是很準確,因爲我只是估計-2到2. – user1809923

7

代碼片段可以從https://github.com/iutinvg/compass

它不使用棄用的東西,應用低通濾波器。

+0

標準是什麼來決定'最終浮動阿爾法= 0.97f;' 您已經使用0.97作爲濾波常數,谷歌已使用0.8。 – DeltaCap

+1

它會影響箭頭旋轉的速度。所以選擇是基於視覺感覺:更平滑的運動。 – iutinvg