2012-11-08 6 views
13

Ich versuche, einen Kompass mit Android mit dem Accelometer und dem Magnetfeldsensor zu programmieren, jetzt frage ich mich, wie man den richtigen Winkel für meinen Kompass bekommt.Kompass in Android

Ich lese die Werte des Beschleunigungsmessers und des Magnetfeldsensors in "accel" bzw. "magne" ein. Um den Winkel zu erhalten, führe ich folgendes:

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

Später, verwende ich eine Rotationsmatrix meine Nadel zu setzen:

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

Nun wird die Dokumentation von GetOrientation sagt, dass die Orientierung [0] sollte die Rotation um die z-Achse sein. Die Dokumentation für TYPE_ORIENTATION besagt, dass "Azimut, Winkel zwischen der magnetischen Nordrichtung und der y-Achse, um die z-Achse (0 bis 359). 0 = Norden, 90 = Osten, 180 = Süden, 270 = Westen".

Mein Azimut liegt jedoch nicht zwischen 0 und 359, sondern eher bei -2 bis 2. Was genau ist der Azimut von getOrientation und wie kann ich ihn in einen Winkel umwandeln?

Antwort

20

Verwendung erhalten Sie wie folgt aus dem gegebenen Azimut in Radianten zu konvertieren (-PI , + PI) in Grad (0, 360)

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

Variablennamen der Einfachheit halber verwendet ;-)

+0

danke :) Was genau ist die letzte if-Anweisung für? – user1809923

+0

Die Math.toDegrees() geben Ihnen einen Winkel zwischen -180 und 180 aus -PI und + PI Radianten Winkel. Dies bringt alles in die positive Richtung. – rgrocha

+0

Dies ist die richtige Antwort. –

2

ich dieses ApiDemos der in der Google gefunden:

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

Wie Sie sehen können Sie den Grad zwischen 0 bis 360

+0

das wäre toll, wenn du es erklärst :) – user1809923

+0

Ok, ich werde meine Antwort bearbeiten. –

+0

hi, das ist ein interessanter Ansatz, aber ich denke, das könnte nicht sehr genau sein, da ich nur die -2 bis 2 geschätzt. – user1809923

7

Ein Code-Snippet kann von https://github.com/iutinvg/compass

abgerufen werden. Es verwendet keine veralteten Materialien, wendet Tiefpassfilter an.

+0

Was sind die Kriterien zu entscheiden? Final float alpha = 0,97f; ' Sie haben 0,97 als Filterkonstante google verwendet hat 0,8 verwendet. – DeltaCap

+1

Es wird die Geschwindigkeit der Pfeilrotation beeinflussen. Die Wahl basiert also auf dem visuellen Sinn: mehr glatte Bewegung. – iutinvg